Skip to content
This repository was archived by the owner on Jul 13, 2020. It is now read-only.

Commit db44390

Browse files
committed
support top-level await, windows test fixes, bug fix
1 parent c5bdd07 commit db44390

File tree

4 files changed

+167
-118
lines changed

4 files changed

+167
-118
lines changed

core/loader-polyfill.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ function Loader () {
4949
Loader.prototype.constructor = Loader;
5050

5151
function ensureInstantiated (module) {
52-
if (!(module instanceof ModuleNamespace || module[toStringTag] === 'module'))
52+
if (module === undefined)
53+
return;
54+
if (module instanceof ModuleNamespace === false && module[toStringTag] !== 'module')
5355
throw new TypeError('Module instantiation did not return a valid namespace object.');
5456
return module;
5557
}

core/register-loader.js

Lines changed: 161 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ function createLoadRecord (state, key, registration) {
100100
// will be the array of dependency load record or a module namespace
101101
dependencyInstantiations: undefined,
102102

103+
// top-level await!
104+
evaluatePromise: undefined,
105+
103106
// NB optimization and way of ensuring module objects in setters
104107
// indicates setters which should run pre-execution of that dependency
105108
// setters is then just for completely executed module objects
@@ -117,7 +120,7 @@ RegisterLoader.prototype[Loader.resolveInstantiate] = function (key, parentKey)
117120

118121
return resolveInstantiate(loader, key, parentKey, registry, state)
119122
.then(function (instantiated) {
120-
if (instantiated instanceof ModuleNamespace)
123+
if (instantiated instanceof ModuleNamespace || instantiated[toStringTag] === 'module')
121124
return instantiated;
122125

123126
// resolveInstantiate always returns a load record with a link record and no module value
@@ -132,7 +135,7 @@ RegisterLoader.prototype[Loader.resolveInstantiate] = function (key, parentKey)
132135

133136
return deepInstantiateDeps(loader, instantiated, link, registry, state)
134137
.then(function () {
135-
return ensureEvaluate(loader, instantiated, link, registry, state, undefined);
138+
return ensureEvaluate(loader, instantiated, link, registry, state);
136139
});
137140
});
138141
};
@@ -496,23 +499,22 @@ ContextualLoader.prototype.import = function (key) {
496499
return this.loader.resolve(key, this.key);
497500
};*/
498501

499-
// this is the execution function bound to the Module namespace record
500-
function ensureEvaluate (loader, load, link, registry, state, seen) {
502+
function ensureEvaluate (loader, load, link, registry, state) {
501503
if (load.module)
502504
return load.module;
503-
504505
if (load.evalError)
505506
throw load.evalError;
507+
if (link.evaluatePromise)
508+
return link.evaluatePromise;
506509

507-
if (seen && seen.indexOf(load) !== -1)
508-
return load.linkRecord.moduleObj;
509-
510-
// for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless
511-
// for dynamic loads, we pass seen if also dynamic
512-
var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []);
513-
if (err)
514-
throw err;
515-
510+
if (link.setters) {
511+
var evaluatePromise = doEvaluateDeclarative(loader, load, link, registry, state, [load]);
512+
if (evaluatePromise)
513+
return evaluatePromise;
514+
}
515+
else {
516+
doEvaluateDynamic(loader, load, link, registry, state, [load]);
517+
}
516518
return load.module;
517519
}
518520

@@ -524,10 +526,23 @@ function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations
524526
var depLoad = dependencyInstantiations[i];
525527
var module;
526528

527-
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module')
529+
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module') {
528530
module = depLoad;
529-
else
530-
module = ensureEvaluate(loader, depLoad, depLoad.linkRecord, registry, state, seen);
531+
}
532+
else {
533+
if (depLoad.evalError)
534+
throw depLoad.evalError;
535+
if (depLoad.module === undefined && seen.indexOf(depLoad) === -1 && !depLoad.linkRecord.evaluatePromise) {
536+
if (depLoad.linkRecord.setters) {
537+
doEvaluateDeclarative(loader, depLoad, depLoad.linkRecord, registry, state, [depLoad]);
538+
}
539+
else {
540+
seen.push(depLoad);
541+
doEvaluateDynamic(loader, depLoad, depLoad.linkRecord, registry, state, seen);
542+
}
543+
}
544+
module = depLoad.module || depLoad.linkRecord.moduleObj;
545+
}
531546

532547
return '__useDefault' in module ? module.__useDefault : module;
533548
}
@@ -536,129 +551,161 @@ function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations
536551
};
537552
}
538553

539-
// ensures the given es load is evaluated
540-
// returns the error if any
541-
function doEvaluate (loader, load, link, registry, state, seen) {
542-
seen.push(load);
543-
544-
var err;
554+
function evalError (load, err) {
555+
load.linkRecord = undefined;
556+
var evalError = addToError(err, 'Evaluating ' + load.key);
557+
if (load.evalError === undefined)
558+
load.evalError = evalError;
559+
throw evalError;
560+
}
545561

546-
// es modules evaluate dependencies first
547-
// non es modules explicitly call moduleEvaluate through require
548-
if (link.setters) {
549-
var depLoad, depLink;
550-
for (var i = 0; i < link.dependencies.length; i++) {
551-
depLoad = link.dependencyInstantiations[i];
552-
553-
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module')
554-
continue;
555-
556-
// custom Module returned from instantiate
557-
depLink = depLoad.linkRecord;
558-
if (depLink && seen.indexOf(depLoad) === -1) {
559-
if (depLoad.evalError)
560-
err = depLoad.evalError;
561-
else
562-
// dynamic / declarative boundaries clear the "seen" list
563-
// we just let cross format circular throw as would happen in real implementations
564-
err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []);
562+
// es modules evaluate dependencies first
563+
// returns the error if any
564+
function doEvaluateDeclarative (loader, load, link, registry, state, seen) {
565+
var depLoad, depLink;
566+
var depLoadPromises;
567+
for (var i = 0; i < link.dependencies.length; i++) {
568+
var depLoad = link.dependencyInstantiations[i];
569+
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module')
570+
continue;
571+
572+
// custom Module returned from instantiate
573+
depLink = depLoad.linkRecord;
574+
if (depLink) {
575+
if (depLoad.evalError) {
576+
evalError(load, depLoad.evalError);
565577
}
566-
567-
if (err) {
568-
load.linkRecord = undefined;
569-
load.evalError = addToError(err, 'Evaluating ' + load.key);
570-
return load.evalError;
578+
else if (depLink.setters) {
579+
if (seen.indexOf(depLoad) === -1) {
580+
seen.push(depLoad);
581+
try {
582+
var depLoadPromise = doEvaluateDeclarative(loader, depLoad, depLink, registry, state, seen);
583+
}
584+
catch (e) {
585+
evalError(load, e);
586+
}
587+
if (depLoadPromise) {
588+
depLoadPromises = depLoadPromises || [];
589+
depLoadPromises.push(depLoadPromise.catch(function (err) {
590+
evalError(load, err);
591+
}));
592+
}
593+
}
594+
}
595+
else {
596+
try {
597+
doEvaluateDynamic(loader, depLoad, depLink, registry, state, [depLoad]);
598+
}
599+
catch (e) {
600+
evalError(load, e);
601+
}
571602
}
572603
}
573604
}
574605

575-
// link.execute won't exist for Module returns from instantiate on top-level load
606+
if (depLoadPromises)
607+
return Promise.all(depLoadPromises)
608+
.then(function () {
609+
if (link.execute) {
610+
// ES System.register execute
611+
// "this" is null in ES
612+
try {
613+
var execPromise = link.execute.call(nullContext);
614+
}
615+
catch (e) {
616+
evalError(load, e);
617+
}
618+
if (execPromise)
619+
return execPromise.catch(function (e) {
620+
evalError(load, e);
621+
});
622+
}
623+
624+
// dispose link record
625+
load.linkRecord = undefined;
626+
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
627+
});
628+
576629
if (link.execute) {
577630
// ES System.register execute
578631
// "this" is null in ES
579-
if (link.setters) {
580-
err = declarativeExecute(link.execute);
632+
try {
633+
var execPromise = link.execute.call(nullContext);
581634
}
582-
// System.registerDynamic execute
583-
// "this" is "exports" in CJS
584-
else {
585-
var module = { id: load.key };
586-
var moduleObj = link.moduleObj;
587-
Object.defineProperty(module, 'exports', {
588-
configurable: true,
589-
set: function (exports) {
590-
moduleObj.default = moduleObj.__useDefault = exports;
591-
},
592-
get: function () {
593-
return moduleObj.__useDefault;
594-
}
635+
catch (e) {
636+
evalError(load, e);
637+
}
638+
if (execPromise)
639+
return execPromise.catch(function (e) {
640+
evalError(load, e);
595641
});
642+
}
596643

597-
var require = makeDynamicRequire(loader, load.key, link.dependencies, link.dependencyInstantiations, registry, state, seen);
598-
599-
// evaluate deps first
600-
if (!link.executingRequire)
601-
for (var i = 0; i < link.dependencies.length; i++)
602-
require(link.dependencies[i]);
644+
// dispose link record
645+
load.linkRecord = undefined;
646+
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
647+
}
603648

604-
err = dynamicExecute(link.execute, require, moduleObj.default, module);
649+
// non es modules explicitly call moduleEvaluate through require
650+
function doEvaluateDynamic (loader, load, link, registry, state, seen) {
651+
// System.registerDynamic execute
652+
// "this" is "exports" in CJS
653+
var module = { id: load.key };
654+
var moduleObj = link.moduleObj;
655+
Object.defineProperty(module, 'exports', {
656+
configurable: true,
657+
set: function (exports) {
658+
moduleObj.default = moduleObj.__useDefault = exports;
659+
},
660+
get: function () {
661+
return moduleObj.__useDefault;
662+
}
663+
});
605664

606-
// pick up defineProperty calls to module.exports when we can
607-
if (module.exports !== moduleObj.__useDefault)
608-
moduleObj.default = moduleObj.__useDefault = module.exports;
665+
var require = makeDynamicRequire(loader, load.key, link.dependencies, link.dependencyInstantiations, registry, state, seen);
609666

610-
var moduleDefault = moduleObj.default;
667+
// evaluate deps first
668+
if (!link.executingRequire)
669+
for (var i = 0; i < link.dependencies.length; i++)
670+
require(link.dependencies[i]);
611671

612-
// __esModule flag extension support via lifting
613-
if (moduleDefault && moduleDefault.__esModule) {
614-
for (var p in moduleDefault) {
615-
if (Object.hasOwnProperty.call(moduleDefault, p))
616-
moduleObj[p] = moduleDefault[p];
617-
}
618-
}
619-
}
672+
try {
673+
var output = link.execute.call(global, require, moduleObj.default, module);
674+
if (output !== undefined)
675+
module.exports = output;
676+
}
677+
catch (e) {
678+
evalError(load, e);
620679
}
621680

622-
// dispose link record
623681
load.linkRecord = undefined;
624682

625-
if (err)
626-
return load.evalError = addToError(err, 'Evaluating ' + load.key);
683+
// pick up defineProperty calls to module.exports when we can
684+
if (module.exports !== moduleObj.__useDefault)
685+
moduleObj.default = moduleObj.__useDefault = module.exports;
686+
687+
var moduleDefault = moduleObj.default;
688+
689+
// __esModule flag extension support via lifting
690+
if (moduleDefault && moduleDefault.__esModule) {
691+
for (var p in moduleDefault) {
692+
if (Object.hasOwnProperty.call(moduleDefault, p))
693+
moduleObj[p] = moduleDefault[p];
694+
}
695+
}
627696

628697
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
629698

630-
// if not an esm module, run importer setters and clear them
699+
// run importer setters and clear them
631700
// this allows dynamic modules to update themselves into es modules
632701
// as soon as execution has completed
633-
if (!link.setters) {
634-
if (load.importerSetters)
635-
for (var i = 0; i < load.importerSetters.length; i++)
636-
load.importerSetters[i](load.module);
637-
load.importerSetters = undefined;
638-
}
702+
if (load.importerSetters)
703+
for (var i = 0; i < load.importerSetters.length; i++)
704+
load.importerSetters[i](load.module);
705+
load.importerSetters = undefined;
639706
}
640707

641-
// {} is the closest we can get to call(undefined)
642-
var nullContext = {};
708+
// the closest we can get to call(undefined)
709+
var nullContext = Object.create(null);
643710
if (Object.freeze)
644711
Object.freeze(nullContext);
645-
646-
function declarativeExecute (execute) {
647-
try {
648-
execute.call(nullContext);
649-
}
650-
catch (e) {
651-
return e;
652-
}
653-
}
654-
655-
function dynamicExecute (execute, require, exports, module) {
656-
try {
657-
var output = execute.call(global, require, exports, module);
658-
if (output !== undefined)
659-
module.exports = output;
660-
}
661-
catch (e) {
662-
return e;
663-
}
664-
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "es-module-loader",
33
"description": "An ES Module Loader shim",
4-
"version": "2.2.8",
4+
"version": "2.2.9",
55
"homepage": "https://github.com/ModuleLoader/es-module-loader",
66
"author": {
77
"name": "Guy Bedford, Luke Hoban, Addy Osmani",
@@ -26,7 +26,7 @@
2626
"babel-plugin-transform-es2015-modules-systemjs": "^6.14.0",
2727
"benchmark": "^2.1.1",
2828
"mocha": "^3.0.2",
29-
"node-es-module-loader": "^0.1.1",
29+
"node-es-module-loader": "^0.3.8",
3030
"systemjs": "^0.19.36"
3131
},
3232
"keywords": [

test/3-register-loader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ describe('System Register Loader', function() {
217217
var err = await getImportError('./register-modules/load-non-existent.js');
218218
var lines = err.split('\n ');
219219
assert(lines[0].startsWith('Error: '));
220-
assert(lines[0].endsWith('open \'' + testPath + 'non-existent.js\''));
220+
assert(lines[0].endsWith('open \'' + testPath.replace(/\//g, path.sep) + 'non-existent.js\''));
221221
assert.equal(lines[1], 'Instantiating ' + testPath + 'non-existent.js');
222222
assert.equal(lines[2], 'Loading ' + testPath + 'load-non-existent.js');
223223
assert.equal(lines[3], 'Loading ./register-modules/load-non-existent.js');

0 commit comments

Comments
 (0)