diff --git a/require-es6.js b/require-es6.js index 2bb4af54..372f5825 100644 --- a/require-es6.js +++ b/require-es6.js @@ -48,7 +48,7 @@ var nameParts = name.split('/'); if (prefixParts.length > nameParts.length) return false; - for (var i = 0; i < prefixParts.length; i++) { + for (var i = 0; i < prefixParts.length; i++) if (nameParts[i] != prefixParts[i]) return false; return true; @@ -56,6 +56,8 @@ // get the configuration package for a given module name var getPackage = function(name) { + if (!name) + return ''; var p = ''; for (var _p in config.packages) { if (!prefixMatch(name, _p)) @@ -92,7 +94,7 @@ // hooks without plugin logic var loaderHooks = { normalize: function(name, options) { - var parentName = options.referer.name; + var parentName = options.referer && options.referer.name; // if the extension is js, and not an absolute URL, remove the extension if (name.substr(name.length - 3, 3) == '.js' && !name.match(absUrlRegEx)) @@ -127,40 +129,56 @@ // do standard normalization name = System.normalize(name, options); + return name; + }, + resolve: function(name, options) { + var parentName = options.referer && options.referer.name; + + // store the normalized name + options.normalizedName = name; + // do package config var p = getPackage(name); if (p) { // a sub-package path if (name.length > p.length) - name = config.packages[p].path + '/' + name.substr(p.length); + name = config.packages[p].path + name.substr(p.length); // the exact package - the main call else { - var main = config.packages[i].main || 'index'; + var main = config.packages[p].main || 'index'; // ensure that main is a relative ID if not a plugin form if (main.indexOf('!') == -1 && (main.substr(0, 2) != '..' || main.substr(0, 2) != './')) main = './' + main; // normalize the main - name = this.normalize(main, { referer: { name: name } }); + name = this.normalize(main, { referer: { name: config.packages[p].path + '/' } }); } } - return name + pluginArgument; - }, - resolve: function(name, options) { - // store the normalized name - options.normalizedName = name; - // paths configuration - for (var p in config.paths) { - if (!prefixMatch(name, p)) - continue; + // check the parent package first + var parentPackage = config.packages[getPackage(parentName)]; + var appliedParentPaths = false; + if (parentPackage && parentPackage.paths) { + for (var p in parentPackage.paths) { + if (!prefixMatch(name, p)) + continue; - name = config.paths[p] + name.substr(p.length); - break; + name = parentPackage.paths[p] + name.substr(p.length); + appliedParentPaths = true; + break; + } } + if (!appliedParentPaths) + for (var p in config.paths) { + if (!prefixMatch(name, p)) + continue; + + name = config.paths[p] + name.substr(p.length); + break; + } // then just use standard resolution return System.resolve(name); @@ -180,56 +198,82 @@ } System.fetch(url, options); }, - translate: function(source, options) { + link: function(source, options) { // check if there are any import syntax. If not, use the global shim config if (source.match(importRegEx) || source.match(exportRegEx) || source.match(moduleRegEx)) return; + var shimDeps; + // apply shim configuration with careful global management - var p = getPackage(name); - if (p.shimDeps) - for (var s in p.shimDeps) { - if (!prefixMatch(options.normalizedName, s)) + var p = getPackage(options.normalizedName); + if (p) + for (var s in config.packages[p].shimDeps) { + if (!prefixMatch(options.normalizedName, p + '/' + s)) continue; - options.shimDeps = p.shimDeps[s]; + shimDeps = config.packages[p].shimDeps[s]; break; } + else for (var s in config.shimDeps) { if (!prefixMatch(options.normalizedName, s)) continue; - options.shimDeps = config.shimDeps[s]; + shimDeps = config.shimDeps[s]; break; } - // normalize deps - for (var i = 0; i < options.shimDeps.length; i++) - options.shimDeps[i] = loader.normalize(options.shimDeps[i], { referer: { name: options.normalizedName } }); - - // add adjustments to the source to prepare the global - // and then retrieve global changes after the module - source = - "requireES6.__setGlobal(" + JSON.stringify(shimDeps) + ");" + - source + - "requireES6.set('" + options.normalizedName + "', requireES6.__getGlobal());"; - - return source; - }, - link: function(source, options) { - if (!options.shimDeps) - return; - return { - imports: options.shimDeps + imports: shimDeps || [], + execute: function(deps) { + setGlobal(deps); + loader.eval(source); + return new Module(getGlobal()); + } }; } }; + // given a module's global dependencies, prepare the global object + // to contain the union of the defined properties of its dependent modules + var globalObj = {}; + function setGlobal(deps) { + // first, we add all the dependency module properties to the global + if (deps) { + for (var i = 0; i < deps.length; i++) { + var dep = deps[i]; + for (var m in dep) + loader.global[m] = dep[m]; + } + } + + // now we store a complete copy of the global object + // in order to detect changes + for (var g in loader.global) { + if (loader.global.hasOwnProperty(g)) + globalObj[g] = loader.global[g]; + } + } + + // go through the global object to find any changes + // the differences become the returned global for this object + // the global object is left as is + function getGlobal() { + var moduleGlobal = {}; + + for (var g in loader.global) { + if (loader.global.hasOwnProperty(g) && g != 'window' && globalObj[g] != loader.global[g]) + moduleGlobal[g] = loader.global[g]; + } + return moduleGlobal; + } + + var loader = new Loader({ - baseUrl: config.baseURL, + baseURL: config.baseURL, normalize: function(name, options) { // plugin shorthand @@ -240,7 +284,7 @@ } // plugin normalization - option.pluginArgument = ''; + options.pluginArgument = ''; var pluginIndex = name.indexOf('!'); if (pluginIndex != -1) { options.pluginArgument = name.substr(pluginIndex); @@ -301,7 +345,7 @@ if (config.translate) return config.translate.call(loaderHooks, source, options); else - return loaderHooks.translate(source, options); + return source; }, link: function(source, options) { if (config.link) @@ -334,46 +378,9 @@ requireES6.set = loader.set.bind(loader); requireES6.has = loader.has.bind(loader); requireES6.delete = loader.delete.bind(loader); + + requireES6.loader = loader; - // global shim functions - - // given a module's global dependencies, prepare the global object - // to contain the union of the defined properties of its dependent modules - var globalObj = {}; - requireES6.__setGlobal = function(deps) { - // first, we add all the dependency module properties to the global - if (deps) { - for (var i = 0; i < deps.length; i++) { - var dep = requireES6.get(deps[i]); - for (var m in dep) - loader.global[m] = dep[m]; - } - } - - // now we store a complete copy of the global object - // in order to detect changes - for (var g in loader.global) { - if (!loader.global.hasOwnProperty(g)) - globalObj[g] = loader.global[g]; - } - } - - // go through the global object to find any changes - // the differences become the returned global for this object - // the global object is left as is - requireES6.__getGlobal = function() { - - var moduleGlobal = {}; - - for (var g in loader.global) { - if (!loader.global.hasOwnProperty(g)) - if (globalObj[g] != loader.global[g]) - moduleGlobal[g] = loader.global[g]; - } - - return moduleGlobal; - } - var cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)['"]\s*\)/g; loader.set('__require', require); diff --git a/require-es6-sample.html b/test/full-spec.html similarity index 97% rename from require-es6-sample.html rename to test/full-spec.html index 2c991f0d..4be04e17 100644 --- a/require-es6-sample.html +++ b/test/full-spec.html @@ -1,6 +1,6 @@ + + diff --git a/test/test-runner.js b/test/test-runner.js new file mode 100644 index 00000000..dde9ae91 --- /dev/null +++ b/test/test-runner.js @@ -0,0 +1,61 @@ + +var TestPage = function(el) { + this.$results = el.querySelectorAll('tr td.result'); + this.$summary = el.querySelector('.summary'); +} +TestPage.render = function(o) { + var _ = '' + + ''; + + for (var i = 0; i < o.tests.length; i++) + _ += ''; + + _ += '
TestResult
' + o.tests[i].name + '
'; + _ += '

' + return _; +} +TestPage.prototype = { + setResult: function(index, result) { + if (result) + this.$results[index].innerText = result; + else + this.$results[index].innerText = 'Passed'; + }, + setSummary: function(passed, failed) { + this.$summary.innerText = passed + ' tests passed, ' + failed + ' tests failed.'; + } +}; + +export function execute(tests) { + // draw the test table + document.body.innerHTML = TestPage.render({ + id: 'test-table', + tests: tests + }); + var testPage = new TestPage(document.body); + + // run the tests + var curTest = 0; + var passed = 0; + var failed = 0; + doNextTest = function() { + tests[curTest].run(function() { + var result = tests[curTest].confirm.apply(null, arguments); + testPage.setResult(curTest, result); + + if (result) + failed++; + else + passed++; + + testPage.setSummary(passed, failed); + + curTest++; + if (curTest == tests.length) + testPage.setSummary(passed, failed); + else + doNextTest(); + }); + } + doNextTest(); +} \ No newline at end of file diff --git a/test/test.html b/test/test.html new file mode 100644 index 00000000..5aed9157 --- /dev/null +++ b/test/test.html @@ -0,0 +1,176 @@ + + + + + + \ No newline at end of file diff --git a/test/tests/global-dep.js b/test/tests/global-dep.js new file mode 100644 index 00000000..7c2c9cae --- /dev/null +++ b/test/tests/global-dep.js @@ -0,0 +1,3 @@ +window.jQuery = { + v: '1.8.3' +}; \ No newline at end of file diff --git a/test/tests/global-with-dep.js b/test/tests/global-with-dep.js new file mode 100644 index 00000000..aaa6cfb5 --- /dev/null +++ b/test/tests/global-with-dep.js @@ -0,0 +1,2 @@ + +window.jQueryVersion = jQuery.v; \ No newline at end of file diff --git a/test/tests/global.js b/test/tests/global.js new file mode 100644 index 00000000..86568096 --- /dev/null +++ b/test/tests/global.js @@ -0,0 +1,6 @@ +window.jQuery = { + v: '2.0..0' +}; +window.another = { + some: 'thing' +}; \ No newline at end of file diff --git a/test/tests/map-test-dep.js b/test/tests/map-test-dep.js new file mode 100644 index 00000000..e033fe1b --- /dev/null +++ b/test/tests/map-test-dep.js @@ -0,0 +1 @@ +export var dep = 'maptest'; diff --git a/test/tests/map-test.js b/test/tests/map-test.js new file mode 100644 index 00000000..a0415581 --- /dev/null +++ b/test/tests/map-test.js @@ -0,0 +1,4 @@ +import { d: dep } from './map-test-dep'; + +export var maptest = d; + diff --git a/test/tests/package-test/global-dep.js b/test/tests/package-test/global-dep.js new file mode 100644 index 00000000..b03066ec --- /dev/null +++ b/test/tests/package-test/global-dep.js @@ -0,0 +1,2 @@ +console.log('dep ex'); +window.globalDep = 'global dep'; \ No newline at end of file diff --git a/test/tests/package-test/jquery-mapped.js b/test/tests/package-test/jquery-mapped.js new file mode 100644 index 00000000..0313a2ca --- /dev/null +++ b/test/tests/package-test/jquery-mapped.js @@ -0,0 +1,5 @@ +export var jQuery = { + fn: { + jquery: '1' + } +}; diff --git a/test/tests/package-test/map-test.js b/test/tests/package-test/map-test.js new file mode 100644 index 00000000..e47c84c7 --- /dev/null +++ b/test/tests/package-test/map-test.js @@ -0,0 +1,3 @@ +import { jQuery: jQuery } from 'jquery'; + +export var mapDep = jQuery.fn.jquery; \ No newline at end of file diff --git a/test/tests/package-test/path-test.js b/test/tests/package-test/path-test.js new file mode 100644 index 00000000..d5d0d17c --- /dev/null +++ b/test/tests/package-test/path-test.js @@ -0,0 +1,3 @@ +import { jQuery: jQuery } from 'jquery-cdn'; + +export var jQuery = jQuery; \ No newline at end of file diff --git a/test/tests/package-test/shim-test.js b/test/tests/package-test/shim-test.js new file mode 100644 index 00000000..758cf389 --- /dev/null +++ b/test/tests/package-test/shim-test.js @@ -0,0 +1,5 @@ +$.fn.myPlugin = 'plugin'; + +window.myPlugin = { + jQuery: $ +}; \ No newline at end of file diff --git a/test/tests/package-test/sub.js b/test/tests/package-test/sub.js new file mode 100644 index 00000000..4ac6edf9 --- /dev/null +++ b/test/tests/package-test/sub.js @@ -0,0 +1 @@ +export var package = 'package'; \ No newline at end of file diff --git a/test/tests/package-test/themain.js b/test/tests/package-test/themain.js new file mode 100644 index 00000000..f9a91cfc --- /dev/null +++ b/test/tests/package-test/themain.js @@ -0,0 +1 @@ +export var package = 'mypackage'; diff --git a/test/tests/path.js b/test/tests/path.js new file mode 100644 index 00000000..b09cdce8 --- /dev/null +++ b/test/tests/path.js @@ -0,0 +1 @@ +window.p = 'path';