better support for module loading in packed mode

pull/3/head
nightwing 2015-02-11 14:20:44 +04:00
rodzic 591e5d841e
commit 1c11468fe0
2 zmienionych plików z 209 dodań i 150 usunięć

Wyświetl plik

@ -38,7 +38,7 @@ window.normalizeModule = function(parentId, moduleName) {
var base = parentId.split("/").slice(0, -1).join("/");
moduleName = (base ? base + "/" : "") + moduleName;
while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
var previous = moduleName;
moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
}
@ -101,9 +101,9 @@ window.define = function(id, deps, factory) {
}
if (!deps.length)
// If there is no dependencies, we inject 'require', 'exports' and
// 'module' as dependencies, to provide CommonJS compatibility.
deps = ['require', 'exports', 'module'];
// If there is no dependencies, we inject "require", "exports" and
// "module" as dependencies, to provide CommonJS compatibility.
deps = ["require", "exports", "module"];
var req = function(childId) {
return window.require(id, childId);
@ -114,16 +114,16 @@ window.define = function(id, deps, factory) {
factory: function() {
var module = this;
var returnExports = factory.apply(this, deps.map(function(dep) {
switch(dep) {
// Because 'require', 'exports' and 'module' aren't actual
// dependencies, we must handle them seperately.
case 'require': return req;
case 'exports': return module.exports;
case 'module': return module;
// But for all other dependencies, we can just go ahead and
// require them.
default: return req(dep);
}
switch (dep) {
// Because "require", "exports" and "module" aren't actual
// dependencies, we must handle them seperately.
case "require": return req;
case "exports": return module.exports;
case "module": return module;
// But for all other dependencies, we can just go ahead and
// require them.
default: return req(dep);
}
}));
if (returnExports)
module.exports = returnExports;
@ -186,7 +186,7 @@ window.onmessage = function(e) {
sender = window.sender = initSender();
var clazz = require(msg.module)[msg.classname];
main = window.main = new clazz(sender);
}
}
else if (msg.event && sender) {
sender._signal(msg.event, msg.data);
}

Wyświetl plik

@ -1,91 +1,175 @@
(function() {
var ACE_NAMESPACE = "";
var MODULE_LOAD_URL = "/load/module";
var global = (function() { return this; })();
if (!global && typeof window != "undefined") global = window; // can happen in strict mode
var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;
var cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g;
if (!ACE_NAMESPACE && typeof requirejs !== "undefined")
return;
var _define = function(module, deps, payload) {
if (typeof module !== 'string') {
if (_define.original)
_define.original.apply(window, arguments);
else {
console.error('dropping module because define wasn\'t a string.');
console.trace();
}
return;
function getInlineDeps(fn) {
var deps = [];
if (fn.length) {
fn.toString().replace(commentRegExp, "")
.replace(cjsRequireRegExp, function (match, dep) {
deps.push(dep);
});
deps = ["require", "exports", "module"].concat(deps);
}
return deps;
}
if (arguments.length == 2)
payload = deps;
_define.amd = true;
if (!_define.modules) {
_define.modules = {};
_define.payloads = {};
var define = function(name, deps, callback) {
// Allow for anonymous modules
if (typeof name !== "string") {
callback = deps;
deps = name;
name = null;
}
if (_define.modules[module])
// This module may not have dependencies
if (deps && !Array.isArray(deps)) {
callback = deps;
deps = null;
}
if (!name)
return defQueue.push([deps, callback]);
if (define.loaded[name])
return;
_define.payloads[module] = payload;
_define.modules[module] = null;
if (!deps && typeof callback == "function")
deps = getInlineDeps(callback);
define.loaded[name] = {
id: name,
deps: normalizeNames(name, deps),
factory: callback,
exports: {},
packaged: true
};
};
var defQueue = [];
var addToLoadQueue = function(missing, deps, callback) {
define.queue.push(function() { _require('', deps, callback); });
for (var i = 0; i < missing.length; ++i)
require.load(missing[i]);
};
/**
* Get at functionality define()ed using the function above
*/
var _require = function(parentId, module, callback) {
if (Object.prototype.toString.call(module) === "[object Array]") {
var params = [];
for (var i = 0, l = module.length; i < l; ++i) {
var moduleName = normalizeModule(parentId, module[i]);
var dep = lookup(parentId, moduleName);
if (!dep && _require.load) {
return _require.load(moduleName, function() {
if (lookup(parentId, moduleName))
_require(parentId, module, callback);
});
var processLoadQueue = function(err, id) {
if (defQueue.length) {
if (err)
throw err;
if (defQueue.length > 1)
throw new Error("more than one module in defqueue");
define(id, defQueue[0][0], defQueue[0][1]);
defQueue.length = 0;
}
var queue = define.queue;
define.queue = [];
queue.forEach(function(f) { f(); });
};
define.amd = true;
define.queue = [];
define.loaded = {};
define.modules = { require: 1, exports: 1, module: 1 };
define.fetchedUrls = {};
var activateModule = function(name) {
var module = define.loaded[name];
var exports = module.exports;
if (typeof module.factory !== "function") {
exports = module.factory;
} else {
var req = function(path, callback) {
return _require(name, path, callback);
};
req.toUrl = require.toUrl;
var modules = define.modules;
var missing = checkMissing(module.deps);
if (missing.length)
return missing;
modules.require = req;
modules.exports = exports;
modules.module = module;
define.modules[name] = exports;
var args = module.deps.slice(0, module.factory.length);
var returnValue = args.length
? module.factory.apply(module, args.map(lookup))
: module.factory(req, exports, module);
exports = returnValue || module.exports;
}
delete define.loaded[name];
define.modules[name] = exports;
};
var checkMissing = function(deps, seen, missing) {
missing = missing || {};
seen = seen || {};
for (var i = 0; i < deps.length; ++i) {
var depName = deps[i];
if (!define.modules[depName]) {
var dep = define.loaded[depName];
if (!dep)
missing[depName] = 1;
else if (!missing[depName] && !seen[depName]) {
seen[depName] = 1;
checkMissing(dep.deps, seen, missing);
}
params.push(dep);
}
if (callback) {
callback.apply(null, params);
}
}
else if (typeof module === 'string') {
var payload = lookup(parentId, module);
if (!payload && _require.original)
return _require.original.apply(this, arguments);
if (callback) {
callback();
}
return payload;
}
else {
if (_require.original)
return _require.original.apply(this, arguments);
}
return Object.keys(missing);
};
var normalizeModule = function(parentId, moduleName) {
var lookup = function(moduleName) {
var mod = define.modules[moduleName];
if (mod === undefined && define.loaded[moduleName]) {
activateModule(moduleName);
mod = define.modules[moduleName];
}
return mod;
};
var _require = function(parentId, moduleName, callback) {
if (typeof moduleName === "string") {
var depName = normalizeName(parentId, moduleName);
var module = lookup(depName);
if (module !== undefined) {
callback && callback(module);
return module;
}
} else if (Array.isArray(moduleName)) {
var deps = normalizeNames(parentId, moduleName);
var missing = checkMissing(deps);
if (!missing.length) {
var args = moduleName.map(lookup);
return callback && callback.apply(null, args);
} else {
return addToLoadQueue(missing, deps, callback);
}
}
if (_require.original)
return _require.original.apply(this, arguments);
};
var normalizeName = function(parentId, moduleName) {
// normalize plugin requires
if (moduleName.indexOf("!") !== -1) {
var chunks = moduleName.split("!");
return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
return normalizeName(parentId, chunks[0]) + "!" + normalizeName(parentId, chunks[1]);
}
// normalize relative requires
if (moduleName.charAt(0) == ".") {
var base = parentId.split("/").slice(0, -1).join("/");
moduleName = (base || parentId) + "/" + moduleName;
while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
var previous = moduleName;
moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
}
@ -94,117 +178,80 @@ var normalizeModule = function(parentId, moduleName) {
return moduleName;
};
/**
* Internal function to lookup moduleNames and resolve them by calling the
* definition function if needed.
*/
var lookup = function(parentId, moduleName) {
moduleName = normalizeModule(parentId, moduleName);
var module = _define.modules[moduleName];
if (!module) {
module = _define.payloads[moduleName];
var exports = {};
if (typeof module === 'function') {
var mod = {
id: moduleName,
uri: '',
exports: exports,
packaged: true
};
var req = function(module, callback) {
return _require(moduleName, module, callback);
};
req.toUrl = require.toUrl;
_define.modules[moduleName] = exports;
var returnValue = module(req, exports, mod);
exports = returnValue || mod.exports;
_define.modules[moduleName] = exports;
delete _define.payloads[moduleName];
} else {
exports = module;
}
module = _define.modules[moduleName] = exports;
}
return module;
var normalizeNames = function(parentId, moduleNames) {
return moduleNames.map(function(name) {
return normalizeName(parentId, name);
});
};
function exportAce(ns) {
var root = global;
if (ns) {
if (!global[ns])
global[ns] = {};
root = global[ns];
}
if (!root.define || !root.define.packaged) {
_define.original = root.define;
root.define = _define;
root.define.packaged = true;
}
if (!root.require || !root.require.packaged) {
// _require.original = root.require || _require.original;
root.require = require;
root.require.packaged = true;
}
root.miniRequire = require;
}
var require = function(module, callback) {
return _require("", module, callback);
};
require.MODULE_LOAD_URL = MODULE_LOAD_URL;
require.toUrl = function(url) {
var root = "/static";
var urlMap = require.urlMap || {};
var parts = url.split("/");
var top = parts[0];
parts.shift();
return [root, urlMap[top] || top].concat(parts).join("/");
require.undef = function(module, callback) {
module = normalizeName("", module);
var path = require.toUrl(module);
delete define.loaded[module];
delete define.modules[module];
delete define.fetchedUrls[path];
};
var loadScript = function(path, callback) {
var head = document.head || document.documentElement;
var s = document.createElement('script');
require.MODULE_LOAD_URL = MODULE_LOAD_URL;
require.toUrl = function(module, ext) {
var path = module;
if (!/https?:\/\//.test(path))
path = require.MODULE_LOAD_URL + "/" + path + (ext || "");
return path;
};
var loadScript = function(path, id, callback) {
var head = document.head || document.documentElement;
var s = document.createElement("script");
s.src = path;
s.charset = 'utf-8';
s.async = true;
head.appendChild(s);
s.onload = s.onreadystatechange = function(_, isAbort) {
if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") {
s = s.onload = s.onreadystatechange = null;
if (!isAbort)
callback();
callback(null, id);
}
};
};
_require.load = function(module, callback) {
require.load = function(module) {
var i = module.indexOf("!") + 1;
if (i) {
var plugin = module.substring(0, i);
module = module.substr(i);
if (require[plugin]) {
require[plugin](module, callback);
require[plugin](module, processLoadQueue);
} else {
console.error("require plugin " + plugin + "missing");
}
} else {
loadScript(require.MODULE_LOAD_URL + "/" + module + ".js", callback);
var url = require.toUrl(module, ".js");
if (define.fetchedUrls[url] & 1)
return false;
define.fetchedUrls[url] |= 1;
loadScript(url, module, processLoadQueue);
}
};
/*** plugins ***/
require["text!"] = function(module, callback) {
var url = require.toUrl(module);
if (define.fetchedUrls[url] & 2)
return false;
define.fetchedUrls[url] |= 2;
var cb = function(e, val) {
if (e) console.error("Couldn't load module " + module, e);
_define.modules["text!" + module] = val;
define("text!" + module, [], val);
callback();
};
var url = require.MODULE_LOAD_URL + "/" + module;
var xhr = new window.XMLHttpRequest();
xhr.open("GET", url + "?access_token=fake_token", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
@ -213,6 +260,18 @@ require["text!"] = function(module, callback) {
xhr.send("");
};
exportAce(ACE_NAMESPACE);
/*** add global define ***/
if (!global.define || !global.define.packaged) {
define.original = global.define;
global.define = define;
global.define.packaged = true;
}
if (!global.require || !global.require.packaged) {
global.require = require;
global.require.packaged = true;
}
global.miniRequire = require;
})();