Bones/node_modules/systemjs/lib/scriptLoader.js

197 lines
6.2 KiB
JavaScript
Raw Normal View History

2017-05-17 13:45:25 -04:00
/*
* Script tag fetch
*
* When load.metadata.scriptLoad is true, we load via script tag injection.
*/
(function() {
if (typeof document != 'undefined')
var head = document.getElementsByTagName('head')[0];
var curSystem;
var curRequire;
// if doing worker executing, this is set to the load record being executed
var workerLoad = null;
// interactive mode handling method courtesy RequireJS
var ieEvents = head && (function() {
var s = document.createElement('script');
var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]';
return s.attachEvent && !(s.attachEvent.toString && s.attachEvent.toString().indexOf('[native code') < 0) && !isOpera;
})();
// IE interactive-only part
// we store loading scripts array as { script: <script>, load: {...} }
var interactiveLoadingScripts = [];
var interactiveScript;
function getInteractiveScriptLoad() {
if (interactiveScript && interactiveScript.script.readyState === 'interactive')
return interactiveScript.load;
for (var i = 0; i < interactiveLoadingScripts.length; i++)
if (interactiveLoadingScripts[i].script.readyState == 'interactive') {
interactiveScript = interactiveLoadingScripts[i];
return interactiveScript.load;
}
}
// System.register, System.registerDynamic, AMD define pipeline
// this is called by the above methods when they execute
// we then run the reduceRegister_ collection function either immediately
// if we are in IE and know the currently executing script (interactive)
// or later if we need to wait for the synchronous load callback to know the script
var loadingCnt = 0;
var registerQueue = [];
hook('pushRegister_', function(pushRegister) {
return function(register) {
// if using eval-execution then skip
if (pushRegister.call(this, register))
return false;
// if using worker execution, then we're done
if (workerLoad)
this.reduceRegister_(workerLoad, register);
// detect if we know the currently executing load (IE)
// if so, immediately call reduceRegister
else if (ieEvents)
this.reduceRegister_(getInteractiveScriptLoad(), register);
// otherwise, add to our execution queue
// to call reduceRegister on sync script load event
else if (loadingCnt)
registerQueue.push(register);
// if we're not currently loading anything though
// then do the reduction against a null load
// (out of band named define or named register)
// note even in non-script environments, this catch is used
else
this.reduceRegister_(null, register);
return true;
};
});
function webWorkerImport(loader, load) {
return new Promise(function(resolve, reject) {
if (load.metadata.integrity)
reject(new Error('Subresource integrity checking is not supported in web workers.'));
workerLoad = load;
try {
importScripts(load.address);
}
catch(e) {
workerLoad = null;
reject(e);
}
workerLoad = null;
// if nothing registered, then something went wrong
if (!load.metadata.entry)
reject(new Error(load.address + ' did not call System.register or AMD define'));
resolve('');
});
}
// override fetch to use script injection
hook('fetch', function(fetch) {
return function(load) {
var loader = this;
if (load.metadata.format == 'json' || !load.metadata.scriptLoad || (!isBrowser && !isWorker))
return fetch.call(this, load);
if (isWorker)
return webWorkerImport(loader, load);
return new Promise(function(resolve, reject) {
var s = document.createElement('script');
s.async = true;
if (load.metadata.crossOrigin)
s.crossOrigin = load.metadata.crossOrigin;
if (load.metadata.integrity)
s.setAttribute('integrity', load.metadata.integrity);
if (ieEvents) {
s.attachEvent('onreadystatechange', complete);
interactiveLoadingScripts.push({
script: s,
load: load
});
}
else {
s.addEventListener('load', complete, false);
s.addEventListener('error', error, false);
}
loadingCnt++;
curSystem = __global.System;
curRequire = __global.require;
s.src = load.address;
head.appendChild(s);
function complete(evt) {
if (s.readyState && s.readyState != 'loaded' && s.readyState != 'complete')
return;
loadingCnt--;
// complete call is sync on execution finish
// (in ie already done reductions)
if (!load.metadata.entry && !registerQueue.length) {
loader.reduceRegister_(load);
}
else if (!ieEvents) {
for (var i = 0; i < registerQueue.length; i++)
loader.reduceRegister_(load, registerQueue[i]);
registerQueue = [];
}
cleanup();
// if nothing registered, then something went wrong
if (!load.metadata.entry && !load.metadata.bundle)
reject(new Error(load.name + ' did not call System.register or AMD define. If loading a global module configure the global name via the meta exports property for script injection support.'));
resolve('');
}
function error(evt) {
cleanup();
reject(new Error('Unable to load script ' + load.address));
}
function cleanup() {
__global.System = curSystem;
__global.require = curRequire;
if (s.detachEvent) {
s.detachEvent('onreadystatechange', complete);
for (var i = 0; i < interactiveLoadingScripts.length; i++)
if (interactiveLoadingScripts[i].script == s) {
if (interactiveScript && interactiveScript.script == s)
interactiveScript = null;
interactiveLoadingScripts.splice(i, 1);
}
}
else {
s.removeEventListener('load', complete, false);
s.removeEventListener('error', error, false);
}
head.removeChild(s);
}
});
};
});
})();