",
6 | "homepage": "https://github.com/caridy/es6-micro-loader",
7 | "keywords": [
8 | "es6",
9 | "module",
10 | "loader",
11 | "system",
12 | "register"
13 | ],
14 | "bugs": "https://github.com/caridy/es6-micro-loader/issues",
15 | "main": "index.js",
16 | "files": [
17 | "index.js",
18 | "server.js",
19 | "dist/"
20 | ],
21 | "scripts": {
22 | "test": "npm run test-compile; ./node_modules/.bin/_mocha tests/unit/*.js --reporter spec",
23 | "test-compile": "cd tests/unit/src/; ../../../node_modules/.bin/compile-modules convert -f es6-module-transpiler-system-formatter **/*.js -o ../build",
24 | "benchmark-compile-cjs": "cd tests/benchmark/src/; ../../../node_modules/.bin/compile-modules convert -f commonjs *.js -o ../cjs",
25 | "benchmark-compile-bundle": "cd tests/benchmark/src/; ../../../node_modules/.bin/compile-modules convert -f bundle *.js -o ../bundle/main.js",
26 | "benchmark-compile-system": "cd tests/benchmark/src/; ../../../node_modules/.bin/compile-modules convert -f es6-module-transpiler-system-formatter *.js -o ../system",
27 | "benchmark": "npm run benchmark-compile-bundle; npm run benchmark-compile-cjs; npm run benchmark-compile-system; node tests/benchmark/run.js"
28 | },
29 | "license": "MIT",
30 | "dependencies": {
31 | "es6-promise": "^1.0.0"
32 | },
33 | "devDependencies": {
34 | "grunt": "^0.4.5",
35 | "grunt-cli": "0.1.*",
36 | "grunt-contrib-copy": "^0.5.0",
37 | "grunt-contrib-uglify": "^0.5.1",
38 | "grunt-contrib-jshint": "^0.10.0",
39 | "benchmark": "^1.0.0",
40 | "es6-module-transpiler": "~0.8.2",
41 | "es6-module-transpiler-system-formatter": "~0.2.0",
42 | "chai": "*",
43 | "mocha": "*",
44 | "xunit-file": "*",
45 | "chai-as-promised": "*"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | /* jslint node: true */
2 |
3 | var path = require('path');
4 |
5 | var seen = Object.create(null);
6 | var internalRegistry = Object.create(null);
7 | var externalRegistry = Object.create(null);
8 |
9 | function ensuredExecute (name) {
10 | var mod = internalRegistry[name];
11 | if (mod && !seen[name]) {
12 | seen[name] = true;
13 | // one time operation to execute the module body
14 | mod.execute();
15 | }
16 | return mod && mod.proxy;
17 | }
18 | function set (name, values) {
19 | externalRegistry[name] = values;
20 | }
21 | function get (name) {
22 | return externalRegistry[name] || ensuredExecute(name);
23 | }
24 | function has (name) {
25 | return !!externalRegistry[name] || !!internalRegistry[name];
26 | }
27 |
28 |
29 |
30 | // exporting the System object
31 | exports.System = {
32 | set: set,
33 | get: get,
34 | has: has,
35 | import: function(name) {
36 | return new Promise(function (resolve, reject) {
37 | var mod = patchedRequire(path.resolve(name));
38 | return mod ? resolve(mod) : reject(new Error('Could not find module ' + name));
39 | });
40 | },
41 | register: function(name, deps, wrapper) {
42 | var mod,
43 | externalDeps = [];
44 | // creating a new module entry that will be added to the cache later on
45 | mod = {
46 | name: name,
47 | setters: null,
48 | proxy: Object.create(null),
49 | deps: deps.map(function(dep) {
50 | if (dep.charAt(0) !== '.') {
51 | externalDeps.push(dep);
52 | return dep;
53 | }
54 | var parts = dep.split('/'),
55 | parentBase = name.split('/').slice(0, -1);
56 | while (parts[0] === '.' || parts[0] === '..') {
57 | if (parts.shift() === '..') {
58 | parentBase.pop();
59 | }
60 | }
61 | return parentBase.concat(parts).join('/');
62 | }),
63 | externalDeps: externalDeps,
64 | // other modules that depends on this so we can push updates into those modules
65 | dependants: [],
66 | // method used to push updates of dependencies into the module body
67 | update: function(moduleName, moduleObj) {
68 | mod.setters[mod.deps.indexOf(moduleName)](moduleObj);
69 | },
70 | execute: wrapper
71 | };
72 | newEntry = mod;
73 | }
74 | };
75 |
76 |
77 |
78 | var newEntry;
79 | var m = require('module');
80 | var Module = require('module').Module;
81 | var originalLoader = require('module')._load;
82 |
83 | // monkey patching `require()` during a brief period of time
84 | function patchedRequire(name) {
85 | m._load = function patchedLoader(request, parent, isMain) {
86 | var values, filename, cachedModule, metaModule, esModule;
87 | newEntry = undefined;
88 | values = originalLoader.apply(this, arguments);
89 | if (newEntry) {
90 | filename = Module._resolveFilename(request, parent);
91 | cachedModule = Module._cache[filename];
92 | if (cachedModule && !cachedModule._esModule) {
93 | cachedModule._esModule = esModule = newEntry;
94 | esModule.address = filename;
95 | esModule.basePath = request.slice(0, -esModule.name.length);
96 | esModule.parent = parent;
97 | // collecting execute() and setters[]
98 | metaModule = esModule.execute(function(identifier, value) {
99 | values[identifier] = value;
100 | esModule.lock = true; // locking down the updates on the module to avoid infinite loop
101 | esModule.dependants.forEach(function(dependant) {
102 | if (!dependant.lock) {
103 | dependant.update(esModule.name, values);
104 | }
105 | });
106 | esModule.lock = false;
107 | if (!Object.getOwnPropertyDescriptor(esModule.proxy, identifier)) {
108 | Object.defineProperty(esModule.proxy, identifier, {
109 | enumerable: true,
110 | get: function() {
111 | return values[identifier];
112 | }
113 | });
114 | }
115 | return value;
116 | });
117 | esModule.setters = metaModule.setters;
118 | esModule.deps.forEach(function(dep) {
119 | var imports = externalRegistry[dep],
120 | depRequest, depFilename, depModule;
121 | if (!imports) {
122 | if (~esModule.externalDeps.indexOf(dep)) {
123 | imports = require(Module._resolveFilename(dep, cachedModule));
124 | } else {
125 | depRequest = path.resolve(path.join(esModule.basePath, dep));
126 | imports = require(depRequest);
127 | depFilename = Module._resolveFilename(depRequest, cachedModule);
128 | depModule = Module._cache[depFilename]._esModule;
129 | if (depModule) {
130 | depModule.dependants.push(esModule);
131 | }
132 | }
133 | }
134 | esModule.update(dep, imports);
135 | });
136 | // executing the module body
137 | metaModule.execute();
138 | }
139 | }
140 | return values;
141 | };
142 | var mod = require(name);
143 | // removing the patch
144 | m._load = originalLoader;
145 | return mod;
146 | }
147 |
--------------------------------------------------------------------------------
/tests/benchmark/run.js:
--------------------------------------------------------------------------------
1 | var Benchmark = require("benchmark");
2 | var System = require("../../"); // es6-micro-loader
3 |
4 | System.import("tests/benchmark/system/main").then(function (systemMod) {
5 |
6 | var suite = new Benchmark.Suite(),
7 | a = 0, aFn = require("./cjs/main").checkForOdd,
8 | b = 0, bFn = systemMod.checkForOdd,
9 | c = 0, cFn = require("./bundle/main") && global.checkForOdd;
10 |
11 | // add tests
12 | suite.add("cjs", function() {
13 | // commonjs modules which use require() and defineProperties() to preserve ES semantics
14 | aFn(a++);
15 | })
16 | .add("system", function() {
17 | // System.register() modules which preserve ES semantics
18 | bFn(b++);
19 | })
20 | .add("bundle", function() {
21 | // using a global variable, and a rollup without preserving bindings or any other ES Semantics
22 | cFn(c++);
23 | })
24 | // add listeners
25 | .on("cycle", function(event) {
26 | console.log(String(event.target));
27 | })
28 | .on("complete", function() {
29 | console.log("Fastest is " + this.filter("fastest").pluck("name"));
30 | })
31 | // run async
32 | .run({ "async": true });
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/tests/benchmark/src/evens.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | export default function (n) {
4 | return n % 2 === 0;
5 | }
6 |
--------------------------------------------------------------------------------
/tests/benchmark/src/main.js:
--------------------------------------------------------------------------------
1 | /* jslint esnext: true */
2 |
3 | import isOdd from "./odds";
4 |
5 | export function checkForOdd(n) {
6 | return isOdd(n);
7 | }
8 |
9 | // this is needed for `bundle` output
10 | if (typeof global !== 'undefined') {
11 | global.checkForOdd = checkForOdd;
12 | }
13 |
--------------------------------------------------------------------------------
/tests/benchmark/src/odds.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import isEven from "./evens";
4 |
5 | export default function (n) {
6 | return !isEven(n);
7 | }
8 |
--------------------------------------------------------------------------------
/tests/unit/manual.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | using System polyfill thru micro-loader
6 |
7 |
8 |
9 | Look at the browser's console for details.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tests/unit/src/circular-init/a.js:
--------------------------------------------------------------------------------
1 | import B from './b';
2 | import C from './c';
3 |
4 | var b = new B();
5 | var c = new C();
6 |
--------------------------------------------------------------------------------
/tests/unit/src/circular-init/b.js:
--------------------------------------------------------------------------------
1 | import C from './c';
2 |
3 | function B() {
4 | console.log('B');
5 | }
6 |
7 | B.prototype.createC = function() {
8 | return new C();
9 | };
10 |
11 | export default B;
12 |
--------------------------------------------------------------------------------
/tests/unit/src/circular-init/c.js:
--------------------------------------------------------------------------------
1 | import B from './b';
2 |
3 | function C() {
4 | B.call(this);
5 | console.log('C');
6 | }
7 |
8 | C.prototype = Object.create(B.prototype);
9 | C.prototype.constructor = C;
10 |
11 | export default C;
12 |
--------------------------------------------------------------------------------
/tests/unit/src/fixtures/bar.js:
--------------------------------------------------------------------------------
1 | import foo from "./foo";
2 |
3 | export default function (a, b) {
4 | return foo(a, b);
5 | };
6 |
7 | export function multi () {
8 | return foo.apply(this, arguments);
9 | }
10 |
--------------------------------------------------------------------------------
/tests/unit/src/fixtures/baz.js:
--------------------------------------------------------------------------------
1 | import simple from "./bar";
2 | import {multi} from "./bar";
3 |
4 | class Baz {
5 |
6 | constructor(config) {
7 | this.config = config;
8 | }
9 |
10 | simple(a, b) {
11 | let r = simple(a, b);
12 | return r;
13 | }
14 |
15 | multi() {
16 | return multi.apply(this, arguments);
17 | }
18 |
19 | };
20 |
21 | export default Baz;
22 |
--------------------------------------------------------------------------------
/tests/unit/src/fixtures/foo.js:
--------------------------------------------------------------------------------
1 |
2 | var foo = { something: 1};
3 |
4 | export default function () {
5 | var n = 0;
6 | Array.prototype.slice(arguments).forEach(function (v) {
7 | n += v;
8 | });
9 | return n;
10 | };
11 |
--------------------------------------------------------------------------------
/tests/unit/src/live/a.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import { counter, increment, decrement } from "./b";
4 |
5 | export function up () {
6 | increment();
7 | return counter;
8 | }
9 |
10 | export function down () {
11 | decrement();
12 | return counter;
13 | }
14 |
15 | export function current () {
16 | return counter;
17 | }
18 |
--------------------------------------------------------------------------------
/tests/unit/src/live/b.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | export var counter = 0;
4 |
5 | export function increment () {
6 | counter++;
7 | }
8 |
9 | export function decrement () {
10 | counter--;
11 | }
12 |
--------------------------------------------------------------------------------
/tests/unit/src/others/evens.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import { nextOdd } from './odds';
4 |
5 | /**
6 | * We go through these gymnastics to eager-bind to nextOdd. This is done to
7 | * ensure that both this module and the 'odds' module eagerly use something
8 | * from the other.
9 | */
10 | export var nextEven = (function() {
11 | return function(n) {
12 | var no = nextOdd(n);
13 | return (no === n + 2) ?
14 | no - 1 : no;
15 | };
16 | })(nextOdd);
17 |
18 | export function isEven(n) {
19 | return n % 2 === 0;
20 | }
21 |
--------------------------------------------------------------------------------
/tests/unit/src/others/odds.js:
--------------------------------------------------------------------------------
1 | /* jshint esnext:true */
2 |
3 | import { isEven } from './evens';
4 |
5 | export function nextOdd(n) {
6 | return isEven(n) ? n + 1 : n + 2;
7 | }
8 |
9 | /**
10 | * We go through these gymnastics to eager-bind to isEven. This is done to
11 | * ensure that both this module and the 'evens' module eagerly use something
12 | * from the other.
13 | */
14 | export var isOdd = (function(isEven) {
15 | return function(n) {
16 | return !isEven(n);
17 | };
18 | })(isEven);
19 |
--------------------------------------------------------------------------------
/tests/unit/system-live-test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, beforeEach */
2 | 'use strict';
3 |
4 | var System = require('../../'),
5 | expect = require('chai').expect;
6 |
7 | describe('System', function() {
8 |
9 | it('.import() should be a function', function() {
10 | expect(System.import).to.be.a('function');
11 | });
12 |
13 | describe('import("tests/unit/build/live/a")', function() {
14 |
15 | it('should support a live counter', function(next) {
16 | var p = System.import("tests/unit/build/live/a");
17 | p.then(function (a) {
18 | expect(a.up).to.be.a('function');
19 | expect(a.down).to.be.a('function');
20 | expect(a.current).to.be.a('function');
21 | expect(a.current()).to.be.a('number').equal(0);
22 | // testing live bindings
23 | a.up();
24 | a.up();
25 | expect(a.current()).to.be.a('number').equal(2);
26 | a.down();
27 | expect(a.current()).to.be.a('number').equal(1);
28 | next();
29 | }).catch(next);
30 | });
31 |
32 | it('should maintain the state after second import() call', function(next) {
33 | var p = System.import("tests/unit/build/live/a");
34 | p.then(function (a) {
35 | expect(a.up).to.be.a('function');
36 | expect(a.down).to.be.a('function');
37 | expect(a.current).to.be.a('function');
38 | expect(a.current()).to.be.a('number').equal(1);
39 | next();
40 | }).catch(next);
41 | });
42 |
43 | });
44 |
45 | });
46 |
--------------------------------------------------------------------------------
/tests/unit/system.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, beforeEach */
2 | 'use strict';
3 |
4 | var System = require('../../'),
5 | expect = require('chai').expect;
6 |
7 | describe('System', function() {
8 |
9 | it('.import() should be a function', function() {
10 | expect(System.import).to.be.a('function');
11 | });
12 |
13 | it('.has() should be a function', function() {
14 | expect(System.has).to.be.a('function');
15 | });
16 |
17 | it('.get() should be a function', function() {
18 | expect(System.get).to.be.a('function');
19 | });
20 |
21 | it('.register() should be a function', function() {
22 | expect(System.register).to.be.a('function');
23 | });
24 |
25 | });
26 |
--------------------------------------------------------------------------------