Better currentScript fallback
The previous heuristic didn't work under all circumstances, so try something more robust.
This commit is contained in:
parent
ae2e1ff7bd
commit
d131633471
|
@ -20,6 +20,8 @@ function createSymbol (name) {
|
|||
return hasSymbol ? Symbol() : '@@' + name;
|
||||
}
|
||||
|
||||
var toStringTag = hasSymbol && Symbol.toStringTag;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -93,7 +95,7 @@ function LoaderError__Check_error_message_for_loader_stack (childErr, newMessage
|
|||
return err;
|
||||
}
|
||||
|
||||
var resolvedPromise = Promise.resolve();
|
||||
var resolvedPromise$1 = Promise.resolve();
|
||||
|
||||
/*
|
||||
* Simple Array values shim
|
||||
|
@ -140,7 +142,9 @@ function Loader () {
|
|||
Loader.prototype.constructor = Loader;
|
||||
|
||||
function ensureInstantiated (module) {
|
||||
if (!(module instanceof ModuleNamespace))
|
||||
if (module === undefined)
|
||||
return;
|
||||
if (module instanceof ModuleNamespace === false && module[toStringTag] !== 'module')
|
||||
throw new TypeError('Module instantiation did not return a valid namespace object.');
|
||||
return module;
|
||||
}
|
||||
|
@ -151,7 +155,7 @@ Loader.prototype.import = function (key, parent) {
|
|||
throw new TypeError('Loader import method must be passed a module key string');
|
||||
// custom resolveInstantiate combined hook for better perf
|
||||
var loader = this;
|
||||
return resolvedPromise
|
||||
return resolvedPromise$1
|
||||
.then(function () {
|
||||
return loader[RESOLVE_INSTANTIATE](key, parent);
|
||||
})
|
||||
|
@ -193,7 +197,7 @@ function ensureResolution (resolvedKey) {
|
|||
|
||||
Loader.prototype.resolve = function (key, parent) {
|
||||
var loader = this;
|
||||
return resolvedPromise
|
||||
return resolvedPromise$1
|
||||
.then(function() {
|
||||
return loader[RESOLVE](key, parent);
|
||||
})
|
||||
|
@ -261,7 +265,7 @@ Registry.prototype.get = function (key) {
|
|||
};
|
||||
// 4.4.7
|
||||
Registry.prototype.set = function (key, namespace) {
|
||||
if (!(namespace instanceof ModuleNamespace))
|
||||
if (!(namespace instanceof ModuleNamespace || namespace[toStringTag] === 'module'))
|
||||
throw new Error('Registry must be set with an instance of Module Namespace');
|
||||
this[REGISTRY][key] = namespace;
|
||||
return this;
|
||||
|
@ -318,8 +322,8 @@ function ModuleNamespace (baseObject/*, evaluate*/) {
|
|||
// 8.4.2
|
||||
ModuleNamespace.prototype = Object.create(null);
|
||||
|
||||
if (typeof Symbol !== 'undefined' && Symbol.toStringTag)
|
||||
Object.defineProperty(ModuleNamespace.prototype, Symbol.toStringTag, {
|
||||
if (toStringTag)
|
||||
Object.defineProperty(ModuleNamespace.prototype, toStringTag, {
|
||||
value: 'Module'
|
||||
});
|
||||
|
||||
|
@ -366,7 +370,9 @@ Module.evaluate = function (ns) {
|
|||
function throwResolveError (relUrl, parentUrl) {
|
||||
throw new RangeError('Unable to resolve "' + relUrl + '" to ' + parentUrl);
|
||||
}
|
||||
var backslashRegEx = /\\/g;
|
||||
function resolveIfNotPlain (relUrl, parentUrl) {
|
||||
if (relUrl[0] === ' ' || relUrl[relUrl.length - 1] === ' ')
|
||||
relUrl = relUrl.trim();
|
||||
var parentProtocol = parentUrl && parentUrl.substr(0, parentUrl.indexOf(':') + 1);
|
||||
|
||||
|
@ -377,12 +383,16 @@ function resolveIfNotPlain (relUrl, parentUrl) {
|
|||
if (firstChar === '/' && secondChar === '/') {
|
||||
if (!parentProtocol)
|
||||
throwResolveError(relUrl, parentUrl);
|
||||
if (relUrl.indexOf('\\') !== -1)
|
||||
relUrl = relUrl.replace(backslashRegEx, '/');
|
||||
return parentProtocol + relUrl;
|
||||
}
|
||||
// relative-url
|
||||
else if (firstChar === '.' && (secondChar === '/' || secondChar === '.' && (relUrl[2] === '/' || relUrl.length === 2 && (relUrl += '/')) ||
|
||||
relUrl.length === 1 && (relUrl += '/')) ||
|
||||
firstChar === '/') {
|
||||
if (relUrl.indexOf('\\') !== -1)
|
||||
relUrl = relUrl.replace(backslashRegEx, '/');
|
||||
var parentIsPlain = !parentProtocol || parentUrl[parentProtocol.length] !== '/';
|
||||
|
||||
// read pathname from parent if a URL
|
||||
|
@ -475,12 +485,13 @@ function resolveIfNotPlain (relUrl, parentUrl) {
|
|||
if (isNode) {
|
||||
// C:\x becomes file:///c:/x (we don't support C|\x)
|
||||
if (relUrl[1] === ':' && relUrl[2] === '\\' && relUrl[0].match(/[a-z]/i))
|
||||
return 'file:///' + relUrl.replace(/\\/g, '/');
|
||||
return 'file:///' + relUrl.replace(backslashRegEx, '/');
|
||||
}
|
||||
return relUrl;
|
||||
}
|
||||
}
|
||||
|
||||
var resolvedPromise = Promise.resolve();
|
||||
/*
|
||||
* Register Loader
|
||||
*
|
||||
|
@ -575,6 +586,9 @@ function createLoadRecord (state, key, registration) {
|
|||
// will be the array of dependency load record or a module namespace
|
||||
dependencyInstantiations: undefined,
|
||||
|
||||
// top-level await!
|
||||
evaluatePromise: undefined,
|
||||
|
||||
// NB optimization and way of ensuring module objects in setters
|
||||
// indicates setters which should run pre-execution of that dependency
|
||||
// setters is then just for completely executed module objects
|
||||
|
@ -592,7 +606,7 @@ RegisterLoader$1.prototype[Loader.resolveInstantiate] = function (key, parentKey
|
|||
|
||||
return resolveInstantiate(loader, key, parentKey, registry, state)
|
||||
.then(function (instantiated) {
|
||||
if (instantiated instanceof ModuleNamespace)
|
||||
if (instantiated instanceof ModuleNamespace || instantiated[toStringTag] === 'module')
|
||||
return instantiated;
|
||||
|
||||
// resolveInstantiate always returns a load record with a link record and no module value
|
||||
|
@ -607,7 +621,7 @@ RegisterLoader$1.prototype[Loader.resolveInstantiate] = function (key, parentKey
|
|||
|
||||
return deepInstantiateDeps(loader, instantiated, link, registry, state)
|
||||
.then(function () {
|
||||
return ensureEvaluate(loader, instantiated, link, registry, state, undefined);
|
||||
return ensureEvaluate(loader, instantiated, link, registry, state);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -672,14 +686,14 @@ function createProcessAnonRegister (loader, load, state) {
|
|||
function instantiate (loader, load, link, registry, state) {
|
||||
return link.instantiatePromise || (link.instantiatePromise =
|
||||
// if there is already an existing registration, skip running instantiate
|
||||
(load.registration ? Promise.resolve() : Promise.resolve().then(function () {
|
||||
(load.registration ? resolvedPromise : resolvedPromise.then(function () {
|
||||
state.lastRegister = undefined;
|
||||
return loader[INSTANTIATE](load.key, loader[INSTANTIATE].length > 1 && createProcessAnonRegister(loader, load, state));
|
||||
}))
|
||||
.then(function (instantiation) {
|
||||
// direct module return from instantiate -> we're done
|
||||
if (instantiation !== undefined) {
|
||||
if (!(instantiation instanceof ModuleNamespace))
|
||||
if (!(instantiation instanceof ModuleNamespace || instantiation[toStringTag] === 'module'))
|
||||
throw new TypeError('Instantiate did not return a valid Module object.');
|
||||
|
||||
delete state.records[load.key];
|
||||
|
@ -826,7 +840,7 @@ function registerDeclarative (loader, load, link, declare) {
|
|||
return value;
|
||||
}, new ContextualLoader(loader, load.key));
|
||||
|
||||
link.setters = declared.setters;
|
||||
link.setters = declared.setters || [];
|
||||
link.execute = declared.execute;
|
||||
if (declared.exports) {
|
||||
link.moduleObj = moduleObj = declared.exports;
|
||||
|
@ -854,7 +868,7 @@ function instantiateDeps (loader, load, link, registry, state) {
|
|||
if (setter) {
|
||||
var instantiation = dependencyInstantiations[i];
|
||||
|
||||
if (instantiation instanceof ModuleNamespace) {
|
||||
if (instantiation instanceof ModuleNamespace || instantiation[toStringTag] === 'module') {
|
||||
setter(instantiation);
|
||||
}
|
||||
else {
|
||||
|
@ -890,39 +904,32 @@ function instantiateDeps (loader, load, link, registry, state) {
|
|||
}
|
||||
|
||||
function deepInstantiateDeps (loader, load, link, registry, state) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var seen = [];
|
||||
var loadCnt = 0;
|
||||
function queueLoad (load) {
|
||||
var link = load.linkRecord;
|
||||
function addDeps (load, link) {
|
||||
if (!link)
|
||||
return;
|
||||
|
||||
return resolvedPromise;
|
||||
if (seen.indexOf(load) !== -1)
|
||||
return;
|
||||
return resolvedPromise;
|
||||
seen.push(load);
|
||||
|
||||
loadCnt++;
|
||||
instantiateDeps(loader, load, link, registry, state)
|
||||
.then(processLoad, reject);
|
||||
}
|
||||
function processLoad (load) {
|
||||
loadCnt--;
|
||||
var link = load.linkRecord;
|
||||
if (link) {
|
||||
return instantiateDeps(loader, load, link, registry, state)
|
||||
.then(function () {
|
||||
var depPromises;
|
||||
for (var i = 0; i < link.dependencies.length; i++) {
|
||||
var depLoad = link.dependencyInstantiations[i];
|
||||
if (!(depLoad instanceof ModuleNamespace))
|
||||
queueLoad(depLoad);
|
||||
if (!(depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module')) {
|
||||
depPromises = depPromises || [];
|
||||
depPromises.push(addDeps(depLoad, depLoad.linkRecord));
|
||||
}
|
||||
}
|
||||
if (loadCnt === 0)
|
||||
resolve();
|
||||
}
|
||||
queueLoad(load);
|
||||
if (depPromises)
|
||||
return Promise.all(depPromises);
|
||||
});
|
||||
}
|
||||
|
||||
return addDeps(load, link);
|
||||
}
|
||||
|
||||
/*
|
||||
* System.register
|
||||
*/
|
||||
|
@ -981,23 +988,22 @@ ContextualLoader.prototype.import = function (key) {
|
|||
return this.loader.resolve(key, this.key);
|
||||
};*/
|
||||
|
||||
// this is the execution function bound to the Module namespace record
|
||||
function ensureEvaluate (loader, load, link, registry, state, seen) {
|
||||
function ensureEvaluate (loader, load, link, registry, state) {
|
||||
if (load.module)
|
||||
return load.module;
|
||||
|
||||
if (load.evalError)
|
||||
throw load.evalError;
|
||||
if (link.evaluatePromise)
|
||||
return link.evaluatePromise;
|
||||
|
||||
if (seen && seen.indexOf(load) !== -1)
|
||||
return load.linkRecord.moduleObj;
|
||||
|
||||
// for ES loads we always run ensureEvaluate on top-level, so empty seen is passed regardless
|
||||
// for dynamic loads, we pass seen if also dynamic
|
||||
var err = doEvaluate(loader, load, link, registry, state, link.setters ? [] : seen || []);
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
if (link.setters) {
|
||||
var evaluatePromise = doEvaluateDeclarative(loader, load, link, registry, state, [load]);
|
||||
if (evaluatePromise)
|
||||
return evaluatePromise;
|
||||
}
|
||||
else {
|
||||
doEvaluateDynamic(loader, load, link, registry, state, [load]);
|
||||
}
|
||||
return load.module;
|
||||
}
|
||||
|
||||
|
@ -1009,10 +1015,23 @@ function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations
|
|||
var depLoad = dependencyInstantiations[i];
|
||||
var module;
|
||||
|
||||
if (depLoad instanceof ModuleNamespace)
|
||||
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module') {
|
||||
module = depLoad;
|
||||
else
|
||||
module = ensureEvaluate(loader, depLoad, depLoad.linkRecord, registry, state, seen);
|
||||
}
|
||||
else {
|
||||
if (depLoad.evalError)
|
||||
throw depLoad.evalError;
|
||||
if (depLoad.module === undefined && seen.indexOf(depLoad) === -1 && !depLoad.linkRecord.evaluatePromise) {
|
||||
if (depLoad.linkRecord.setters) {
|
||||
doEvaluateDeclarative(loader, depLoad, depLoad.linkRecord, registry, state, [depLoad]);
|
||||
}
|
||||
else {
|
||||
seen.push(depLoad);
|
||||
doEvaluateDynamic(loader, depLoad, depLoad.linkRecord, registry, state, seen);
|
||||
}
|
||||
}
|
||||
module = depLoad.module || depLoad.linkRecord.moduleObj;
|
||||
}
|
||||
|
||||
return '__useDefault' in module ? module.__useDefault : module;
|
||||
}
|
||||
|
@ -1021,52 +1040,113 @@ function makeDynamicRequire (loader, key, dependencies, dependencyInstantiations
|
|||
};
|
||||
}
|
||||
|
||||
// ensures the given es load is evaluated
|
||||
// returns the error if any
|
||||
function doEvaluate (loader, load, link, registry, state, seen) {
|
||||
seen.push(load);
|
||||
|
||||
var err;
|
||||
function evalError (load, err) {
|
||||
load.linkRecord = undefined;
|
||||
var evalError = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key);
|
||||
if (load.evalError === undefined)
|
||||
load.evalError = evalError;
|
||||
throw evalError;
|
||||
}
|
||||
|
||||
// es modules evaluate dependencies first
|
||||
// non es modules explicitly call moduleEvaluate through require
|
||||
if (link.setters) {
|
||||
// returns the error if any
|
||||
function doEvaluateDeclarative (loader, load, link, registry, state, seen) {
|
||||
var depLoad, depLink;
|
||||
var depLoadPromises;
|
||||
for (var i = 0; i < link.dependencies.length; i++) {
|
||||
depLoad = link.dependencyInstantiations[i];
|
||||
|
||||
if (depLoad instanceof ModuleNamespace)
|
||||
var depLoad = link.dependencyInstantiations[i];
|
||||
if (depLoad instanceof ModuleNamespace || depLoad[toStringTag] === 'module')
|
||||
continue;
|
||||
|
||||
// custom Module returned from instantiate
|
||||
depLink = depLoad.linkRecord;
|
||||
if (depLink && seen.indexOf(depLoad) === -1) {
|
||||
if (depLoad.evalError)
|
||||
err = depLoad.evalError;
|
||||
else
|
||||
// dynamic / declarative boundaries clear the "seen" list
|
||||
// we just let cross format circular throw as would happen in real implementations
|
||||
err = doEvaluate(loader, depLoad, depLink, registry, state, depLink.setters ? seen : []);
|
||||
if (depLink) {
|
||||
if (depLoad.evalError) {
|
||||
evalError(load, depLoad.evalError);
|
||||
}
|
||||
else if (depLink.setters) {
|
||||
if (seen.indexOf(depLoad) === -1) {
|
||||
seen.push(depLoad);
|
||||
try {
|
||||
var depLoadPromise = doEvaluateDeclarative(loader, depLoad, depLink, registry, state, seen);
|
||||
}
|
||||
catch (e) {
|
||||
evalError(load, e);
|
||||
}
|
||||
if (depLoadPromise) {
|
||||
depLoadPromises = depLoadPromises || [];
|
||||
depLoadPromises.push(depLoadPromise.catch(function (err) {
|
||||
evalError(load, err);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
doEvaluateDynamic(loader, depLoad, depLink, registry, state, [depLoad]);
|
||||
}
|
||||
catch (e) {
|
||||
evalError(load, e);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
load.linkRecord = undefined;
|
||||
load.evalError = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key);
|
||||
return load.evalError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// link.execute won't exist for Module returns from instantiate on top-level load
|
||||
if (depLoadPromises)
|
||||
return link.evaluatePromise = Promise.all(depLoadPromises)
|
||||
.then(function () {
|
||||
if (link.execute) {
|
||||
// ES System.register execute
|
||||
// "this" is null in ES
|
||||
if (link.setters) {
|
||||
err = declarativeExecute(link.execute);
|
||||
try {
|
||||
var execPromise = link.execute.call(nullContext);
|
||||
}
|
||||
catch (e) {
|
||||
evalError(load, e);
|
||||
}
|
||||
if (execPromise)
|
||||
return execPromise.catch(function (e) {
|
||||
evalError(load, e);
|
||||
})
|
||||
.then(function () {
|
||||
load.linkRecord = undefined;
|
||||
return registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
|
||||
});
|
||||
}
|
||||
|
||||
// dispose link record
|
||||
load.linkRecord = undefined;
|
||||
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
|
||||
});
|
||||
|
||||
if (link.execute) {
|
||||
// ES System.register execute
|
||||
// "this" is null in ES
|
||||
try {
|
||||
var execPromise = link.execute.call(nullContext);
|
||||
}
|
||||
catch (e) {
|
||||
evalError(load, e);
|
||||
}
|
||||
if (execPromise)
|
||||
return link.evaluatePromise = execPromise.catch(function (e) {
|
||||
evalError(load, e);
|
||||
})
|
||||
.then(function () {
|
||||
load.linkRecord = undefined;
|
||||
return registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
|
||||
});
|
||||
}
|
||||
|
||||
// dispose link record
|
||||
load.linkRecord = undefined;
|
||||
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
|
||||
}
|
||||
|
||||
// non es modules explicitly call moduleEvaluate through require
|
||||
function doEvaluateDynamic (loader, load, link, registry, state, seen) {
|
||||
// System.registerDynamic execute
|
||||
// "this" is "exports" in CJS
|
||||
else {
|
||||
var module = { id: load.key };
|
||||
var moduleObj = link.moduleObj;
|
||||
Object.defineProperty(module, 'exports', {
|
||||
|
@ -1086,7 +1166,16 @@ function doEvaluate (loader, load, link, registry, state, seen) {
|
|||
for (var i = 0; i < link.dependencies.length; i++)
|
||||
require(link.dependencies[i]);
|
||||
|
||||
err = dynamicExecute(link.execute, require, moduleObj.default, module);
|
||||
try {
|
||||
var output = link.execute.call(envGlobal, require, moduleObj.default, module);
|
||||
if (output !== undefined)
|
||||
module.exports = output;
|
||||
}
|
||||
catch (e) {
|
||||
evalError(load, e);
|
||||
}
|
||||
|
||||
load.linkRecord = undefined;
|
||||
|
||||
// pick up defineProperty calls to module.exports when we can
|
||||
if (module.exports !== moduleObj.__useDefault)
|
||||
|
@ -1101,53 +1190,23 @@ function doEvaluate (loader, load, link, registry, state, seen) {
|
|||
moduleObj[p] = moduleDefault[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dispose link record
|
||||
load.linkRecord = undefined;
|
||||
|
||||
if (err)
|
||||
return load.evalError = LoaderError__Check_error_message_for_loader_stack(err, 'Evaluating ' + load.key);
|
||||
|
||||
registry[load.key] = load.module = new ModuleNamespace(link.moduleObj);
|
||||
|
||||
// if not an esm module, run importer setters and clear them
|
||||
// run importer setters and clear them
|
||||
// this allows dynamic modules to update themselves into es modules
|
||||
// as soon as execution has completed
|
||||
if (!link.setters) {
|
||||
if (load.importerSetters)
|
||||
for (var i = 0; i < load.importerSetters.length; i++)
|
||||
load.importerSetters[i](load.module);
|
||||
load.importerSetters = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// {} is the closest we can get to call(undefined)
|
||||
var nullContext = {};
|
||||
// the closest we can get to call(undefined)
|
||||
var nullContext = Object.create(null);
|
||||
if (Object.freeze)
|
||||
Object.freeze(nullContext);
|
||||
|
||||
function declarativeExecute (execute) {
|
||||
try {
|
||||
execute.call(nullContext);
|
||||
}
|
||||
catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
function dynamicExecute (execute, require, exports, module) {
|
||||
try {
|
||||
var output = execute.call(envGlobal, require, exports, module);
|
||||
if (output !== undefined)
|
||||
module.exports = output;
|
||||
}
|
||||
catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
var loader;
|
||||
|
||||
// <script type="module"> support
|
||||
|
@ -1284,9 +1343,16 @@ var WorkerPool = function (script, size) {
|
|||
var current = document.currentScript;
|
||||
// IE doesn't support currentScript
|
||||
if (!current) {
|
||||
// We should be the last loaded script
|
||||
// Find an entry with out basename
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
current = scripts[scripts.length - 1];
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.indexOf("browser-es-module-loader.js") !== -1) {
|
||||
current = scripts[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!current)
|
||||
throw Error("Could not find own <script> element");
|
||||
}
|
||||
script = current.src.substr(0, current.src.lastIndexOf("/")) + "/" + script;
|
||||
this._workers = new Array(size);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -140,9 +140,16 @@ var WorkerPool = function (script, size) {
|
|||
var current = document.currentScript;
|
||||
// IE doesn't support currentScript
|
||||
if (!current) {
|
||||
// We should be the last loaded script
|
||||
// Find an entry with out basename
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
current = scripts[scripts.length - 1];
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
if (scripts[i].src.indexOf("browser-es-module-loader.js") !== -1) {
|
||||
current = scripts[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!current)
|
||||
throw Error("Could not find own <script> element");
|
||||
}
|
||||
script = current.src.substr(0, current.src.lastIndexOf("/")) + "/" + script;
|
||||
this._workers = new Array(size);
|
||||
|
|
Loading…
Reference in New Issue