diff --git a/shadow.js b/shadow.js index 8b2ba9a..2d1ec3d 100644 --- a/shadow.js +++ b/shadow.js @@ -1,7 +1,7 @@ /** * @license MIT http://troopjs.mit-license.org/ */ -define([ "text" ], function (text) { +define([ "text"], function(text) { "use strict"; /** @@ -21,12 +21,19 @@ define([ "text" ], function (text) { var REQUIRE_VERSION = require.version; var buildMap = {}; - function amdify (scriptText, hashVal) { + function amdify(scriptText, hashVal) { var pattern = /([^=&]+)=([^&]+)/g; var m; var deps = []; var args = []; + var isAmd = scriptText.indexOf("define(") !== -1; + + // export amd module + if (isAmd) { + scriptText += ";\nreturn __export__;\n"; + } + while (hashVal && (m = pattern.exec(hashVal))) { if (m[1] === EXPORTS) { scriptText += ";\nreturn " + m[2] + ";\n"; @@ -37,9 +44,16 @@ define([ "text" ], function (text) { } } - return "define([" + deps.join(", ") + "], function (" + args.join(", ") + ") {\n" - + scriptText + // minified content of shadow_define.js is reflected here + var define_stub = 'var args=arguments;var __export__;function define(r,n){var e=/\\(([^)]+)\\)/;function t(r){return e.exec(r.toString())[1].split(",").map(function(r){return r.trim()})}var a=t(n);var u=t(moduleDefine);var i=a.map(function(r){return args[u.indexOf(r)]});return __export__=n.apply(null,i)}'; + + var source; + source = "define([" + deps.join(", ") + "], function moduleDefine(" + args.join(", ") + ") {\n" + + ( isAmd ? define_stub + ";\n" : "") + + scriptText + "});"; + + return source; } function cmpVersion(a, b) { @@ -61,7 +75,7 @@ define([ "text" ], function (text) { } return { - load : function (name, req, onLoad, config) { + load: function(name, req, onLoad, config) { var m; var hashVal; var content; @@ -92,17 +106,17 @@ define([ "text" ], function (text) { // need to manually require the module after the call to onLoad.fromText() if (cmpVersion(REQUIRE_VERSION, "2.1.0") < 0) { req([ name ], onLoad); - } + } }); } }, - write : function (pluginName, moduleName, write) { + write: function(pluginName, moduleName, write) { var content; if (moduleName in buildMap) { content = buildMap[moduleName]; - content = content.replace(/define\(/, function (match) { + content = content.replace(/define\(/, function(match) { return match + '"' + [pluginName, moduleName].join('!') + '",'; }); write(content); diff --git a/shadow_define.js b/shadow_define.js new file mode 100644 index 0000000..727e74e --- /dev/null +++ b/shadow_define.js @@ -0,0 +1,29 @@ +/* + * Note: This script is part of the shadow plugin and it not to be used standalone. + * content of which is to be injected to prepend to an AMD module, overriding the original "define" function there. + */ + +var args = arguments; +var __export__; + +// override the "define" function in the shadow scope +function define(list, callback) { + var RE_FUNC_PARAMS = /\(([^)]+)\)/; + + function getargs(fn) { + return RE_FUNC_PARAMS.exec(fn.toString())[1].split(',').map(function(arg) { + return arg.trim(); + }); + } + + var deps = getargs(callback); + var actuals = getargs(moduleDefine); + + // re-order the dependencies according to name match. + var vals = deps.map(function(dep) { + return args[actuals.indexOf(dep)]; + }); + + // invoke the module and to export the return value. + return (__export__ = callback.apply(null, vals)); +} diff --git a/test/assets/dep1.js b/test/assets/dep1.js index 7ce1579..85e8500 100644 --- a/test/assets/dep1.js +++ b/test/assets/dep1.js @@ -1,3 +1,3 @@ define(function() { - return "dep1"; + return "export1"; }); diff --git a/test/assets/dep2.js b/test/assets/dep2.js index b3bcfa0..1941963 100644 --- a/test/assets/dep2.js +++ b/test/assets/dep2.js @@ -1,3 +1,3 @@ define(function() { - return "dep2"; + return "export2"; }); diff --git a/test/assets/foo-amd.js b/test/assets/foo-amd.js new file mode 100644 index 0000000..bcfa46e --- /dev/null +++ b/test/assets/foo-amd.js @@ -0,0 +1,3 @@ +define(['test/dep1', 'test/dep2'], function(dep1, dep2) { + return [dep1, dep2, "foo"].join(','); +}); diff --git a/test/plugin-browser.js b/test/plugin-browser.js index 3fed1fb..dc2fe3e 100644 --- a/test/plugin-browser.js +++ b/test/plugin-browser.js @@ -33,7 +33,7 @@ buster.testCase("plugin", function (run){ }, "shadow load non-amd module": function(done) { this.require(['shadow!test/foo#dep1=test/dep1&dep2=test/dep2&exports=Foo'], function(foo) { - assert.equals(foo, "dep1,dep2,foo"); + assert.equals(foo, "export1,export2,foo"); done(); }); } diff --git a/test/plugin-node.js b/test/plugin-node.js index a7a6200..9b90144 100644 --- a/test/plugin-node.js +++ b/test/plugin-node.js @@ -12,21 +12,23 @@ buster.testCase("plugin", function (run) { var self = this; self.timeout = 1000; requirejs.config({ - "baseUrl": "./", + "baseUrl": "./bower_components", + "paths": { + "shadow": "../shadow", + "json": "../json", + "mv": "../multiversion" + }, "packages": [ { "name" : "test", - "location" : "test/assets" + "location": "../test/assets" }, { "name": "text", - "location": "bower_components/requirejs-text", + "location": "requirejs-text", "main": "text" } ], - "maps": { - "mv": "multiversion" - }, deps: ['require'], "callback": function(localRequire) { self.require = localRequire; @@ -34,9 +36,15 @@ buster.testCase("plugin", function (run) { } }); }, - "shadow load non-amd module": function (done) { + "shadow load - non-amd module": function(done) { this.require(['shadow!test/foo#dep1=test/dep1&dep2=test/dep2&exports=Foo'], function(foo) { - assert.equals(foo, "dep1,dep2,foo"); + assert.equals(foo, "export1,export2,foo"); + done(); + }); + }, + "shadow load - amd module": function(done) { + this.require(['shadow!test/foo-amd#dep2=test/dep2&dep1=test/dep1'], function(foo) { + assert.equals(foo, "export1,export2,foo"); done(); }); }