| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- // ES6 Module functionality tests -- verifies functionality of import and export statements
- WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
- function testScript(source, message, shouldFail = false, explicitAsync = false) {
- message += " (script)";
- let testfunc = () => testRunner.LoadScript(source, undefined, shouldFail, explicitAsync);
- if (shouldFail) {
- let caught = false;
- assert.throws(testfunc, SyntaxErrr, message);
- assert.isTrue(caught, `Expected error not thrown: ${message}`);
- } else {
- assert.doesNotThrow(testfunc, message);
- }
- }
- function testModuleScript(source, message, shouldFail = false, explicitAsync = false) {
- message += " (module)";
- let testfunc = () => testRunner.LoadModule(source, 'samethread', shouldFail, explicitAsync);
- if (shouldFail) {
- let caught = false;
- // We can't use assert.throws here because the SyntaxError used to construct the thrown error
- // is from a different context so it won't be strictly equal to our SyntaxError.
- try {
- testfunc();
- } catch(e) {
- caught = true;
- // Compare toString output of SyntaxError and other context SyntaxError constructor.
- assert.areEqual(e.constructor.toString(), SyntaxError.toString(), message);
- }
- assert.isTrue(caught, `Expected error not thrown: ${message}`);
- } else {
- assert.doesNotThrow(testfunc, message);
- }
- }
- function testDynamicImport(importFunc, thenFunc, catchFunc, _asyncEnter, _asyncExit) {
- var promise = importFunc();
- assert.isTrue(promise instanceof Promise);
- promise.then((v)=>{
- _asyncEnter();
- thenFunc(v);
- _asyncExit();
- }).catch((err)=>{
- _asyncEnter();
- catchFunc(err);
- _asyncExit();
- });
- }
- function testDoubleDynamicImport(importFunc, secondFunc, thirdFunc, catchFunc, _asyncEnter, _asyncExit) {
- let promise = importFunc();
- assert.isTrue(promise instanceof Promise);
- promise.then((v)=>{
- _asyncEnter();
- let secondPromise = secondFunc(v);
- secondPromise.then((v2)=>{
- _asyncEnter();
- thirdFunc(v2);
- _asyncExit();
- });
- _asyncExit();
- }).catch((err)=>{
- _asyncEnter();
- catchFunc(err);
- _asyncExit();
- });
- }
- var tests = [
- {
- name: "Runtime evaluation of module specifier",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>{
- var getName = ()=>{ return 'ModuleSimpleExport'; };
- return import( getName() + '.js');
- },
- (v)=>{
- assert.areEqual('ModuleSimpleExport', v.ModuleSimpleExport_foo(), 'Failed to import ModuleSimpleExport_foo from ModuleSimpleExport.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit
- )`;
- testScript(functionBody, "Test importing a simple exported function", false, true);
- testModuleScript(functionBody, "Test importing a simple exported function", false, true);
- }
- },
- {
- name: "Validate a simple module export",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>{ return import('ModuleSimpleExport.js'); },
- (v)=>{ assert.areEqual('ModuleSimpleExport', v.ModuleSimpleExport_foo(), 'Failed to import ModuleSimpleExport_foo from ModuleSimpleExport.js'); },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit
- )`;
- testScript(functionBody, "Test importing a simple exported function", false, true);
- testModuleScript(functionBody, "Test importing a simple exported function", false, true);
- }
- },
- {
- name: "Validate importing from multiple modules",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexExports.js'),
- (v)=>{
- assert.areEqual('foo', v.foo2(), 'Failed to import foo2 from ModuleComplexExports.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit
- )`;
- testScript(functionBody, "Test importing from multiple modules", false, true);
- testModuleScript(functionBody, "Test importing from multiple modules", false, true);
- }
- },
- {
- name: "Validate a variety of more complex exports",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexExports.js'),
- (v)=>{
- assert.areEqual('foo', v.foo(), 'Failed to import foo from ModuleComplexExports.js');
- assert.areEqual('foo', v.foo2(), 'Failed to import foo2 from ModuleComplexExports.js');
- assert.areEqual('bar', v.bar(), 'Failed to import bar from ModuleComplexExports.js');
- assert.areEqual('bar', v.bar2(), 'Failed to import bar2 from ModuleComplexExports.js');
- assert.areEqual('let2', v.let2, 'Failed to import let2 from ModuleComplexExports.js');
- assert.areEqual('let3', v.let3, 'Failed to import let3 from ModuleComplexExports.js');
- assert.areEqual('let2', v.let4, 'Failed to import let4 from ModuleComplexExports.js');
- assert.areEqual('let3', v.let5, 'Failed to import let5 from ModuleComplexExports.js');
- assert.areEqual('const2', v.const2, 'Failed to import const2 from ModuleComplexExports.js');
- assert.areEqual('const3', v.const3, 'Failed to import const3 from ModuleComplexExports.js');
- assert.areEqual('const2', v.const4, 'Failed to import const4 from ModuleComplexExports.js');
- assert.areEqual('const3', v.const5, 'Failed to import const5 from ModuleComplexExports.js');
- assert.areEqual('var2', v.var2, 'Failed to import var2 from ModuleComplexExports.js');
- assert.areEqual('var3', v.var3, 'Failed to import var3 from ModuleComplexExports.js');
- assert.areEqual('var2', v.var4, 'Failed to import var4 from ModuleComplexExports.js');
- assert.areEqual('var3', v.var5, 'Failed to import var5 from ModuleComplexExports.js');
- assert.areEqual('class2', v.class2.static_member(), 'Failed to import class2 from ModuleComplexExports.js');
- assert.areEqual('class2', new v.class2().member(), 'Failed to create intance of class2 from ModuleComplexExports.js');
- assert.areEqual('class2', v.class3.static_member(), 'Failed to import class3 from ModuleComplexExports.js');
- assert.areEqual('class2', new v.class3().member(), 'Failed to create intance of class3 from ModuleComplexExports.js');
- assert.areEqual('class4', v.class4.static_member(), 'Failed to import class4 from ModuleComplexExports.js');
- assert.areEqual('class4', new v.class4().member(), 'Failed to create intance of class4 from ModuleComplexExports.js');
- assert.areEqual('class4', v.class5.static_member(), 'Failed to import class4 from ModuleComplexExports.js');
- assert.areEqual('class4', new v.class5().member(), 'Failed to create intance of class4 from ModuleComplexExports.js');
- assert.areEqual('default', v.default(), 'Failed to import default from ModuleComplexExports.js');
- assert.areEqual('ModuleComplexExports', v.function, 'Failed to import v.function from ModuleComplexExports.js');
- assert.areEqual('ModuleComplexExports', v.export, 'Failed to import v.export from ModuleComplexExports.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Test importing a variety of exports", false, true);
- testModuleScript(functionBody, "Test importing a variety of exports", false, true);
- }
- },
- {
- name: "Exporting module changes exported value",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexExports.js'),
- (v)=>{
- v.reset();
- assert.areEqual('before', v.target(), 'Failed to import target from ModuleComplexExports.js');
- assert.areEqual('ok', v.changeTarget(), 'Failed to import changeTarget from ModuleComplexExports.js');
- assert.areEqual('after', v.target(), 'changeTarget failed to change export value');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Changing exported value", false, true);
- testModuleScript(functionBody, "Changing exported value", false, true);
- }
- },
- {
- name: "Simple re-export forwards import to correct slot",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleSimpleReexport.js'),
- (v)=>{
- assert.areEqual('ModuleSimpleExport', v.ModuleSimpleExport_foo(), 'Failed to import ModuleSimpleExport_foo from ModuleSimpleReexport.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Simple re-export from one module to another", false, true);
- testModuleScript(functionBody, "Simple re-export from one module to another", false, true);
- }
- },
- {
- name: "Renamed re-export and dynamic import",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexReexports.js'),
- (v)=>{
- assert.areEqual('bar', v.ModuleComplexReexports_foo(), 'Failed to import ModuleComplexReexports_foo from ModuleComplexReexports.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Rename already renamed re-export", false, true);
- testModuleScript(functionBody, "Rename already renamed re-export", false, true);
- }
- },
- {
- name: "Explicit export/import to default binding",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleDefaultExport1.js'),
- (v)=>{
- assert.areEqual('ModuleDefaultExport1', v.default(), 'Failed to import default from ModuleDefaultExport1.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Explicitly export and import a local name to the default binding", false, true);
- testModuleScript(functionBody, "Explicitly export and import a local name to the default binding", false, true);
- }
- },
- {
- name: "Explicit import of default binding",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleDefaultExport2.js'),
- (v)=>{
- assert.areEqual('ModuleDefaultExport2', v.default(), 'Failed to import default from ModuleDefaultExport2.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Explicitly import the default export binding", false, true);
- testModuleScript(functionBody, "Explicitly import the default export binding", false, true);
- }
- },
- {
- name: "Exporting module changes value of default export",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleDefaultExport3.js'),
- (v)=>{
- assert.areEqual(2, v.default, 'Failed to import default from ModuleDefaultExport3.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Exported value incorrectly bound", false, true);
- testModuleScript(functionBody, "Exported value incorrectly bound", false, true);
- functionBody =
- `testDynamicImport(
- ()=>import('ModuleDefaultExport4.js'),
- (v)=>{
- assert.areEqual(1, v.default, 'Failed to import default from ModuleDefaultExport4.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Exported value incorrectly bound", false, true);
- testModuleScript(functionBody, "Exported value incorrectly bound", false, true);
- }
- },
- {
- name: "Import bindings used in a nested function",
- body: function () {
- let functionBody =
- `function test(func) {
- assert.areEqual('ModuleDefaultExport2', func(), 'Failed to import default from ModuleDefaultExport2.js');
- }
- testDynamicImport(
- ()=>import('ModuleDefaultExport2.js'),
- (v)=>test(v.default),
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Failed to find imported name correctly in nested function", false, true);
- testModuleScript(functionBody, "Failed to find imported name correctly in nested function", false, true);
- }
- },
- {
- name: "Exported name may be any keyword",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexExports.js'),
- (v)=>{
- assert.areEqual('ModuleComplexExports', v.export, 'Failed to import export from ModuleDefaultExport2.js');
- assert.areEqual('ModuleComplexExports', v.function, 'Failed to import function from ModuleDefaultExport2.js');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Exported name may be a keyword (import binding must be binding identifier)", false, true);
- testModuleScript(functionBody, "Exported name may be a keyword (import binding must be binding identifier)", false, true);
- }
- },
- {
- name: "Odd case of 'export { as as as }; import { as as as };'",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexExports.js'),
- (v)=>{
- assert.areEqual('as', v.as(), 'String "as" is not reserved word');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Test 'import { as as as}'", false, true);
- testModuleScript(functionBody, "Test 'import { as as as}'", false, true);
- }
- },
- {
- name: "Typeof a module export",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleDefaultExport2.js'),
- (v)=>{
- assert.areEqual('function', typeof v.default, 'typeof default export from ModuleDefaultExport2.js is function');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Typeof a module export", false, true);
- testModuleScript(functionBody, "Typeof a module export", false, true);
- }
- },
- {
- name: "Circular module dependency",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleCircularFoo.js'),
- (v)=>{
- v.reset();
- assert.areEqual(2, v.circular_foo(), 'This function calls between both modules in the circular dependency incrementing a counter in each');
- assert.areEqual(4, v.rexportbar(), 'Second call originates in the other module but still increments the counter twice');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Circular module dependency", false, true);
- testModuleScript(functionBody, "Circular module dependency", false, true);
- }
- },
- {
- name: "Implicitly re-exporting an import binding (import { foo } from ''; export { foo };)",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>import('ModuleComplexReexports.js'),
- (v)=>{
- assert.areEqual('foo', v.foo(), 'Simple implicit re-export');
- assert.areEqual('foo', v.baz(), 'Renamed export imported and renamed during implicit re-export');
- assert.areEqual('foo', v.localfoo(), 'Export renamed as import and implicitly re-exported');
- assert.areEqual('foo', v.bar(), 'Renamed export renamed as import and renamed again during implicit re-exported');
- assert.areEqual('foo', v.localfoo2(), 'Renamed export renamed as import and implicitly re-exported');
- assert.areEqual('foo', v.bar2(), 'Renamed export renamed as import and renamed again during implicit re-export');
- },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit);
- `;
- testScript(functionBody, "Implicitly re-exporting an import binding (import { foo } from ''; export { foo };)", false, true);
- testModuleScript(functionBody, "Implicitly re-exporting an import binding (import { foo } from ''; export { foo };)", false, true);
- }
- },
- {
- name: "Validate a simple module export inside eval()",
- body: function () {
- let functionBody =
- `testDynamicImport(
- ()=>{ return eval("import('ModuleSimpleExport.js')"); },
- (v)=>{ assert.areEqual('ModuleSimpleExport', v.ModuleSimpleExport_foo(), 'Failed to import ModuleSimpleExport_foo from ModuleSimpleExport.js'); },
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit
- )`;
- testScript(functionBody, "Test importing a simple exported function", false, true);
- testModuleScript(functionBody, "Test importing a simple exported function", false, true);
- }
- },
- {
- name: "Test dynamic import of an un-parsed module from a module",
- body: function () {
- let functionBody =
- `testDoubleDynamicImport(
- ()=>{ return import('testDynamicImportfromModule.js'); },
- (v)=>{ return v.foo; },
- (v2)=>{ assert.areEqual(true, v.foo.success, "Failed to load module dynamicly from module");},
- (err)=>{ assert.fail(err.message); }, _asyncEnter, _asyncExit
- )`;
- testModuleScript(functionBody, "Test dynamic import of an un-parsed module from a module", false, true);
- //note exclusion of testScript case intentional - running the code from a script loads the module
- //then the test from Module uses the one loaded by the script - do not add testScript here
- }
- },
- {
- name : "Test 'new import()' throws - Bug Issue 5797",
- body: function() {
- assert.throws(()=>{eval('new import("ModuleSimpleExport.js")')}, SyntaxError);
- }
- },
- {
- name : "Test that import() always gives different promise objects - Bug Issue #5795",
- body: function () {
- WScript.RegisterModuleSource("testModule", "export const a = 5;");
- let functionBody =
- `testDynamicImport(function () {
- const first = import ('ModuleSimpleExport.js');
- const second = import ('ModuleSimpleExport.js');
- assert.isTrue(first !== second, 'import() should not return the same promise');
- return Promise.all([first, second]).then ((results) => ({first, second, results}));
- }, function (imports) {
- assert.isTrue(imports.first !== imports.second, 'import() should not return the same promise after resolution');
- assert.isTrue(imports.results[0] === imports.results[1], 'import() should return the same namespace object');
- }, function (e) {
- print ("Test should not throw, threw " + e);
- }, _asyncEnter, _asyncExit);`;
- testScript(functionBody, "Test that import() always gives different promise objects", false, true);
- testModuleScript(functionBody, "Test that import() always gives different promise objects", false, true);
- }
- }
- ];
- testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });
|