From 1c11468fe0c4b2cc0aaa0890618004ed25f007da Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 11 Feb 2015 14:20:44 +0400 Subject: [PATCH] better support for module loading in packed mode --- node_modules/ace/lib/ace/worker/worker.js | 30 +- .../build_support/mini_require.js | 329 +++++++++++------- 2 files changed, 209 insertions(+), 150 deletions(-) diff --git a/node_modules/ace/lib/ace/worker/worker.js b/node_modules/ace/lib/ace/worker/worker.js index 1054178f..8c4fe7c1 100644 --- a/node_modules/ace/lib/ace/worker/worker.js +++ b/node_modules/ace/lib/ace/worker/worker.js @@ -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); } diff --git a/node_modules/architect-build/build_support/mini_require.js b/node_modules/architect-build/build_support/mini_require.js index 2236743e..03979273 100644 --- a/node_modules/architect-build/build_support/mini_require.js +++ b/node_modules/architect-build/build_support/mini_require.js @@ -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; + })();