Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

es6-module-loader

Package Overview
Dependencies
Maintainers
2
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

es6-module-loader - npm Package Compare versions

Comparing version 0.3.3 to 0.4.0

1818

lib/es6-module-loader.js
/*
* es6-module-loader
* https://github.com/addyosmani/es6-module-loader
* ES6 Module Loader Polyfill
* https://github.com/ModuleLoader/es6-module-loader
*
* Based on the 2013-12-02 specification draft
* System loader based on example implementation as of 2013-12-03
*
* Copyright (c) 2013 Guy Bedford, Luke Hoban, Addy Osmani
* Licensed under the MIT license.
*
*/
/*
ToDo
- Traceur ModuleTransformer update for new system
- getImports to use visitor pattern
- Loader Iterator support
- System ondemand functionality
- Tracking these and spec issues with 'NB' comments in this code
*/
(function () {
(function() {
var isBrowser = typeof window != 'undefined';
var global = isBrowser ? window : exports;
var global = isBrowser ? window : this;
var exports = isBrowser ? window : module.exports;
var defineProperty = function(obj, prop, opt) {
var nextTick = isBrowser ? function(fn) { setTimeout(fn, 1); } : process.nextTick;
/*
*********************************************************************************************
Simple Promises A+ Implementation
Adapted from https://github.com/RubenVerborgh/promiscuous
Copyright 2013 Ruben Verborgh
*********************************************************************************************
*/
var Promise = (function(nextTick) {
function createDeferred() {
// The `handler` variable points to the function that will
// 1) handle a .then(onFulfilled, onRejected) call
// 2) handle a .resolve or .reject call (if not fulfilled)
// Before 2), `handler` holds a queue of callbacks.
// After 2), `handler` is a simple .then handler.
// We use only one function to save memory and complexity.
var handler = function handlerFunction(onFulfilled, onRejected, value) {
// Case 1) handle a .then(onFulfilled, onRejected) call
if (onFulfilled !== Promise) {
var d = createDeferred();
handlerFunction.c.push({ d: d, resolve: onFulfilled, reject: onRejected });
return d.promise;
}
// Case 2) handle a .resolve or .reject call
// (`onFulfilled` acts as a sentinel)
// The actual function signature is
// .re[ject|solve](sentinel, success, value)
// Check if the value is a promise and try to obtain its `then` method
var then;
if (value !== null && (typeof value === 'object' || typeof value === 'function')) {
try { then = value.then; }
catch (reason) { onRejected = false; value = reason; }
}
// If the value is a promise, take over its state
if (typeof then === 'function') {
// Make a local copy of the _current_ handler
onFulfilled = handler;
try {
then.call(this, function (value) {
then && (then = null, onFulfilled(Promise, true, value));
},
function (reason) {
then && (then = null, onFulfilled(Promise, false, reason));
});
}
catch (reason) {
then && (then = null, onFulfilled(Promise, false, reason));
}
}
// The value is not a promise; handle resolve/reject
else {
var action = onRejected ? 'resolve' : 'reject', queue = handlerFunction.c;
for (var i = 0, l = queue.length; i < l; i++) {
var c = queue[i], deferred = c.d, callback = c[action];
// If no callback, just fulfill the promise
if (typeof callback !== 'function')
deferred[action](value);
// Otherwise, fulfill the promise with the result of the callback
else
execute(callback, value, deferred);
}
// Replace this handler with a simple resolved or rejected handler
handler = createHandler(promise, value, onRejected);
}
},
promise = {
then: function (onFulfilled, onRejected) {
return handler(onFulfilled, onRejected);
}
};
// The queue of deferreds
handler.c = [];
return {
promise: promise,
// Only resolve / reject when there is a deferreds queue
resolve: function (value) { handler.c && handler(Promise, true, value); },
reject : function (reason) { handler.c && handler(Promise, false, reason); }
};
}
// Creates a fulfilled or rejected .then function
function createHandler(promise, value, success) {
return function (onFulfilled, onRejected) {
var callback = success ? onFulfilled : onRejected, result;
if (typeof callback !== 'function')
return promise;
execute(callback, value, result = createDeferred());
return result.promise;
};
}
// Executes the callback with the specified value,
// resolving or rejecting the deferred
function execute(callback, value, deferred) {
nextTick(function () {
try {
// Return the result if it's not a promise
var result = callback(value),
then = (result !== null && (typeof result === 'object' || typeof result === 'function')) && result.then;
if (typeof then !== 'function')
deferred.resolve(result);
// If it's a promise, make sure it's not circular
else if (result === deferred.promise)
deferred.reject(new TypeError());
// Take over the promise's state
else
then.call(result, deferred.resolve, deferred.reject);
}
catch (error) {
deferred.reject(error);
}
});
}
function Promise(fn) {
var defer = createDeferred();
try {
fn(defer.resolve, defer.reject);
}
catch(e) {
defer.reject(e);
}
return defer.promise;
}
// Returns a resolved promise
Promise.resolve = function(value) {
var promise = {};
promise.then = createHandler(promise, value, true);
return promise;
}
// Returns a rejected promise
Promise.reject = function(reason) {
var promise = {};
promise.then = createHandler(promise, reason, false);
return promise;
}
// Returns a deferred
Promise.deferred = createDeferred;
Promise.all = function(promises) {
var defer = createDeferred();
if (!promises.length)
nextTick(defer.resolve);
var outputs = [];
var resolved = 0;
var rejected = false;
for (var i = 0, l = promises.length; i < l; i++) (function(i) {
promises[i].then(function(resolvedVal) {
outputs[i] = resolvedVal;
resolved++;
if (resolved == promises.length)
defer.resolve(outputs);
}, rejected);
})(i);
function rejected(exception) {
if (!rejected) {
rejected = true;
defer.reject(exception);
}
}
return defer.promise;
}
return Promise;
})(nextTick);
/*
*********************************************************************************************
Loader Polyfill
- Implemented exactly to the 2013-12-02 Specification Draft -
https://github.com/jorendorff/js-loaders/blob/e60d3651/specs/es6-modules-2013-12-02.pdf
with the only exceptions as described here
- Abstract functions have been combined where possible, and their associated functions
commented
- Declarative Module Support is entirely disabled, and an error will be thrown if
the instantiate loader hook returns undefined
- With this assumption, instead of Link, LinkDynamicModules is run directly
- ES6 support is thus provided through the translate function of the System loader
- EnsureEvaluated is removed, but may in future implement dynamic execution pending
issue - https://github.com/jorendorff/js-loaders/issues/63
- Realm implementation is entirely omitted. As such, Loader.global and Loader.realm
accessors will throw errors, as well as Loader.eval
- Loader module table iteration currently not yet implemented
*********************************************************************************************
*/
// Some Helpers
// logs a linkset snapshot for debugging
/* function snapshot(loader) {
console.log('\n');
for (var i = 0; i < loader._loads.length; i++) {
var load = loader._loads[i];
var linkSetLog = load.name + ' (' + load.status + '): ';
for (var j = 0; j < load.linkSets.length; j++) {
linkSetLog += '{'
linkSetLog += logloads(load.linkSets[j].loads);
linkSetLog += '} ';
}
console.log(linkSetLog);
}
console.log('\n');
}
function logloads(loads) {
var log = '';
for (var k = 0; k < loads.length; k++)
log += loads[k].name + (k != loads.length - 1 ? ' ' : '');
return log;
} */
function assert(name, expression) {
if (!expression)
console.log('Assertion Failed - ' + name);
}
function defineProperty(obj, prop, opt) {
if (Object.defineProperty)

@@ -21,4 +265,9 @@ Object.defineProperty(obj, prop, opt);

};
function preventExtensions(obj) {
if (Object.preventExtensions)
Object.preventExtensions(obj);
}
var indexOf = Array.prototype.indexOf || function (item) { // Define an IE-friendly shim good-enough for purposes
// Define an IE-friendly shim good-enough for purposes
var indexOf = Array.prototype.indexOf || function (item) {
for (var i = 0, thisLen = this.length; i < thisLen; i++) {

@@ -32,362 +281,474 @@ if (this[i] === item) {

// new Loader( options ) - Module loader constructor
// The Loader constructor creates a new loader. The argument is the
// options object
//
// options.global - The loader's global object
// options.intrinsics - The loader's intrinsic methods
// options.strict - should code evaluated in the loader be in strict mode?
// options.normalize( request [, referer] ) - normalize hook
// options.resolve( normalized, { referer, metadata } ) - The URL resolution hook
// options.fetch( resolved, fulfill, reject, { normalized, referer, metadata } ) - The module loading hook
// options.translate( source, { normalized, address, metadata, type } ) - source translation hook
// options.link( source, { normalized, address, metadata, type } ) - the link hook
function Loader(options) {
// Load Abstract Functions
// Initialization of loader state from options
function createLoad(name) {
return {
status: 'loading',
name: name,
metadata: {},
linkSets: []
};
}
this.global = options.global || window;
this.strict = !!options.strict;
this.normalize = options.normalize || global.System.normalize;
this.resolve = options.resolve || global.System.resolve;
this.fetch = options.fetch || global.System.fetch;
this.translate = options.translate || global.System.translate;
this.link = options.link || global.System.link;
// promise for a load record, can be in registry, already loading, or not
function requestLoad(loader, request, refererName, refererAddress) {
return Promise(function(resolve) {
// CallNormalize
resolve(loader.normalize(request, refererName, refererAddress));
})
// The internal table of module instance objects
this._mios = {};
// GetOrCreateLoad
.then(function(name) {
var load;
if (loader._modules[name]) {
load = createLoad(name);
load.status = 'linked';
return load;
}
// the internal table of loaded scripts
this._sloaded = {};
// modules currently loading
// key is normalized name, value is an array of callback functions to be queued (optional)
this._mloads = {};
// scripts
this._sloads = {};
for (var i = 0, l = loader._loads.length; i < l; i++) {
load = loader._loads[i];
if (load.name == name) {
assert('loading or loaded', load.status == 'loading' || load.status == 'loaded');
return load;
}
}
// CreateLoad
load = createLoad(name);
loader._loads.push(load);
proceedToLocate(loader, load);
return load;
});
}
function proceedToLocate(loader, load) {
proceedToFetch(loader, load,
Promise.resolve()
// CallLocate
.then(function() {
return loader.locate({ name: load.name, metadata: load.metadata });
})
);
}
function proceedToFetch(loader, load, p) {
proceedToTranslate(loader, load,
p
// CallFetch
.then(function(address) {
if (load.linkSets.length == 0)
return undefined;
load.address = address;
return loader.fetch({ name: load.name, metadata: load.metadata, address: address });
})
);
}
function proceedToTranslate(loader, load, p) {
p
// CallTranslate
.then(function(source) {
if (load.linkSets.length == 0)
return undefined;
// Loader.prototype.load( address, callback, errback [, referer = null] )
//
// The load method takes a string representing a module URL and a
// callback that receives the result of loading, compiling, and
// executing the module at that URL. The compiled code is statically
// associated with this loader, and its URL is the given URL. The
// additional callback is used if an error occurs.
//
// load will handle import statements, but export statements are a
// syntax error
Loader.prototype.load = function (url, callback, errback) {
var self = this;
if (url instanceof Array) {
var scriptCnt = 0;
for (var i = 0; i < url.length; i++) (function (i) {
self.load(url[i], function () {
scriptCnt++;
if (scriptCnt == url.length) {
callback && callback();
}
}, errback)
})(i);
return;
}
return loader.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source })
})
if (this._sloaded[url]) {
callback && callback();
return;
}
// CallInstantiate
.then(function(source) {
if (load.linkSets.length == 0)
return undefined;
// store the callbacks in a load queue for multiple requests
if (this._sloads[url]) {
this._sloads[url].push({
callback: callback,
errback: errback
});
return;
}
else {
this._sloads[url] = [{
callback: callback,
errback: errback
}];
}
var _callback = function() {
for (var i = 0; i < self._sloads[url].length; i++)
self._sloads[url][i].callback && self._sloads[url][i].callback();
delete self._sloads[url];
}
var _errback = function(err) {
var allCalled = true;
for (var i = 0; i < self._sloads[url].length; i++) {
if (self._sloads[url][i].errback) {
self._sloads[url][i].errback(err);
}
else {
allCalled = false;
}
load.source = source;
return loader.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source });
})
// InstantiateSucceeded
.then(function(instantiateResult) {
if (load.linkSets.length == 0)
return undefined;
var depsList;
if (instantiateResult === undefined)
throw 'Declarative parsing is not implemented by the polyfill.';
else if (typeof instantiateResult == 'object') {
depsList = instantiateResult.deps || [];
load.execute = instantiateResult.execute;
load.kind = 'dynamic';
}
delete self._sloads[url];
// if any didn't have an error handler, throw
if (!allCalled)
throw err;
}
else
throw TypeError('Invalid instantiate return value');
this.fetch(url, function (source) {
var opt = {
address: url,
type: 'script'
};
source = self.translate(source, opt);
// ProcessLoadDependencies
load.dependencies = {};
var loadPromises = [];
for (var i = 0, l = depsList.length; i < l; i++) (function(request) {
var p = requestLoad(loader, request, load.name, load.address);
self._linkExecute(url, source, opt, _callback, _errback, true);
}, _errback);
};
// AddDependencyLoad (load is parentLoad)
p.then(function(depLoad) {
assert('not already a dependency', !load.dependencies[request]);
load.dependencies[request] = depLoad.name;
// Loader.prototype.import( name, callback, errback, referer = null )
// Asynchronously load a module or sequence of modules by name.
Loader.prototype['import'] = function (name, callback, errback, referer) {
var self = this;
if (name instanceof Array) {
var modules = [];
var moduleCnt = 0;
var self = this;
for (var i = 0; i < name.length; i++) (function(i) {
Loader.prototype['import'].call(self, name[i], function(m) {
modules[i] = m;
moduleCnt++;
if (moduleCnt == name.length) {
callback && callback.apply(null, modules);
if (depLoad.status != 'linked') {
var linkSets = load.linkSets.concat([]);
for (var i = 0, l = linkSets.length; i < l; i++)
addLoadToLinkSet(linkSets[i], depLoad);
}
}, errback, referer);
})(i);
return;
}
});
name = this.normalize(name, referer);
loadPromises.push(p);
})(depsList[i]);
var opt = {
referer: referer,
metadata: typeof name == 'object' ? name.metadata : null
};
// name is now the normalized name in this function
if (typeof name != 'string') {
name = name.normalized;
}
return Promise.all(loadPromises)
if (this._mios[name]) {
return callback && callback(this._mios[name]);
}
// LoadSucceeded
.then(function() {
assert('is loading', load.status == 'loading');
// store the callbacks in a load queue for multiple requests
if (this._mloads[name]) {
this._mloads[name].push({
callback: callback,
errback: errback
load.status = 'loaded';
// console.log('load succeeeded ' + load.name);
// snapshot(loader);
var linkSets = load.linkSets.concat([]);
for (var i = 0, l = linkSets.length; i < l; i++)
updateLinkSetOnLoad(linkSets[i], load);
});
return;
}
else {
this._mloads[name] = [{
callback: callback,
errback: errback
}];
}
var _callback = function(module) {
self._mios[name] = module;
for (var i = 0; i < self._mloads[name].length; i++)
self._mloads[name][i].callback && self._mloads[name][i].callback(module);
delete self._mloads[name];
}
var _errback = function(err) {
var allCalled = true;
if (!self._mloads[name])
throw err;
for (var i = 0; i < self._mloads[name].length; i++) {
if (self._mloads[name][i].errback) {
self._mloads[name][i].errback(err);
}
else {
allCalled = false;
}
}
delete self._mloads[name];
// if any didn't have an error handler, throw
if (!allCalled)
throw err;
}
// LoadFailed
, function(exc) {
assert('is loading on fail', load.status == 'loading');
load.status = 'failed';
load.exception = exc;
for (var i = 0, l = load.linkSets.length; i < l; i++)
linkSetFailed(load.linkSets[i], exc);
assert('fail linkSets removed', load.linkSets.length == 0);
});
}
var url = this.resolve(name, opt);
if (typeof url != 'string') {
url = url.address;
// NB what to do with 'extra'?
}
// LinkSet Abstract Functions
function createLinkSet(loader, startingLoad) {
var deferred = Promise.deferred();
var linkSet = {
loader: loader,
loads: [],
done: deferred.promise,
resolve: deferred.resolve,
reject: deferred.reject,
loadingCount: 0
};
addLoadToLinkSet(linkSet, startingLoad);
return linkSet;
}
function addLoadToLinkSet(linkSet, load) {
assert('loading or loaded on link set', load.status == 'loading' || load.status == 'loaded');
opt.normalized = name;
for (var i = 0, l = linkSet.loads.length; i < l; i++)
if (linkSet.loads[i] == load)
return;
this.fetch(url, function(source) {
opt.address = url;
opt.type = 'module';
source = self.translate(source, opt);
self._linkExecute(name, source, opt, _callback, _errback);
}, _errback, opt);
};
linkSet.loads.push(load);
load.linkSets.push(linkSet);
// Loader.prototype.fetch
// NB spec issue here - this clashes with the instance fetch function!?
if (load.status != 'loaded')
linkSet.loadingCount++;
// _linkExecute - private function
// given a normalized module name, the source, and the options metadata
// run the link and execute hooks, with the callback returning the
// defined module object
// isScript = true implies loading a script so don't define exports
var evalCnt = 0;
Loader.prototype._linkExecute = function (name, source, opt, callback, errback) {
var isScript = opt.type == 'script';
var loader = linkSet.loader;
var link = this.link(source, opt);
for (var dep in load.dependencies) {
var name = load.dependencies[dep];
// 1. module
if (link instanceof Module && !isScript) {
return callback(link);
if (loader._modules[name])
continue;
for (var i = 0, l = loader._loads.length; i < l; i++)
if (loader._loads[i].name == name) {
addLoadToLinkSet(linkSet, loader._loads[i]);
break;
}
}
// console.log('add to linkset ' + load.name);
// snapshot(linkSet.loader);
}
function updateLinkSetOnLoad(linkSet, load) {
// NB https://github.com/jorendorff/js-loaders/issues/85
// assert('no load when updated ' + load.name, indexOf.call(linkSet.loads, load) != -1);
assert('loaded or linked', load.status == 'loaded' || load.status == 'linked');
// preload esprima if necessary
var self = this;
var linkSpecified = typeof link == 'object' && !isScript;
(!linkSpecified ? ES6Parser.loadTraceur : function(name, source, callback) { callback(); }).call(ES6Parser, name, source, function() {
var imports, execute;
// 2. specified imports and execute
if (linkSpecified) {
imports = link.imports;
execute = link.execute;
}
// 3. undefined -> default
else {
var defaultLink = self._link(source, opt);
imports = defaultLink.imports;
execute = defaultLink.execute;
}
// console.log('update linkset on load ' + load.name);
// snapshot(linkSet.loader);
// stops an unnecessary load cascade
if (errback.called)
// see https://github.com/jorendorff/js-loaders/issues/80
linkSet.loadingCount--;
/* for (var i = 0; i < linkSet.loads.length; i++) {
if (linkSet.loads[i].status == 'loading') {
return;
}
} */
if (linkSet.loadingCount > 0)
return;
if (!imports.length)
return callback(execute.call(self));
var startingLoad = linkSet.loads[0];
try {
link(linkSet.loads, linkSet.loader);
}
catch(exc) {
return linkSetFailed(linkSet, exc);
}
opt.normalizeMap = {};
assert('loads cleared', linkSet.loads.length == 0);
linkSet.resolve(startingLoad);
}
function linkSetFailed(linkSet, exc) {
var loads = linkSet.loads.concat([]);
for (var i = 0, l = loads.length; i < l; i++) {
var load = loads[i];
var linkIndex = indexOf.call(load.linkSets, linkSet);
assert('link not present', linkIndex != -1);
load.linkSets.splice(linkIndex, 1);
if (load.linkSets.length == 0) {
var globalLoadsIndex = indexOf.call(linkSet.loader._loads, load);
if (globalLoadsIndex != -1)
linkSet.loader._loads.splice(globalLoadsIndex, 1);
}
}
linkSet.reject(exc);
}
function finishLoad(loader, load) {
// if not anonymous, add to the module table
if (load.name) {
assert('load not in module table', !loader._modules[load.name]);
loader._modules[load.name] = load.module;
}
var loadIndex = indexOf.call(loader._loads, load);
if (loadIndex != -1)
loader._loads.splice(loadIndex, 1);
for (var i = 0, l = load.linkSets.length; i < l; i++) {
loadIndex = indexOf.call(load.linkSets[i].loads, load);
load.linkSets[i].loads.splice(loadIndex, 1);
}
load.linkSets = [];
}
function loadModule(loader, name, options) {
return Promise(asyncStartLoadPartwayThrough(loader, name, options && options.address ? 'fetch' : 'locate', undefined, options && options.address, undefined)).then(function(load) {
return load;
});
}
function asyncStartLoadPartwayThrough(loader, name, step, meta, address, source) {
return function(resolve, reject) {
if (loader._modules[name])
throw new TypeError('Module "' + name + '" already exists in the module table');
for (var i = 0, l = loader._loads.length; i < l; i++)
if (loader._loads[i].name == name)
throw new TypeError('Module "' + name + '" is already loading');
var deps = [];
var depCnt = 0;
for (var i = 0; i < imports.length; i++) (function(i) {
var referer = { name: name, address: opt.address };
var load = createLoad(name);
// run the normalization to get the canonical module name
// to allow imports to be loaded
var normalized = self.normalize(imports[i], referer);
if (meta)
load.metadata = meta;
if (typeof normalized == 'object')
normalized = normalized.normalized;
var linkSet = createLinkSet(loader, load);
opt.normalizeMap[imports[i]] = normalized;
loader._loads.push(load);
Loader.prototype['import'].call(self, imports[i], function (module) {
depCnt++;
deps[i] = module;
if (depCnt == imports.length) {
var output = execute.apply(self, deps);
callback(output);
}
}, errback, referer);
})(i);
// NB spec change as in https://github.com/jorendorff/js-loaders/issues/79
linkSet.done.then(resolve, reject);
}, errback);
};
if (step == 'locate')
proceedToLocate(loader, load);
Loader.prototype._link = function(source, opt) {
if (!isBrowser)
ES6Parser.loadTraceur(opt.normalized, source, function(){}, function(){});
var self = this;
return {
imports: ES6Parser.parseImports(source, opt),
execute: function() {
var exports;
// parses export statements and evaluates in the correct context
// returning the exports object
exports = ES6Parser.parseEval(source, self, {
name: opt.normalized,
sourceURL: opt.address,
isEval: opt.type == 'script',
normalizeMap: opt.normalizeMap
});
// only return exports for a module when not doing script eval
if (opt.normalized && opt.type != 'script')
return new Module(exports || {});
else if (step == 'fetch')
proceedToFetch(loader, load, Promise.resolve(address));
else {
assert('translate step', step == 'translate');
load.address = address;
proceedToTranslate(loader, load, Promise.resolve(source));
}
};
}
}
function evaluateLoadedModule(loader, load) {
assert('is linked ' + load.name, load.status == 'linked');
assert('is a module', load.module instanceof Module);
// Loader.prototype.eval( source )
// Synchronously executes a Script non-terminal.
// If the compilation process results in a fetch, a SyntaxError is thrown.
// The compiled code is statically associated with this loader.
Loader.prototype.eval = function (source) {
ES6Parser.parseEval(source, this, {
isEval: true
});
};
// ensureEvaluated(load.module, [], loader);
// Loader.prototype.parseEval( source )
// Asynchronously executes a Script non-terminal.
// The compiled code is statically associated with this loader.
Loader.prototype.evalAsync = function(source, callback, errback) {
// links and then evals
// when no name is given,
// provide a unique name to cache the syntax tree parsing
var name = '__eval' + evalCnt++;
ES6Parser.parseNames[name] = true;
return load.module;
}
// Module Object
function Module(obj) {
if (typeof obj != 'object')
throw new TypeError('Expected object');
var self = this;
ES6Parser.loadTraceur(name, source, function() {
self._linkExecute(null, source, { type: 'script', address: name, normalized: name }, callback || function() {}, errback || function() {});
}, errback);
for (var key in obj) {
(function (key, value) {
defineProperty(self, key, {
configurable: false,
enumerable: true,
get: function () {
return value;
}
});
})(key, obj[key]);
}
preventExtensions(self);
}
// Module.prototype = null;
// Loader.prototype.get ( name )
//
// Look up a module in the loader’s registry, using a name that is assumed
// to be normalized.
Loader.prototype.get = function (name) {
return this._mios[name] || null;
};
// Linking
// Link is directly LinkDynamicModules assuming all modules are dynamic
function link(loads, loader) {
// console.log('linking {' + logloads(loads) + '}');
// Loader.prototype.set( name, mod )
//
// Stores (possibly overwriting) a module instance object
// in the loader’s registry, using a name that is assumed to be normalized.
Loader.prototype.set = function (name, mod) {
this._mios[name] = new Module(mod);
};
// continue until all linked
// NB circular dependencies will stall this loop
var loopCnt = 0;
while (loads.length) {
loopCnt++;
// search through to find a load with all its dependencies linked
search: for (var i = 0; i < loads.length; i++) {
var load = loads[i];
var depModules = [];
for (var d in load.dependencies) {
var dep = load.dependencies[d];
// being in the module table means it is linked
var depModule = loader._modules[dep];
if (!depModule)
continue search;
depModules.push(depModule);
}
Loader.prototype.has = function (name) {
return !!this._mios[name];
};
// all dependencies linked now, so we can execute
var module = load.execute.apply(null, depModules);
if (!(module instanceof Module))
throw new TypeError('Execution must define a Module instance');
load.module = module;
load.status = 'linked';
finishLoad(loader, load);
}
if (loopCnt === 1000) {
console.log('Circular Dependency Detected');
return;
}
}
// console.log('linked');
}
Loader.prototype['delete'] = function (name) {
delete this._mios[name];
};
// Loader
function Loader(options) {
if (typeof options != 'object')
throw new TypeError('Options must be an object');
// Loader.prototype.defineBuiltins( [ obj ] )
//
// The defineBuiltins method takes an object and defines all the built-in
// objects and functions of the ES6 standard library associated with this
// loader's intrinsics as properties on the object.
Loader.prototype.defineBuiltins = function (o) {
for (var p in o) {
if (o.hasOwnProperty(p)) {
this.global[p] = o[p];
if (options.normalize)
this.normalize = options.normalize;
if (options.locate)
this.locate = options.locate;
if (options.fetch)
this.fetch = options.fetch;
if (options.translate)
this.translate = options.translate;
if (options.instantiate)
this.instantiate = options.instantiate;
defineProperty(this, 'global', {
get: function() {
throw new TypeError('global accessor not provided by polyfill');
}
});
defineProperty(this, 'realm', {
get: function() {
throw new TypeError('Realms not implemented in polyfill');
}
});
this._modules = {};
this._loads = [];
}
// NB importPromises hacks ability to import a module twice without error - https://github.com/jorendorff/js-loaders/issues/60
var importPromises = {};
Loader.prototype = {
define: function(name, source, options) {
if (importPromises[name])
throw new TypeError('Module is already loading.');
importPromises[name] = Promise(asyncStartLoadPartwayThrough(this, name, 'translate', options && options.meta || {}, options && options.address, source));
return importPromises[name].then(function() { delete importPromises[name]; });
},
load: function(request, options) {
if (importPromises[name])
return importPromises[name];
importPromises[name] = loadModule(this, request, options);
return importPromises[name].then(function() { delete importPromises[name]; })
},
module: function(source, options) {
var load = createLoad();
load.address = options && options.address;
var linkSet = createLinkSet(this, load);
var sourcePromise = Promise.resolve(source);
var p = linkSet.done.then(function() {
evaluateLoadedModule(this, load);
});
proceedToTranslate(this, load, sourcePromise);
return p;
},
import: function(name, options) {
if (this._modules[name])
return Promise.resolve(this._modules[name]);
return (importPromises[name] || (importPromises[name] = loadModule(this, name, options)))
.then(function(load) {
delete importPromises[name];
return evaluateLoadedModule(this, load);
});
},
eval: function(source) {
throw new TypeError('Eval not implemented in polyfill')
},
get: function(key) {
return this._modules[key];
},
has: function(name) {
return !!this._modules[name];
},
set: function(name, module) {
if (!(module instanceof Module))
throw new TypeError('Set must be a module');
this._modules[name] = module;
},
delete: function(name) {
return this._modules[name] ? delete this._modules[name] : false;
},
// NB implement iterations
entries: function() {
throw new TypeError('Iteration not yet implemented in the polyfill');
},
keys: function() {
throw new TypeError('Iteration not yet implemented in the polyfill');
},
values: function() {
throw new TypeError('Iteration not yet implemented in the polyfill');
},
normalize: function(name, refererName, refererAddress) {
return name;
},
locate: function(load) {
return load.name;
},
fetch: function(load) {
throw new TypeError('Fetch not implemented');
},
translate: function(load) {
return load.source;
},
instantiate: function(load) {
}

@@ -397,33 +758,74 @@ };

function Module (o) {
/*
*********************************************************************************************
if (typeof o != 'object') throw new TypeError("Expected object");
if (o instanceof Module) {
return o;
} else {
var self = this;
for (var key in o) {
(function (key) {
defineProperty(self, key, {
configurable: false,
enumerable: true,
get: function () {
return o[key];
}
});
})(key);
}
}
};
System Loader Implementation
- Implemented to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js,
except for Instantiate function
// Pre-configured Loader instance for easier use
var absUrlRegEx = /^\/|([^\:\/]*:\/\/)/;
var isAbsoluteUrl = function(name) {
return name.match(absUrlRegEx);
- Instantiate function determines if ES6 module syntax is being used, if so parses with
Traceur and returns a dynamic InstantiateResult for loading ES6 module syntax in ES5.
- Custom loaders thus can be implemented by using this System.instantiate function as
the fallback loading scenario, after other module format detections.
- Traceur is loaded dynamically when module syntax is detected by a regex (with over-
classification), either from require('traceur') on the server, or the
'data-traceur-src' property on the current script in the browser, or if not set,
'traceur.js' in the same URL path as the current script in the browser.
- ondemand / paths functionality currently not yet implemented
- <script type="module"> supported, but <module> tag not
*********************************************************************************************
*/
// Helpers
// Absolute URL parsing, from https://gist.github.com/Yaffle/1088850
function parseURI(url) {
var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
// authority = '//' + user + ':' + pass '@' + hostname + ':' port
return (m ? {
href : m[0] || '',
protocol : m[1] || '',
authority: m[2] || '',
host : m[3] || '',
hostname : m[4] || '',
port : m[5] || '',
pathname : m[6] || '',
search : m[7] || '',
hash : m[8] || ''
} : null);
}
var fetch;
function toAbsoluteURL(base, href) {
function removeDotSegments(input) {
var output = [];
input.replace(/^(\.\.?(\/|$))+/, '')
.replace(/\/(\.(\/|$))+/g, '/')
.replace(/\/\.\.$/, '/../')
.replace(/\/?[^\/]*/g, function (p) {
if (p === '/..')
output.pop();
else
output.push(p);
});
return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
}
href = parseURI(href || '');
base = parseURI(base || '');
return !href || !base ? null : (href.protocol || base.protocol) +
(href.protocol || href.authority ? href.authority : base.authority) +
removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
href.hash;
}
var fetchTextFromURL;
if (isBrowser) {
fetch = function(url, fulfill, reject) {
fetchTextFromURL = function(url, fulfill, reject) {
var xhr = new XMLHttpRequest();

@@ -458,3 +860,3 @@ if (!('withCredentials' in xhr)) {

var fs = require('fs');
fetch = function(url, fulfill, reject) {
fetchTextFromURL = function(url, fulfill, reject) {
return fs.readFile(url, function(err, data) {

@@ -469,420 +871,431 @@ if (err)

// '../a/b', '../c/d/e' -> '../c/a/b'
var resolvePath = function(name, parentName) {
if (!parentName)
return name;
var System = new Loader({
global: isBrowser ? window : global,
strict: true,
normalize: function(name, parentName, parentAddress) {
if (typeof name != 'string')
throw new TypeError('Module name must be a string');
// all resolutions in this function are relative
if (name.substr(0, 2) == './')
name = name.substr(2);
var segments = name.split('/');
// anything after the last slash is assumed a file name
var lastSlash = parentName.lastIndexOf('/');
if (lastSlash == -1)
return name;
if (lastSlash != parentName.length - 1)
parentName = parentName.substr(0, lastSlash + 1);
if (segments.length == 0)
throw new TypeError('No module name provided');
// simple additive resolution (most cases)
if (name.substr(0, 1) != '.')
return parentName + name;
// current segment
var i = 0;
// is the module name relative
var rel = false;
// number of backtracking segments
var dotdots = 0;
if (segments[0] == '.') {
i++;
if (i == segments.length)
throw new TypeError('Illegal module name "' + name + '"');
rel = true;
}
else {
while (segments[i] == '..') {
i++;
if (i == segments.length)
throw new TypeError('Illegal module name "' + name + '"');
}
if (i)
rel = true;
dotdots = i;
}
// begin backtracking
var parentParts = parentName.split('/');
var nameParts = name.split('/');
for (var j = i; j < segments.length; j++) {
var segment = segments[j];
if (segment == '' || segment == '.' || segment == '..')
throw new TypeError('Illegal module name"' + name + '"');
}
parentParts.pop();
if (!rel)
return name;
var curPart;
while (nameParts[0] == '..') {
curPart = nameParts.shift();
if (!parentParts.length || parentParts[parentParts.length - 1] == '..')
parentParts.push('..');
else
parentParts.pop();
}
// build the full module name
var normalizedParts = [];
var parentParts = (parentName || '').split('/');
var normalizedLen = parentParts.length - 1 - dotdots;
return parentParts.join('/') + (parentParts.length ? '/' : '') + nameParts.join('/');
}
normalizedParts = normalizedParts.concat(parentParts.splice(0, parentParts.length - 1 - dotdots));
normalizedParts = normalizedParts.concat(segments.splice(i));
var defaultSystemLoader = new Loader({
global: isBrowser ? window : global,
strict: true,
normalize: function(name, referer) {
if (isAbsoluteUrl(name))
return name;
if (name.substr(0, 1) == '.')
return resolvePath(name, referer && referer.name);
else
return name;
return normalizedParts.join('/');
},
resolve: function (name, options) {
for (var r in this.ondemandTable) {
if (indexOf.call(this.ondemandTable[r], name) != -1) {
return r;
}
}
if (isAbsoluteUrl(name))
return name;
return resolvePath(name + '.js', this.baseURL + (this.baseURL.charAt(this.baseURL.length - 1) != '/' ? '/' : ''));
locate: function(load) {
// NB Implement System.ondemand here
return toAbsoluteURL(this.baseURL, escape(load.name + '.js'));
},
fetch: fetch,
translate: function (source, options) {
return source;
fetch: function(load) {
var defer = Promise.deferred();
fetchTextFromURL(toAbsoluteURL(this.baseURL, load.address), defer.resolve, defer.reject);
return defer.promise;
},
link: function (source, options) {}
});
instantiate: function(load) {
// normal eval (non-module code)
// note that anonymous modules (load.name == undefined) are always
// anonymous <module> tags, so we use Traceur for these
if (load.metadata.es6 === false || (load.name && !load.source.match(es6RegEx)))
return {
deps: [],
execute: function() {
__scopedEval(load.source, global, load.address);
defaultSystemLoader.baseURL = isBrowser ? window.location.href.substring(0, window.location.href.lastIndexOf('\/') + 1) : './';
defaultSystemLoader.ondemandTable = {};
defaultSystemLoader.ondemand = function (ondemandTable) {
for (var r in ondemandTable) {
this.ondemandTable[r] = this.ondemandTable[r] || [];
if (ondemandTable[r] instanceof Array)
this.ondemandTable[r] = this.ondemandTable[r].concat(ondemandTable[r]);
else
this.ondemandTable[r].push(ondemandTable[r]);
}
}
// when loading traceur, it overwrites the System
// global. The only way to synchronously ensure it is
// reverted in time not to cause issue is here
if (load.name == 'traceur' && isBrowser) {
global.traceur = global.System.get('../src/traceur.js');
global.System = System;
}
// return an empty module
return new Module({});
}
};
// ES6 -> ES5 conversion
// Syntax Parsing and Source Modifying Polyfills
// Traceur-based parser for module syntax, with pluggable polyfill support
var traceurSrc;
var ES6Parser = {
// iterate the entire syntax tree node object with the given iterator function
traverse: function(object, iterator, parent, parentProperty) {
var key, child;
if (iterator(object, parent, parentProperty) === false)
return;
for (key in object) {
if (!object.hasOwnProperty(key))
continue;
if (key == 'location' || key == 'type')
continue;
child = object[key];
if (typeof child == 'object' && child !== null)
this.traverse(child, iterator, object, key);
}
},
// module syntax regexs - may over-classify but not under-classify
// simply designed as a first level check to catch any use of
// module syntax, before loading Traceur for deeper analysis
es6RegEx: /(?:^\s*|[}{\(\);,\n]\s*)((import|module)\s+[^"']+\s+from\s+['"]|export\s+(\*|\{|default|function|var|const|let|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))/,
checkModuleSyntax: function(name, source) {
if (name == null || this.parseNames[name] === undefined)
this.parseNames[name] = source && !!source.match(this.es6RegEx);
return this.parseNames[name];
},
loadTraceur: function(name, source, callback, errback) {
if (this.traceur)
return callback();
var loader = this;
load.address = load.address || 'anonymous-module-' + anonCnt++;
// load traceur and the module transformer
return getTraceur()
.then(function(traceur) {
// use a regex to check if the source contains 'import', 'export' or 'module' statements
// may incorrectly fire, but the damage is only an http request to do better parsing shortly
if (!this.checkModuleSyntax(name, source))
return callback();
traceur.options.sourceMaps = true;
traceur.options.modules = 'parse';
// traceur.options.blockBinding = true;
// current script tags used to produce the Traceur src (converting collection to array)
if (isBrowser) {
var scripts = document.getElementsByTagName('script');
var reporter = new traceur.util.ErrorReporter();
var curScript;
for (var i = 0; i < scripts.length; i++) {
curScript = scripts[i];
if (curScript.src.match(/es6-module-loader(\.min)?\.js/))
traceurSrc = curScript.src.substr(0, curScript.src.lastIndexOf('/') + 1) + 'traceur.js';
else
traceurSrc = curScript.getAttribute('data-traceur-src');
if (traceurSrc)
break;
reporter.reportMessageInternal = function(location, kind, format, args) {
throw kind + '\n' + location;
}
}
var self = this;
var System = global.System;
(isBrowser ? global.System.load : function(src, callback) {
self.traceur = require('traceur');
callback();
}).call(global.System, traceurSrc, function() {
if (isBrowser) {
if (self.traceur)
return callback();
else
self.traceur = global.System.get('../src/traceur.js');
}
var parser = new traceur.syntax.Parser(reporter, new traceur.syntax.SourceFile(load.address, load.source));
self.traceur.options.sourceMaps = true;
self.traceur.options.modules = 'parse';
var tree = parser.parseModule();
self.reporter = new self.traceur.util.ErrorReporter();
self.reporter.reportMessageInternal = function(location, kind, format, args) {
throw kind + '\n' + location;
}
self.createModuleLoaderTransformer(
self.traceur.codegeneration.ParseTreeFactory,
self.traceur.codegeneration.ParseTreeTransformer
);
var imports = getImports(tree);
global.System = System;
callback();
return {
deps: imports,
execute: function() {
// write dependencies as unique globals
// creating a map from the unnormalized import name to the unique global name
var globalMap = {};
for (var i = 0; i < arguments.length; i++) {
var name = '__moduleDependency' + i;
global[name] = arguments[i];
globalMap[imports[i]] = name;
}
// transform
var transformer = new traceur.codegeneration.FromOptionsTransformer(reporter);
transformer.append(function(tree) {
return new traceur.codegeneration.ModuleLoaderTransformer(globalMap, '__exports').transformAny(tree);
});
tree = transformer.transform(tree);
// convert back to a source string
var sourceMapGenerator = new traceur.outputgeneration.SourceMapGenerator({ file: load.address });
var options = { sourceMapGenerator: sourceMapGenerator };
source = traceur.outputgeneration.TreeWriter.write(tree, options);
if (isBrowser)
source += '\n//# sourceMappingURL=data:application/json;base64,' + btoa(options.sourceMap) + '\n';
global.__exports = {};
__scopedEval(source, global, load.address);
var exports = global.__exports;
delete global.__exports;
for (var i = 0; i < arguments.length; i++)
delete global['__moduleDependency' + i];
return new Module(exports);
}
};
});
},
createModuleLoaderTransformer: function(ParseTreeFactory, ParseTreeTransformer) {
var createAssignmentExpression = ParseTreeFactory.createAssignmentExpression;
var createVariableDeclaration = ParseTreeFactory.createVariableDeclaration;
}
});
// count anonymous evals to have unique name
var anonCnt = 1;
System.baseURL = isBrowser ? window.location.href.substring(0, window.location.href.lastIndexOf('\/') + 1).split('#')[0] : './';
// ES6 to ES5 parsing functions
// comprehensively overclassifying regex detectection for es6 module syntax
var es6RegEx = /(?:^\s*|[}{\(\);,\n]\s*)((import|module)\s+[^"']+\s+from\s+['"]|export\s+(\*|\{|default|function|var|const|let|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))/;
// dynamically load traceur when needed
// populates the traceur, reporter and moduleLoaderTransfomer variables
// NB we need to queue getTraceur callbacks due to https://github.com/jorendorff/js-loaders/issues/60
var traceur, traceurPromise;
function getTraceur() {
if (traceur)
return Promise.resolve(traceur);
if (traceurPromise)
return traceurPromise;
return traceurPromise = (isBrowser ? exports.System.import : function(name, src, callback) {
return Promise.resolve(require('traceur'));
}).call(exports.System, 'traceur', { address: traceurSrc }).then(function(_traceur) {
traceurPromise = null;
var createMemberExpression = ParseTreeFactory.createMemberExpression;
var createCallExpression = ParseTreeFactory.createCallExpression;
if (isBrowser)
_traceur = global.traceur;
var createVariableDeclarationList = ParseTreeFactory.createVariableDeclarationList;
var createArgumentList = ParseTreeFactory.createArgumentList;
var createStringLiteral = ParseTreeFactory.createStringLiteral;
var createIdentifierExpression = ParseTreeFactory.createIdentifierExpression;
traceur = _traceur;
var createMemberLookupExpression = ParseTreeFactory.createMemberLookupExpression;
traceur.codegeneration.ModuleLoaderTransformer = createModuleLoaderTransformer(
traceur.codegeneration.ParseTreeFactory,
traceur.codegeneration.ParseTreeTransformer
);
var createCommaExpression = ParseTreeFactory.createCommaExpression;
var createVariableStatement = ParseTreeFactory.createVariableStatement;
return traceur;
});
}
var createAssignmentStatement = ParseTreeFactory.createAssignmentStatement;
var createExpressionStatement = ParseTreeFactory.createExpressionStatement;
// NB update to new transformation system
function createModuleLoaderTransformer(ParseTreeFactory, ParseTreeTransformer) {
var createAssignmentExpression = ParseTreeFactory.createAssignmentExpression;
var createVariableDeclaration = ParseTreeFactory.createVariableDeclaration;
var createCallExpression = ParseTreeFactory.createCallExpression;
// var VARIABLE = __Loader.get('MODULE_NAME')['VALUE'], ...
// var VARIABLE = __Loader.get('MODULE_NAME'), ...
var createModuleVariableDeclaration = function(moduleName, variables, values, location) {
var variableDeclarations = variables.map(function(variable, i) {
return createVariableDeclaration(variable, createImportExpression(moduleName, values[i]));
});
var varList = createVariableDeclarationList('var', variableDeclarations);
varList.location = location;
return createVariableStatement(varList);
}
var createVariableDeclarationList = ParseTreeFactory.createVariableDeclarationList;
var createStringLiteral = ParseTreeFactory.createStringLiteral;
var createIdentifierExpression = ParseTreeFactory.createIdentifierExpression;
// __Loader.get('MODULE_NAME')['VALUE']
var createImportExpression = function(moduleName, value) {
var expression = createCallExpression(
createMemberExpression('__Loader', 'get'),
createArgumentList([createStringLiteral(moduleName)])
);
return value ? createMemberLookupExpression(expression, createStringLiteral(value)) : expression;
}
var createMemberLookupExpression = ParseTreeFactory.createMemberLookupExpression;
// __exports['EXPORT_NAME']
var createExportExpression = function(exportName) {
return createMemberLookupExpression(createIdentifierExpression('__exports'), createStringLiteral(exportName));
}
var createCommaExpression = ParseTreeFactory.createCommaExpression;
var createVariableStatement = ParseTreeFactory.createVariableStatement;
var createAssignmentStatement = ParseTreeFactory.createAssignmentStatement;
var createExpressionStatement = ParseTreeFactory.createExpressionStatement;
var self = this;
var ModuleLoaderTransformer = function(globalMap, exportGlobal) {
this.depMap = globalMap;
this.exportGlobal = exportGlobal;
}
ModuleLoaderTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
// var VARIABLE = __moduleDependencyX['VALUE'], ...
// var VARIABLE = __moduleDependencyX, ...
ModuleLoaderTransformer.prototype.createModuleVariableDeclaration = function(moduleName, variables, values, location) {
var self = this;
var ModuleTransformer = function(normalizeMap) {
this.nMap = normalizeMap;
}
ModuleTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
var variableDeclarations = variables.map(function(variable, i) {
return createVariableDeclaration(variable, self.createImportExpression(moduleName, values[i]));
});
var varList = createVariableDeclarationList('var', variableDeclarations);
varList.location = location;
return createVariableStatement(varList);
}
ModuleTransformer.prototype.transformImportDeclaration = function(tree) {
var moduleName = tree.moduleSpecifier.token.processedValue;
moduleName = this.nMap[moduleName] || moduleName;
// __moduleDependencyX['VALUE']
ModuleLoaderTransformer.prototype.createImportExpression = function(moduleName, value) {
var expression = createIdentifierExpression(this.depMap[moduleName]);
return value ? createMemberLookupExpression(expression, createStringLiteral(value)) : expression;
}
var variables = [];
var values = [];
// __exports['EXPORT_NAME']
ModuleLoaderTransformer.prototype.createExportExpression = function(exportName) {
return createMemberLookupExpression(createIdentifierExpression(this.exportGlobal), createStringLiteral(exportName));
}
// import $ from 'jquery';
if (tree.importClause.binding) {
variables.push(tree.importClause.binding.identifierToken);
values.push('default');
ModuleLoaderTransformer.prototype.transformImportDeclaration = function(tree) {
var moduleName = tree.moduleSpecifier.token.processedValue;
var variables = [];
var values = [];
// import 'jquery';
// import $ from 'jquery';
if (tree.importClause && tree.importClause.binding) {
variables.push(tree.importClause.binding.identifierToken);
values.push('default');
}
// import { ... } from 'jquery';
else if (tree.importClause) {
var specifiers = tree.importClause.specifiers;
for (var i = 0; i < specifiers.length; i++) {
var specifier = specifiers[i];
variables.push(specifier.rhs ? specifier.rhs.value : specifier.lhs.value);
values.push(specifier.lhs.value);
}
}
return this.createModuleVariableDeclaration(moduleName, variables, values, tree.location);
}
ModuleLoaderTransformer.prototype.transformModuleDeclaration = function(tree) {
var moduleName = tree.expression.token.processedValue;
return this.createModuleVariableDeclaration(moduleName, [tree.identifier], [null], tree.location);
}
ModuleLoaderTransformer.prototype.transformExportDeclaration = function(tree) {
var declaration = tree.declaration;
// import { ... } from 'jquery';
else {
var specifiers = tree.importClause.specifiers;
if (declaration.type == 'NAMED_EXPORT') {
var moduleName = declaration.moduleSpecifier && declaration.moduleSpecifier.token.processedValue;
// export {a as b, c as d}
// export {a as b, c as d} from 'module'
if (declaration.specifierSet.type != 'EXPORT_STAR') {
var expressions = [];
var specifiers = declaration.specifierSet.specifiers;
for (var i = 0; i < specifiers.length; i++) {
var specifier = specifiers[i];
variables.push(specifier.rhs ? specifier.rhs.value : specifier.lhs.value);
values.push(specifier.lhs.value);
expressions.push(createAssignmentExpression(
this.createExportExpression(specifier.rhs ? specifier.rhs.value : specifier.lhs.value),
moduleName
? this.createImportExpression(moduleName, specifier.lhs.value)
: createIdentifierExpression(specifier.lhs.value)
));
}
var commaExpression = createExpressionStatement(createCommaExpression(expressions));
commaExpression.location = tree.location;
return commaExpression;
}
return createModuleVariableDeclaration(moduleName, variables, values, tree.location);
else {
var exportStarStatement = createAssignmentStatement(createIdentifierExpression(this.exportGlobal), this.createImportExpression(moduleName));
exportStarStatement.location = tree.location;
return exportStarStatement;
}
}
ModuleTransformer.prototype.transformModuleDeclaration = function(tree) {
var moduleName = tree.expression.token.processedValue;
moduleName = this.nMap[moduleName] || moduleName;
return createModuleVariableDeclaration(moduleName, [tree.identifier], [null], tree.location);
// export var p = 4;
else if (declaration.type == 'VARIABLE_STATEMENT') {
// export var p = ...
var varDeclaration = declaration.declarations.declarations[0];
varDeclaration.initialiser = createAssignmentExpression(
this.createExportExpression(varDeclaration.lvalue.identifierToken.value),
this.transformAny(varDeclaration.initialiser)
);
return declaration;
}
ModuleTransformer.prototype.transformExportDeclaration = function(tree) {
var declaration = tree.declaration;
if (declaration.type == 'NAMED_EXPORT') {
var moduleName = declaration.moduleSpecifier && declaration.moduleSpecifier.token.processedValue;
if (moduleName)
moduleName = this.nMap[moduleName] || moduleName;
// export {a as b, c as d}
// export {a as b, c as d} from 'module'
if (declaration.specifierSet.type != 'EXPORT_STAR') {
var expressions = [];
var specifiers = declaration.specifierSet.specifiers;
for (var i = 0; i < specifiers.length; i++) {
var specifier = specifiers[i];
expressions.push(createAssignmentExpression(
createExportExpression(specifier.rhs ? specifier.rhs.value : specifier.lhs.value),
moduleName
? createImportExpression(moduleName, specifier.lhs.value)
: createIdentifierExpression(specifier.lhs.value)
));
}
var commaExpression = createExpressionStatement(createCommaExpression(expressions));
commaExpression.location = tree.location;
return commaExpression;
}
else {
var exportStarStatement = createAssignmentStatement(createIdentifierExpression('__exports'), createImportExpression(moduleName));
exportStarStatement.location = tree.location;
return exportStarStatement;
}
}
// export var p = 4;
else if (declaration.type == 'VARIABLE_STATEMENT') {
// export var p = ...
var varDeclaration = declaration.declarations.declarations[0];
varDeclaration.initializer = createAssignmentExpression(
createExportExpression(varDeclaration.lvalue.identifierToken.value),
this.transformAny(varDeclaration.initializer)
);
return declaration;
}
// export function q() {}
else if (declaration.type == 'FUNCTION_DECLARATION') {
var varDeclaration = createVariableDeclaration(
declaration.name.identifierToken.value,
createAssignmentStatement(
createExportExpression(declaration.name.identifierToken.value),
this.transformAny(declaration)
)
);
varDeclaration.location = tree.location;
return createVariableDeclarationList('var', [varDeclaration]);
}
// export default ...
else if (declaration.type == 'EXPORT_DEFAULT') {
return createAssignmentStatement(
createExportExpression('default'),
this.transformAny(declaration.expression)
);
}
return tree;
// export function q() {}
else if (declaration.type == 'FUNCTION_DECLARATION') {
var varDeclaration = createVariableDeclaration(
declaration.name.identifierToken.value,
createAssignmentStatement(
this.createExportExpression(declaration.name.identifierToken.value),
this.transformAny(declaration)
)
);
varDeclaration.location = tree.location;
return createVariableDeclarationList('var', [varDeclaration]);
}
this.ModuleTransformer = ModuleTransformer;
},
// store the names of modules which needed to be parsed by esprima
parseNames: {},
// store the syntax trees for modules parsed by esprima
treeCache: {},
getSyntaxTree: function(source, options) {
var name = options.normalized || options.address;
if (this.treeCache[name])
return this.treeCache[name];
var parser = new this.traceur.syntax.Parser(this.reporter, new this.traceur.syntax.SourceFile(options.address, source));
var tree = options.type == 'module' ? parser.parseModule() : parser.parseScript();
return this.treeCache[name] = tree;
},
getTransformedSyntaxTree: function(source, options) {
var tree = this.getSyntaxTree(source, options);
if (options.es6) {
var project = new this.traceur.semantics.symbols.Project(options.address);
var transformer = new this.traceur.codegeneration.ProgramTransformer(this.reporter, project);
tree = transformer.transform(tree);
// export default ...
else if (declaration.type == 'EXPORT_DEFAULT') {
return createAssignmentStatement(
this.createExportExpression('default'),
this.transformAny(declaration.expression)
);
}
return tree;
}
return ModuleLoaderTransformer;
}
return (new this.ModuleTransformer(options.normalizeMap || {})).transformAny(tree);
},
// parse the list of import module names for a given source
parseImports: function(source, options) {
if (!this.checkModuleSyntax(options.normalized || options.address, source))
return [];
// tree traversal, NB should use visitor pattern here
function traverse(object, iterator, parent, parentProperty) {
var key, child;
if (iterator(object, parent, parentProperty) === false)
return;
for (key in object) {
if (!object.hasOwnProperty(key))
continue;
if (key == 'location' || key == 'type')
continue;
child = object[key];
if (typeof child == 'object' && child !== null)
traverse(child, iterator, object, key);
}
}
var tree = this.getSyntaxTree(source, options);
var imports = [];
// given a syntax tree, return the import list
function getImports(moduleTree) {
var imports = [];
// NB switch this to a Visitor implementation
this.traverse(tree, function(node) {
// import {} from 'foo';
// export * from 'foo';
// export { ... } from 'foo';
// module x from 'foo';
if (node.type == 'EXPORT_DECLARATION') {
if (node.declaration.moduleSpecifier)
imports.push(node.declaration.moduleSpecifier.token.processedValue);
}
else if (node.type == 'IMPORT_DECLARATION')
imports.push(node.moduleSpecifier.token.processedValue);
else if (node.type == 'MODULE_DECLARATION')
imports.push(node.expression.token.processedValue);
});
return imports;
},
// runs an eval of code with module syntax
// opt = {
// name: name, // normalized module name, used to load cached syntax tree
// normalizeMap: normalizeMap, // normalization map to save having to renormalize again
// sourceURL: opt.address, // used for source map
// isEval: isScript // indicate if exports should be parsed
// }
// return value is any exports as a plain object
parseEval: function(source, loader, opt) {
// NB if no normalizeMap, run normalization function
function addImport(name) {
if (indexOf.call(imports, name) == -1)
imports.push(name);
}
// regex showed no need for esprima - normal eval
if (!this.checkModuleSyntax(opt.name, source)) {
loader.global.__Loader = loader;
__scopedEval((loader.strict ? '"use strict";\n' : '') + source, loader.global, opt.sourceURL);
delete loader.global.__Loader;
return;
traverse(moduleTree, function(node) {
// import {} from 'foo';
// export * from 'foo';
// export { ... } from 'foo';
// module x from 'foo';
if (node.type == 'EXPORT_DECLARATION') {
if (node.declaration.moduleSpecifier)
addImport(node.declaration.moduleSpecifier.token.processedValue);
}
else if (node.type == 'IMPORT_DECLARATION')
addImport(node.moduleSpecifier.token.processedValue);
else if (node.type == 'MODULE_DECLARATION')
addImport(node.expression.token.processedValue);
});
return imports;
}
var tree = this.getTransformedSyntaxTree(source, { es6: true, normalized: opt.name, address: opt.sourceURL, normalizeMap: opt.normalizeMap });
delete this.treeCache[opt.name || opt.address];
// generate source
var sourceMapGenerator = new this.traceur.outputgeneration.SourceMapGenerator({ file: opt.sourceURL });
var options = { sourceMapGenerator: sourceMapGenerator };
// Export the Loader class
exports.Loader = Loader;
// Export the Module class
exports.Module = Module;
// Export the System object
exports.System = System;
source = this.traceur.outputgeneration.TreeWriter.write(tree, options);
if (isBrowser)
source += '\n//# sourceMappingURL=data:application/json;base64,' + btoa(options.sourceMap) + '\n'
var traceurSrc;
loader.global.__Loader = loader;
loader.global.__exports = {};
// <script type="module"> support
// allow a data-init function callback once loaded
if (isBrowser) {
var curScript = document.getElementsByTagName('script');
curScript = curScript[curScript.length - 1];
__scopedEval((loader.strict ? '"use strict";\n' : '') + source, loader.global, opt.sourceURL);
// set the path to traceur
traceurSrc = curScript.getAttribute('data-traceur-src')
|| curScript.src.substr(0, curScript.src.lastIndexOf('/') + 1) + 'traceur.js';
delete loader.global.__Loader;
var exports = loader.global.__exports;
delete loader.global.__exports;
document.onreadystatechange = function() {
if (document.readyState == 'interactive') {
var scripts = document.getElementsByTagName('script');
// if exports are defined and it is an eval, throw
if (opt.isEval) {
for (var e in exports) {
throw 'Exports only supported for modules, not script evaluation.'
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
if (script.type == 'module') {
// <script type="module" name="" src=""> support
var name = script.getAttribute('name');
var address = script.getAttribute('src');
var source = script.innerHTML;
(name
? System.define(name, source, { address: address })
: System.module(source, { address: address })
).then(function() {}, function(err) { nextTick(function() { throw err; }); });
}
}
}
return exports;
}
};
// Export the Loader class
global.Loader = Loader;
// Export the Module class
global.Module = Module;
// Export the System object
global.System = defaultSystemLoader;
// run the data-init function on the script tag
if (curScript.getAttribute('data-init'))
window[curScript.getAttribute('data-init')]();
}

@@ -892,3 +1305,3 @@ })();

// carefully scoped eval with given global
var __scopedEval = function(__source, global, __sourceURL) {
function __scopedEval(__source, global, __sourceURL) {
eval('with(global) { (function() { ' + __source + ' \n }).call(global); }'

@@ -900,22 +1313,1 @@ + (__sourceURL && !__source.match(/\/\/[@#] ?(sourceURL|sourceMappingURL)=(.+)/)

})();
(function() {
// allow a data-init function callback once loaded
if (typeof window != 'undefined') {
var curScript = document.getElementsByTagName('script');
curScript = curScript[curScript.length - 1];
if (curScript.getAttribute('data-init'))
window[curScript.getAttribute('data-init')]();
document.onreadystatechange = function() {
if (document.readyState == 'interactive') {
var scripts = document.getElementsByTagName('script');
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].type == 'module') {
System.evalAsync(scripts[i].innerHTML);
}
}
}
}
}
})();
{
"name": "es6-module-loader",
"description": "An ES6 Module Loader shim",
"version": "0.3.3",
"version": "0.4.0",
"homepage": "https://github.com/ModuleLoader/es6-module-loader",

@@ -24,5 +24,2 @@ "author": {

],
"dependencies": {
"traceur": "0.0.6"
},
"devDependencies": {

@@ -47,5 +44,7 @@ "grunt": "~0.4.1",

"files": [
"lib/es6-module-loader.js",
"lib/esprima-es6.min.js"
]
"lib/es6-module-loader.js"
],
"dependencies": {
"traceur": "0.0.8"
}
}

@@ -1,14 +0,26 @@

# ES6 Module Loader
# ES6 Module Loader Polyfill
ES6 Module Loader polyfill based on [http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders](http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders) by Luke Hoban, Addy Osmani and Guy Bedford.
_Fully up to date with the latest specification_
* [Dynamically load ES6 modules](#getting-started) in all modern browsers including IE8+
* Uses [Traceur](https://github.com/google/traceur-compiler) for [compiling ES6 modules and syntax into ES5 in the browser with source map support](#integration-with-traceur)
The new ES6 module specification defines a module system in JavaScript using `import` and `export` syntax, along with a module loader factory (`new Loader`).
A separate browser specification defines the `window.System` loader, a dynamic browser loader for JavaScript modules, as well as a new `<module>` tag (`<script type="module">` for compatibility with existing browsers).
This polyfill implements the `Loader` and `Module` globals, exactly as specified in the [2013-12-02 ES6 Module Specification Draft](https://github.com/jorendorff/js-loaders/blob/e60d3651/specs/es6-modules-2013-12-02.pdf) and the `System` browser loader exactly as suggested in the [sample implementation](https://github.com/jorendorff/js-loaders/blob/964623c75d/browser-loader.js).
The complete combined polyfill comes to 16KB minified, making it suitable for production use in future, provided that modules are built into ES5 making them independent of Traceur. Build workflows are currently in progress.
* Provides an asynchronous loader (`System.import`) to [dynamically load ES6 modules](#getting-started) in all modern browsers including IE8+
* Adds support for the `<script type="module">` tag allowing inline module loading.
* Uses [Traceur](https://github.com/google/traceur-compiler) for compiling ES6 modules and syntax into ES5 in the browser with source map support
* Use as a base for creating a [custom spec-compliant module loader](#creating-a-custom-loader)
* Fully compatible with NodeJS allowing for spec-compliant server-side module loading
Not yet suitable for production use while the specification is still subject to change.
_Not yet suitable for production use while the specification is still subject to change._
See the [demo folder](https://github.com/ModuleLoader/es6-module-loader/blob/master/demo/index.html) in this repo for a working example demonstrating both module loading the module tag.
## Getting Started
Download both [es6-module-loader.js](https://raw.github.com/ModuleLoader/es6-module-loader/master/dist/es6-module-loader.js) and [traceur.js](https://raw.github.com/ModuleLoader/es6-module-loader/master/dist/traceur.js) into the same folder.
Download both [es6-module-loader.js](https://raw.github.com/ModuleLoader/es6-module-loader/master/dist/es6-module-loader.js) and [traceur.js](https://raw.github.com/ModuleLoader/es6-module-loader/master/lib/traceur.js) into the same folder.

@@ -18,14 +30,35 @@ Then include the `es6-module-loader.js` file on its own in the page:

```html
<script src="path/to/es6-module-loader.js"></script>
<script src="es6-module-loader.js"></script>
```
Traceur will be downloaded only when needed for ES6 syntax parsing.
Traceur will be downloaded only when needed for ES6 syntax parsing, detected as the existence of module syntax, or as specified by the `metadata.es6` property.
If we have an ES6 module file located at `/lib/app/main.js`, we can then load this with the system loader:
Write an ES6 module:
mymodule.js:
```javascript
export class q {
constructor() {
console.log('this is an es6 class!');
}
}
```
We can then load this module with a module tag in the page:
```html
<script type="module">
// loads the 'q' export from 'mymodule.js' in the same path as the page
import { q } from 'mymodule';
new q(); // -> 'this is an es6 class!'
</script>
```
Or we can also use the dynamic loader:
```html
<script>
System.baseURL = '/lib';
System.import('app/main', function(app) {
new app.Application();
System.import('mymodule').then(function(m) {
new m.q();
});

@@ -35,67 +68,103 @@ </script>

Any module dependencies of the file will be dynamically loaded and linked as per the ES6 module specification.
The dynamic loader returns an instance of the `Module` class, which contains getters for the named exports (in this case, `q`).
Modules are loaded by **Module Name** roughly using the rule:
## Terminology
### Modules and Module Loaders
A module is simply a JavaScript file written with module syntax. Modules _export_ values, which can then be _imported_ by other modules.
[CommonJS](http://wiki.commonjs.org/wiki/CommonJS) and [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) JavaScript files are modules.
A module loader provides the ability to dynamically load modules, and also keeps track of all loaded modules in a module registry.
Typically, in production, the module registry would be populated by an initial compiled bundle of modules. Later in the page state, it may become necessary to dynamically
load a new module. This module can then share dependencies with the initial page bundle without having to reload any dependencies.
The ES6 Module Specification defines the module syntax for ES6 module files, and also defines a module loader factory class for creating ES6-compatible module loaders.
Module code is treated differently to scripts due to the nature of exports and imports. This is why the `<script type="module">` tag (which will become the `<module>` tag in modern browsers) is introduced to distinguish script code from module code. Scripts cannot export or import, but are able to use the dynamic loader `System.import(...)`.
### Module Names and baseURL
Module names are just like moduleIDs in RequireJS. Non-relative module names (not starting with `.`) are converted to a URL with the following rule:
```javascript
URL = baseURL + '/' + ModuleName + '.js'
URL = absolutePath(baseURL, ModuleName + '.js')
```
Relative module names can be written `'./local-module'` to load relative to the parent module name.
Relative module names can be written `'./local-module'` to load relative to their parent module name. `..` syntax is also supported allowing easily portable modules.
## Writing and Loading ES6 Modules
The `baseURL` is set to the current page path by default. It is a property of the `System` loader and can be changed:
The contents of `/lib/app/main.js` can be written:
```javascript
System.baseURL = '/lib/';
System.baseURL = 'http://mysite.com/js/';
```
## ES6 Module Syntax
### Exporting
ES6 module syntax is most similar to the `exports.method = function() {}` pattern in NodeJS of creating multiple named exports.
In CommonJS one might write:
```javascript
import { Helpers } from './app-dep';
exports.someMethod = function() {
export class Application {
constructor() {
console.log('Initialized ES6 App Module');
},
foo() {
Helpers.foo();
}
}
exports.another = {};
```
With `/lib/app/app-dep.js` containing:
In ES6, this same code would be written:
exporter.js:
```javascript
export var Helpers = { ... };
export function someMethod() {
}
export var another = {};
```
When loaded, as with the `System.import` call above, these module files are dynamically loaded and compiled to ES5 in the browser and executed.
Notice that the name of the function, class or variable gets used as the export name.
## Moving to Production
### Importing
When in production, one wouldn't want to load ES6 modules and syntax in the browser. Rather the modules would be built into ES5 and AMD to be loaded.
When importing, we import any exports we need by name, and can also choose to rename them:
One can construct an AMD loader from this polyfill in under 30KB for such a scenario.
importer.js:
```javascript
import { someMethod, another as newName } from './exporter';
Think of this module as RequireJS, and [Traceur](https://github.com/google/traceur-compiler) as the r.js optimizer.
someMethod();
typeof newName == 'object';
```
Bundling techniques for ES6 are an active area of development.
### Default Import and Export
## Module Tag
Sometimes one doesn't want to write an import name at all. For this we can use the default export:
Modules can also be loaded with the module tag:
export-default.js:
```javascript
export default function foo() {
console.log('foo');
}
```
```html
<script src="/path/to/es6-module-loader.js"></script>
<script>System.baseURL = '/lib'</script>
<script type="module">
import { Application } from 'app/main';
import-default.js:
```javascript
import customName from './export-default';
new Application();
</script>
customName(); // -> 'foo'
```
## Full Module Syntax Summary
### All Supported Syntax
The following module syntax is supported by this polyfill, which is to the latest specification (November 2013):
There are a few other variations of module syntax, the full list of supported statements is listed below.
```javascript
//import 'jquery'; // import a module ** awaiting support in Traceur
import 'jquery'; // import a module without any import bindings
import $ from 'jquery'; // import the default export of a module

@@ -120,2 +189,62 @@ import { $ } from 'jquery'; // import a named export of a module

Note that any valid declaration can be exported. In ES6, this includes `class` (as in the example above), `const`, and `let`.
## Dynamic Module Loading
The dynamic module loader uses promises for resolution. Modules can have both a resolve and reject handler:
```javascript
System.import('some-module').then(function(m) {
// got Module instance m
}, function(err) {
// error
});
```
## Moving to Production
When in production, one wouldn't want to load ES6 modules and syntax in the browser. Rather the modules would be built into ES5 and AMD to be loaded.
Also, suitable bundling would need to be used.
We are actively working on these workflows.
## Module Tag
The module tag supports both named and anonymous use.
### Anonymous Module
This is just like an anonymous &lt;script> tag, allowing code to be run directly:
```html
<script type="module">
import 'some-import';
class q {
}
new q();
</script>
```
### Named Module
A named module is just like an anonymous module, but defines the module in the registry as well:
```html
<script type="module" name="my-module">
export var p = 'named-module';
</script>
<script>
// later on -
setTimeout(function() {
System.import('my-module').then(function(m) {
console.log(m.p); // -> named-module
});
}, 100);
</script>
```
## NodeJS Support

@@ -131,3 +260,3 @@

Tracuer support requires `npm install traceur`, allowing ES6 syntax in NodeJS:
Traceur support requires `npm install traceur`, allowing ES6 syntax in NodeJS:

@@ -151,10 +280,10 @@ ```javascript

* Normalize: Given the import name, provide the canonical module name.
* Resolve: Given a canonical module name, provide the URL for the resource.
* Locate: Given a canonical module name, provide the URL for the resource.
* Fetch: Given a URL for a resource, fetch its content.
* Translate: Given module source, make any source modifications.
* Link: Given module source, determine its dependencies, and execute it.
* Instantiate: Given module source, determine its dependencies, and execute it.
Variations of these hooks can allow creating many different styles of loader.
Evey hook is optional for a new loader, with default behaviours defined.
Each hook can either return a result directly, or a promise (thenable) for the result.

@@ -165,20 +294,22 @@ To create a new loader, use the `Loader` constructor:

var MyLoader = new Loader({
global: window,
strict: false,
normalize: function (name, referer) {
return canonicalName;
normalize: function (name, parentName, parentAddress) {
return resolvedName;
},
resolve: function (normalized, options) {
return this.baseURL + '/' + normalized + '.js';
locate: function (load) {
// load.name is normalized name
return this.baseURL + '/' + load.name + '.js';
},
fetch: function (url, fulfill, reject, options) {
myXhr.get(url, fulfill, reject);
fetch: function (load) {
// return a promise. Alternatively, just use the system fetch
// promise -return System.fetch(load)
var defer = MyPromiseLibrary.createDeferred();
myXhr.get(load.address, defer.resolve, defer.reject);
return defer.promise;
},
translate: function (source, options) {
return compile(source);
translate: function (load) {
return load.source;
},
link: function (source, options) {
instantiate: function (load) {
// use standard es6 linking
return;
return System.instantiate(load);

@@ -188,3 +319,3 @@ // provide custom linking

return {
imports: ['some', 'dependencies'],
deps: ['some', 'dependencies'],
execute: function(depA, depB) {

@@ -200,12 +331,57 @@ return new Module({

For a more in-depth overview of creating with custom loaders, see [Yehuda Katz's essay](https://gist.github.com/wycats/51c96e3adcdb3a68cbc3) or the [ES6 Module Specification](http://wiki.ecmascript.org/doku.php?id=harmony:module_loaders).
For a more in-depth overview of creating with custom loaders, some resources are provided below:
* The [System Loader implementation](https://github.com/ModuleLoader/es6-module-loader/blob/master/lib/es6-module-loader.js#L804)
* [ES6 Module Specification, latest draft](https://github.com/jorendorff/js-loaders/blob/e60d3651/specs/es6-modules-2013-12-02.pdf)
* [Yehuda Katz's essay](https://gist.github.com/wycats/51c96e3adcdb3a68cbc3) (outdated)
### Specification Notes
## Specification Notes
The polyfill is in the process of being updated to the latest complete draft of the module specification.
Notes on the exact specification implementation differences are included below.
This will alter the custom loader API entirely, but the import syntax will remain mostly identical.
### Loader Polyfill
To follow the current the specification changes, see https://github.com/ModuleLoader/es6-module-loader/issues?labels=specification&page=1&state=open.
* Implemented exactly to the 2013-12-02 Specification Draft -
https://github.com/jorendorff/js-loaders/blob/e60d3651/specs/es6-modules-2013-12-02.pdf
with the only exceptions as described here
* Abstract functions have been combined where possible, and their associated functions
commented
* Declarative Module Support is entirely disabled, and an error will be thrown if
the instantiate loader hook returns undefined
* With this assumption, instead of Link, LinkDynamicModules is run directly
* ES6 support is thus provided through the translate function of the System loader
* EnsureEvaluated is removed, but may in future implement dynamic execution pending
issue - https://github.com/jorendorff/js-loaders/issues/63
* Realm implementation is entirely omitted. As such, Loader.global and Loader.realm
accessors will throw errors, as well as Loader.eval
* Loader module table iteration currently not yet implemented
### System Loader Implementation
* Implemented to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js,
except for Instantiate function
* Instantiate function determines if ES6 module syntax is being used, if so parses with
Traceur and returns a dynamic InstantiateResult for loading ES6 module syntax in ES5.
* Custom loaders thus can be implemented by using this System.instantiate function as
the fallback loading scenario, after other module format detections.
* Traceur is loaded dynamically when module syntax is detected by a regex (with over-
classification), either from require('traceur') on the server, or the
'data-traceur-src' property on the current script in the browser, or if not set,
'traceur.js' in the same URL path as the current script in the browser.
* The `<script type="module">` tag is supported, but the `<module>` tag is not
* ondemand / paths functionality currently not yet implemented
To follow the current the specification changes, see the marked issues https://github.com/ModuleLoader/es6-module-loader/issues?labels=specification&page=1&state=open.
## Projects using us

@@ -221,2 +397,4 @@

## Release History
* 0.4.0 Update to revised specification exact algorithm
* 0.3.3 Traceur parser update, detection regex fixes, better error messages
* 0.3.2 Use Traceur for all parsing, module tag support, syntax updates, test workflow

@@ -223,0 +401,0 @@ * 0.3.1 IE9 Cross Domain fix, module x from y syntax support, data-init callback support, Traceur fixes

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc