systemjs
Version:
System loader extension for flexible AMD & CommonJS support
145 lines (118 loc) • 4.47 kB
JavaScript
/*
SystemJS Global Format
Supports
metadata.deps
metadata.init
metadata.exports
Also detects writes to the global object avoiding global collisions.
See the SystemJS readme global support section for further information.
*/
function global(loader) {
function readGlobalProperty(p, value) {
var pParts = p.split('.');
while (pParts.length)
value = value[pParts.shift()];
return value;
}
function createHelpers(loader) {
if (loader.has('@@global-helpers'))
return;
var hasOwnProperty = loader.global.hasOwnProperty;
var moduleGlobals = {};
var curGlobalObj;
var ignoredGlobalProps;
loader.set('@@global-helpers', loader.newModule({
prepareGlobal: function(moduleName, deps) {
// first, we add all the dependency modules to the global
for (var i = 0; i < deps.length; i++) {
var moduleGlobal = moduleGlobals[deps[i]];
if (moduleGlobal)
for (var m in moduleGlobal)
loader.global[m] = moduleGlobal[m];
}
// now store a complete copy of the global object
// in order to detect changes
curGlobalObj = {};
ignoredGlobalProps = ['indexedDB', 'sessionStorage', 'localStorage',
'clipboardData', 'frames', 'webkitStorageInfo', 'toolbar', 'statusbar',
'scrollbars', 'personalbar', 'menubar', 'locationbar', 'webkitIndexedDB'
];
for (var g in loader.global) {
if (indexOf.call(ignoredGlobalProps, g) != -1) { continue; }
if (!hasOwnProperty || loader.global.hasOwnProperty(g)) {
try {
curGlobalObj[g] = loader.global[g];
} catch (e) {
ignoredGlobalProps.push(g);
}
}
}
},
retrieveGlobal: function(moduleName, exportName, init) {
var singleGlobal;
var multipleExports;
var exports = {};
// run init
if (init) {
var depModules = [];
for (var i = 0; i < deps.length; i++)
depModules.push(require(deps[i]));
singleGlobal = init.apply(loader.global, depModules);
}
// check for global changes, creating the globalObject for the module
// if many globals, then a module object for those is created
// if one global, then that is the module directly
else if (exportName) {
var firstPart = exportName.split('.')[0];
singleGlobal = readGlobalProperty(exportName, loader.global);
exports[firstPart] = loader.global[firstPart];
}
else {
for (var g in loader.global) {
if (indexOf.call(ignoredGlobalProps, g) != -1)
continue;
if ((!hasOwnProperty || loader.global.hasOwnProperty(g)) && g != loader.global && curGlobalObj[g] != loader.global[g]) {
exports[g] = loader.global[g];
if (singleGlobal) {
if (singleGlobal !== loader.global[g])
multipleExports = true;
}
else if (singleGlobal !== false) {
singleGlobal = loader.global[g];
}
}
}
}
moduleGlobals[moduleName] = exports;
return multipleExports ? exports : singleGlobal;
}
}));
}
createHelpers(loader);
var loaderInstantiate = loader.instantiate;
loader.instantiate = function(load) {
var loader = this;
createHelpers(loader);
var exportName = load.metadata.exports;
if (!load.metadata.format)
load.metadata.format = 'global';
// global is a fallback module format
if (load.metadata.format == 'global') {
load.metadata.execute = function(require, exports, module) {
loader.get('@@global-helpers').prepareGlobal(module.id, load.metadata.deps);
if (exportName)
load.source += '\nthis["' + exportName + '"] = ' + exportName + ';';
// disable AMD detection
var define = loader.global.define;
loader.global.define = undefined;
// ensure no NodeJS environment detection
loader.global.module = undefined;
loader.global.exports = undefined;
loader.__exec(load);
loader.global.define = define;
return loader.get('@@global-helpers').retrieveGlobal(module.id, exportName, load.metadata.init);
}
}
return loaderInstantiate.call(loader, load);
}
}