function readMemberExpression(p, value) { var pParts = p.split('.'); while (pParts.length) value = value[pParts.shift()]; return value; } function getMapMatch(map, name) { var bestMatch, bestMatchLength = 0; for (var p in map) { if (name.substr(0, p.length) == p && (name.length == p.length || name[p.length] == '/')) { var curMatchLength = p.split('/').length; if (curMatchLength <= bestMatchLength) continue; bestMatch = p; bestMatchLength = curMatchLength; } } return bestMatch; } 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: !isBuilder && isProduction, dev: isBuilder || !isProduction, build: isBuilder, 'default': true })); } hookConstructor(function(constructor) { return function() { constructor.call(this); // support baseURL this.baseURL = baseURI; // 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.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' }; // support the empty module, as a concept this.set('@empty', this.newModule({})); setProduction.call(this, false, false); }; }); // include the node require since we're overriding it if (typeof require != 'undefined' && typeof process != 'undefined' && !process.browser) SystemJSLoader.prototype._nodeRequire = require; /* Core SystemJS Normalization If a name is relative, we apply URL normalization to the page If a name is an absolute URL, we leave it as-is Plain names (neither of the above) run through the map and paths normalization phases. The paths normalization phase applies last (paths extension), which defines the `decanonicalize` function and normalizes everything into a URL. */ 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 (!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); } function coreResolve(name, parentName) { // standard URL resolution if (isRel(name)) return urlResolve(name, parentName); else if (isAbsolute(name)) return name; // plain names not starting with './', '://' and '/' go through custom resolution var mapMatch = getMapMatch(this.map, name); if (mapMatch) { name = this.map[mapMatch] + name.substr(mapMatch.length); 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 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; }; }); // percent encode just '#' in urls if using HTTP requests var httpRequest = typeof XMLHttpRequest != 'undefined'; hook('locate', function(locate) { return function(load) { return Promise.resolve(locate.call(this, load)) .then(function(address) { if (httpRequest) return address.replace(/#/g, '%23'); return address; }); }; }); /* * Fetch with authorization */ hook('fetch', function() { return function(load) { return new Promise(function(resolve, reject) { fetchTextFromURL(load.address, load.metadata.authorization, resolve, reject); }); }; }); /* __useDefault When a module object looks like: newModule( __useDefault: true, default: 'some-module' }) Then importing that module provides the 'some-module' result directly instead of the full module. Useful for eg module.exports = function() {} */ hook('import', function(systemImport) { return function(name, parentName, parentAddress) { if (parentName && parentName.name) warn.call(this, 'SystemJS.import(name, { name: parentName }) is deprecated for SystemJS.import(name, parentName), while importing ' + name + ' from ' + parentName.name); return systemImport.call(this, name, parentName, parentAddress).then(function(module) { return module.__useDefault ? module['default'] : module; }); }; }); /* * Allow format: 'detect' meta to enable format detection */ hook('translate', function(systemTranslate) { return function(load) { if (load.metadata.format == 'detect') load.metadata.format = undefined; return systemTranslate.apply(this, arguments); }; }); /* * JSON format support * * Supports loading JSON files as a module format itself * * Usage: * * SystemJS.config({ * meta: { * '*.json': { format: 'json' } * } * }); * * Module is returned as if written: * * export default {JSON} * * No named exports are provided * * Files ending in ".json" are treated as json automatically by SystemJS */ hook('instantiate', function(instantiate) { return function(load) { if (load.metadata.format == 'json' && !this.builder) { var entry = load.metadata.entry = createEntry(); entry.deps = []; entry.execute = function() { try { return JSON.parse(load.source); } catch(e) { throw new Error("Invalid JSON file " + load.name); } }; } }; }) /* Extend config merging one deep only loader.config({ some: 'random', config: 'here', deep: { config: { too: 'too' } } }); <=> loader.some = 'random'; loader.config = 'here' loader.deep = loader.deep || {}; loader.deep.config = { too: 'too' }; Normalizes meta and package configs allowing for: SystemJS.config({ meta: { './index.js': {} } }); To become SystemJS.meta['https://thissite.com/index.js'] = {}; For easy normalization canonicalization with latest URL support. */ 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.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; // transpiler deprecation path if (cfg.transpilerRuntime === false) loader._loader.loadedTranspilerRuntime = 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 (cfg.paths) extend(loader.paths, cfg.paths); envSet(loader, cfg, function(cfg) { if (cfg.paths) extend(loader.paths, cfg.paths); }); // 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) { loader.defaultJSExtensions = cfg.defaultJSExtensions; warn.call(loader, 'The defaultJSExtensions configuration option is deprecated, use packages configuration instead.'); } if (cfg.pluginFirst) loader.pluginFirst = cfg.pluginFirst; if (cfg.map) { var objMaps = ''; for (var p in cfg.map) { var v = cfg.map[p]; // object map backwards-compat into packages configuration if (typeof v !== 'string') { objMaps += (objMaps.length ? ', ' : '') + '"' + p + '"'; 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 = ''; for (var pkg in loader.packages) { if (prop.substr(0, pkg.length) == pkg && (!prop[pkg.length] || prop[pkg.length] == '/') && pkgMatch.split('/').length < pkg.split('/').length) pkgMatch = pkg; } if (pkgMatch && loader.packages[pkgMatch].main) prop = prop.substr(0, prop.length - loader.packages[pkgMatch].main.length - 1); var pkg = loader.packages[prop] = loader.packages[prop] || {}; pkg.map = v; } else { loader.map[p] = v; } } if (objMaps) warn.call(loader, 'The map configuration for ' + objMaps + ' uses object submaps, which is deprecated in global map.\nUpdate this to use package contextual map with configs like SystemJS.config({ packages: { "' + p + '": { map: {...} } } }).'); } if (cfg.packageConfigPaths) { var packageConfigPaths = []; 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 = coreResolve.call(loader, path.substr(0, packageLength)); packageConfigPaths[i] = normalized + path.substr(packageLength); } loader.packageConfigPaths = packageConfigPaths; } if (cfg.bundles) { for (var p in cfg.bundles) { var bundle = []; 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; } } if (cfg.packages) { for (var p in cfg.packages) { if (p.match(/^([^\/]+:)?\/\/$/)) throw new TypeError('"' + p + '" is not a valid package name.'); var prop = coreResolve.call(loader, p); // allow trailing slash in packages if (prop[prop.length - 1] == '/') prop = prop.substr(0, prop.length - 1); setPkgConfig(loader, prop, cfg.packages[p], false); } } for (var c in cfg) { var v = cfg[c]; 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) { loader[c] = v; } else { loader[c] = loader[c] || {}; for (var p in v) { // base-level wildcard meta does not normalize to retain catch-all quality 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); }); };