diff options
Diffstat (limited to 'lib/global-helpers.js')
-rw-r--r-- | lib/global-helpers.js | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/lib/global-helpers.js b/lib/global-helpers.js new file mode 100644 index 000000000..2e87f0882 --- /dev/null +++ b/lib/global-helpers.js @@ -0,0 +1,147 @@ + + +function getGlobalValue(exports) { + if (typeof exports == 'string') + return readMemberExpression(exports, __global); + + if (!(exports instanceof Array)) + throw new Error('Global exports must be a string or array.'); + + var globalValue = {}; + var first = true; + for (var i = 0; i < exports.length; i++) { + var val = readMemberExpression(exports[i], __global); + if (first) { + globalValue['default'] = val; + first = false; + } + globalValue[exports[i].split('.').pop()] = val; + } + return globalValue; +} + +hook('reduceRegister_', function(reduceRegister) { + return function(load, register) { + if (register || (!load.metadata.exports && !(isWorker && load.metadata.format == 'global'))) + return reduceRegister.call(this, load, register); + + load.metadata.format = 'global'; + var entry = load.metadata.entry = createEntry(); + entry.deps = load.metadata.deps; + var globalValue = getGlobalValue(load.metadata.exports); + entry.execute = function() { + return globalValue; + }; + }; +}); + +hookConstructor(function(constructor) { + return function() { + var loader = this; + constructor.call(loader); + + var hasOwnProperty = Object.prototype.hasOwnProperty; + + // bare minimum ignores + var ignoredGlobalProps = ['_g', 'sessionStorage', 'localStorage', 'clipboardData', 'frames', 'frameElement', 'external', + 'mozAnimationStartTime', 'webkitStorageInfo', 'webkitIndexedDB', 'mozInnerScreenY', 'mozInnerScreenX']; + + var globalSnapshot; + + function forEachGlobal(callback) { + if (Object.keys) + Object.keys(__global).forEach(callback); + else + for (var g in __global) { + if (!hasOwnProperty.call(__global, g)) + continue; + callback(g); + } + } + + function forEachGlobalValue(callback) { + forEachGlobal(function(globalName) { + if (indexOf.call(ignoredGlobalProps, globalName) != -1) + return; + try { + var value = __global[globalName]; + } + catch (e) { + ignoredGlobalProps.push(globalName); + } + callback(globalName, value); + }); + } + + loader.set('@@global-helpers', loader.newModule({ + prepareGlobal: function(moduleName, exports, globals, encapsulate) { + // disable module detection + var curDefine = __global.define; + + __global.define = undefined; + + // set globals + var oldGlobals; + if (globals) { + oldGlobals = {}; + for (var g in globals) { + oldGlobals[g] = __global[g]; + __global[g] = globals[g]; + } + } + + // store a complete copy of the global object in order to detect changes + if (!exports) { + globalSnapshot = {}; + + forEachGlobalValue(function(name, value) { + globalSnapshot[name] = value; + }); + } + + // return function to retrieve global + return function() { + var globalValue = exports ? getGlobalValue(exports) : {}; + + var singleGlobal; + var multipleExports = !!exports; + + if (!exports || encapsulate) + forEachGlobalValue(function(name, value) { + if (globalSnapshot[name] === value) + return; + if (typeof value == 'undefined') + return; + + // allow global encapsulation where globals are removed + if (encapsulate) + __global[name] = undefined; + + if (!exports) { + globalValue[name] = value; + + if (typeof singleGlobal != 'undefined') { + if (!multipleExports && singleGlobal !== value) + multipleExports = true; + } + else { + singleGlobal = value; + } + } + }); + + globalValue = multipleExports ? globalValue : singleGlobal; + + // revert globals + if (oldGlobals) { + for (var g in oldGlobals) + __global[g] = oldGlobals[g]; + } + __global.define = curDefine; + + return globalValue; + }; + } + })); + }; +}); |