aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-09-26 18:00:21 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-09-26 18:00:26 +0200
commit211e8c25d52644552cb37531cdb637f4f12c8782 (patch)
tree1ba56cb19a88b5dc9cbc4950b4814d84128ab3db
parentc89c90b7fa69b030c82f8cc73a29f89987016250 (diff)
downloadwallet-core-211e8c25d52644552cb37531cdb637f4f12c8782.tar.xz
fix bug in retrying logic for reserve status
-rw-r--r--lib/vendor/system-csp-production.src.js1621
-rw-r--r--lib/wallet/chromeBadge.ts5
-rw-r--r--lib/wallet/wallet.ts12
3 files changed, 1010 insertions, 628 deletions
diff --git a/lib/vendor/system-csp-production.src.js b/lib/vendor/system-csp-production.src.js
index 0887780ca..9c5e56532 100644
--- a/lib/vendor/system-csp-production.src.js
+++ b/lib/vendor/system-csp-production.src.js
@@ -1,8 +1,71 @@
/*
- * SystemJS v0.19.17
+ * SystemJS v0.19.39
*/
(function() {
-function bootstrap() {(function(__global) {
+function bootstrap() {// from https://gist.github.com/Yaffle/1088850
+(function(global) {
+function URLPolyfill(url, baseURL) {
+ if (typeof url != 'string')
+ throw new TypeError('URL must be a string');
+ var m = String(url).replace(/^\s+|\s+$/g, "").match(/^([^:\/?#]+:)?(?:\/\/(?:([^:@\/?#]*)(?::([^:@\/?#]*))?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
+ if (!m)
+ throw new RangeError('Invalid URL format');
+ var protocol = m[1] || "";
+ var username = m[2] || "";
+ var password = m[3] || "";
+ var host = m[4] || "";
+ var hostname = m[5] || "";
+ var port = m[6] || "";
+ var pathname = m[7] || "";
+ var search = m[8] || "";
+ var hash = m[9] || "";
+ if (baseURL !== undefined) {
+ var base = baseURL instanceof URLPolyfill ? baseURL : new URLPolyfill(baseURL);
+ var flag = !protocol && !host && !username;
+ if (flag && !pathname && !search)
+ search = base.search;
+ if (flag && pathname[0] !== "/")
+ pathname = (pathname ? (((base.host || base.username) && !base.pathname ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + pathname) : base.pathname);
+ // dot segments removal
+ var output = [];
+ pathname.replace(/^(\.\.?(\/|$))+/, "")
+ .replace(/\/(\.(\/|$))+/g, "/")
+ .replace(/\/\.\.$/, "/../")
+ .replace(/\/?[^\/]*/g, function (p) {
+ if (p === "/..")
+ output.pop();
+ else
+ output.push(p);
+ });
+ pathname = output.join("").replace(/^\//, pathname[0] === "/" ? "/" : "");
+ if (flag) {
+ port = base.port;
+ hostname = base.hostname;
+ host = base.host;
+ password = base.password;
+ username = base.username;
+ }
+ if (!protocol)
+ protocol = base.protocol;
+ }
+
+ // convert URLs to use / always
+ pathname = pathname.replace(/\\/g, '/');
+
+ this.origin = host ? protocol + (protocol !== "" || host !== "" ? "//" : "") + host : "";
+ this.href = protocol + (protocol && host || protocol == "file:" ? "//" : "") + (username !== "" ? username + (password !== "" ? ":" + password : "") + "@" : "") + host + pathname + search + hash;
+ this.protocol = protocol;
+ this.username = username;
+ this.password = password;
+ this.host = host;
+ this.hostname = hostname;
+ this.port = port;
+ this.pathname = pathname;
+ this.search = search;
+ this.hash = hash;
+}
+global.URLPolyfill = URLPolyfill;
+})(typeof self != 'undefined' ? self : global);(function(__global) {
var isWorker = typeof window == 'undefined' && typeof self != 'undefined' && typeof importScripts != 'undefined';
var isBrowser = typeof window != 'undefined' && typeof document != 'undefined';
@@ -37,24 +100,32 @@ function bootstrap() {(function(__global) {
}
})();
+ var errArgs = new Error(0, '_').fileName == '_';
+
function addToError(err, msg) {
- var newErr;
- if (err instanceof Error) {
- newErr = new Error(err.message, err.fileName, err.lineNumber);
- if (isBrowser) {
- newErr.message = err.message + '\n\t' + msg;
- newErr.stack = err.stack;
+ // parse the stack removing loader code lines for simplification
+ if (!err.originalErr) {
+ var stack = ((err.message || err) + (err.stack ? '\n' + err.stack : '')).toString().split('\n');
+ var newStack = [];
+ for (var i = 0; i < stack.length; i++) {
+ if (typeof $__curScript == 'undefined' || stack[i].indexOf($__curScript.src) == -1)
+ newStack.push(stack[i]);
}
- else {
- // node errors only look correct with the stack modified
- newErr.message = err.message;
- newErr.stack = err.stack + '\n\t' + msg;
- }
- }
- else {
- newErr = err + '\n\t' + msg;
}
-
+
+ var newMsg = '(SystemJS) ' + (newStack ? newStack.join('\n\t') : err.message.substr(11)) + '\n\t' + msg;
+
+ // Convert file:/// URLs to paths in Node
+ if (!isBrowser)
+ newMsg = newMsg.replace(isWindows ? /file:\/\/\//g : /file:\/\//g, '');
+
+ var newErr = errArgs ? new Error(newMsg, err.fileName, err.lineNumber) : new Error(newMsg);
+
+ newErr.stack = newMsg;
+
+ // track the original error
+ newErr.originalErr = err.originalErr || err;
+
return newErr;
}
@@ -68,6 +139,7 @@ function bootstrap() {(function(__global) {
}
var baseURI;
+
// environent baseURI detection
if (typeof document != 'undefined' && document.getElementsByTagName) {
baseURI = document.baseURI;
@@ -76,8 +148,13 @@ function bootstrap() {(function(__global) {
var bases = document.getElementsByTagName('base');
baseURI = bases[0] && bases[0].href || window.location.href;
}
+ }
+ else if (typeof location != 'undefined') {
+ baseURI = __global.location.href;
+ }
- // sanitize out the hash and querystring
+ // sanitize out the hash and querystring
+ if (baseURI) {
baseURI = baseURI.split('#')[0].split('?')[0];
baseURI = baseURI.substr(0, baseURI.lastIndexOf('/') + 1);
}
@@ -86,14 +163,17 @@ function bootstrap() {(function(__global) {
if (isWindows)
baseURI = baseURI.replace(/\\/g, '/');
}
- else if (typeof location != 'undefined') {
- baseURI = __global.location.href;
- }
else {
throw new TypeError('No environment baseURI');
}
- var URL = __global.URLPolyfill || __global.URL;
+ try {
+ var nativeURL = new __global.URL('test:///').protocol == 'test:';
+ }
+ catch(e) {}
+
+ var URL = nativeURL ? __global.URL : __global.URLPolyfill;
+
/*
*********************************************************************************************
@@ -239,11 +319,13 @@ function logloads(loads) {
// 15.2.3.2 Load Records and LoadRequest Objects
+ var anonCnt = 0;
+
// 15.2.3.2.1
function createLoad(name) {
return {
status: 'loading',
- name: name,
+ name: name || '<Anonymous' + ++anonCnt + '>',
linkSets: [],
dependencies: [],
metadata: {}
@@ -288,7 +370,6 @@ function logloads(loads) {
load = loader.loads[i];
if (load.name != name)
continue;
- console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded');
return load;
}
@@ -328,8 +409,6 @@ function logloads(loads) {
);
}
- var anonCnt = 0;
-
// 15.2.4.5
function proceedToTranslate(loader, load, p) {
p
@@ -338,6 +417,8 @@ function logloads(loads) {
if (load.status != 'loading')
return;
+ load.address = load.address || load.name;
+
return Promise.resolve(loader.loaderObj.translate({ name: load.name, metadata: load.metadata, address: load.address, source: source }))
// 15.2.4.5.2 CallInstantiate
@@ -348,38 +429,14 @@ function logloads(loads) {
// 15.2.4.5.3 InstantiateSucceeded
.then(function(instantiateResult) {
- if (instantiateResult === undefined) {
- load.address = load.address || '<Anonymous Module ' + ++anonCnt + '>';
-
- // instead of load.kind, use load.isDeclarative
- load.isDeclarative = true;
- return transpile.call(loader.loaderObj, load)
- .then(function(transpiled) {
- // Hijack System.register to set declare function
- var curSystem = __global.System;
- var curRegister = curSystem.register;
- curSystem.register = function(name, deps, declare) {
- if (typeof name != 'string') {
- declare = deps;
- deps = name;
- }
- // store the registered declaration as load.declare
- // store the deps as load.deps
- load.declare = declare;
- load.depsList = deps;
- }
- // empty {} context is closest to undefined 'this' we can get
- __eval(transpiled, load.address, {});
- curSystem.register = curRegister;
- });
- }
- else if (typeof instantiateResult == 'object') {
- load.depsList = instantiateResult.deps || [];
- load.execute = instantiateResult.execute;
- load.isDeclarative = false;
- }
- else
- throw TypeError('Invalid instantiate return value');
+ if (instantiateResult === undefined)
+ throw new TypeError('Declarative modules unsupported in the polyfill.');
+
+ if (typeof instantiateResult != 'object')
+ throw new TypeError('Invalid instantiate return value');
+
+ load.depsList = instantiateResult.deps || [];
+ load.execute = instantiateResult.execute;
})
// 15.2.4.6 ProcessLoadDependencies
.then(function() {
@@ -421,8 +478,6 @@ function logloads(loads) {
// console.log('LoadSucceeded ' + load.name);
// snapshot(loader);
- console.assert(load.status == 'loading', 'is loading');
-
load.status = 'loaded';
var linkSets = load.linkSets.concat([]);
@@ -525,8 +580,6 @@ function logloads(loads) {
if (load.status == 'failed')
return;
- console.assert(load.status == 'loading' || load.status == 'loaded', 'loading or loaded on link set');
-
for (var i = 0, l = linkSet.loads.length; i < l; i++)
if (linkSet.loads[i] == load)
return;
@@ -601,9 +654,7 @@ function logloads(loads) {
var loads = [].concat(linkSet.loads);
for (var i = 0, l = loads.length; i < l; i++) {
var load = loads[i];
- load.module = !load.isDeclarative ? {
- module: _newModule({})
- } : {
+ load.module = {
name: load.name,
module: _newModule({}),
evaluated: true
@@ -691,13 +742,12 @@ function logloads(loads) {
depMap: depMap,
address: load.address,
metadata: load.metadata,
- source: load.source,
- kind: load.isDeclarative ? 'declarative' : 'dynamic'
+ source: load.source
};
}
// if not anonymous, add to the module table
if (load.name) {
- console.assert(!loader.modules[load.name], 'load not in module table');
+ console.assert(!loader.modules[load.name] || loader.modules[load.name].module === load.module.module, 'load not in module table');
loader.modules[load.name] = load.module;
}
var loadIndex = indexOf.call(loader.loads, load);
@@ -771,7 +821,6 @@ function logloads(loads) {
get: function(key) {
if (!this._loader.modules[key])
return;
- doEnsureEvaluated(this._loader.modules[key], [], this);
return this._loader.modules[key].module;
},
// 26.3.3.7
@@ -791,16 +840,14 @@ function logloads(loads) {
.then(function(name) {
var loader = loaderObj._loader;
- if (loader.modules[name]) {
- doEnsureEvaluated(loader.modules[name], [], loader._loader);
+ if (loader.modules[name])
return loader.modules[name].module;
- }
return loader.importPromises[name] || createImportPromise(loaderObj, name,
loadModule(loader, name, {})
.then(function(load) {
delete loader.importPromises[name];
- return evaluateLoadedModule(loader, load);
+ return load.module.module;
}));
});
},
@@ -830,7 +877,7 @@ function logloads(loads) {
var sourcePromise = Promise.resolve(source);
var loader = this._loader;
var p = linkSet.done.then(function() {
- return evaluateLoadedModule(loader, load);
+ return load.module.module;
});
proceedToTranslate(loader, load, sourcePromise);
return p;
@@ -855,10 +902,16 @@ function logloads(loads) {
enumerable: true,
get: function () {
return obj[key];
+ },
+ set: function() {
+ throw new Error('Module exports cannot be changed externally.');
}
});
})(pNames[i]);
+ if (Object.freeze)
+ Object.freeze(m);
+
return m;
},
// 26.3.3.14
@@ -874,9 +927,7 @@ function logloads(loads) {
// 26.3.3.17 @@toStringTag not implemented
// 26.3.3.18.1
- normalize: function(name, referrerName, referrerAddress) {
- return name;
- },
+ normalize: function(name, referrerName, referrerAddress) {},
// 26.3.3.18.2
locate: function(load) {
return load.name;
@@ -894,8 +945,9 @@ function logloads(loads) {
};
var _newModule = Loader.prototype.newModule;
+
/*
- * ES6 Module Declarative Linking Code - Dev Build Only
+ * ES6 Module Declarative Linking Code
*/
function link(linkSet, linkError) {
@@ -922,57 +974,98 @@ function logloads(loads) {
}
}
- function evaluateLoadedModule(loader, load) {
- console.assert(load.status == 'linked', 'is linked ' + load.name);
- return load.module.module;
- }
+})();
- function doEnsureEvaluated() {}
+var System;
- function transpile() {
- throw new TypeError('ES6 transpilation is only provided in the dev module loader build.');
- }
-})();/*
-*********************************************************************************************
+// SystemJS Loader Class and Extension helpers
+function SystemJSLoader() {
+ Loader.call(this);
- System Loader Implementation
+ this.paths = {};
+ this._loader.paths = {};
- - Implemented to https://github.com/jorendorff/js-loaders/blob/master/browser-loader.js
+ systemJSConstructor.call(this);
+}
- - <script type="module"> supported
+// inline Object.create-style class extension
+function SystemProto() {};
+SystemProto.prototype = Loader.prototype;
+SystemJSLoader.prototype = new SystemProto();
+SystemJSLoader.prototype.constructor = SystemJSLoader;
-*********************************************************************************************
-*/
+var systemJSConstructor;
-var System;
+function hook(name, hook) {
+ SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {});
+}
+function hookConstructor(hook) {
+ systemJSConstructor = hook(systemJSConstructor || function() {});
+}
-function SystemLoader() {
- Loader.call(this);
- this.paths = {};
+
+var absURLRegEx = /^[^\/]+:\/\//;
+function isAbsolute(name) {
+ return name.match(absURLRegEx);
+}
+function isRel(name) {
+ return (name[0] == '.' && (!name[1] || name[1] == '/' || name[1] == '.')) || name[0] == '/';
+}
+function isPlain(name) {
+ return !isRel(name) && !isAbsolute(name);
+}
+
+var baseURIObj = new URL(baseURI);
+
+function urlResolve(name, parent) {
+ // url resolution shortpaths
+ if (name[0] == '.') {
+ // dot-relative url normalization
+ if (name[1] == '/' && name[2] != '.')
+ return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name.substr(2);
+ }
+ else if (name[0] != '/' && name.indexOf(':') == -1) {
+ // plain parent normalization
+ return (parent && parent.substr(0, parent.lastIndexOf('/') + 1) || baseURI) + name;
+ }
+
+ return new URL(name, parent && parent.replace(/#/g, '%05') || baseURIObj).href.replace(/%05/g, '#');
}
// NB no specification provided for System.paths, used ideas discussed in https://github.com/jorendorff/js-loaders/issues/25
-function applyPaths(paths, name) {
+function applyPaths(loader, name) {
// most specific (most number of slashes in path) match wins
var pathMatch = '', wildcard, maxWildcardPrefixLen = 0;
+ var paths = loader.paths;
+ var pathsCache = loader._loader.paths;
+
// check to see if we have a paths entry
for (var p in paths) {
- var pathParts = p.split('*');
- if (pathParts.length > 2)
- throw new TypeError('Only one wildcard in a path is permitted');
+ if (paths.hasOwnProperty && !paths.hasOwnProperty(p))
+ continue;
+
+ // paths sanitization
+ var path = paths[p];
+ if (path !== pathsCache[p])
+ path = paths[p] = pathsCache[p] = urlResolve(paths[p], isRel(paths[p]) ? baseURI : loader.baseURL);
// exact path match
- if (pathParts.length == 1) {
+ if (p.indexOf('*') === -1) {
if (name == p)
return paths[p];
// support trailing / in paths rules
- else if (name.substr(0, p.length - 1) == p.substr(0, p.length - 1) && (name.length < p.length || name[p.length - 1] == p[p.length - 1]) && paths[p][paths[p].length - 1] == '/')
- return paths[p].substr(0, paths[p].length - 1) + (name.length > p.length ? '/' + name.substr(p.length) : '');
+ else if (name.substr(0, p.length - 1) == p.substr(0, p.length - 1) && (name.length < p.length || name[p.length - 1] == p[p.length - 1]) && (paths[p][paths[p].length - 1] == '/' || paths[p] == '')) {
+ return paths[p].substr(0, paths[p].length - 1) + (name.length > p.length ? (paths[p] && '/' || '') + name.substr(p.length) : '');
+ }
}
// wildcard path match
else {
+ var pathParts = p.split('*');
+ if (pathParts.length > 2)
+ throw new TypeError('Only one wildcard in a path is permitted');
+
var wildcardPrefixLen = pathParts[0].length;
if (wildcardPrefixLen >= maxWildcardPrefixLen &&
name.substr(0, pathParts[0].length) == pathParts[0] &&
@@ -991,36 +1084,6 @@ function applyPaths(paths, name) {
return outPath;
}
-// inline Object.create-style class extension
-function LoaderProto() {}
-LoaderProto.prototype = Loader.prototype;
-SystemLoader.prototype = new LoaderProto();
-// SystemJS Loader Class and Extension helpers
-
-function SystemJSLoader() {
- SystemLoader.call(this);
-
- systemJSConstructor.call(this);
-}
-
-// inline Object.create-style class extension
-function SystemProto() {};
-SystemProto.prototype = SystemLoader.prototype;
-SystemJSLoader.prototype = new SystemProto();
-SystemJSLoader.prototype.constructor = SystemJSLoader;
-
-// remove ESML instantiate
-SystemJSLoader.prototype.instantiate = function() {};
-
-var systemJSConstructor;
-
-function hook(name, hook) {
- SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {});
-}
-function hookConstructor(hook) {
- systemJSConstructor = hook(systemJSConstructor || function() {});
-}
-
function dedupe(deps) {
var newDeps = [];
for (var i = 0, l = deps.length; i < l; i++)
@@ -1057,20 +1120,18 @@ catch(e) {
function getESModule(exports) {
var esModule = {};
// don't trigger getters/setters in environments that support them
- if (typeof exports == 'object' || typeof exports == 'function') {
- if (getOwnPropertyDescriptor) {
- var d;
- for (var p in exports)
- if (d = Object.getOwnPropertyDescriptor(exports, p))
- defineProperty(esModule, p, d);
- }
- else {
- var hasOwnProperty = exports && exports.hasOwnProperty;
- for (var p in exports) {
- if (!hasOwnProperty || exports.hasOwnProperty(p))
- esModule[p] = exports[p];
+ if ((typeof exports == 'object' || typeof exports == 'function') && exports !== __global) {
+ if (getOwnPropertyDescriptor) {
+ for (var p in exports) {
+ // The default property is copied to esModule later on
+ if (p === 'default')
+ continue;
+ defineOrCopyProperty(esModule, exports, p);
+ }
+ }
+ else {
+ extend(esModule, exports);
}
- }
}
esModule['default'] = exports;
defineProperty(esModule, '__useDefault', {
@@ -1079,23 +1140,40 @@ function getESModule(exports) {
return esModule;
}
+function defineOrCopyProperty(targetObj, sourceObj, propName) {
+ try {
+ var d;
+ if (d = Object.getOwnPropertyDescriptor(sourceObj, propName))
+ defineProperty(targetObj, propName, d);
+ }
+ catch (ex) {
+ // Object.getOwnPropertyDescriptor threw an exception, fall back to normal set property
+ // we dont need hasOwnProperty here because getOwnPropertyDescriptor would have returned undefined above
+ targetObj[propName] = sourceObj[propName];
+ return false;
+ }
+}
+
function extend(a, b, prepend) {
+ var hasOwnProperty = b && b.hasOwnProperty;
for (var p in b) {
+ if (hasOwnProperty && !b.hasOwnProperty(p))
+ continue;
if (!prepend || !(p in a))
a[p] = b[p];
}
return a;
}
-// package configuration options
-var packageProperties = ['main', 'format', 'defaultExtension', 'meta', 'map', 'basePath', 'depCache'];
-
// meta first-level extends where:
// array + array appends
// object + object extends
// other properties replace
function extendMeta(a, b, prepend) {
+ var hasOwnProperty = b && b.hasOwnProperty;
for (var p in b) {
+ if (hasOwnProperty && !b.hasOwnProperty(p))
+ continue;
var val = b[p];
if (!(p in a))
a[p] = val;
@@ -1108,32 +1186,196 @@ function extendMeta(a, b, prepend) {
}
}
+function extendPkgConfig(pkgCfgA, pkgCfgB, pkgName, loader, warnInvalidProperties) {
+ for (var prop in pkgCfgB) {
+ if (indexOf.call(['main', 'format', 'defaultExtension', 'basePath'], prop) != -1) {
+ pkgCfgA[prop] = pkgCfgB[prop];
+ }
+ else if (prop == 'map') {
+ extend(pkgCfgA.map = pkgCfgA.map || {}, pkgCfgB.map);
+ }
+ else if (prop == 'meta') {
+ extend(pkgCfgA.meta = pkgCfgA.meta || {}, pkgCfgB.meta);
+ }
+ else if (prop == 'depCache') {
+ for (var d in pkgCfgB.depCache) {
+ var dNormalized;
+
+ if (d.substr(0, 2) == './')
+ dNormalized = pkgName + '/' + d.substr(2);
+ else
+ dNormalized = coreResolve.call(loader, d);
+ loader.depCache[dNormalized] = (loader.depCache[dNormalized] || []).concat(pkgCfgB.depCache[d]);
+ }
+ }
+ else if (warnInvalidProperties && indexOf.call(['browserConfig', 'nodeConfig', 'devConfig', 'productionConfig'], prop) == -1 &&
+ (!pkgCfgB.hasOwnProperty || pkgCfgB.hasOwnProperty(prop))) {
+ warn.call(loader, '"' + prop + '" is not a valid package configuration option in package ' + pkgName);
+ }
+ }
+}
+
+// deeply-merge (to first level) config with any existing package config
+function setPkgConfig(loader, pkgName, cfg, prependConfig) {
+ var pkg;
+
+ // first package is config by reference for fast path, cloned after that
+ if (!loader.packages[pkgName]) {
+ pkg = loader.packages[pkgName] = cfg;
+ }
+ else {
+ var basePkg = loader.packages[pkgName];
+ pkg = loader.packages[pkgName] = {};
+
+ extendPkgConfig(pkg, prependConfig ? cfg : basePkg, pkgName, loader, prependConfig);
+ extendPkgConfig(pkg, prependConfig ? basePkg : cfg, pkgName, loader, !prependConfig);
+ }
+
+ // main object becomes main map
+ if (typeof pkg.main == 'object') {
+ pkg.map = pkg.map || {};
+ pkg.map['./@main'] = pkg.main;
+ pkg.main['default'] = pkg.main['default'] || './';
+ pkg.main = '@main';
+ }
+
+ return pkg;
+}
+
function warn(msg) {
if (this.warnings && typeof console != 'undefined' && console.warn)
console.warn(msg);
-}var absURLRegEx = /^[^\/]+:\/\//;
-
-function readMemberExpression(p, value) {
- var pParts = p.split('.');
- while (pParts.length)
- value = value[pParts.shift()];
- return value;
}
+ var fetchTextFromURL;
+ if (typeof XMLHttpRequest != 'undefined') {
+ fetchTextFromURL = function(url, authorization, fulfill, reject) {
+ var xhr = new XMLHttpRequest();
+ var sameDomain = true;
+ var doTimeout = false;
+ if (!('withCredentials' in xhr)) {
+ // check if same domain
+ var domainCheck = /^(\w+:)?\/\/([^\/]+)/.exec(url);
+ if (domainCheck) {
+ sameDomain = domainCheck[2] === window.location.host;
+ if (domainCheck[1])
+ sameDomain &= domainCheck[1] === window.location.protocol;
+ }
+ }
+ if (!sameDomain && typeof XDomainRequest != 'undefined') {
+ xhr = new XDomainRequest();
+ xhr.onload = load;
+ xhr.onerror = error;
+ xhr.ontimeout = error;
+ xhr.onprogress = function() {};
+ xhr.timeout = 0;
+ doTimeout = true;
+ }
+ function load() {
+ fulfill(xhr.responseText);
+ }
+ function error() {
+ reject(new Error('XHR error' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url));
+ }
-var baseURLCache = {};
-function getBaseURLObj() {
- if (baseURLCache[this.baseURL])
- return baseURLCache[this.baseURL];
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState === 4) {
+ // in Chrome on file:/// URLs, status is 0
+ if (xhr.status == 0) {
+ if (xhr.responseText) {
+ load();
+ }
+ else {
+ // when responseText is empty, wait for load or error event
+ // to inform if it is a 404 or empty file
+ xhr.addEventListener('error', error);
+ xhr.addEventListener('load', load);
+ }
+ }
+ else if (xhr.status === 200) {
+ load();
+ }
+ else {
+ error();
+ }
+ }
+ };
+ xhr.open("GET", url, true);
+
+ if (xhr.setRequestHeader) {
+ xhr.setRequestHeader('Accept', 'application/x-es-module, */*');
+ // can set "authorization: true" to enable withCredentials only
+ if (authorization) {
+ if (typeof authorization == 'string')
+ xhr.setRequestHeader('Authorization', authorization);
+ xhr.withCredentials = true;
+ }
+ }
- // normalize baseURL if not already
- if (this.baseURL[this.baseURL.length - 1] != '/')
- this.baseURL += '/';
+ if (doTimeout) {
+ setTimeout(function() {
+ xhr.send();
+ }, 0);
+ } else {
+ xhr.send(null);
+ }
+ };
+ }
+ else if (typeof require != 'undefined' && typeof process != 'undefined') {
+ var fs;
+ fetchTextFromURL = function(url, authorization, fulfill, reject) {
+ if (url.substr(0, 8) != 'file:///')
+ throw new Error('Unable to fetch "' + url + '". Only file URLs of the form file:/// allowed running in Node.');
+ fs = fs || require('fs');
+ if (isWindows)
+ url = url.replace(/\//g, '\\').substr(8);
+ else
+ url = url.substr(7);
+ return fs.readFile(url, function(err, data) {
+ if (err) {
+ return reject(err);
+ }
+ else {
+ // Strip Byte Order Mark out if it's the leading char
+ var dataString = data + '';
+ if (dataString[0] === '\ufeff')
+ dataString = dataString.substr(1);
- var baseURL = new URL(this.baseURL, baseURI);
+ fulfill(dataString);
+ }
+ });
+ };
+ }
+ else if (typeof self != 'undefined' && typeof self.fetch != 'undefined') {
+ fetchTextFromURL = function(url, authorization, fulfill, reject) {
+ var opts = {
+ headers: {'Accept': 'application/x-es-module, */*'}
+ };
- this.baseURL = baseURL.href;
+ if (authorization) {
+ if (typeof authorization == 'string')
+ opts.headers['Authorization'] = authorization;
+ opts.credentials = 'include';
+ }
- return (baseURLCache[this.baseURL] = baseURL);
+ fetch(url, opts)
+ .then(function (r) {
+ if (r.ok) {
+ return r.text();
+ } else {
+ throw new Error('Fetch error: ' + r.status + ' ' + r.statusText);
+ }
+ })
+ .then(fulfill, reject);
+ }
+ }
+ else {
+ throw new TypeError('No environment fetch API available.');
+ }
+function readMemberExpression(p, value) {
+ var pParts = p.split('.');
+ while (pParts.length)
+ value = value[pParts.shift()];
+ return value;
}
function getMapMatch(map, name) {
@@ -1152,48 +1394,57 @@ function getMapMatch(map, name) {
return bestMatch;
}
-function setProduction(isProduction) {
- this.set('@system-env', this.newModule({
+function prepareBaseURL(loader) {
+ // ensure baseURl is fully normalized
+ if (this._loader.baseURL !== this.baseURL) {
+ if (this.baseURL[this.baseURL.length - 1] != '/')
+ this.baseURL += '/';
+
+ this._loader.baseURL = this.baseURL = new URL(this.baseURL, baseURIObj).href;
+ }
+}
+
+var envModule;
+function setProduction(isProduction, isBuilder) {
+ this.set('@system-env', envModule = this.newModule({
browser: isBrowser,
node: !!this._nodeRequire,
- production: isProduction
+ production: !isBuilder && isProduction,
+ dev: isBuilder || !isProduction,
+ build: isBuilder,
+ 'default': true
}));
}
-var baseURIObj = new URL(baseURI);
-
hookConstructor(function(constructor) {
return function() {
constructor.call(this);
// support baseURL
- this.baseURL = baseURI.substr(0, baseURI.lastIndexOf('/') + 1);
+ this.baseURL = baseURI;
- // support map
+ // support map and paths
this.map = {};
+ // make the location of the system.js script accessible
+ if (typeof $__curScript != 'undefined')
+ this.scriptSrc = $__curScript.src;
+
// global behaviour flags
this.warnings = false;
this.defaultJSExtensions = false;
- this.globalEvaluationScope = true;
this.pluginFirst = false;
+ this.loaderErrorStack = false;
// by default load ".json" files as json
// leading * meta doesn't need normalization
// NB add this in next breaking release
// this.meta['*.json'] = { format: 'json' };
- // Default settings for globalEvaluationScope:
- // Disabled for WebWorker, Chrome Extensions and jsdom
- if (isWorker
- || isBrowser && window.chrome && window.chrome.extension
- || isBrowser && navigator.userAgent.match(/^Node\.js/))
- this.globalEvaluationScope = false;
-
// support the empty module, as a concept
this.set('@empty', this.newModule({}));
- setProduction.call(this, false);
+ setProduction.call(this, false, false);
};
});
@@ -1201,11 +1452,6 @@ hookConstructor(function(constructor) {
if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser)
SystemJSLoader.prototype._nodeRequire = require;
-var nodeCoreModules = ['assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
- 'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'module', 'net', 'os', 'path',
- 'process', 'punycode', 'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'sys', 'timers',
- 'tls', 'tty', 'url', 'util', 'vm', 'zlib'];
-
/*
Core SystemJS Normalization
@@ -1219,54 +1465,66 @@ var nodeCoreModules = ['assert', 'buffer', 'child_process', 'cluster', 'console'
defines the `decanonicalize` function and normalizes everything into
a URL.
*/
-hook('normalize', function(normalize) {
- return function(name, parentName) {
- // first run map config
- if (name[0] != '.' && name[0] != '/' && !name.match(absURLRegEx)) {
- var mapMatch = getMapMatch(this.map, name);
- if (mapMatch)
- name = this.map[mapMatch] + name.substr(mapMatch.length);
- }
- // dynamically load node-core modules when requiring `@node/fs` for example
- if (name.substr(0, 6) == '@node/' && nodeCoreModules.indexOf(name.substr(6)) != -1) {
- if (!this._nodeRequire)
- throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.');
- this.set(name, this.newModule(getESModule(this._nodeRequire(name.substr(6)))));
- }
-
- // relative URL-normalization
- if (name[0] == '.' || name[0] == '/') {
- if (parentName)
- name = new URL(name, parentName.replace(/#/g, '%05')).href.replace(/%05/g, '#');
- else
- name = new URL(name, baseURIObj).href;
- }
+var parentModuleContext;
+function getNodeModule(name, baseURL) {
+ if (!isPlain(name))
+ throw new Error('Node module ' + name + ' can\'t be loaded as it is not a package require.');
- // if the module is in the registry already, use that
- if (this.has(name))
- return name;
+ if (!parentModuleContext) {
+ var Module = this._nodeRequire('module');
+ var base = baseURL.substr(isWindows ? 8 : 7);
+ parentModuleContext = new Module(base);
+ parentModuleContext.paths = Module._nodeModulePaths(base);
+ }
+ return parentModuleContext.require(name);
+}
- if (name.match(absURLRegEx)) {
- // defaultJSExtensions backwards compatibility
- if (this.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js')
- name += '.js';
- return name;
- }
+function coreResolve(name, parentName) {
+ // standard URL resolution
+ if (isRel(name))
+ return urlResolve(name, parentName);
+ else if (isAbsolute(name))
+ return name;
- // applyPaths implementation provided from ModuleLoader system.js source
- name = applyPaths(this.paths, name) || name;
+ // plain names not starting with './', '://' and '/' go through custom resolution
+ var mapMatch = getMapMatch(this.map, name);
- // defaultJSExtensions backwards compatibility
- if (this.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js')
- name += '.js';
+ if (mapMatch) {
+ name = this.map[mapMatch] + name.substr(mapMatch.length);
- // ./x, /x -> page-relative
- if (name[0] == '.' || name[0] == '/')
- return new URL(name, baseURIObj).href;
- // x -> baseURL-relative
+ if (isRel(name))
+ return urlResolve(name);
+ else if (isAbsolute(name))
+ return name;
+ }
+
+ if (this.has(name))
+ return name;
+
+ // dynamically load node-core modules when requiring `@node/fs` for example
+ if (name.substr(0, 6) == '@node/') {
+ if (!this._nodeRequire)
+ throw new TypeError('Error loading ' + name + '. Can only load node core modules in Node.');
+ if (this.builder)
+ this.set(name, this.newModule({}));
else
- return new URL(name, getBaseURLObj.call(this)).href;
+ this.set(name, this.newModule(getESModule(getNodeModule.call(this, name.substr(6), this.baseURL))));
+ return name;
+ }
+
+ // prepare the baseURL to ensure it is normalized
+ prepareBaseURL.call(this);
+
+ return applyPaths(this, name) || this.baseURL + name;
+}
+
+hook('normalize', function(normalize) {
+ return function(name, parentName, skipExt) {
+ var resolved = coreResolve.call(this, name, parentName);
+ if (this.defaultJSExtensions && !skipExt && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved))
+ resolved += '.js';
+ return resolved;
};
});
@@ -1325,7 +1583,7 @@ hook('translate', function(systemTranslate) {
return function(load) {
if (load.metadata.format == 'detect')
load.metadata.format = undefined;
- return systemTranslate.call(this, load);
+ return systemTranslate.apply(this, arguments);
};
});
@@ -1402,10 +1660,43 @@ hook('instantiate', function(instantiate) {
For easy normalization canonicalization with latest URL support.
*/
-SystemJSLoader.prototype.env = 'development';
+function envSet(loader, cfg, envCallback) {
+ if (envModule.browser && cfg.browserConfig)
+ envCallback(cfg.browserConfig);
+ if (envModule.node && cfg.nodeConfig)
+ envCallback(cfg.nodeConfig);
+ if (envModule.dev && cfg.devConfig)
+ envCallback(cfg.devConfig);
+ if (envModule.build && cfg.buildConfig)
+ envCallback(cfg.buildConfig);
+ if (envModule.production && cfg.productionConfig)
+ envCallback(cfg.productionConfig);
+}
-SystemJSLoader.prototype.config = function(cfg) {
+SystemJSLoader.prototype.getConfig = function(name) {
+ var cfg = {};
var loader = this;
+ for (var p in loader) {
+ if (loader.hasOwnProperty && !loader.hasOwnProperty(p) || p in SystemJSLoader.prototype && p != 'transpiler')
+ continue;
+ if (indexOf.call(['_loader', 'amdDefine', 'amdRequire', 'defined', 'failed', 'version', 'loads'], p) == -1)
+ cfg[p] = loader[p];
+ }
+ cfg.production = envModule.production;
+ return cfg;
+};
+
+var curCurScript;
+SystemJSLoader.prototype.config = function(cfg, isEnvConfig) {
+ var loader = this;
+
+ if ('loaderErrorStack' in cfg) {
+ curCurScript = $__curScript;
+ if (cfg.loaderErrorStack)
+ $__curScript = undefined;
+ else
+ $__curScript = curCurScript;
+ }
if ('warnings' in cfg)
loader.warnings = cfg.warnings;
@@ -1414,20 +1705,47 @@ SystemJSLoader.prototype.config = function(cfg) {
if (cfg.transpilerRuntime === false)
loader._loader.loadedTranspilerRuntime = true;
- // always configure baseURL first
- if (cfg.baseURL) {
- var hasConfig = false;
- function checkHasConfig(obj) {
- for (var p in obj)
- return true;
+ if ('production' in cfg || 'build' in cfg)
+ setProduction.call(loader, !!cfg.production, !!(cfg.build || envModule && envModule.build));
+
+ if (!isEnvConfig) {
+ // if using nodeConfig / browserConfig / productionConfig, take baseURL from there
+ // these exceptions will be unnecessary when we can properly implement config queuings
+ var baseURL;
+ envSet(loader, cfg, function(cfg) {
+ baseURL = baseURL || cfg.baseURL;
+ });
+ baseURL = baseURL || cfg.baseURL;
+
+ // always configure baseURL first
+ if (baseURL) {
+ var hasConfig = false;
+ function checkHasConfig(obj) {
+ for (var p in obj)
+ if (obj.hasOwnProperty(p))
+ return true;
+ }
+ if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths))
+ throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.');
+
+ this.baseURL = baseURL;
+ prepareBaseURL.call(this);
}
- if (checkHasConfig(loader.packages) || checkHasConfig(loader.meta) || checkHasConfig(loader.depCache) || checkHasConfig(loader.bundles) || checkHasConfig(loader.packageConfigPaths))
- throw new TypeError('Incorrect configuration order. The baseURL must be configured with the first SystemJS.config call.');
- loader.baseURL = cfg.baseURL;
+ if (cfg.paths)
+ extend(loader.paths, cfg.paths);
+
+ envSet(loader, cfg, function(cfg) {
+ if (cfg.paths)
+ extend(loader.paths, cfg.paths);
+ });
- // sanitize baseURL
- getBaseURLObj.call(loader);
+ // warn on wildcard path deprecations
+ if (this.warnings) {
+ for (var p in loader.paths)
+ if (p.indexOf('*') != -1)
+ warn.call(loader, 'Paths configuration "' + p + '" -> "' + loader.paths[p] + '" uses wildcards which are being deprecated for simpler trailing "/" folder paths.');
+ }
}
if (cfg.defaultJSExtensions) {
@@ -1438,14 +1756,6 @@ SystemJSLoader.prototype.config = function(cfg) {
if (cfg.pluginFirst)
loader.pluginFirst = cfg.pluginFirst;
- if (cfg.production)
- setProduction.call(loader, true);
-
- if (cfg.paths) {
- for (var p in cfg.paths)
- loader.paths[p] = cfg.paths[p];
- }
-
if (cfg.map) {
var objMaps = '';
for (var p in cfg.map) {
@@ -1455,11 +1765,10 @@ SystemJSLoader.prototype.config = function(cfg) {
if (typeof v !== 'string') {
objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"';
- var prop = loader.decanonicalize(p + (p[p.length - 1] != '/' ? '/' : ''));
-
- // allow trailing '/' in package config
- if (prop[prop.length - 1] == '/')
- prop = prop.substr(0, prop.length - 1);
+ var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js';
+ var prop = loader.decanonicalize(p);
+ if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js')
+ prop = prop.substr(0, prop.length - 3);
// if a package main, revert it
var pkgMatch = '';
@@ -1488,9 +1797,8 @@ SystemJSLoader.prototype.config = function(cfg) {
for (var i = 0; i < cfg.packageConfigPaths.length; i++) {
var path = cfg.packageConfigPaths[i];
var packageLength = Math.max(path.lastIndexOf('*') + 1, path.lastIndexOf('/'));
- var normalized = loader.decanonicalize(path.substr(0, packageLength) + '/');
- normalized = normalized.substr(0, normalized.length - 1) + path.substr(packageLength);
- packageConfigPaths[i] = normalized;
+ var normalized = coreResolve.call(loader, path.substr(0, packageLength));
+ packageConfigPaths[i] = normalized + path.substr(packageLength);
}
loader.packageConfigPaths = packageConfigPaths;
}
@@ -1498,8 +1806,13 @@ SystemJSLoader.prototype.config = function(cfg) {
if (cfg.bundles) {
for (var p in cfg.bundles) {
var bundle = [];
- for (var i = 0; i < cfg.bundles[p].length; i++)
- bundle.push(loader.decanonicalize(cfg.bundles[p][i]));
+ for (var i = 0; i < cfg.bundles[p].length; i++) {
+ var defaultJSExtension = loader.defaultJSExtensions && cfg.bundles[p][i].substr(cfg.bundles[p][i].length - 3, 3) != '.js';
+ var normalizedBundleDep = loader.decanonicalize(cfg.bundles[p][i]);
+ if (defaultJSExtension && normalizedBundleDep.substr(normalizedBundleDep.length - 3, 3) == '.js')
+ normalizedBundleDep = normalizedBundleDep.substr(0, normalizedBundleDep.length - 3);
+ bundle.push(normalizedBundleDep);
+ }
loader.bundles[p] = bundle;
}
}
@@ -1509,38 +1822,21 @@ SystemJSLoader.prototype.config = function(cfg) {
if (p.match(/^([^\/]+:)?\/\/$/))
throw new TypeError('"' + p + '" is not a valid package name.');
- // trailing slash allows paths matches here
- // NB deprecate this to just remove trailing /
- // as decanonicalize doesn't respond to trailing /
- // and paths wildcards should deprecate
- var prop = loader.decanonicalize(p + (p[p.length - 1] != '/' ? '/' : ''));
+ var prop = coreResolve.call(loader, p);
- // allow trailing '/' in package config
+ // allow trailing slash in packages
if (prop[prop.length - 1] == '/')
prop = prop.substr(0, prop.length - 1);
- loader.packages[prop] = loader.packages[prop] || {};
-
- // meta backwards compatibility
- if (cfg.packages[p].modules) {
- warn.call(loader, 'Package ' + p + ' is configured with "modules", which is deprecated as it has been renamed to "meta".');
- cfg.packages[p].meta = cfg.packages[p].modules;
- delete cfg.packages[p].modules;
- }
-
- for (var q in cfg.packages[p])
- if (indexOf.call(packageProperties, q) == -1)
- warn.call(loader, '"' + q + '" is not a valid package configuration option in package ' + p);
-
- extendMeta(loader.packages[prop], cfg.packages[p]);
+ setPkgConfig(loader, prop, cfg.packages[p], false);
}
}
for (var c in cfg) {
var v = cfg[c];
- var normalizeProp = false;
- if (c == 'baseURL' || c == 'map' || c == 'packages' || c == 'bundles' || c == 'paths' || c == 'warnings' || c == 'packageConfigPaths')
+ if (indexOf.call(['baseURL', 'map', 'packages', 'bundles', 'paths', 'warnings', 'packageConfigPaths',
+ 'loaderErrorStack', 'browserConfig', 'nodeConfig', 'devConfig', 'buildConfig', 'productionConfig'], c) != -1)
continue;
if (typeof v != 'object' || v instanceof Array) {
@@ -1549,20 +1845,35 @@ SystemJSLoader.prototype.config = function(cfg) {
else {
loader[c] = loader[c] || {};
- if (c == 'meta' || c == 'depCache')
- normalizeProp = true;
-
for (var p in v) {
// base-level wildcard meta does not normalize to retain catch-all quality
- if (c == 'meta' && p[0] == '*')
- loader[c][p] = v[p];
- else if (normalizeProp)
- loader[c][loader.decanonicalize(p)] = v[p];
- else
+ if (c == 'meta' && p[0] == '*') {
+ extend(loader[c][p] = loader[c][p] || {}, v[p]);
+ }
+ else if (c == 'meta') {
+ // meta can go through global map, with defaultJSExtensions adding
+ var resolved = coreResolve.call(loader, p);
+ if (loader.defaultJSExtensions && resolved.substr(resolved.length - 3, 3) != '.js' && !isPlain(resolved))
+ resolved += '.js';
+ extend(loader[c][resolved] = loader[c][resolved] || {}, v[p]);
+ }
+ else if (c == 'depCache') {
+ var defaultJSExtension = loader.defaultJSExtensions && p.substr(p.length - 3, 3) != '.js';
+ var prop = loader.decanonicalize(p);
+ if (defaultJSExtension && prop.substr(prop.length - 3, 3) == '.js')
+ prop = prop.substr(0, prop.length - 3);
+ loader[c][prop] = [].concat(v[p]);
+ }
+ else {
loader[c][p] = v[p];
+ }
}
}
}
+
+ envSet(loader, cfg, function(cfg) {
+ loader.config(cfg, true);
+ });
};/*
* Package Configuration Extension
*
@@ -1570,7 +1881,6 @@ SystemJSLoader.prototype.config = function(cfg) {
*
* SystemJS.packages = {
* jquery: {
- * basePath: 'lib', // optionally only use a subdirectory within the package
* main: 'index.js', // when not set, package name is requested directly
* format: 'amd',
* defaultExtension: 'ts', // defaults to 'js', can be set to false
@@ -1592,7 +1902,8 @@ SystemJSLoader.prototype.config = function(cfg) {
*
* // environment-specific map configurations
* './index.js': {
- * '~browser': './index-node.js'
+ * '~browser': './index-node.js',
+ * './custom-condition.js|~export': './index-custom.js'
* }
* },
* // allows for setting package-prefixed depCache
@@ -1623,13 +1934,6 @@ SystemJSLoader.prototype.config = function(cfg) {
* - map targets support conditional interpolation ('./x': './x.#{|env}.js')
* - internal package map targets cannot use boolean conditionals
*
- * In addition, the following modules properties will be allowed to be package
- * -relative as well in the package module config:
- *
- * - loader
- * - alias
- *
- *
* Package Configuration Loading
*
* Not all packages may already have their configuration present in the System config
@@ -1666,7 +1970,7 @@ SystemJSLoader.prototype.config = function(cfg) {
return function() {
constructor.call(this);
this.packages = {};
- this.packageConfigPaths = {};
+ this.packageConfigPaths = [];
};
});
@@ -1685,28 +1989,11 @@ SystemJSLoader.prototype.config = function(cfg) {
return curPkg;
}
- function getBasePath(pkg) {
- // sanitize basePath
- var basePath = pkg.basePath && pkg.basePath != '.' ? pkg.basePath : '';
- if (basePath) {
- if (basePath.substr(0, 2) == './')
- basePath = basePath.substr(2);
- if (basePath[basePath.length - 1] != '/')
- basePath += '/';
- }
- return basePath;
- }
-
- function addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions) {
+ function addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions) {
// don't apply extensions to folders or if defaultExtension = false
if (!subPath || subPath[subPath.length - 1] == '/' || skipExtensions || pkg.defaultExtension === false)
return subPath;
- // NB are you sure about this?
- // skip if we have interpolation conditional syntax in subPath?
- if (subPath.match(interpolationRegEx))
- return subPath;
-
var metaMatch = false;
// exact meta or meta with any content after the last wildcard skips extension
@@ -1718,7 +2005,7 @@ SystemJSLoader.prototype.config = function(cfg) {
// exact global meta or meta with any content after the last wildcard skips extension
if (!metaMatch && loader.meta)
- getMetaMatches(loader.meta, pkgName + '/' + basePath + subPath, function(metaPattern, matchMeta, matchDepth) {
+ getMetaMatches(loader.meta, pkgName + '/' + subPath, function(metaPattern, matchMeta, matchDepth) {
if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1)
return metaMatch = true;
});
@@ -1747,8 +2034,6 @@ SystemJSLoader.prototype.config = function(cfg) {
return pkgName + (loader.defaultJSExtensions ? '.js' : '');
}
- var basePath = getBasePath(pkg);
-
// map config checking without then with extensions
if (pkg.map) {
var mapPath = './' + subPath;
@@ -1757,24 +2042,44 @@ SystemJSLoader.prototype.config = function(cfg) {
// we then check map with the default extension adding
if (!mapMatch) {
- mapPath = './' + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions);
+ mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions);
if (mapPath != './' + subPath)
mapMatch = getMapMatch(pkg.map, mapPath);
}
- if (mapMatch)
- return doMapSync(loader, pkg, pkgName, basePath, mapMatch, mapPath, skipExtensions);
+ if (mapMatch) {
+ var mapped = doMapSync(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions);
+ if (mapped)
+ return mapped;
+ }
}
// normal package resolution
- return pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions);
+ return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions);
+ }
+
+ function validMapping(mapMatch, mapped, pkgName, path) {
+ // disallow internal to subpath maps
+ if (mapMatch == '.')
+ throw new Error('Package ' + pkgName + ' has a map entry for "." which is not permitted.');
+
+ // allow internal ./x -> ./x/y or ./x/ -> ./x/y recursive maps
+ // but only if the path is exactly ./x and not ./x/z
+ if (mapped.substr(0, mapMatch.length) == mapMatch && path.length > mapMatch.length)
+ return false;
+
+ return true;
}
- function doMapSync(loader, pkg, pkgName, basePath, mapMatch, path, skipExtensions) {
+ function doMapSync(loader, pkg, pkgName, mapMatch, path, skipExtensions) {
+ if (path[path.length - 1] == '/')
+ path = path.substr(0, path.length - 1);
var mapped = pkg.map[mapMatch];
- // ignore conditionals in sync
- if (typeof mapped != 'string')
- mapped = mapMatch = path;
+ if (typeof mapped == 'object')
+ throw new Error('Synchronous conditional normalization not supported sync normalizing ' + mapMatch + ' in ' + pkgName);
+
+ if (!validMapping(mapMatch, mapped, pkgName, path) || typeof mapped != 'string')
+ return;
// package map to main / base-level
if (mapped == '.')
@@ -1782,7 +2087,7 @@ SystemJSLoader.prototype.config = function(cfg) {
// internal package map
else if (mapped.substr(0, 2) == './')
- return pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions);
+ return pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions);
// external map reference
return loader.normalizeSync(mapped + path.substr(mapMatch.length), pkgName + '/');
@@ -1800,8 +2105,6 @@ SystemJSLoader.prototype.config = function(cfg) {
return Promise.resolve(pkgName + (loader.defaultJSExtensions ? '.js' : ''));
}
- var basePath = getBasePath(pkg);
-
// map config checking without then with extensions
var mapPath, mapMatch;
@@ -1811,67 +2114,84 @@ SystemJSLoader.prototype.config = function(cfg) {
// we then check map with the default extension adding
if (!mapMatch) {
- mapPath = './' + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions);
+ mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions);
if (mapPath != './' + subPath)
mapMatch = getMapMatch(pkg.map, mapPath);
}
}
- return (mapMatch ? doMap(loader, pkg, pkgName, basePath, mapMatch, mapPath, skipExtensions) : Promise.resolve())
+ return (mapMatch ? doMap(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions) : Promise.resolve())
.then(function(mapped) {
if (mapped)
return Promise.resolve(mapped);
// normal package resolution / fallback resolution for no conditional match
- return Promise.resolve(pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, subPath, skipExtensions));
+ return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions));
});
}
- function doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions) {
+ function doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions) {
// NB the interpolation cases should strictly skip subsequent interpolation
-
// package map to main / base-level
if (mapped == '.')
mapped = pkgName;
// internal package map
else if (mapped.substr(0, 2) == './')
- return Promise.resolve(pkgName + '/' + basePath + addDefaultExtension(loader, pkg, pkgName, basePath, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions))
+ return Promise.resolve(pkgName + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions))
.then(function(name) {
return interpolateConditional.call(loader, name, pkgName + '/');
});
// external map reference
- // NB deprecate the use of the second argument here -> should be fully global reference
return loader.normalize(mapped + path.substr(mapMatch.length), pkgName + '/');
}
- function doMap(loader, pkg, pkgName, basePath, mapMatch, path, skipExtensions) {
+ function doMap(loader, pkg, pkgName, mapMatch, path, skipExtensions) {
+ if (path[path.length - 1] == '/')
+ path = path.substr(0, path.length - 1);
+
var mapped = pkg.map[mapMatch];
- if (typeof mapped == 'string')
- return doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions);
+ if (typeof mapped == 'string') {
+ if (!validMapping(mapMatch, mapped, pkgName, path))
+ return Promise.resolve();
+ return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions);
+ }
// we use a special conditional syntax to allow the builder to handle conditional branch points further
if (loader.builder)
return Promise.resolve(pkgName + '/#:' + path);
+ // we load all conditions upfront
+ var conditionPromises = [];
+ var conditions = [];
+ for (var e in mapped) {
+ var c = parseCondition(e);
+ conditions.push({
+ condition: c,
+ map: mapped[e]
+ });
+ conditionPromises.push(loader['import'](c.module, pkgName));
+ }
+
// map object -> conditional map
- return loader['import'](pkg.map['@env'] || '@system-env', pkgName)
- .then(function(env) {
+ return Promise.all(conditionPromises)
+ .then(function(conditionValues) {
// first map condition to match is used
- for (var e in mapped) {
- var negate = e[0] == '~';
-
- var value = readMemberExpression(negate ? e.substr(1) : e, env);
-
- if (!negate && value || negate && !value)
- return mapped[e];
+ for (var i = 0; i < conditions.length; i++) {
+ var c = conditions[i].condition;
+ var value = readMemberExpression(c.prop, conditionValues[i]);
+ if (!c.negate && value || c.negate && !value)
+ return conditions[i].map;
}
})
.then(function(mapped) {
- if (mapped)
- return doStringMap(loader, pkg, pkgName, basePath, mapMatch, mapped, path, skipExtensions);
+ if (mapped) {
+ if (!validMapping(mapMatch, mapped, pkgName, path))
+ return;
+ return doStringMap(loader, pkg, pkgName, mapMatch, mapped, path, skipExtensions);
+ }
// no environment match -> fallback to original subPath by returning undefined
});
@@ -1884,14 +2204,26 @@ SystemJSLoader.prototype.config = function(cfg) {
// to be deprecated!
hook('decanonicalize', function(decanonicalize) {
return function(name, parentName) {
- var decanonicalized = decanonicalize.call(this, name, parentName);
+ if (this.builder)
+ return decanonicalize.call(this, name, parentName, true);
+
+ var decanonicalized = decanonicalize.call(this, name, parentName, false);
if (!this.defaultJSExtensions)
return decanonicalized;
var pkgName = getPackage(this, decanonicalized);
- var defaultExtension = name[name.length - 1] == '/' ? false : pkgName && this.packages[pkgName].defaultExtension;
+ var pkg = this.packages[pkgName];
+ var defaultExtension = pkg && pkg.defaultExtension;
+
+ if (defaultExtension == undefined && pkg && pkg.meta)
+ getMetaMatches(pkg.meta, decanonicalized.substr(pkgName), function(metaPattern, matchMeta, matchDepth) {
+ if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1) {
+ defaultExtension = false;
+ return true;
+ }
+ });
if ((defaultExtension === false || defaultExtension && defaultExtension != '.js') && name.substr(name.length - 3, 3) != '.js' && decanonicalized.substr(decanonicalized.length - 3, 3) == '.js')
decanonicalized = decanonicalized.substr(0, decanonicalized.length - 3);
@@ -1902,8 +2234,6 @@ SystemJSLoader.prototype.config = function(cfg) {
hook('normalizeSync', function(normalizeSync) {
return function(name, parentName, isPlugin) {
- warn.call(this, 'SystemJS.normalizeSync has been deprecated for SystemJS.decanonicalize.');
-
var loader = this;
isPlugin = isPlugin === true;
@@ -1916,26 +2246,22 @@ SystemJSLoader.prototype.config = function(cfg) {
var parentPackage = parentPackageName && loader.packages[parentPackageName];
- // remove any parent basePath from parentName
- if (parentPackage) {
- var parentBasePath = getBasePath(parentPackage);
- if (parentBasePath && parentName.substr(parentPackageName.length + 1, parentBasePath.length) == parentBasePath)
- parentName = parentPackageName + parentName.substr(parentPackageName.length + parentBasePath.length);
- }
-
// ignore . since internal maps handled by standard package resolution
if (parentPackage && name[0] != '.') {
var parentMap = parentPackage.map;
var parentMapMatch = parentMap && getMapMatch(parentMap, name);
- if (parentMapMatch && typeof parentMap[parentMapMatch] == 'string')
- return doMapSync(loader, parentPackage, parentPackageName, getBasePath(parentPackage), parentMapMatch, name, isPlugin);
+ if (parentMapMatch && typeof parentMap[parentMapMatch] == 'string') {
+ var mapped = doMapSync(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin);
+ if (mapped)
+ return mapped;
+ }
}
var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js';
// apply map, core, paths, contextual package map
- var normalized = normalizeSync.call(loader, name, parentName);
+ var normalized = normalizeSync.call(loader, name, parentName, false);
// undo defaultJSExtension
if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js')
@@ -1971,20 +2297,13 @@ SystemJSLoader.prototype.config = function(cfg) {
var parentPackage = parentPackageName && loader.packages[parentPackageName];
- // remove any parent basePath from parentName
- if (parentPackage) {
- var parentBasePath = getBasePath(parentPackage);
- if (parentBasePath && parentName.substr(parentPackageName.length + 1, parentBasePath.length) == parentBasePath)
- parentName = parentPackageName + parentName.substr(parentPackageName.length + parentBasePath.length);
- }
-
// ignore . since internal maps handled by standard package resolution
if (parentPackage && name.substr(0, 2) != './') {
var parentMap = parentPackage.map;
var parentMapMatch = parentMap && getMapMatch(parentMap, name);
if (parentMapMatch)
- return doMap(loader, parentPackage, parentPackageName, parentBasePath, parentMapMatch, name, isPlugin);
+ return doMap(loader, parentPackage, parentPackageName, parentMapMatch, name, isPlugin);
}
return Promise.resolve();
@@ -1996,7 +2315,7 @@ SystemJSLoader.prototype.config = function(cfg) {
var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js';
// apply map, core, paths, contextual package map
- var normalized = normalize.call(loader, name, parentName);
+ var normalized = normalize.call(loader, name, parentName, false);
// undo defaultJSExtension
if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js')
@@ -2034,8 +2353,7 @@ SystemJSLoader.prototype.config = function(cfg) {
var length = Math.max(lastWildcard + 1, path.lastIndexOf('/'));
return {
length: length,
- // NB handle regex control character escapes or simply create a test function here
- regEx: new RegExp('^(' + path.substr(0, length).replace(/\*/g, '[^\\/]+') + ')(\\/|$)'),
+ regEx: new RegExp('^(' + path.substr(0, length).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^\\/]+') + ')(\\/|$)'),
wildcard: lastWildcard != -1
};
}
@@ -2070,12 +2388,11 @@ SystemJSLoader.prototype.config = function(cfg) {
// NB remove this when json is default
(configLoader.meta[pkgConfigPath] = configLoader.meta[pkgConfigPath] || {}).format = 'json';
+ configLoader.meta[pkgConfigPath].loader = null;
return configLoader.load(pkgConfigPath)
.then(function() {
- pkgConfig = configLoader.get(pkgConfigPath);
-
- var cfg = pkgConfig['default'];
+ var cfg = configLoader.get(pkgConfigPath)['default'];
// support "systemjs" prefixing
if (cfg.systemjs)
@@ -2087,32 +2404,7 @@ SystemJSLoader.prototype.config = function(cfg) {
warn.call(loader, 'Package config file ' + pkgConfigPath + ' is configured with "modules", which is deprecated as it has been renamed to "meta".');
}
- // remove any non-system properties if generic config file (eg package.json)
- for (var p in cfg) {
- if (indexOf.call(packageProperties, p) == -1)
- delete cfg[p];
- }
-
- // deeply-merge (to first level) config with any existing package config
- var pkg = loader.packages[pkgName] = loader.packages[pkgName] || {};
- extendMeta(pkg, cfg, true);
-
- // support external depCache
- var basePath = getBasePath(pkg);
- if (cfg.depCache) {
- for (var d in cfg.depCache) {
- var dNormalized;
-
- if (d.substr(0, 2) == './')
- dNormalized = pkgName + '/' + basePath + d.substr(2);
- else
- dNormalized = coreResolve.call(loader, d);
- loader.depCache[dNormalized] = (loader.depCache[dNormalized] || []).concat(cfg.depCache[d]);
- }
- delete cfg.depCache;
- }
-
- return pkg;
+ return setPkgConfig(loader, pkgName, cfg, true);
});
}
@@ -2138,7 +2430,7 @@ SystemJSLoader.prototype.config = function(cfg) {
}
}
// exact meta
- var exactMeta = pkgMeta[subPath] || pkgMeta['./' + subPath];
+ var exactMeta = pkgMeta[subPath] && pkgMeta.hasOwnProperty && pkgMeta.hasOwnProperty(subPath) ? pkgMeta[subPath] : pkgMeta['./' + subPath];
if (exactMeta)
matchFn(exactMeta, exactMeta, 0);
}
@@ -2151,12 +2443,7 @@ SystemJSLoader.prototype.config = function(cfg) {
var pkgName = getPackage(loader, load.name);
if (pkgName) {
var pkg = loader.packages[pkgName];
- var basePath = getBasePath(pkg);
- var subPath = load.name.substr(pkgName.length + basePath.length + 1);
-
- // format
- if (pkg.format)
- load.metadata.format = load.metadata.format || pkg.format;
+ var subPath = load.name.substr(pkgName.length + 1);
var meta = {};
if (pkg.meta) {
@@ -2169,13 +2456,12 @@ SystemJSLoader.prototype.config = function(cfg) {
extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth);
});
- // allow alias and loader to be package-relative
- if (meta.alias && meta.alias.substr(0, 2) == './')
- meta.alias = pkgName + meta.alias.substr(1);
- if (meta.loader && meta.loader.substr(0, 2) == './')
- meta.loader = pkgName + meta.loader.substr(1);
extendMeta(load.metadata, meta);
}
+
+ // format
+ if (pkg.format && !load.metadata.loader)
+ load.metadata.format = load.metadata.format || pkg.format;
}
return address;
@@ -2195,6 +2481,7 @@ SystemJSLoader.prototype.config = function(cfg) {
var head = document.getElementsByTagName('head')[0];
var curSystem;
+ var curRequire;
// if doing worker executing, this is set to the load record being executed
var workerLoad = null;
@@ -2276,7 +2563,7 @@ SystemJSLoader.prototype.config = function(cfg) {
// if nothing registered, then something went wrong
if (!load.metadata.entry)
- reject(new Error(load.address + ' did not call System.register or AMD define'));
+ reject(new Error(load.address + ' did not call System.register or AMD define. If loading a global, ensure the meta format is set to global.'));
resolve('');
});
@@ -2287,7 +2574,7 @@ SystemJSLoader.prototype.config = function(cfg) {
return function(load) {
var loader = this;
- if (!load.metadata.scriptLoad || (!isBrowser && !isWorker))
+ if (load.metadata.format == 'json' || !load.metadata.scriptLoad || (!isBrowser && !isWorker))
return fetch.call(this, load);
if (isWorker)
@@ -2297,7 +2584,10 @@ SystemJSLoader.prototype.config = function(cfg) {
var s = document.createElement('script');
s.async = true;
-
+
+ if (load.metadata.crossOrigin)
+ s.crossOrigin = load.metadata.crossOrigin;
+
if (load.metadata.integrity)
s.setAttribute('integrity', load.metadata.integrity);
@@ -2316,6 +2606,7 @@ SystemJSLoader.prototype.config = function(cfg) {
loadingCnt++;
curSystem = __global.System;
+ curRequire = __global.require;
s.src = load.address;
head.appendChild(s);
@@ -2353,6 +2644,7 @@ SystemJSLoader.prototype.config = function(cfg) {
function cleanup() {
__global.System = curSystem;
+ __global.require = curRequire;
if (s.detachEvent) {
s.detachEvent('onreadystatechange', complete);
@@ -2427,7 +2719,7 @@ SystemJSLoader.prototype.config = function(cfg) {
*
*/
-var leadingCommentAndMetaRegEx = /^\s*(\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)*\s*/;
+var leadingCommentAndMetaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)*\s*/;
function detectRegisterFormat(source) {
var leadingCommentAndMeta = source.match(leadingCommentAndMetaRegEx);
return leadingCommentAndMeta && source.substr(leadingCommentAndMeta[0].length, 15) == 'System.register';
@@ -2528,9 +2820,9 @@ function createEntry() {
curMeta.bundle = true;
}
// anonymous register
- if (!entry.name || load && entry.name == load.name) {
+ if (!entry.name || load && !curMeta.entry && entry.name == load.name) {
if (!curMeta)
- throw new TypeError('Unexpected anonymous System.register call.');
+ throw new TypeError('Invalid System.register call. Anonymous System.register calls can only be made by modules loaded by SystemJS.import and not via script tags.');
if (curMeta.entry) {
if (curMeta.format == 'register')
throw new Error('Multiple anonymous System.register calls in module ' + load.name + '. If loading a bundle, ensure all the System.register calls are named.');
@@ -2591,9 +2883,7 @@ function createEntry() {
}
}
- function link(name, loader) {
- var startEntry = loader.defined[name];
-
+ function link(name, startEntry, loader) {
// skip if already linked
if (startEntry.module)
return;
@@ -2621,8 +2911,8 @@ function createEntry() {
}
// module binding records
- function Module() {}
- defineProperty(Module, 'toString', {
+ function ModuleRecord() {}
+ defineProperty(ModuleRecord, 'toString', {
value: function() {
return 'Module';
}
@@ -2632,7 +2922,7 @@ function createEntry() {
return moduleRecords[name] || (moduleRecords[name] = {
name: name,
dependencies: [],
- exports: new Module(), // start from an empty module and extend
+ exports: new ModuleRecord(), // start from an empty module and extend
importers: []
});
}
@@ -2661,13 +2951,21 @@ function createEntry() {
var importerModule = module.importers[i];
if (!importerModule.locked) {
var importerIndex = indexOf.call(importerModule.dependencies, module);
- importerModule.setters[importerIndex](exports);
+ var setter = importerModule.setters[importerIndex];
+ if (setter)
+ setter(exports);
}
}
module.locked = false;
return value;
- }, entry.name);
+ }, { id: entry.name });
+
+ if (typeof declaration == 'function')
+ declaration = { setters: [], execute: declaration };
+
+ // allowing undefined declaration was a mistake! To be deprecated.
+ declaration = declaration || { setters: [], execute: function() {} };
module.setters = declaration.setters;
module.execute = declaration.execute;
@@ -2736,7 +3034,7 @@ function createEntry() {
else {
if (entry.declarative)
- ensureEvaluated(name, [], loader);
+ ensureEvaluated(name, entry, [], loader);
else if (!entry.evaluated)
linkDynamicModule(entry, loader);
@@ -2777,24 +3075,29 @@ function createEntry() {
continue;
return getModule(entry.normalizedDeps[i], loader);
}
- throw new Error('Module ' + name + ' not declared as a dependency.');
+ // try and normalize the dependency to see if we have another form
+ var nameNormalized = loader.normalizeSync(name, entry.name);
+ if (indexOf.call(entry.normalizedDeps, nameNormalized) != -1)
+ return getModule(nameNormalized, loader);
+
+ throw new Error('Module ' + name + ' not declared as a dependency of ' + entry.name);
}, exports, module);
- if (output)
+ if (output !== undefined)
module.exports = output;
// create the esModule object, which allows ES6 named imports of dynamics
exports = module.exports;
// __esModule flag treats as already-named
- if (exports && exports.__esModule)
- entry.esModule = exports;
+ if (exports && (exports.__esModule || exports instanceof Module))
+ entry.esModule = loader.newModule(exports);
// set module as 'default' export, then fake named exports by iterating properties
else if (entry.esmExports && exports !== __global)
- entry.esModule = getESModule(exports);
+ entry.esModule = loader.newModule(getESModule(exports));
// just use the 'default' export
else
- entry.esModule = { 'default': exports };
+ entry.esModule = loader.newModule({ 'default': exports, __useDefault: true });
}
/*
@@ -2806,9 +3109,7 @@ function createEntry() {
* Then we evaluate the module itself depth-first left to right
* execution to match ES6 modules
*/
- function ensureEvaluated(moduleName, seen, loader) {
- var entry = loader.defined[moduleName];
-
+ function ensureEvaluated(moduleName, entry, seen, loader) {
// if already seen, that means it's an already-evaluated non circular dependency
if (!entry || entry.evaluated || !entry.declarative)
return;
@@ -2823,7 +3124,7 @@ function createEntry() {
if (!loader.defined[depName])
loader.get(depName);
else
- ensureEvaluated(depName, seen, loader);
+ ensureEvaluated(depName, loader.defined[depName], seen, loader);
}
}
@@ -2849,9 +3150,6 @@ function createEntry() {
load.metadata.format = 'defined';
return '';
}
-
- if (load.metadata.format == 'register' && !load.metadata.authorization && load.metadata.scriptLoad !== false)
- load.metadata.scriptLoad = true;
load.metadata.deps = load.metadata.deps || [];
@@ -2863,7 +3161,7 @@ function createEntry() {
// we run the meta detection here (register is after meta)
return function(load) {
load.metadata.deps = load.metadata.deps || [];
- return Promise.resolve(translate.call(this, load)).then(function(source) {
+ return Promise.resolve(translate.apply(this, arguments)).then(function(source) {
// run detection for register format
if (load.metadata.format == 'register' || !load.metadata.format && detectRegisterFormat(load.source))
load.metadata.format = 'register';
@@ -2872,6 +3170,37 @@ function createEntry() {
};
});
+ // implement a perforance shortpath for System.load with no deps
+ hook('load', function(doLoad) {
+ return function(normalized) {
+ var loader = this;
+ var entry = loader.defined[normalized];
+
+ if (!entry || entry.deps.length)
+ return doLoad.apply(this, arguments);
+
+ entry.originalIndices = entry.normalizedDeps = [];
+
+ // recursively ensure that the module and all its
+ // dependencies are linked (with dependency group handling)
+ link(normalized, entry, loader);
+
+ // now handle dependency execution in correct order
+ ensureEvaluated(normalized, entry, [], loader);
+ if (!entry.esModule)
+ entry.esModule = loader.newModule(entry.module.exports);
+
+ // remove from the registry
+ if (!loader.trace)
+ loader.defined[normalized] = undefined;
+
+ // return the defined module object
+ loader.set(normalized, entry.esModule);
+
+ return Promise.resolve();
+ };
+ });
+
hook('instantiate', function(instantiate) {
return function(load) {
if (load.metadata.format == 'detect')
@@ -2891,6 +3220,7 @@ function createEntry() {
// don't support deps for ES modules
if (!entry.declarative)
entry.deps = entry.deps.concat(load.metadata.deps);
+ entry.deps = entry.deps.concat(load.metadata.deps);
}
// picked up already by an anonymous System.register script injection
@@ -2949,31 +3279,57 @@ function createEntry() {
execute: function() {
// recursively ensure that the module and all its
// dependencies are linked (with dependency group handling)
- link(load.name, loader);
+ link(load.name, entry, loader);
// now handle dependency execution in correct order
- ensureEvaluated(load.name, [], loader);
+ ensureEvaluated(load.name, entry, [], loader);
+
+ if (!entry.esModule)
+ entry.esModule = loader.newModule(entry.module.exports);
// remove from the registry
- loader.defined[load.name] = undefined;
+ if (!loader.trace)
+ loader.defined[load.name] = undefined;
// return the defined module object
- return loader.newModule(entry.declarative ? entry.module.exports : entry.esModule);
+ return entry.esModule;
}
};
});
};
});
})();
+
+
+function getGlobalValue(exports) {
+ if (typeof exports == 'string')
+ return readMemberExpression(exports, __global);
+
+ if (!(exports instanceof Array))
+ throw new Error('Global exports must be a string or array.');
+
+ var globalValue = {};
+ var first = true;
+ for (var i = 0; i < exports.length; i++) {
+ var val = readMemberExpression(exports[i], __global);
+ if (first) {
+ globalValue['default'] = val;
+ first = false;
+ }
+ globalValue[exports[i].split('.').pop()] = val;
+ }
+ return globalValue;
+}
+
hook('reduceRegister_', function(reduceRegister) {
return function(load, register) {
- if (register || !load.metadata.exports)
+ if (register || (!load.metadata.exports && !(isWorker && load.metadata.format == 'global')))
return reduceRegister.call(this, load, register);
load.metadata.format = 'global';
var entry = load.metadata.entry = createEntry();
entry.deps = load.metadata.deps;
- var globalValue = readMemberExpression(load.metadata.exports, __global);
+ var globalValue = getGlobalValue(load.metadata.exports);
entry.execute = function() {
return globalValue;
};
@@ -2987,7 +3343,7 @@ hookConstructor(function(constructor) {
var hasOwnProperty = Object.prototype.hasOwnProperty;
- // bare minimum ignores for IE8
+ // bare minimum ignores
var ignoredGlobalProps = ['_g', 'sessionStorage', 'localStorage', 'clipboardData', 'frames', 'frameElement', 'external',
'mozAnimationStartTime', 'webkitStorageInfo', 'webkitIndexedDB', 'mozInnerScreenY', 'mozInnerScreenX'];
@@ -3019,14 +3375,11 @@ hookConstructor(function(constructor) {
}
loader.set('@@global-helpers', loader.newModule({
- prepareGlobal: function(moduleName, exportName, globals) {
+ prepareGlobal: function(moduleName, exports, globals, encapsulate) {
// disable module detection
var curDefine = __global.define;
__global.define = undefined;
- __global.exports = undefined;
- if (__global.module && __global.module.exports)
- __global.module = undefined;
// set globals
var oldGlobals;
@@ -3039,7 +3392,7 @@ hookConstructor(function(constructor) {
}
// store a complete copy of the global object in order to detect changes
- if (!exportName) {
+ if (!exports) {
globalSnapshot = {};
forEachGlobalValue(function(name, value) {
@@ -3049,33 +3402,36 @@ hookConstructor(function(constructor) {
// return function to retrieve global
return function() {
- var globalValue;
+ var globalValue = exports ? getGlobalValue(exports) : {};
- if (exportName) {
- globalValue = readMemberExpression(exportName, __global);
- }
- else {
- var singleGlobal;
- var multipleExports;
- var exports = {};
+ var singleGlobal;
+ var multipleExports = !!exports;
+ if (!exports || encapsulate)
forEachGlobalValue(function(name, value) {
if (globalSnapshot[name] === value)
return;
if (typeof value == 'undefined')
return;
- exports[name] = value;
-
- if (typeof singleGlobal != 'undefined') {
- if (!multipleExports && singleGlobal !== value)
- multipleExports = true;
- }
- else {
- singleGlobal = value;
+
+ // allow global encapsulation where globals are removed
+ if (encapsulate)
+ __global[name] = undefined;
+
+ if (!exports) {
+ globalValue[name] = value;
+
+ if (typeof singleGlobal != 'undefined') {
+ if (!multipleExports && singleGlobal !== value)
+ multipleExports = true;
+ }
+ else {
+ singleGlobal = value;
+ }
}
});
- globalValue = multipleExports ? exports : singleGlobal;
- }
+
+ globalValue = multipleExports ? globalValue : singleGlobal;
// revert globals
if (oldGlobals) {
@@ -3098,7 +3454,20 @@ hookConstructor(function(constructor) {
if (typeof window != 'undefined' && typeof document != 'undefined' && window.location)
var windowOrigin = location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
+ function stripOrigin(path) {
+ if (path.substr(0, 8) == 'file:///')
+ return path.substr(7 + !!isWindows);
+
+ if (windowOrigin && path.substr(0, windowOrigin.length) == windowOrigin)
+ return path.substr(windowOrigin.length);
+
+ return path;
+ }
+
loader.set('@@cjs-helpers', loader.newModule({
+ requireResolve: function(request, parentId) {
+ return stripOrigin(loader.normalizeSync(request, parentId));
+ },
getPathVars: function(moduleId) {
// remove any plugin syntax
var pluginIndex = moduleId.lastIndexOf('!');
@@ -3112,24 +3481,9 @@ hookConstructor(function(constructor) {
dirname.pop();
dirname = dirname.join('/');
- if (filename.substr(0, 8) == 'file:///') {
- filename = filename.substr(7);
- dirname = dirname.substr(7);
-
- // on windows remove leading '/'
- if (isWindows) {
- filename = filename.substr(1);
- dirname = dirname.substr(1);
- }
- }
- else if (windowOrigin && filename.substr(0, windowOrigin.length) === windowOrigin) {
- filename = filename.substr(windowOrigin.length);
- dirname = dirname.substr(windowOrigin.length);
- }
-
return {
- filename: filename,
- dirname: dirname
+ filename: stripOrigin(filename),
+ dirname: stripOrigin(dirname)
};
}
}))
@@ -3139,6 +3493,16 @@ hookConstructor(function(constructor) {
* Separated into its own file as this is the part needed for full AMD support in SFX builds
* NB since implementations have now diverged this can be merged back with amd.js
*/
+
+hook('fetch', function(fetch) {
+ return function(load) {
+ // script load implies define global leak
+ if (load.metadata.scriptLoad && isBrowser)
+ __global.define = this.amdDefine;
+ return fetch.call(this, load);
+ };
+});
+
hookConstructor(function(constructor) {
return function() {
var loader = this;
@@ -3199,9 +3563,13 @@ hookConstructor(function(constructor) {
// commonjs require
else if (typeof names == 'string') {
- var module = loader.get(loader.decanonicalize(names, referer));
+ var defaultJSExtension = loader.defaultJSExtensions && names.substr(names.length - 3, 3) != '.js';
+ var normalized = loader.decanonicalize(names, referer);
+ if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) == '.js')
+ normalized = normalized.substr(0, normalized.length - 3);
+ var module = loader.get(normalized);
if (!module)
- throw new Error('Module not already loaded loading "' + names + '" from "' + referer + '".');
+ throw new Error('Module not already loaded loading "' + names + '" as ' + normalized + (referer ? ' from "' + referer + '".' : '.'));
return module.__useDefault ? module['default'] : module;
}
@@ -3318,17 +3686,20 @@ hookConstructor(function(constructor) {
var curMeta = load && load.metadata;
var entry = register.entry;
- if (curMeta)
- curMeta.format = 'amd';
+ if (curMeta) {
+ if (!curMeta.format || curMeta.format == 'detect')
+ curMeta.format = 'amd';
+ else if (!entry.name && curMeta.format != 'amd')
+ throw new Error('AMD define called while executing ' + curMeta.format + ' module ' + load.name);
+ }
// anonymous define
if (!entry.name) {
if (!curMeta)
throw new TypeError('Unexpected anonymous AMD define.');
- // already defined anonymously -> throw
- if (curMeta.entry)
- throw new TypeError('Multiple defines for anonymous module ' + load.name);
+ if (curMeta.entry && !curMeta.entry.name)
+ throw new Error('Multiple anonymous defines in module ' + load.name);
curMeta.entry = entry;
}
@@ -3344,7 +3715,7 @@ hookConstructor(function(constructor) {
if (curMeta) {
if (!curMeta.entry && !curMeta.bundle)
curMeta.entry = entry;
- else
+ else if (curMeta.entry && curMeta.entry.name && curMeta.entry.name != load.name)
curMeta.entry = undefined;
// note this is now a bundle
@@ -3358,29 +3729,6 @@ hookConstructor(function(constructor) {
};
});
- // adds define as a global (potentially just temporarily)
- function createDefine() {
- // ensure no NodeJS environment detection
- var oldModule = __global.module;
- var oldExports = __global.exports;
- var oldDefine = __global.define;
-
- __global.module = undefined;
- __global.exports = undefined;
- __global.define = define;
-
- return function() {
- __global.define = oldDefine;
- __global.module = oldModule;
- __global.exports = oldExports;
- };
- }
-
- loader.set('@@amd-helpers', loader.newModule({
- createDefine: createDefine,
- require: require,
- define: define
- }));
loader.amdDefine = define;
loader.amdRequire = require;
};
@@ -3459,8 +3807,8 @@ hookConstructor(function(constructor) {
return function(name, parentName, isPlugin) {
var loader = this;
- parentName = getParentName(this, parentName);
var parsed = parsePlugin(loader, name);
+ parentName = getParentName(this, parentName);
if (!parsed)
return normalizeSync.call(this, name, parentName, isPlugin);
@@ -3488,7 +3836,7 @@ hookConstructor(function(constructor) {
return Promise.all([
loader.normalize(parsed.argument, parentName, true),
- loader.normalize(parsed.plugin, parentName, true)
+ loader.normalize(parsed.plugin, parentName, false)
])
.then(function(normalized) {
return combinePluginParts(loader, normalized[0], normalized[1], checkDefaultExtension(loader, parsed.argument));
@@ -3519,11 +3867,27 @@ hookConstructor(function(constructor) {
return locate.call(loader, load)
.then(function(address) {
+ if (pluginSyntaxIndex != -1 || !load.metadata.loader)
+ return address;
+
+ // normalize plugin relative to parent in locate here when
+ // using plugin via loader metadata
+ return (loader.pluginLoader || loader).normalize(load.metadata.loader, load.name)
+ .then(function(loaderNormalized) {
+ load.metadata.loader = loaderNormalized;
+ return address;
+ });
+ })
+ .then(function(address) {
var plugin = load.metadata.loader;
if (!plugin)
return address;
+ // don't allow a plugin to load itself
+ if (load.name == plugin)
+ throw new Error('Plugin ' + plugin + ' cannot load itself, make sure it is excluded from any wildcard meta configuration via a custom loader: false rule.');
+
// only fetch the plugin itself if this name isn't defined
if (loader.defined && loader.defined[name])
return address;
@@ -3563,41 +3927,41 @@ hookConstructor(function(constructor) {
hook('translate', function(translate) {
return function(load) {
-
- /*
- * Source map sanitization for load.metadata.sourceMap
- * Used to set browser and build-level source maps for
- * translated sources in a general way.
- *
- * This isn't plugin-specific, but can't go anywhere else for now
- * As it is post-translate
- */
- var sourceMap = load.metadata.sourceMap;
-
- // if an object not a JSON string do sanitizing
- if (sourceMap && typeof sourceMap == 'object') {
- var originalName = load.name.split('!')[0];
-
- // force set the filename of the original file
- sourceMap.file = originalName + '!transpiled';
-
- // force set the sources list if only one source
- if (!sourceMap.sources || sourceMap.sources.length == 1)
- sourceMap.sources = [originalName];
- load.metadata.sourceMap = JSON.stringify(sourceMap);
- }
-
var loader = this;
+ var args = arguments;
if (load.metadata.loaderModule && load.metadata.loaderModule.translate && load.metadata.format != 'defined') {
- return Promise.resolve(load.metadata.loaderModule.translate.call(loader, load)).then(function(result) {
- // NB we should probably enforce a string output
+ return Promise.resolve(load.metadata.loaderModule.translate.apply(loader, args)).then(function(result) {
+ var sourceMap = load.metadata.sourceMap;
+
+ // sanitize sourceMap if an object not a JSON string
+ if (sourceMap) {
+ if (typeof sourceMap != 'object')
+ throw new Error('load.metadata.sourceMap must be set to an object.');
+
+ var originalName = load.address.split('!')[0];
+
+ // force set the filename of the original file
+ if (!sourceMap.file || sourceMap.file == load.address)
+ sourceMap.file = originalName + '!transpiled';
+
+ // force set the sources list if only one source
+ if (!sourceMap.sources || sourceMap.sources.length <= 1 && (!sourceMap.sources[0] || sourceMap.sources[0] == load.address))
+ sourceMap.sources = [originalName];
+ }
+
+ // if running on file:/// URLs, sourcesContent is necessary
+ // load.metadata.sourceMap.sourcesContent = [load.source];
+
if (typeof result == 'string')
load.source = result;
- return translate.call(loader, load);
+ else
+ warn.call(this, 'Plugin ' + load.metadata.loader + ' should return the source in translate, instead of setting load.source directly. This support will be deprecated.');
+
+ return translate.apply(loader, args);
});
}
else {
- return translate.call(loader, load);
+ return translate.apply(loader, args);
}
};
});
@@ -3605,9 +3969,18 @@ hookConstructor(function(constructor) {
hook('instantiate', function(instantiate) {
return function(load) {
var loader = this;
+ var calledInstantiate = false;
if (load.metadata.loaderModule && load.metadata.loaderModule.instantiate && !loader.builder && load.metadata.format != 'defined')
- return Promise.resolve(load.metadata.loaderModule.instantiate.call(loader, load)).then(function(result) {
+ return Promise.resolve(load.metadata.loaderModule.instantiate.call(loader, load, function(load) {
+ if (calledInstantiate)
+ throw new Error('Instantiate must only be called once.');
+ calledInstantiate = true;
+ return instantiate.call(loader, load);
+ })).then(function(result) {
+ if (calledInstantiate)
+ return result;
+
load.metadata.entry = createEntry();
load.metadata.entry.execute = function() {
return result;
@@ -3657,10 +4030,12 @@ hookConstructor(function(constructor) {
*
* These conditions can also be negated via:
*
- * import 'es5-shim#?~./conditions.js|es6'
+ * import 'es5-shim#?./conditions.js|~es6'
*
*/
+ var sysConditions = ['browser', 'node', 'dev', 'build', 'production', 'default'];
+
function parseCondition(condition) {
var conditionExport, conditionModule, negation;
@@ -3668,33 +4043,49 @@ hookConstructor(function(constructor) {
var conditionExportIndex = condition.lastIndexOf('|');
if (conditionExportIndex != -1) {
conditionExport = condition.substr(conditionExportIndex + 1);
- conditionModule = condition.substr(negation, conditionExportIndex - negation) || '@system-env';
+ conditionModule = condition.substr(negation, conditionExportIndex - negation);
+
+ if (negation)
+ warn.call(this, 'Condition negation form "' + condition + '" is deprecated for "' + conditionModule + '|~' + conditionExport + '"');
+
+ if (conditionExport[0] == '~') {
+ negation = true;
+ conditionExport = conditionExport.substr(1);
+ }
}
else {
- conditionExport = null;
+ conditionExport = 'default';
conditionModule = condition.substr(negation);
+ if (sysConditions.indexOf(conditionModule) != -1) {
+ conditionExport = conditionModule;
+ conditionModule = null;
+ }
}
return {
- module: conditionModule,
+ module: conditionModule || '@system-env',
prop: conditionExport,
negate: negation
};
}
function serializeCondition(conditionObj) {
- return (conditionObj.negate ? '~' : '') + conditionObj.module + (conditionObj.prop ? '|' + conditionObj.prop : '');
+ return conditionObj.module + '|' + (conditionObj.negate ? '~' : '') + conditionObj.prop;
}
function resolveCondition(conditionObj, parentName, bool) {
- return this['import'](conditionObj.module, parentName)
- .then(function(m) {
- if (conditionObj.prop)
- m = readMemberExpression(conditionObj.prop, m);
- else if (typeof m == 'object' && m + '' == 'Module')
- m = m['default'];
-
- return conditionObj.negate ? !m : m;
+ var self = this;
+ return this.normalize(conditionObj.module, parentName)
+ .then(function(normalizedCondition) {
+ return self.load(normalizedCondition)
+ .then(function(q) {
+ var m = readMemberExpression(conditionObj.prop, self.get(normalizedCondition));
+
+ if (bool && typeof m != 'boolean')
+ throw new TypeError('Condition ' + serializeCondition(conditionObj) + ' did not resolve to a boolean.');
+
+ return conditionObj.negate ? !m : m;
+ });
});
}
@@ -3706,7 +4097,7 @@ hookConstructor(function(constructor) {
if (!conditionalMatch)
return Promise.resolve(name);
- var conditionObj = parseCondition(conditionalMatch[0].substr(2, conditionalMatch[0].length - 3));
+ var conditionObj = parseCondition.call(this, conditionalMatch[0].substr(2, conditionalMatch[0].length - 3));
// in builds, return normalized conditional
if (this.builder)
@@ -3735,7 +4126,7 @@ hookConstructor(function(constructor) {
if (booleanIndex == -1)
return Promise.resolve(name);
- var conditionObj = parseCondition(name.substr(booleanIndex + 2));
+ var conditionObj = parseCondition.call(this, name.substr(booleanIndex + 2));
// in builds, return normalized conditional
if (this.builder)
@@ -3753,11 +4144,11 @@ hookConstructor(function(constructor) {
// normalizeSync does not parse conditionals at all although it could
hook('normalize', function(normalize) {
- return function(name, parentName, parentAddress) {
+ return function(name, parentName, skipExt) {
var loader = this;
return booleanConditional.call(loader, name, parentName)
.then(function(name) {
- return normalize.call(loader, name, parentName, parentAddress);
+ return normalize.call(loader, name, parentName, skipExt);
})
.then(function(normalized) {
return interpolateConditional.call(loader, normalized, parentName);
@@ -3904,6 +4295,12 @@ hookConstructor(function(constructor) {
hook('translate', function(translate) {
return function(load) {
+ // shortpath for bundled
+ if (load.metadata.format == 'defined') {
+ load.metadata.deps = load.metadata.deps || [];
+ return Promise.resolve(load.source);
+ }
+
// NB meta will be post-translate pending transpiler conversion to plugins
var meta = load.source.match(metaRegEx);
if (meta) {
@@ -3946,7 +4343,7 @@ hookConstructor(function(constructor) {
}
}
- return translate.call(this, load);
+ return translate.apply(this, arguments);
};
});
})();
@@ -4074,10 +4471,7 @@ hookConstructor(function(constructor) {
hookConstructor(function(constructor) {
return function() {
constructor.apply(this, arguments);
-
- // prepare amd define
- if (this.has('@@amd-helpers'))
- this.get('@@amd-helpers').createDefine();
+ __global.define = this.amdDefine;
};
});
@@ -4089,40 +4483,24 @@ hook('fetch', function(fetch) {
});System = new SystemJSLoader();
__global.SystemJS = System;
-System.version = '0.19.17 CSP';
- // -- exporting --
-
- if (typeof exports === 'object')
- module.exports = Loader;
-
- __global.Reflect = __global.Reflect || {};
- __global.Reflect.Loader = __global.Reflect.Loader || Loader;
- __global.Reflect.global = __global.Reflect.global || __global;
- __global.LoaderPolyfill = Loader;
-
- if (!System) {
- System = new SystemLoader();
- System.constructor = SystemLoader;
- }
-
- if (typeof exports === 'object')
+System.version = '0.19.39 CSP';
+ if (typeof module == 'object' && module.exports && typeof exports == 'object')
module.exports = System;
__global.System = System;
})(typeof self != 'undefined' ? self : global);}
-// auto-load Promise and URL polyfills if needed in the browser
-try {
- var hasURL = typeof URLPolyfill != 'undefined' || new URL('test:///').protocol == 'test:';
-}
-catch(e) {}
+// auto-load Promise polyfill if needed in the browser
+var doPolyfill = typeof Promise === 'undefined';
-if (typeof Promise === 'undefined' || !hasURL) {
- // document.write
- if (typeof document !== 'undefined') {
- var scripts = document.getElementsByTagName('script');
- $__curScript = scripts[scripts.length - 1];
+// document.write
+if (typeof document !== 'undefined') {
+ var scripts = document.getElementsByTagName('script');
+ $__curScript = scripts[scripts.length - 1];
+ if (document.currentScript && ($__curScript.defer || $__curScript.async))
+ $__curScript = document.currentScript;
+ if (doPolyfill) {
var curPath = $__curScript.src;
var basePath = curPath.substr(0, curPath.lastIndexOf('/') + 1);
window.systemJSBootstrap = bootstrap;
@@ -4130,24 +4508,27 @@ if (typeof Promise === 'undefined' || !hasURL) {
'<' + 'script type="text/javascript" src="' + basePath + 'system-polyfills.js">' + '<' + '/script>'
);
}
- // importScripts
- else if (typeof importScripts !== 'undefined') {
- var basePath = '';
- try {
- throw new Error('_');
- } catch (e) {
- e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/, function(m, url) {
- basePath = url.replace(/\/[^\/]*$/, '/');
- });
- }
- importScripts(basePath + 'system-polyfills.js');
- bootstrap();
- }
else {
bootstrap();
}
}
+// importScripts
+else if (typeof importScripts !== 'undefined') {
+ var basePath = '';
+ try {
+ throw new Error('_');
+ } catch (e) {
+ e.stack.replace(/(?:at|@).*(http.+):[\d]+:[\d]+/, function(m, url) {
+ $__curScript = { src: url };
+ basePath = url.replace(/\/[^\/]*$/, '/');
+ });
+ }
+ if (doPolyfill)
+ importScripts(basePath + 'system-polyfills.js');
+ bootstrap();
+}
else {
+ $__curScript = typeof __filename != 'undefined' ? { src: __filename } : null;
bootstrap();
}
diff --git a/lib/wallet/chromeBadge.ts b/lib/wallet/chromeBadge.ts
index 6586f7e6e..df12fba83 100644
--- a/lib/wallet/chromeBadge.ts
+++ b/lib/wallet/chromeBadge.ts
@@ -86,6 +86,9 @@ export class ChromeBadge implements Badge {
constructor(window?: Window) {
// Allow injecting another window for testing
let bg = window || chrome.extension.getBackgroundPage();
+ if (!bg) {
+ throw Error("no window available");
+ }
this.canvas = bg.document.createElement("canvas");
// Note: changing the width here means changing the font
// size in draw() as well!
@@ -221,4 +224,4 @@ export class ChromeBadge implements Badge {
stopBusy() {
this.isBusy = false;
}
-} \ No newline at end of file
+}
diff --git a/lib/wallet/wallet.ts b/lib/wallet/wallet.ts
index 32b85e7b0..ffd57e201 100644
--- a/lib/wallet/wallet.ts
+++ b/lib/wallet/wallet.ts
@@ -612,8 +612,7 @@ export class Wallet {
* First fetch information requred to withdraw from the reserve,
* then deplete the reserve, withdrawing coins until it is empty.
*/
- private processReserve(reserveRecord: any): void {
- let retryDelayMs = 100;
+ private processReserve(reserveRecord: any, retryDelayMs: number = 250): void {
const opId = "reserve-" + reserveRecord.reserve_pub;
this.startOperation(opId);
this.updateExchangeFromUrl(reserveRecord.exchange_base_url)
@@ -633,11 +632,10 @@ export class Wallet {
return Query(this.db).put("history", depleted).finish();
})
.catch((e) => {
- console.error("Failed to deplete reserve");
- console.error(e);
- setTimeout(() => this.processReserve(reserveRecord), retryDelayMs);
- // exponential backoff truncated at one minute
- retryDelayMs = Math.min(retryDelayMs * 2, 1000 * 60);
+ // random, exponential backoff truncated at 3 minutes
+ let nextDelay = Math.min(2 * retryDelayMs + retryDelayMs * Math.random(), 3000 * 60);
+ console.warn(`Failed to deplete reserve, trying again in ${retryDelayMs} ms`);
+ setTimeout(() => this.processReserve(reserveRecord, nextDelay), retryDelayMs);
});
}