/*
 * SystemJS v0.19.38
 */
(function() {
    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';
            var isWindows = typeof process != 'undefined' && typeof process.platform != 'undefined' && !!process.platform.match(/^win/);

            if (!__global.console)
                __global.console = { assert: function() {} };

            // IE8 support
            var indexOf = Array.prototype.indexOf || function(item) {
                    for (var i = 0, thisLen = this.length; i < thisLen; i++) {
                        if (this[i] === item) {
                            return i;
                        }
                    }
                    return -1;
                };

            var defineProperty;
            (function () {
                try {
                    if (!!Object.defineProperty({}, 'a', {}))
                        defineProperty = Object.defineProperty;
                }
                catch (e) {
                    defineProperty = function(obj, prop, opt) {
                        try {
                            obj[prop] = opt.value || opt.get.call(obj);
                        }
                        catch(e) {}
                    }
                }
            })();

            var errArgs = new Error(0, '_').fileName == '_';

            function addToError(err, msg) {
                // 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]);
                    }
                }

                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;
            }

            function __eval(source, debugName, context) {
                try {
                    new Function(source).call(context);
                }
                catch(e) {
                    throw addToError(e, 'Evaluating ' + debugName);
                }
            }

            var baseURI;

            // environent baseURI detection
            if (typeof document != 'undefined' && document.getElementsByTagName) {
                baseURI = document.baseURI;

                if (!baseURI) {
                    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
            if (baseURI) {
                baseURI = baseURI.split('#')[0].split('?')[0];
                baseURI = baseURI.substr(0, baseURI.lastIndexOf('/') + 1);
            }
            else if (typeof process != 'undefined' && process.cwd) {
                baseURI = 'file://' + (isWindows ? '/' : '') + process.cwd() + '/';
                if (isWindows)
                    baseURI = baseURI.replace(/\\/g, '/');
            }
            else {
                throw new TypeError('No environment baseURI');
            }

            try {
                var nativeURL = new __global.URL('test:///').protocol == 'test:';
            }
            catch(e) {}

            var URL = nativeURL ? __global.URL : __global.URLPolyfill;

            /*
             *********************************************************************************************

             Dynamic Module Loader Polyfill

             - Implemented exactly to the former 2014-08-24 ES6 Specification Draft Rev 27, Section 15
             http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27

             - Functions are commented with their spec numbers, with spec differences commented.

             - Spec bugs are commented in this code with links.

             - Abstract functions have been combined where possible, and their associated functions
             commented.

             - Realm implementation is entirely omitted.

             *********************************************************************************************
             */

            function Module() {}
// http://www.ecma-international.org/ecma-262/6.0/#sec-@@tostringtag
            defineProperty(Module.prototype, 'toString', {
                value: function() {
                    return 'Module';
                }
            });
            function Loader(options) {
                this._loader = {
                    loaderObj: this,
                    loads: [],
                    modules: {},
                    importPromises: {},
                    moduleRecords: {}
                };

                // 26.3.3.6
                defineProperty(this, 'global', {
                    get: function() {
                        return __global;
                    }
                });

                // 26.3.3.13 realm not implemented
            }

            (function() {

// Some Helpers

// logs a linkset snapshot for debugging
                /* function snapshot(loader) {
                 console.log('---Snapshot---');
                 for (var i = 0; i < loader.loads.length; i++) {
                 var load = loader.loads[i];
                 var linkSetLog = '  ' + load.name + ' (' + load.status + '): ';

                 for (var j = 0; j < load.linkSets.length; j++) {
                 linkSetLog += '{' + logloads(load.linkSets[j].loads) + '} ';
                 }
                 console.log(linkSetLog);
                 }
                 console.log('');
                 }
                 function logloads(loads) {
                 var log = '';
                 for (var k = 0; k < loads.length; k++)
                 log += loads[k].name + (k != loads.length - 1 ? ' ' : '');
                 return log;
                 } */


                /* function checkInvariants() {
                 // see https://bugs.ecmascript.org/show_bug.cgi?id=2603#c1

                 var loads = System._loader.loads;
                 var linkSets = [];

                 for (var i = 0; i < loads.length; i++) {
                 var load = loads[i];
                 console.assert(load.status == 'loading' || load.status == 'loaded', 'Each load is loading or loaded');

                 for (var j = 0; j < load.linkSets.length; j++) {
                 var linkSet = load.linkSets[j];

                 for (var k = 0; k < linkSet.loads.length; k++)
                 console.assert(loads.indexOf(linkSet.loads[k]) != -1, 'linkSet loads are a subset of loader loads');

                 if (linkSets.indexOf(linkSet) == -1)
                 linkSets.push(linkSet);
                 }
                 }

                 for (var i = 0; i < loads.length; i++) {
                 var load = loads[i];
                 for (var j = 0; j < linkSets.length; j++) {
                 var linkSet = linkSets[j];

                 if (linkSet.loads.indexOf(load) != -1)
                 console.assert(load.linkSets.indexOf(linkSet) != -1, 'linkSet contains load -> load contains linkSet');

                 if (load.linkSets.indexOf(linkSet) != -1)
                 console.assert(linkSet.loads.indexOf(load) != -1, 'load contains linkSet -> linkSet contains load');
                 }
                 }

                 for (var i = 0; i < linkSets.length; i++) {
                 var linkSet = linkSets[i];
                 for (var j = 0; j < linkSet.loads.length; j++) {
                 var load = linkSet.loads[j];

                 for (var k = 0; k < load.dependencies.length; k++) {
                 var depName = load.dependencies[k].value;
                 var depLoad;
                 for (var l = 0; l < loads.length; l++) {
                 if (loads[l].name != depName)
                 continue;
                 depLoad = loads[l];
                 break;
                 }

                 // loading records are allowed not to have their dependencies yet
                 // if (load.status != 'loading')
                 //  console.assert(depLoad, 'depLoad found');

                 // console.assert(linkSet.loads.indexOf(depLoad) != -1, 'linkset contains all dependencies');
                 }
                 }
                 }
                 } */

                // 15.2.3 - Runtime Semantics: Loader State

                // 15.2.3.11
                function createLoaderLoad(object) {
                    return {
                        // modules is an object for ES5 implementation
                        modules: {},
                        loads: [],
                        loaderObj: object
                    };
                }

                // 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 || '<Anonymous' + ++anonCnt + '>',
                        linkSets: [],
                        dependencies: [],
                        metadata: {}
                    };
                }

                // 15.2.3.2.2 createLoadRequestObject, absorbed into calling functions

                // 15.2.4

                // 15.2.4.1
                function loadModule(loader, name, options) {
                    return new Promise(asyncStartLoadPartwayThrough({
                        step: options.address ? 'fetch' : 'locate',
                        loader: loader,
                        moduleName: name,
                        // allow metadata for import https://bugs.ecmascript.org/show_bug.cgi?id=3091
                        moduleMetadata: options && options.metadata || {},
                        moduleSource: options.source,
                        moduleAddress: options.address
                    }));
                }

                // 15.2.4.2
                function requestLoad(loader, request, refererName, refererAddress) {
                    // 15.2.4.2.1 CallNormalize
                    return new Promise(function(resolve, reject) {
                        resolve(loader.loaderObj.normalize(request, refererName, refererAddress));
                    })
                    // 15.2.4.2.2 GetOrCreateLoad
                        .then(function(name) {
                            var load;
                            if (loader.modules[name]) {
                                load = createLoad(name);
                                load.status = 'linked';
                                // https://bugs.ecmascript.org/show_bug.cgi?id=2795
                                load.module = loader.modules[name];
                                return load;
                            }

                            for (var i = 0, l = loader.loads.length; i < l; i++) {
                                load = loader.loads[i];
                                if (load.name != name)
                                    continue;
                                return load;
                            }

                            load = createLoad(name);
                            loader.loads.push(load);

                            proceedToLocate(loader, load);

                            return load;
                        });
                }

                // 15.2.4.3
                function proceedToLocate(loader, load) {
                    proceedToFetch(loader, load,
                        Promise.resolve()
                        // 15.2.4.3.1 CallLocate
                            .then(function() {
                                return loader.loaderObj.locate({ name: load.name, metadata: load.metadata });
                            })
                    );
                }

                // 15.2.4.4
                function proceedToFetch(loader, load, p) {
                    proceedToTranslate(loader, load,
                        p
                        // 15.2.4.4.1 CallFetch
                            .then(function(address) {
                                // adjusted, see https://bugs.ecmascript.org/show_bug.cgi?id=2602
                                if (load.status != 'loading')
                                    return;
                                load.address = address;

                                return loader.loaderObj.fetch({ name: load.name, metadata: load.metadata, address: address });
                            })
                    );
                }

                // 15.2.4.5
                function proceedToTranslate(loader, load, p) {
                    p
                    // 15.2.4.5.1 CallTranslate
                        .then(function(source) {
                            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
                                .then(function(source) {
                                    load.source = source;
                                    return loader.loaderObj.instantiate({ name: load.name, metadata: load.metadata, address: load.address, source: source });
                                })

                                // 15.2.4.5.3 InstantiateSucceeded
                                .then(function(instantiateResult) {
                                    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() {
                                    load.dependencies = [];
                                    var depsList = load.depsList;

                                    var loadPromises = [];
                                    for (var i = 0, l = depsList.length; i < l; i++) (function(request, index) {
                                        loadPromises.push(
                                            requestLoad(loader, request, load.name, load.address)

                                            // 15.2.4.6.1 AddDependencyLoad (load is parentLoad)
                                                .then(function(depLoad) {

                                                    // adjusted from spec to maintain dependency order
                                                    // this is due to the System.register internal implementation needs
                                                    load.dependencies[index] = {
                                                        key: request,
                                                        value: depLoad.name
                                                    };

                                                    if (depLoad.status != 'linked') {
                                                        var linkSets = load.linkSets.concat([]);
                                                        for (var i = 0, l = linkSets.length; i < l; i++)
                                                            addLoadToLinkSet(linkSets[i], depLoad);
                                                    }

                                                    // console.log('AddDependencyLoad ' + depLoad.name + ' for ' + load.name);
                                                    // snapshot(loader);
                                                })
                                        );
                                    })(depsList[i], i);

                                    return Promise.all(loadPromises);
                                })

                                // 15.2.4.6.2 LoadSucceeded
                                .then(function() {
                                    // console.log('LoadSucceeded ' + load.name);
                                    // snapshot(loader);

                                    load.status = 'loaded';

                                    var linkSets = load.linkSets.concat([]);
                                    for (var i = 0, l = linkSets.length; i < l; i++)
                                        updateLinkSetOnLoad(linkSets[i], load);
                                });
                        })
                        // 15.2.4.5.4 LoadFailed
                        ['catch'](function(exc) {
                        load.status = 'failed';
                        load.exception = exc;

                        var linkSets = load.linkSets.concat([]);
                        for (var i = 0, l = linkSets.length; i < l; i++) {
                            linkSetFailed(linkSets[i], load, exc);
                        }

                        console.assert(load.linkSets.length == 0, 'linkSets not removed');
                    });
                }

                // 15.2.4.7 PromiseOfStartLoadPartwayThrough absorbed into calling functions

                // 15.2.4.7.1
                function asyncStartLoadPartwayThrough(stepState) {
                    return function(resolve, reject) {
                        var loader = stepState.loader;
                        var name = stepState.moduleName;
                        var step = stepState.step;

                        if (loader.modules[name])
                            throw new TypeError('"' + name + '" already exists in the module table');

                        // adjusted to pick up existing loads
                        var existingLoad;
                        for (var i = 0, l = loader.loads.length; i < l; i++) {
                            if (loader.loads[i].name == name) {
                                existingLoad = loader.loads[i];

                                if (step == 'translate' && !existingLoad.source) {
                                    existingLoad.address = stepState.moduleAddress;
                                    proceedToTranslate(loader, existingLoad, Promise.resolve(stepState.moduleSource));
                                }

                                // a primary load -> use that existing linkset if it is for the direct load here
                                // otherwise create a new linkset unit
                                if (existingLoad.linkSets.length && existingLoad.linkSets[0].loads[0].name == existingLoad.name)
                                    return existingLoad.linkSets[0].done.then(function() {
                                        resolve(existingLoad);
                                    });
                            }
                        }

                        var load = existingLoad || createLoad(name);

                        load.metadata = stepState.moduleMetadata;

                        var linkSet = createLinkSet(loader, load);

                        loader.loads.push(load);

                        resolve(linkSet.done);

                        if (step == 'locate')
                            proceedToLocate(loader, load);

                        else if (step == 'fetch')
                            proceedToFetch(loader, load, Promise.resolve(stepState.moduleAddress));

                        else {
                            console.assert(step == 'translate', 'translate step');
                            load.address = stepState.moduleAddress;
                            proceedToTranslate(loader, load, Promise.resolve(stepState.moduleSource));
                        }
                    }
                }

                // Declarative linking functions run through alternative implementation:
                // 15.2.5.1.1 CreateModuleLinkageRecord not implemented
                // 15.2.5.1.2 LookupExport not implemented
                // 15.2.5.1.3 LookupModuleDependency not implemented

                // 15.2.5.2.1
                function createLinkSet(loader, startingLoad) {
                    var linkSet = {
                        loader: loader,
                        loads: [],
                        startingLoad: startingLoad, // added see spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995
                        loadingCount: 0
                    };
                    linkSet.done = new Promise(function(resolve, reject) {
                        linkSet.resolve = resolve;
                        linkSet.reject = reject;
                    });
                    addLoadToLinkSet(linkSet, startingLoad);
                    return linkSet;
                }
                // 15.2.5.2.2
                function addLoadToLinkSet(linkSet, load) {
                    if (load.status == 'failed')
                        return;

                    for (var i = 0, l = linkSet.loads.length; i < l; i++)
                        if (linkSet.loads[i] == load)
                            return;

                    linkSet.loads.push(load);
                    load.linkSets.push(linkSet);

                    // adjustment, see https://bugs.ecmascript.org/show_bug.cgi?id=2603
                    if (load.status != 'loaded') {
                        linkSet.loadingCount++;
                    }

                    var loader = linkSet.loader;

                    for (var i = 0, l = load.dependencies.length; i < l; i++) {
                        if (!load.dependencies[i])
                            continue;

                        var name = load.dependencies[i].value;

                        if (loader.modules[name])
                            continue;

                        for (var j = 0, d = loader.loads.length; j < d; j++) {
                            if (loader.loads[j].name != name)
                                continue;

                            addLoadToLinkSet(linkSet, loader.loads[j]);
                            break;
                        }
                    }
                    // console.log('add to linkset ' + load.name);
                    // snapshot(linkSet.loader);
                }

                // linking errors can be generic or load-specific
                // this is necessary for debugging info
                function doLink(linkSet) {
                    var error = false;
                    try {
                        link(linkSet, function(load, exc) {
                            linkSetFailed(linkSet, load, exc);
                            error = true;
                        });
                    }
                    catch(e) {
                        linkSetFailed(linkSet, null, e);
                        error = true;
                    }
                    return error;
                }

                // 15.2.5.2.3
                function updateLinkSetOnLoad(linkSet, load) {
                    // console.log('update linkset on load ' + load.name);
                    // snapshot(linkSet.loader);

                    console.assert(load.status == 'loaded' || load.status == 'linked', 'loaded or linked');

                    linkSet.loadingCount--;

                    if (linkSet.loadingCount > 0)
                        return;

                    // adjusted for spec bug https://bugs.ecmascript.org/show_bug.cgi?id=2995
                    var startingLoad = linkSet.startingLoad;

                    // non-executing link variation for loader tracing
                    // on the server. Not in spec.
                    /***/
                    if (linkSet.loader.loaderObj.execute === false) {
                        var loads = [].concat(linkSet.loads);
                        for (var i = 0, l = loads.length; i < l; i++) {
                            var load = loads[i];
                            load.module = {
                                name: load.name,
                                module: _newModule({}),
                                evaluated: true
                            };
                            load.status = 'linked';
                            finishLoad(linkSet.loader, load);
                        }
                        return linkSet.resolve(startingLoad);
                    }
                    /***/

                    var abrupt = doLink(linkSet);

                    if (abrupt)
                        return;

                    console.assert(linkSet.loads.length == 0, 'loads cleared');

                    linkSet.resolve(startingLoad);
                }

                // 15.2.5.2.4
                function linkSetFailed(linkSet, load, exc) {
                    var loader = linkSet.loader;
                    var requests;

                    checkError:
                        if (load) {
                            if (linkSet.loads[0].name == load.name) {
                                exc = addToError(exc, 'Error loading ' + load.name);
                            }
                            else {
                                for (var i = 0; i < linkSet.loads.length; i++) {
                                    var pLoad = linkSet.loads[i];
                                    for (var j = 0; j < pLoad.dependencies.length; j++) {
                                        var dep = pLoad.dependencies[j];
                                        if (dep.value == load.name) {
                                            exc = addToError(exc, 'Error loading ' + load.name + ' as "' + dep.key + '" from ' + pLoad.name);
                                            break checkError;
                                        }
                                    }
                                }
                                exc = addToError(exc, 'Error loading ' + load.name + ' from ' + linkSet.loads[0].name);
                            }
                        }
                        else {
                            exc = addToError(exc, 'Error linking ' + linkSet.loads[0].name);
                        }


                    var loads = linkSet.loads.concat([]);
                    for (var i = 0, l = loads.length; i < l; i++) {
                        var load = loads[i];

                        // store all failed load records
                        loader.loaderObj.failed = loader.loaderObj.failed || [];
                        if (indexOf.call(loader.loaderObj.failed, load) == -1)
                            loader.loaderObj.failed.push(load);

                        var linkIndex = indexOf.call(load.linkSets, linkSet);
                        console.assert(linkIndex != -1, 'link not present');
                        load.linkSets.splice(linkIndex, 1);
                        if (load.linkSets.length == 0) {
                            var globalLoadsIndex = indexOf.call(linkSet.loader.loads, load);
                            if (globalLoadsIndex != -1)
                                linkSet.loader.loads.splice(globalLoadsIndex, 1);
                        }
                    }
                    linkSet.reject(exc);
                }

                // 15.2.5.2.5
                function finishLoad(loader, load) {
                    // add to global trace if tracing
                    if (loader.loaderObj.trace) {
                        if (!loader.loaderObj.loads)
                            loader.loaderObj.loads = {};
                        var depMap = {};
                        load.dependencies.forEach(function(dep) {
                            depMap[dep.key] = dep.value;
                        });
                        loader.loaderObj.loads[load.name] = {
                            name: load.name,
                            deps: load.dependencies.map(function(dep){ return dep.key }),
                            depMap: depMap,
                            address: load.address,
                            metadata: load.metadata,
                            source: load.source
                        };
                    }
                    // if not anonymous, add to the module table
                    if (load.name) {
                        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);
                    if (loadIndex != -1)
                        loader.loads.splice(loadIndex, 1);
                    for (var i = 0, l = load.linkSets.length; i < l; i++) {
                        loadIndex = indexOf.call(load.linkSets[i].loads, load);
                        if (loadIndex != -1)
                            load.linkSets[i].loads.splice(loadIndex, 1);
                    }
                    load.linkSets.splice(0, load.linkSets.length);
                }

                function doDynamicExecute(linkSet, load, linkError) {
                    try {
                        var module = load.execute();
                    }
                    catch(e) {
                        linkError(load, e);
                        return;
                    }
                    if (!module || !(module instanceof Module))
                        linkError(load, new TypeError('Execution must define a Module instance'));
                    else
                        return module;
                }

                // 26.3 Loader

                // 26.3.1.1
                // defined at top

                // importPromises adds ability to import a module twice without error - https://bugs.ecmascript.org/show_bug.cgi?id=2601
                function createImportPromise(loader, name, promise) {
                    var importPromises = loader._loader.importPromises;
                    return importPromises[name] = promise.then(function(m) {
                        importPromises[name] = undefined;
                        return m;
                    }, function(e) {
                        importPromises[name] = undefined;
                        throw e;
                    });
                }

                Loader.prototype = {
                    // 26.3.3.1
                    constructor: Loader,
                    // 26.3.3.2
                    define: function(name, source, options) {
                        // check if already defined
                        if (this._loader.importPromises[name])
                            throw new TypeError('Module is already loading.');
                        return createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({
                            step: 'translate',
                            loader: this._loader,
                            moduleName: name,
                            moduleMetadata: options && options.metadata || {},
                            moduleSource: source,
                            moduleAddress: options && options.address
                        })));
                    },
                    // 26.3.3.3
                    'delete': function(name) {
                        var loader = this._loader;
                        delete loader.importPromises[name];
                        delete loader.moduleRecords[name];
                        return loader.modules[name] ? delete loader.modules[name] : false;
                    },
                    // 26.3.3.4 entries not implemented
                    // 26.3.3.5
                    get: function(key) {
                        if (!this._loader.modules[key])
                            return;
                        return this._loader.modules[key].module;
                    },
                    // 26.3.3.7
                    has: function(name) {
                        return !!this._loader.modules[name];
                    },
                    // 26.3.3.8
                    'import': function(name, parentName, parentAddress) {
                        if (typeof parentName == 'object')
                            parentName = parentName.name;

                        // run normalize first
                        var loaderObj = this;

                        // added, see https://bugs.ecmascript.org/show_bug.cgi?id=2659
                        return Promise.resolve(loaderObj.normalize(name, parentName))
                            .then(function(name) {
                                var loader = loaderObj._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 load.module.module;
                                            }));
                            });
                    },
                    // 26.3.3.9 keys not implemented
                    // 26.3.3.10
                    load: function(name) {
                        var loader = this._loader;
                        if (loader.modules[name])
                            return Promise.resolve();
                        return loader.importPromises[name] || createImportPromise(this, name, new Promise(asyncStartLoadPartwayThrough({
                                step: 'locate',
                                loader: loader,
                                moduleName: name,
                                moduleMetadata: {},
                                moduleSource: undefined,
                                moduleAddress: undefined
                            }))
                                .then(function() {
                                    delete loader.importPromises[name];
                                }));
                    },
                    // 26.3.3.11
                    module: function(source, options) {
                        var load = createLoad();
                        load.address = options && options.address;
                        var linkSet = createLinkSet(this._loader, load);
                        var sourcePromise = Promise.resolve(source);
                        var loader = this._loader;
                        var p = linkSet.done.then(function() {
                            return load.module.module;
                        });
                        proceedToTranslate(loader, load, sourcePromise);
                        return p;
                    },
                    // 26.3.3.12
                    newModule: function (obj) {
                        if (typeof obj != 'object')
                            throw new TypeError('Expected object');

                        var m = new Module();

                        var pNames = [];
                        if (Object.getOwnPropertyNames && obj != null)
                            pNames = Object.getOwnPropertyNames(obj);
                        else
                            for (var key in obj)
                                pNames.push(key);

                        for (var i = 0; i < pNames.length; i++) (function(key) {
                            defineProperty(m, key, {
                                configurable: false,
                                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
                    set: function(name, module) {
                        if (!(module instanceof Module))
                            throw new TypeError('Loader.set(' + name + ', module) must be a module');
                        this._loader.modules[name] = {
                            module: module
                        };
                    },
                    // 26.3.3.15 values not implemented
                    // 26.3.3.16 @@iterator not implemented
                    // 26.3.3.17 @@toStringTag not implemented

                    // 26.3.3.18.1
                    normalize: function(name, referrerName, referrerAddress) {},
                    // 26.3.3.18.2
                    locate: function(load) {
                        return load.name;
                    },
                    // 26.3.3.18.3
                    fetch: function(load) {
                    },
                    // 26.3.3.18.4
                    translate: function(load) {
                        return load.source;
                    },
                    // 26.3.3.18.5
                    instantiate: function(load) {
                    }
                };

                var _newModule = Loader.prototype.newModule;

                /*
                 * ES6 Module Declarative Linking Code
                 */
                function link(linkSet, linkError) {

                    var loader = linkSet.loader;

                    if (!linkSet.loads.length)
                        return;

                    var loads = linkSet.loads.concat([]);

                    for (var i = 0; i < loads.length; i++) {
                        var load = loads[i];

                        var module = doDynamicExecute(linkSet, load, linkError);
                        if (!module)
                            return;
                        load.module = {
                            name: load.name,
                            module: module
                        };
                        load.status = 'linked';

                        finishLoad(loader, load);
                    }
                }

            })();

            var System;

            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));
                    }

                    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;
                        }
                    }

                    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);

                            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, */*'}
                    };

                    if (authorization) {
                        if (typeof authorization == 'string')
                            opts.headers['Authorization'] = authorization;
                        opts.credentials = 'include';
                    }

                    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.');
            }
            /*
             * Traceur, Babel and TypeScript transpile hook for Loader
             */
            var transpile = (function() {

                // use Traceur by default
                Loader.prototype.transpiler = 'traceur';

                function transpile(load) {
                    var self = this;

                    return Promise.resolve(__global[self.transpiler == 'typescript' ? 'ts' : self.transpiler]
                        || (self.pluginLoader || self)['import'](self.transpiler))
                        .then(function(transpiler) {
                            if (transpiler.__useDefault)
                                transpiler = transpiler['default'];

                            var transpileFunction;
                            if (transpiler.Compiler)
                                transpileFunction = traceurTranspile;
                            else if (transpiler.createLanguageService)
                                transpileFunction = typescriptTranspile;
                            else
                                transpileFunction = babelTranspile;

                            // note __moduleName will be part of the transformer meta in future when we have the spec for this
                            return '(function(__moduleName){' + transpileFunction.call(self, load, transpiler) + '\n})("' + load.name + '");\n//# sourceURL=' + load.address + '!transpiled';
                        });
                };

                function traceurTranspile(load, traceur) {
                    var options = this.traceurOptions || {};
                    options.modules = 'instantiate';
                    options.script = false;
                    if (options.sourceMaps === undefined)
                        options.sourceMaps = 'inline';
                    options.filename = load.address;
                    options.inputSourceMap = load.metadata.sourceMap;
                    options.moduleName = false;

                    var compiler = new traceur.Compiler(options);

                    return doTraceurCompile(load.source, compiler, options.filename);
                }
                function doTraceurCompile(source, compiler, filename) {
                    try {
                        return compiler.compile(source, filename);
                    }
                    catch(e) {
                        // on older versions of traceur (<0.9.3), an array of errors is thrown
                        // rather than a single error.
                        if (e.length) {
                            throw e[0];
                        }
                        throw e;
                    }
                }

                function babelTranspile(load, babel) {
                    var options = this.babelOptions || {};
                    options.modules = 'system';
                    if (options.sourceMap === undefined)
                        options.sourceMap = 'inline';
                    options.inputSourceMap = load.metadata.sourceMap;
                    options.filename = load.address;
                    options.code = true;
                    options.ast = false;

                    return babel.transform(load.source, options).code;
                }

                function typescriptTranspile(load, ts) {
                    var options = this.typescriptOptions || {};
                    options.target = options.target || ts.ScriptTarget.ES5;
                    if (options.sourceMap === undefined)
                        options.sourceMap = true;
                    if (options.sourceMap && options.inlineSourceMap !== false)
                        options.inlineSourceMap = true;

                    options.module = ts.ModuleKind.System;

                    return ts.transpile(load.source, options, load.address);
                }

                return transpile;
            })();
// SystemJS Loader Class and Extension helpers
            function SystemJSLoader() {
                Loader.call(this);

                this.paths = {};
                this._loader.paths = {};

                systemJSConstructor.call(this);
            }

// inline Object.create-style class extension
            function SystemProto() {};
            SystemProto.prototype = Loader.prototype;
            SystemJSLoader.prototype = new SystemProto();
            SystemJSLoader.prototype.constructor = SystemJSLoader;

            var systemJSConstructor;

            function hook(name, hook) {
                SystemJSLoader.prototype[name] = hook(SystemJSLoader.prototype[name] || function() {});
            }
            function hookConstructor(hook) {
                systemJSConstructor = hook(systemJSConstructor || function() {});
            }


            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(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) {
                    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 (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] == '/' || 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] &&
                            name.substr(name.length - pathParts[1].length) == pathParts[1]) {
                            maxWildcardPrefixLen = wildcardPrefixLen;
                            pathMatch = p;
                            wildcard = name.substr(pathParts[0].length, name.length - pathParts[1].length - pathParts[0].length);
                        }
                    }
                }

                var outPath = paths[pathMatch];
                if (typeof wildcard == 'string')
                    outPath = outPath.replace('*', wildcard);

                return outPath;
            }

            function dedupe(deps) {
                var newDeps = [];
                for (var i = 0, l = deps.length; i < l; i++)
                    if (indexOf.call(newDeps, deps[i]) == -1)
                        newDeps.push(deps[i])
                return newDeps;
            }

            function group(deps) {
                var names = [];
                var indices = [];
                for (var i = 0, l = deps.length; i < l; i++) {
                    var index = indexOf.call(names, deps[i]);
                    if (index === -1) {
                        names.push(deps[i]);
                        indices.push([i]);
                    }
                    else {
                        indices[index].push(i);
                    }
                }
                return { names: names, indices: indices };
            }

            var getOwnPropertyDescriptor = true;
            try {
                Object.getOwnPropertyDescriptor({ a: 0 }, 'a');
            }
            catch(e) {
                getOwnPropertyDescriptor = false;
            }

// converts any module.exports object into an object ready for SystemJS.newModule
            function getESModule(exports) {
                var esModule = {};
                // don't trigger getters/setters in environments that support them
                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', {
                    value: true
                });
                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;
            }

// 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;
                    else if (val instanceof Array && a[p] instanceof Array)
                        a[p] = [].concat(prepend ? val : a[p]).concat(prepend ? a[p] : val);
                    else if (typeof val == 'object' && val !== null && typeof a[p] == 'object')
                        a[p] = extend(extend({}, a[p]), val, prepend);
                    else if (!prepend)
                        a[p] = val;
                }
            }

            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);
            }
// we define a __exec for globally-scoped execution
// used by module format implementations
            var __exec;

            (function() {

                var hasBuffer = typeof Buffer != 'undefined';
                try {
                    if (hasBuffer && new Buffer('a').toString('base64') != 'YQ==')
                        hasBuffer = false;
                }
                catch(e) {
                    hasBuffer = false;
                }

                var sourceMapPrefix = '\n//# sourceMappingURL=data:application/json;base64,';
                function inlineSourceMap(sourceMapString) {
                    if (hasBuffer)
                        return sourceMapPrefix + new Buffer(sourceMapString).toString('base64');
                    else if (typeof btoa != 'undefined')
                        return sourceMapPrefix + btoa(unescape(encodeURIComponent(sourceMapString)));
                    else
                        return '';
                }

                function getSource(load, wrap) {
                    var lastLineIndex = load.source.lastIndexOf('\n');

                    // wrap ES formats with a System closure for System global encapsulation
                    if (load.metadata.format == 'global')
                        wrap = false;

                    var sourceMap = load.metadata.sourceMap;
                    if (sourceMap) {
                        if (typeof sourceMap != 'object')
                            throw new TypeError('load.metadata.sourceMap must be set to an object.');

                        sourceMap = JSON.stringify(sourceMap);
                    }

                    return (wrap ? '(function(System, SystemJS) {' : '') + load.source + (wrap ? '\n})(System, System);' : '')
                        // adds the sourceURL comment if not already present
                        + (load.source.substr(lastLineIndex, 15) != '\n//# sourceURL='
                            ? '\n//# sourceURL=' + load.address + (sourceMap ? '!transpiled' : '') : '')
                        // add sourceMappingURL if load.metadata.sourceMap is set
                        + (sourceMap && inlineSourceMap(sourceMap) || '');
                }

                var curLoad;

                // System.register, System.registerDynamic, AMD define pipeline
                // if currently evalling code here, immediately reduce the registered entry against the load record
                hook('pushRegister_', function() {
                    return function(register) {
                        if (!curLoad)
                            return false;

                        this.reduceRegister_(curLoad, register);
                        return true;
                    };
                });

                // System clobbering protection (mostly for Traceur)
                var curSystem;
                var callCounter = 0;
                function preExec(loader, load) {
                    curLoad = load;
                    if (callCounter++ == 0)
                        curSystem = __global.System;
                    __global.System = __global.SystemJS = loader;
                }
                function postExec() {
                    if (--callCounter == 0)
                        __global.System = __global.SystemJS = curSystem;
                    curLoad = undefined;
                }

                var useVm;
                var vm;
                __exec = function(load) {
                    if (!load.source)
                        return;
                    if ((load.metadata.integrity || load.metadata.nonce) && supportsScriptExec)
                        return scriptExec.call(this, load);
                    try {
                        preExec(this, load);
                        curLoad = load;
                        // global scoped eval for node (avoids require scope leak)
                        if (!vm && this._nodeRequire) {
                            vm = this._nodeRequire('vm');
                            useVm = vm.runInThisContext("typeof System !== 'undefined' && System") === this;
                        }
                        if (useVm)
                            vm.runInThisContext(getSource(load, true), { filename: load.address + (load.metadata.sourceMap ? '!transpiled' : '') });
                        else
                            (0, eval)(getSource(load, true));
                        postExec();
                    }
                    catch(e) {
                        postExec();
                        throw addToError(e, 'Evaluating ' + load.address);
                    }
                };

                var supportsScriptExec = false;
                if (isBrowser && typeof document != 'undefined' && document.getElementsByTagName) {
                    var scripts = document.getElementsByTagName('script');
                    $__curScript = scripts[scripts.length - 1];

                    if (!(window.chrome && window.chrome.extension || navigator.userAgent.match(/^Node\.js/)))
                        supportsScriptExec = true;
                }

                // script execution via injecting a script tag into the page
                // this allows CSP integrity and nonce to be set for CSP environments
                var head;
                function scriptExec(load) {
                    if (!head)
                        head = document.head || document.body || document.documentElement;

                    var script = document.createElement('script');
                    script.text = getSource(load, false);
                    var onerror = window.onerror;
                    var e;
                    window.onerror = function(_e) {
                        e = addToError(_e, 'Evaluating ' + load.address);
                        if (onerror)
                            onerror.apply(this, arguments);
                    }
                    preExec(this, load);

                    if (load.metadata.integrity)
                        script.setAttribute('integrity', load.metadata.integrity);
                    if (load.metadata.nonce)
                        script.setAttribute('nonce', load.metadata.nonce);

                    head.appendChild(script);
                    head.removeChild(script);
                    postExec();
                    window.onerror = onerror;
                    if (e)
                        throw e;
                }

            })();
            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);
                });
            };/*
             * Package Configuration Extension
             *
             * Example:
             *
             * SystemJS.packages = {
             *   jquery: {
             *     main: 'index.js', // when not set, package name is requested directly
             *     format: 'amd',
             *     defaultExtension: 'ts', // defaults to 'js', can be set to false
             *     modules: {
             *       '*.ts': {
             *         loader: 'typescript'
             *       },
             *       'vendor/sizzle.js': {
             *         format: 'global'
             *       }
             *     },
             *     map: {
             *        // map internal require('sizzle') to local require('./vendor/sizzle')
             *        sizzle: './vendor/sizzle.js',
             *        // map any internal or external require of 'jquery/vendor/another' to 'another/index.js'
             *        './vendor/another.js': './another/index.js',
             *        // test.js / test -> lib/test.js
             *        './test.js': './lib/test.js',
             *
             *        // environment-specific map configurations
             *        './index.js': {
             *          '~browser': './index-node.js',
             *          './custom-condition.js|~export': './index-custom.js'
             *        }
             *     },
             *     // allows for setting package-prefixed depCache
             *     // keys are normalized module names relative to the package itself
             *     depCache: {
             *       // import 'package/index.js' loads in parallel package/lib/test.js,package/vendor/sizzle.js
             *       './index.js': ['./test'],
             *       './test.js': ['external-dep'],
             *       'external-dep/path.js': ['./another.js']
             *     }
             *   }
             * };
             *
             * Then:
             *   import 'jquery'                       -> jquery/index.js
             *   import 'jquery/submodule'             -> jquery/submodule.js
             *   import 'jquery/submodule.ts'          -> jquery/submodule.ts loaded as typescript
             *   import 'jquery/vendor/another'        -> another/index.js
             *
             * Detailed Behaviours
             * - main can have a leading "./" can be added optionally
             * - map and defaultExtension are applied to the main
             * - defaultExtension adds the extension only if the exact extension is not present
             * - defaultJSExtensions applies after map when defaultExtension is not set
             * - if a meta value is available for a module, map and defaultExtension are skipped
             * - like global map, package map also applies to subpaths (sizzle/x, ./vendor/another/sub)
             * - condition module map is '@env' module in package or '@system-env' globally
             * - map targets support conditional interpolation ('./x': './x.#{|env}.js')
             * - internal package map targets cannot use boolean conditionals
             *
             * Package Configuration Loading
             *
             * Not all packages may already have their configuration present in the System config
             * For these cases, a list of packageConfigPaths can be provided, which when matched against
             * a request, will first request a ".json" file by the package name to derive the package
             * configuration from. This allows dynamic loading of non-predetermined code, a key use
             * case in SystemJS.
             *
             * Example:
             *
             *   SystemJS.packageConfigPaths = ['packages/test/package.json', 'packages/*.json'];
             *
             *   // will first request 'packages/new-package/package.json' for the package config
             *   // before completing the package request to 'packages/new-package/path'
             *   SystemJS.import('packages/new-package/path');
             *
             *   // will first request 'packages/test/package.json' before the main
             *   SystemJS.import('packages/test');
             *
             * When a package matches packageConfigPaths, it will always send a config request for
             * the package configuration.
             * The package name itself is taken to be the match up to and including the last wildcard
             * or trailing slash.
             * The most specific package config path will be used.
             * Any existing package configurations for the package will deeply merge with the
             * package config, with the existing package configurations taking preference.
             * To opt-out of the package configuration request for a package that matches
             * packageConfigPaths, use the { configured: true } package config option.
             *
             */
            (function() {

                hookConstructor(function(constructor) {
                    return function() {
                        constructor.call(this);
                        this.packages = {};
                        this.packageConfigPaths = [];
                    };
                });

                function getPackage(loader, normalized) {
                    // use most specific package
                    var curPkg, curPkgLen = 0, pkgLen;
                    for (var p in loader.packages) {
                        if (normalized.substr(0, p.length) === p && (normalized.length === p.length || normalized[p.length] === '/')) {
                            pkgLen = p.split('/').length;
                            if (pkgLen > curPkgLen) {
                                curPkg = p;
                                curPkgLen = pkgLen;
                            }
                        }
                    }
                    return curPkg;
                }

                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;

                    var metaMatch = false;

                    // exact meta or meta with any content after the last wildcard skips extension
                    if (pkg.meta)
                        getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) {
                            if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1)
                                return metaMatch = true;
                        });

                    // exact global meta or meta with any content after the last wildcard skips extension
                    if (!metaMatch && loader.meta)
                        getMetaMatches(loader.meta, pkgName + '/' + subPath, function(metaPattern, matchMeta, matchDepth) {
                            if (matchDepth == 0 || metaPattern.lastIndexOf('*') != metaPattern.length - 1)
                                return metaMatch = true;
                        });

                    if (metaMatch)
                        return subPath;

                    // work out what the defaultExtension is and add if not there already
                    // NB reconsider if default should really be ".js"?
                    var defaultExtension = '.' + (pkg.defaultExtension || 'js');
                    if (subPath.substr(subPath.length - defaultExtension.length) != defaultExtension)
                        return subPath + defaultExtension;
                    else
                        return subPath;
                }

                function applyPackageConfigSync(loader, pkg, pkgName, subPath, skipExtensions) {
                    // main
                    if (!subPath) {
                        if (pkg.main)
                            subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main;
                        // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js')
                        else
                        // NB can add a default package main convention here when defaultJSExtensions is deprecated
                        // if it becomes internal to the package then it would no longer be an exit path
                            return pkgName + (loader.defaultJSExtensions ? '.js' : '');
                    }

                    // map config checking without then with extensions
                    if (pkg.map) {
                        var mapPath = './' + subPath;

                        var mapMatch = getMapMatch(pkg.map, mapPath);

                        // we then check map with the default extension adding
                        if (!mapMatch) {
                            mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions);
                            if (mapPath != './' + subPath)
                                mapMatch = getMapMatch(pkg.map, mapPath);
                        }
                        if (mapMatch) {
                            var mapped = doMapSync(loader, pkg, pkgName, mapMatch, mapPath, skipExtensions);
                            if (mapped)
                                return mapped;
                        }
                    }

                    // normal package resolution
                    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, mapMatch, path, skipExtensions) {
                    if (path[path.length - 1] == '/')
                        path = path.substr(0, path.length - 1);
                    var mapped = pkg.map[mapMatch];

                    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 == '.')
                        mapped = pkgName;

                    // internal package map
                    else if (mapped.substr(0, 2) == './')
                        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 + '/');
                }

                function applyPackageConfig(loader, pkg, pkgName, subPath, skipExtensions) {
                    // main
                    if (!subPath) {
                        if (pkg.main)
                            subPath = pkg.main.substr(0, 2) == './' ? pkg.main.substr(2) : pkg.main;
                        // also no submap if name is package itself (import 'pkg' -> 'path/to/pkg.js')
                        else
                        // NB can add a default package main convention here when defaultJSExtensions is deprecated
                        // if it becomes internal to the package then it would no longer be an exit path
                            return Promise.resolve(pkgName + (loader.defaultJSExtensions ? '.js' : ''));
                    }

                    // map config checking without then with extensions
                    var mapPath, mapMatch;

                    if (pkg.map) {
                        mapPath = './' + subPath;
                        mapMatch = getMapMatch(pkg.map, mapPath);

                        // we then check map with the default extension adding
                        if (!mapMatch) {
                            mapPath = './' + addDefaultExtension(loader, pkg, pkgName, subPath, skipExtensions);
                            if (mapPath != './' + subPath)
                                mapMatch = getMapMatch(pkg.map, mapPath);
                        }
                    }

                    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 + '/' + addDefaultExtension(loader, pkg, pkgName, subPath, 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 + '/' + addDefaultExtension(loader, pkg, pkgName, mapped.substr(2) + path.substr(mapMatch.length), skipExtensions))
                            .then(function(name) {
                                return interpolateConditional.call(loader, name, pkgName + '/');
                            });

                    // external map reference
                    return loader.normalize(mapped + path.substr(mapMatch.length), pkgName + '/');
                }

                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') {
                        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 Promise.all(conditionPromises)
                        .then(function(conditionValues) {
                            // first map condition to match is used
                            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) {
                                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
                        });
                }

                // normalizeSync = decanonicalize + package resolution
                SystemJSLoader.prototype.normalizeSync = SystemJSLoader.prototype.decanonicalize = SystemJSLoader.prototype.normalize;

                // decanonicalize must JUST handle package defaultExtension: false case when defaultJSExtensions is set
                // to be deprecated!
                hook('decanonicalize', function(decanonicalize) {
                    return function(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 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);

                        return decanonicalized;
                    };
                });

                hook('normalizeSync', function(normalizeSync) {
                    return function(name, parentName, isPlugin) {
                        var loader = this;
                        isPlugin = isPlugin === true;

                        // apply contextual package map first
                        // (we assume the parent package config has already been loaded)
                        if (parentName)
                            var parentPackageName = getPackage(loader, parentName) ||
                                loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' &&
                                getPackage(loader, parentName.substr(0, parentName.length - 3));

                        var parentPackage = parentPackageName && loader.packages[parentPackageName];

                        // 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') {
                                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, false);

                        // undo defaultJSExtension
                        if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js')
                            defaultJSExtension = false;
                        if (defaultJSExtension)
                            normalized = normalized.substr(0, normalized.length - 3);

                        var pkgConfigMatch = getPackageConfigMatch(loader, normalized);
                        var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized);

                        if (!pkgName)
                            return normalized + (defaultJSExtension ? '.js' : '');

                        var subPath = normalized.substr(pkgName.length + 1);

                        return applyPackageConfigSync(loader, loader.packages[pkgName] || {}, pkgName, subPath, isPlugin);
                    };
                });

                hook('normalize', function(normalize) {
                    return function(name, parentName, isPlugin) {
                        var loader = this;
                        isPlugin = isPlugin === true;

                        return Promise.resolve()
                            .then(function() {
                                // apply contextual package map first
                                // (we assume the parent package config has already been loaded)
                                if (parentName)
                                    var parentPackageName = getPackage(loader, parentName) ||
                                        loader.defaultJSExtensions && parentName.substr(parentName.length - 3, 3) == '.js' &&
                                        getPackage(loader, parentName.substr(0, parentName.length - 3));

                                var parentPackage = parentPackageName && loader.packages[parentPackageName];

                                // 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, parentMapMatch, name, isPlugin);
                                }

                                return Promise.resolve();
                            })
                            .then(function(mapped) {
                                if (mapped)
                                    return mapped;

                                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, false);

                                // undo defaultJSExtension
                                if (defaultJSExtension && normalized.substr(normalized.length - 3, 3) != '.js')
                                    defaultJSExtension = false;
                                if (defaultJSExtension)
                                    normalized = normalized.substr(0, normalized.length - 3);

                                var pkgConfigMatch = getPackageConfigMatch(loader, normalized);
                                var pkgName = pkgConfigMatch && pkgConfigMatch.packageName || getPackage(loader, normalized);

                                if (!pkgName)
                                    return Promise.resolve(normalized + (defaultJSExtension ? '.js' : ''));

                                var pkg = loader.packages[pkgName];

                                // if package is already configured or not a dynamic config package, use existing package config
                                var isConfigured = pkg && (pkg.configured || !pkgConfigMatch);
                                return (isConfigured ? Promise.resolve(pkg) : loadPackageConfigPath(loader, pkgName, pkgConfigMatch.configPath))
                                    .then(function(pkg) {
                                        var subPath = normalized.substr(pkgName.length + 1);

                                        return applyPackageConfig(loader, pkg, pkgName, subPath, isPlugin);
                                    });
                            });
                    };
                });

                // check if the given normalized name matches a packageConfigPath
                // if so, loads the config
                var packageConfigPaths = {};

                // data object for quick checks against package paths
                function createPkgConfigPathObj(path) {
                    var lastWildcard = path.lastIndexOf('*');
                    var length = Math.max(lastWildcard + 1, path.lastIndexOf('/'));
                    return {
                        length: length,
                        regEx: new RegExp('^(' + path.substr(0, length).replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^\\/]+') + ')(\\/|$)'),
                        wildcard: lastWildcard != -1
                    };
                }

                // most specific match wins
                function getPackageConfigMatch(loader, normalized) {
                    var pkgName, exactMatch = false, configPath;
                    for (var i = 0; i < loader.packageConfigPaths.length; i++) {
                        var packageConfigPath = loader.packageConfigPaths[i];
                        var p = packageConfigPaths[packageConfigPath] || (packageConfigPaths[packageConfigPath] = createPkgConfigPathObj(packageConfigPath));
                        if (normalized.length < p.length)
                            continue;
                        var match = normalized.match(p.regEx);
                        if (match && (!pkgName || (!(exactMatch && p.wildcard) && pkgName.length < match[1].length))) {
                            pkgName = match[1];
                            exactMatch = !p.wildcard;
                            configPath = pkgName + packageConfigPath.substr(p.length);
                        }
                    }

                    if (!pkgName)
                        return;

                    return {
                        packageName: pkgName,
                        configPath: configPath
                    };
                }

                function loadPackageConfigPath(loader, pkgName, pkgConfigPath) {
                    var configLoader = loader.pluginLoader || loader;

                    // 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() {
                            var cfg = configLoader.get(pkgConfigPath)['default'];

                            // support "systemjs" prefixing
                            if (cfg.systemjs)
                                cfg = cfg.systemjs;

                            // modules backwards compatibility
                            if (cfg.modules) {
                                cfg.meta = cfg.modules;
                                warn.call(loader, 'Package config file ' + pkgConfigPath + ' is configured with "modules", which is deprecated as it has been renamed to "meta".');
                            }

                            return setPkgConfig(loader, pkgName, cfg, true);
                        });
                }

                function getMetaMatches(pkgMeta, subPath, matchFn) {
                    // wildcard meta
                    var meta = {};
                    var wildcardIndex;
                    for (var module in pkgMeta) {
                        // allow meta to start with ./ for flexibility
                        var dotRel = module.substr(0, 2) == './' ? './' : '';
                        if (dotRel)
                            module = module.substr(2);

                        wildcardIndex = module.indexOf('*');
                        if (wildcardIndex === -1)
                            continue;

                        if (module.substr(0, wildcardIndex) == subPath.substr(0, wildcardIndex)
                            && module.substr(wildcardIndex + 1) == subPath.substr(subPath.length - module.length + wildcardIndex + 1)) {
                            // alow match function to return true for an exit path
                            if (matchFn(module, pkgMeta[dotRel + module], module.split('/').length))
                                return;
                        }
                    }
                    // exact meta
                    var exactMeta = pkgMeta[subPath] && pkgMeta.hasOwnProperty && pkgMeta.hasOwnProperty(subPath) ? pkgMeta[subPath] : pkgMeta['./' + subPath];
                    if (exactMeta)
                        matchFn(exactMeta, exactMeta, 0);
                }

                hook('locate', function(locate) {
                    return function(load) {
                        var loader = this;
                        return Promise.resolve(locate.call(this, load))
                            .then(function(address) {
                                var pkgName = getPackage(loader, load.name);
                                if (pkgName) {
                                    var pkg = loader.packages[pkgName];
                                    var subPath = load.name.substr(pkgName.length + 1);

                                    var meta = {};
                                    if (pkg.meta) {
                                        var bestDepth = 0;

                                        // NB support a main shorthand in meta here?
                                        getMetaMatches(pkg.meta, subPath, function(metaPattern, matchMeta, matchDepth) {
                                            if (matchDepth > bestDepth)
                                                bestDepth = matchDepth;
                                            extendMeta(meta, matchMeta, matchDepth && bestDepth > matchDepth);
                                        });

                                        extendMeta(load.metadata, meta);
                                    }

                                    // format
                                    if (pkg.format && !load.metadata.loader)
                                        load.metadata.format = load.metadata.format || pkg.format;
                                }

                                return address;
                            });
                    };
                });

            })();
            /*
             * Script tag fetch
             *
             * When load.metadata.scriptLoad is true, we load via script tag injection.
             */
            (function() {

                if (typeof document != 'undefined')
                    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;

                // interactive mode handling method courtesy RequireJS
                var ieEvents = head && (function() {
                        var s = document.createElement('script');
                        var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]';
                        return s.attachEvent && !(s.attachEvent.toString && s.attachEvent.toString().indexOf('[native code') < 0) && !isOpera;
                    })();

                // IE interactive-only part
                // we store loading scripts array as { script: <script>, load: {...} }
                var interactiveLoadingScripts = [];
                var interactiveScript;
                function getInteractiveScriptLoad() {
                    if (interactiveScript && interactiveScript.script.readyState === 'interactive')
                        return interactiveScript.load;

                    for (var i = 0; i < interactiveLoadingScripts.length; i++)
                        if (interactiveLoadingScripts[i].script.readyState == 'interactive') {
                            interactiveScript = interactiveLoadingScripts[i];
                            return interactiveScript.load;
                        }
                }

                // System.register, System.registerDynamic, AMD define pipeline
                // this is called by the above methods when they execute
                // we then run the reduceRegister_ collection function either immediately
                // if we are in IE and know the currently executing script (interactive)
                // or later if we need to wait for the synchronous load callback to know the script
                var loadingCnt = 0;
                var registerQueue = [];
                hook('pushRegister_', function(pushRegister) {
                    return function(register) {
                        // if using eval-execution then skip
                        if (pushRegister.call(this, register))
                            return false;

                        // if using worker execution, then we're done
                        if (workerLoad)
                            this.reduceRegister_(workerLoad, register);

                        // detect if we know the currently executing load (IE)
                        // if so, immediately call reduceRegister
                        else if (ieEvents)
                            this.reduceRegister_(getInteractiveScriptLoad(), register);

                        // otherwise, add to our execution queue
                        // to call reduceRegister on sync script load event
                        else if (loadingCnt)
                            registerQueue.push(register);

                        // if we're not currently loading anything though
                        // then do the reduction against a null load
                        // (out of band named define or named register)
                        // note even in non-script environments, this catch is used
                        else
                            this.reduceRegister_(null, register);

                        return true;
                    };
                });

                function webWorkerImport(loader, load) {
                    return new Promise(function(resolve, reject) {
                        if (load.metadata.integrity)
                            reject(new Error('Subresource integrity checking is not supported in web workers.'));

                        workerLoad = load;
                        try {
                            importScripts(load.address);
                        }
                        catch(e) {
                            workerLoad = null;
                            reject(e);
                        }
                        workerLoad = null;

                        // if nothing registered, then something went wrong
                        if (!load.metadata.entry)
                            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('');
                    });
                }

                // override fetch to use script injection
                hook('fetch', function(fetch) {
                    return function(load) {
                        var loader = this;

                        if (load.metadata.format == 'json' || !load.metadata.scriptLoad || (!isBrowser && !isWorker))
                            return fetch.call(this, load);

                        if (isWorker)
                            return webWorkerImport(loader, load);

                        return new Promise(function(resolve, reject) {
                            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);

                            if (ieEvents) {
                                s.attachEvent('onreadystatechange', complete);
                                interactiveLoadingScripts.push({
                                    script: s,
                                    load: load
                                });
                            }
                            else {
                                s.addEventListener('load', complete, false);
                                s.addEventListener('error', error, false);
                            }

                            loadingCnt++;

                            curSystem = __global.System;
                            curRequire = __global.require;

                            s.src = load.address;
                            head.appendChild(s);

                            function complete(evt) {
                                if (s.readyState && s.readyState != 'loaded' && s.readyState != 'complete')
                                    return;

                                loadingCnt--;

                                // complete call is sync on execution finish
                                // (in ie already done reductions)
                                if (!load.metadata.entry && !registerQueue.length) {
                                    loader.reduceRegister_(load);
                                }
                                else if (!ieEvents) {
                                    for (var i = 0; i < registerQueue.length; i++)
                                        loader.reduceRegister_(load, registerQueue[i]);
                                    registerQueue = [];
                                }

                                cleanup();

                                // if nothing registered, then something went wrong
                                if (!load.metadata.entry && !load.metadata.bundle)
                                    reject(new Error(load.name + ' did not call System.register or AMD define. If loading a global module configure the global name via the meta exports property for script injection support.'));

                                resolve('');
                            }

                            function error(evt) {
                                cleanup();
                                reject(new Error('Unable to load script ' + load.address));
                            }

                            function cleanup() {
                                __global.System = curSystem;
                                __global.require = curRequire;

                                if (s.detachEvent) {
                                    s.detachEvent('onreadystatechange', complete);
                                    for (var i = 0; i < interactiveLoadingScripts.length; i++)
                                        if (interactiveLoadingScripts[i].script == s) {
                                            if (interactiveScript && interactiveScript.script == s)
                                                interactiveScript = null;
                                            interactiveLoadingScripts.splice(i, 1);
                                        }
                                }
                                else {
                                    s.removeEventListener('load', complete, false);
                                    s.removeEventListener('error', error, false);
                                }

                                head.removeChild(s);
                            }
                        });
                    };
                });
            })();
            /*
             * Instantiate registry extension
             *
             * Supports Traceur System.register 'instantiate' output for loading ES6 as ES5.
             *
             * - Creates the loader.register function
             * - Also supports metadata.format = 'register' in instantiate for anonymous register modules
             * - Also supports metadata.deps, metadata.execute and metadata.executingRequire
             *     for handling dynamic modules alongside register-transformed ES6 modules
             *
             *
             * The code here replicates the ES6 linking groups algorithm to ensure that
             * circular ES6 compiled into System.register can work alongside circular AMD
             * and CommonJS, identically to the actual ES6 loader.
             *
             */


            /*
             * Registry side table entries in loader.defined
             * Registry Entry Contains:
             *    - name
             *    - deps
             *    - declare for declarative modules
             *    - execute for dynamic modules, different to declarative execute on module
             *    - executingRequire indicates require drives execution for circularity of dynamic modules
             *    - declarative optional boolean indicating which of the above
             *
             * Can preload modules directly on SystemJS.defined['my/module'] = { deps, execute, executingRequire }
             *
             * Then the entry gets populated with derived information during processing:
             *    - normalizedDeps derived from deps, created in instantiate
             *    - groupIndex used by group linking algorithm
             *    - evaluated indicating whether evaluation has happend
             *    - module the module record object, containing:
             *      - exports actual module exports
             *
             *    For dynamic we track the es module with:
             *    - esModule actual es module value
             *    - esmExports whether to extend the esModule with named exports
             *
             *    Then for declarative only we track dynamic bindings with the 'module' records:
             *      - name
             *      - exports
             *      - setters declarative setter functions
             *      - dependencies, module records of dependencies
             *      - importers, module records of dependents
             *
             * After linked and evaluated, entries are removed, declarative module records remain in separate
             * module binding table
             *
             */

            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';
            }

            function createEntry() {
                return {
                    name: null,
                    deps: null,
                    originalIndices: null,
                    declare: null,
                    execute: null,
                    executingRequire: false,
                    declarative: false,
                    normalizedDeps: null,
                    groupIndex: null,
                    evaluated: false,
                    module: null,
                    esModule: null,
                    esmExports: false
                };
            }

            (function() {

                /*
                 * There are two variations of System.register:
                 * 1. System.register for ES6 conversion (2-3 params) - System.register([name, ]deps, declare)
                 *    see https://github.com/ModuleLoader/es6-module-loader/wiki/System.register-Explained
                 *
                 * 2. System.registerDynamic for dynamic modules (3-4 params) - System.registerDynamic([name, ]deps, executingRequire, execute)
                 * the true or false statement
                 *
                 * this extension implements the linking algorithm for the two variations identical to the spec
                 * allowing compiled ES6 circular references to work alongside AMD and CJS circular references.
                 *
                 */
                SystemJSLoader.prototype.register = function(name, deps, declare) {
                    if (typeof name != 'string') {
                        declare = deps;
                        deps = name;
                        name = null;
                    }

                    // dynamic backwards-compatibility
                    // can be deprecated eventually
                    if (typeof declare == 'boolean')
                        return this.registerDynamic.apply(this, arguments);

                    var entry = createEntry();
                    // ideally wouldn't apply map config to bundle names but
                    // dependencies go through map regardless so we can't restrict
                    // could reconsider in shift to new spec
                    entry.name = name && (this.decanonicalize || this.normalize).call(this, name);
                    entry.declarative = true;
                    entry.deps = deps;
                    entry.declare = declare;

                    this.pushRegister_({
                        amd: false,
                        entry: entry
                    });
                };
                SystemJSLoader.prototype.registerDynamic = function(name, deps, declare, execute) {
                    if (typeof name != 'string') {
                        execute = declare;
                        declare = deps;
                        deps = name;
                        name = null;
                    }

                    // dynamic
                    var entry = createEntry();
                    entry.name = name && (this.decanonicalize || this.normalize).call(this, name);
                    entry.deps = deps;
                    entry.execute = execute;
                    entry.executingRequire = declare;

                    this.pushRegister_({
                        amd: false,
                        entry: entry
                    });
                };
                hook('reduceRegister_', function() {
                    return function(load, register) {
                        if (!register)
                            return;

                        var entry = register.entry;
                        var curMeta = load && load.metadata;

                        // named register
                        if (entry.name) {
                            if (!(entry.name in this.defined))
                                this.defined[entry.name] = entry;

                            if (curMeta)
                                curMeta.bundle = true;
                        }
                        // anonymous register
                        if (!entry.name || load && !curMeta.entry && entry.name == load.name) {
                            if (!curMeta)
                                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.');
                                else
                                    throw new Error('Module ' + load.name + ' interpreted as ' + curMeta.format + ' module format, but called System.register.');
                            }
                            if (!curMeta.format)
                                curMeta.format = 'register';
                            curMeta.entry = entry;
                        }
                    };
                });

                hookConstructor(function(constructor) {
                    return function() {
                        constructor.call(this);

                        this.defined = {};
                        this._loader.moduleRecords = {};
                    };
                });

                function buildGroups(entry, loader, groups) {
                    groups[entry.groupIndex] = groups[entry.groupIndex] || [];

                    if (indexOf.call(groups[entry.groupIndex], entry) != -1)
                        return;

                    groups[entry.groupIndex].push(entry);

                    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
                        var depName = entry.normalizedDeps[i];
                        var depEntry = loader.defined[depName];

                        // not in the registry means already linked / ES6
                        if (!depEntry || depEntry.evaluated)
                            continue;

                        // now we know the entry is in our unlinked linkage group
                        var depGroupIndex = entry.groupIndex + (depEntry.declarative != entry.declarative);

                        // the group index of an entry is always the maximum
                        if (depEntry.groupIndex === null || depEntry.groupIndex < depGroupIndex) {

                            // if already in a group, remove from the old group
                            if (depEntry.groupIndex !== null) {
                                groups[depEntry.groupIndex].splice(indexOf.call(groups[depEntry.groupIndex], depEntry), 1);

                                // if the old group is empty, then we have a mixed depndency cycle
                                if (groups[depEntry.groupIndex].length == 0)
                                    throw new Error("Mixed dependency cycle detected");
                            }

                            depEntry.groupIndex = depGroupIndex;
                        }

                        buildGroups(depEntry, loader, groups);
                    }
                }

                function link(name, startEntry, loader) {
                    // skip if already linked
                    if (startEntry.module)
                        return;

                    startEntry.groupIndex = 0;

                    var groups = [];

                    buildGroups(startEntry, loader, groups);

                    var curGroupDeclarative = !!startEntry.declarative == groups.length % 2;
                    for (var i = groups.length - 1; i >= 0; i--) {
                        var group = groups[i];
                        for (var j = 0; j < group.length; j++) {
                            var entry = group[j];

                            // link each group
                            if (curGroupDeclarative)
                                linkDeclarativeModule(entry, loader);
                            else
                                linkDynamicModule(entry, loader);
                        }
                        curGroupDeclarative = !curGroupDeclarative;
                    }
                }

                // module binding records
                function ModuleRecord() {}
                defineProperty(ModuleRecord, 'toString', {
                    value: function() {
                        return 'Module';
                    }
                });

                function getOrCreateModuleRecord(name, moduleRecords) {
                    return moduleRecords[name] || (moduleRecords[name] = {
                            name: name,
                            dependencies: [],
                            exports: new ModuleRecord(), // start from an empty module and extend
                            importers: []
                        });
                }

                function linkDeclarativeModule(entry, loader) {
                    // only link if already not already started linking (stops at circular)
                    if (entry.module)
                        return;

                    var moduleRecords = loader._loader.moduleRecords;
                    var module = entry.module = getOrCreateModuleRecord(entry.name, moduleRecords);
                    var exports = entry.module.exports;

                    var declaration = entry.declare.call(__global, function(name, value) {
                        module.locked = true;

                        if (typeof name == 'object') {
                            for (var p in name)
                                exports[p] = name[p];
                        }
                        else {
                            exports[name] = value;
                        }

                        for (var i = 0, l = module.importers.length; i < l; i++) {
                            var importerModule = module.importers[i];
                            if (!importerModule.locked) {
                                var importerIndex = indexOf.call(importerModule.dependencies, module);
                                var setter = importerModule.setters[importerIndex];
                                if (setter)
                                    setter(exports);
                            }
                        }

                        module.locked = false;
                        return value;
                    }, { 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;

                    if (!module.setters || !module.execute) {
                        throw new TypeError('Invalid System.register form for ' + entry.name);
                    }

                    // now link all the module dependencies
                    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
                        var depName = entry.normalizedDeps[i];
                        var depEntry = loader.defined[depName];
                        var depModule = moduleRecords[depName];

                        // work out how to set depExports based on scenarios...
                        var depExports;

                        if (depModule) {
                            depExports = depModule.exports;
                        }
                        // dynamic, already linked in our registry
                        else if (depEntry && !depEntry.declarative) {
                            depExports = depEntry.esModule;
                        }
                        // in the loader registry
                        else if (!depEntry) {
                            depExports = loader.get(depName);
                        }
                        // we have an entry -> link
                        else {
                            linkDeclarativeModule(depEntry, loader);
                            depModule = depEntry.module;
                            depExports = depModule.exports;
                        }

                        // only declarative modules have dynamic bindings
                        if (depModule && depModule.importers) {
                            depModule.importers.push(module);
                            module.dependencies.push(depModule);
                        }
                        else {
                            module.dependencies.push(null);
                        }

                        // run setters for all entries with the matching dependency name
                        var originalIndices = entry.originalIndices[i];
                        for (var j = 0, len = originalIndices.length; j < len; ++j) {
                            var index = originalIndices[j];
                            if (module.setters[index]) {
                                module.setters[index](depExports);
                            }
                        }
                    }
                }

                // An analog to loader.get covering execution of all three layers (real declarative, simulated declarative, simulated dynamic)
                function getModule(name, loader) {
                    var exports;
                    var entry = loader.defined[name];

                    if (!entry) {
                        exports = loader.get(name);
                        if (!exports)
                            throw new Error('Unable to load dependency ' + name + '.');
                    }

                    else {
                        if (entry.declarative)
                            ensureEvaluated(name, entry, [], loader);

                        else if (!entry.evaluated)
                            linkDynamicModule(entry, loader);

                        exports = entry.module.exports;
                    }

                    if ((!entry || entry.declarative) && exports && exports.__useDefault)
                        return exports['default'];

                    return exports;
                }

                function linkDynamicModule(entry, loader) {
                    if (entry.module)
                        return;

                    var exports = {};

                    var module = entry.module = { exports: exports, id: entry.name };

                    // AMD requires execute the tree first
                    if (!entry.executingRequire) {
                        for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
                            var depName = entry.normalizedDeps[i];
                            // we know we only need to link dynamic due to linking algorithm
                            var depEntry = loader.defined[depName];
                            if (depEntry)
                                linkDynamicModule(depEntry, loader);
                        }
                    }

                    // now execute
                    entry.evaluated = true;
                    var output = entry.execute.call(__global, function(name) {
                        for (var i = 0, l = entry.deps.length; i < l; i++) {
                            if (entry.deps[i] != name)
                                continue;
                            return getModule(entry.normalizedDeps[i], loader);
                        }
                        // 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 !== 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 || 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 = loader.newModule(getESModule(exports));
                    // just use the 'default' export
                    else
                        entry.esModule = loader.newModule({ 'default': exports });
                }

                /*
                 * Given a module, and the list of modules for this current branch,
                 *  ensure that each of the dependencies of this module is evaluated
                 *  (unless one is a circular dependency already in the list of seen
                 *  modules, in which case we execute it)
                 *
                 * Then we evaluate the module itself depth-first left to right
                 * execution to match ES6 modules
                 */
                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;

                    // this only applies to declarative modules which late-execute

                    seen.push(moduleName);

                    for (var i = 0, l = entry.normalizedDeps.length; i < l; i++) {
                        var depName = entry.normalizedDeps[i];
                        if (indexOf.call(seen, depName) == -1) {
                            if (!loader.defined[depName])
                                loader.get(depName);
                            else
                                ensureEvaluated(depName, loader.defined[depName], seen, loader);
                        }
                    }

                    if (entry.evaluated)
                        return;

                    entry.evaluated = true;
                    entry.module.execute.call(__global);
                }

                // override the delete method to also clear the register caches
                hook('delete', function(del) {
                    return function(name) {
                        delete this._loader.moduleRecords[name];
                        delete this.defined[name];
                        return del.call(this, name);
                    };
                });

                hook('fetch', function(fetch) {
                    return function(load) {
                        if (this.defined[load.name]) {
                            load.metadata.format = 'defined';
                            return '';
                        }

                        load.metadata.deps = load.metadata.deps || [];

                        return fetch.call(this, load);
                    };
                });

                hook('translate', function(translate) {
                    // we run the meta detection here (register is after meta)
                    return function(load) {
                        load.metadata.deps = load.metadata.deps || [];
                        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';
                            return source;
                        });
                    };
                });

                // 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')
                            load.metadata.format = undefined;

                        // assumes previous instantiate is sync
                        // (core json support)
                        instantiate.call(this, load);

                        var loader = this;

                        var entry;

                        // first we check if this module has already been defined in the registry
                        if (loader.defined[load.name]) {
                            entry = loader.defined[load.name];
                            // 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
                        // or via the dynamic formats
                        else if (load.metadata.entry) {
                            entry = load.metadata.entry;
                            entry.deps = entry.deps.concat(load.metadata.deps);
                        }

                        // Contains System.register calls
                        // (dont run bundles in the builder)
                        else if (!(loader.builder && load.metadata.bundle)
                            && (load.metadata.format == 'register' || load.metadata.format == 'esm' || load.metadata.format == 'es6')) {

                            if (typeof __exec != 'undefined')
                                __exec.call(loader, load);

                            if (!load.metadata.entry && !load.metadata.bundle)
                                throw new Error(load.name + ' detected as ' + load.metadata.format + ' but didn\'t execute.');

                            entry = load.metadata.entry;

                            // support metadata deps for System.register
                            if (entry && load.metadata.deps)
                                entry.deps = entry.deps.concat(load.metadata.deps);
                        }

                        // named bundles are just an empty module
                        if (!entry) {
                            entry = createEntry();
                            entry.deps = load.metadata.deps;
                            entry.execute = function() {};
                        }

                        // place this module onto defined for circular references
                        loader.defined[load.name] = entry;

                        var grouped = group(entry.deps);

                        entry.deps = grouped.names;
                        entry.originalIndices = grouped.indices;
                        entry.name = load.name;
                        entry.esmExports = load.metadata.esmExports !== false;

                        // first, normalize all dependencies
                        var normalizePromises = [];
                        for (var i = 0, l = entry.deps.length; i < l; i++)
                            normalizePromises.push(Promise.resolve(loader.normalize(entry.deps[i], load.name)));

                        return Promise.all(normalizePromises).then(function(normalizedDeps) {

                            entry.normalizedDeps = normalizedDeps;

                            return {
                                deps: entry.deps,
                                execute: function() {
                                    // recursively ensure that the module and all its
                                    // dependencies are linked (with dependency group handling)
                                    link(load.name, entry, loader);

                                    // now handle dependency execution in correct order
                                    ensureEvaluated(load.name, entry, [], loader);

                                    if (!entry.esModule)
                                        entry.esModule = loader.newModule(entry.module.exports);

                                    // remove from the registry
                                    if (!loader.trace)
                                        loader.defined[load.name] = undefined;

                                    // return the defined module object
                                    return entry.esModule;
                                }
                            };
                        });
                    };
                });
            })();
            /*
             * Extension to detect ES6 and auto-load Traceur or Babel for processing
             */
            (function() {
                // good enough ES6 module detection regex - format detections not designed to be accurate, but to handle the 99% use case
                var esmRegEx = /(^\s*|[}\);\n]\s*)(import\s*(['"]|(\*\s+as\s+)?[^"'\(\)\n;]+\s*from\s*['"]|\{)|export\s+\*\s+from\s+["']|export\s*(\{|default|function|class|var|const|let|async\s+function))/;

                var traceurRuntimeRegEx = /\$traceurRuntime\s*\./;
                var babelHelpersRegEx = /babelHelpers\s*\./;

                hook('translate', function(translate) {
                    return function(load) {
                        var loader = this;
                        var args = arguments;
                        return translate.apply(loader, args)
                            .then(function(source) {
                                // detect & transpile ES6
                                if (load.metadata.format == 'esm' || load.metadata.format == 'es6' || !load.metadata.format && source.match(esmRegEx)) {
                                    if (load.metadata.format == 'es6')
                                        warn.call(loader, 'Module ' + load.name + ' has metadata setting its format to "es6", which is deprecated.\nThis should be updated to "esm".');

                                    load.metadata.format = 'esm';

                                    if (load.metadata.deps) {
                                        var depInject = '';
                                        for (var i = 0; i < load.metadata.deps.length; i++)
                                            depInject += 'import "' + load.metadata.deps[i] + '"; ';
                                        load.source = depInject + source;
                                    }

                                    if (loader.transpiler === false) {
                                        // we accept translation to esm for builds though to enable eg rollup optimizations
                                        if (loader.builder)
                                            return source;
                                        throw new TypeError('Unable to dynamically transpile ES module as SystemJS.transpiler set to false.');
                                    }

                                    // setting _loader.loadedTranspiler = false tells the next block to
                                    // do checks for setting transpiler metadata
                                    loader._loader.loadedTranspiler = loader._loader.loadedTranspiler || false;
                                    if (loader.pluginLoader)
                                        loader.pluginLoader._loader.loadedTranspiler = loader._loader.loadedTranspiler || false;

                                    // do transpilation
                                    return (loader._loader.transpilerPromise || (
                                        loader._loader.transpilerPromise = Promise.resolve(
                                            __global[loader.transpiler == 'typescript' ? 'ts' : loader.transpiler] || (loader.pluginLoader || loader)['import'](loader.transpiler)
                                        ))).then(function(transpiler) {
                                        loader._loader.loadedTranspilerRuntime = true;

                                        // translate hooks means this is a transpiler plugin instead of a raw implementation
                                        if (transpiler.translate) {
                                            // if transpiler is the same as the plugin loader, then don't run twice
                                            if (transpiler == load.metadata.loaderModule)
                                                return load.source;

                                            // convert the source map into an object for transpilation chaining
                                            if (typeof load.metadata.sourceMap == 'string')
                                                load.metadata.sourceMap = JSON.parse(load.metadata.sourceMap);

                                            return Promise.resolve(transpiler.translate.apply(loader, args))
                                                .then(function(source) {
                                                    // sanitize sourceMap if an object not a JSON string
                                                    var sourceMap = load.metadata.sourceMap;
                                                    if (sourceMap && typeof sourceMap == '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 (load.metadata.format == 'esm' && !loader.builder && detectRegisterFormat(source))
                                                        load.metadata.format = 'register';
                                                    return source;
                                                });
                                        }

                                        // legacy builder support
                                        if (loader.builder)
                                            load.metadata.originalSource = load.source;

                                        // defined in es6-module-loader/src/transpile.js
                                        return transpile.call(loader, load)
                                            .then(function(source) {
                                                // clear sourceMap as transpiler embeds it
                                                load.metadata.sourceMap = undefined;
                                                return source;
                                            });
                                    }, function(err) {
                                        throw addToError(err, 'Unable to load transpiler to transpile ' + load.name);
                                    });
                                }

                                // skip transpiler and transpiler runtime loading when transpiler is disabled
                                if (loader.transpiler === false)
                                    return source;

                                // load the transpiler correctly
                                if (loader._loader.loadedTranspiler === false && (loader.transpiler == 'traceur' || loader.transpiler == 'typescript' || loader.transpiler == 'babel')
                                    && load.name == loader.normalizeSync(loader.transpiler)) {

                                    // always load transpiler as a global
                                    if (source.length > 100 && !load.metadata.format) {
                                        load.metadata.format = 'global';

                                        if (loader.transpiler === 'traceur')
                                            load.metadata.exports = 'traceur';
                                        if (loader.transpiler === 'typescript')
                                            load.metadata.exports = 'ts';
                                    }

                                    loader._loader.loadedTranspiler = true;
                                }

                                // load the transpiler runtime correctly
                                if (loader._loader.loadedTranspilerRuntime === false) {
                                    if (load.name == loader.normalizeSync('traceur-runtime')
                                        || load.name == loader.normalizeSync('babel/external-helpers*')) {
                                        if (source.length > 100)
                                            load.metadata.format = load.metadata.format || 'global';

                                        loader._loader.loadedTranspilerRuntime = true;
                                    }
                                }

                                // detect transpiler runtime usage to load runtimes
                                if ((load.metadata.format == 'register' || load.metadata.bundle) && loader._loader.loadedTranspilerRuntime !== true) {
                                    if (loader.transpiler == 'traceur' && !__global.$traceurRuntime && load.source.match(traceurRuntimeRegEx)) {
                                        loader._loader.loadedTranspilerRuntime = loader._loader.loadedTranspilerRuntime || false;
                                        return loader['import']('traceur-runtime').then(function() {
                                            return source;
                                        });
                                    }
                                    if (loader.transpiler == 'babel' && !__global.babelHelpers && load.source.match(babelHelpersRegEx)) {
                                        loader._loader.loadedTranspilerRuntime = loader._loader.loadedTranspilerRuntime || false;
                                        return loader['import']('babel/external-helpers').then(function() {
                                            return source;
                                        });
                                    }
                                }

                                return source;
                            });
                    };
                });

            })();
            /*
             SystemJS Global Format

             Supports
             metadata.deps
             metadata.globals
             metadata.exports

             Without metadata.exports, detects writes to the global object.
             */
            var __globalName = typeof self != 'undefined' ? 'self' : 'global';

            hook('fetch', function(fetch) {
                return function(load) {
                    if (load.metadata.exports && !load.metadata.format)
                        load.metadata.format = 'global';
                    return fetch.call(this, load);
                };
            });

// ideally we could support script loading for globals, but the issue with that is that
// we can't do it with AMD support side-by-side since AMD support means defining the
// global define, and global support means not definining it, yet we don't have any hook
// into the "pre-execution" phase of a script tag being loaded to handle both cases
            hook('instantiate', function(instantiate) {
                return function(load) {
                    var loader = this;

                    if (!load.metadata.format)
                        load.metadata.format = 'global';

                    // global is a fallback module format
                    if (load.metadata.format == 'global' && !load.metadata.entry) {

                        var entry = createEntry();

                        load.metadata.entry = entry;

                        entry.deps = [];

                        for (var g in load.metadata.globals) {
                            var gl = load.metadata.globals[g];
                            if (gl)
                                entry.deps.push(gl);
                        }

                        entry.execute = function(require, exports, module) {

                            var globals;
                            if (load.metadata.globals) {
                                globals = {};
                                for (var g in load.metadata.globals)
                                    if (load.metadata.globals[g])
                                        globals[g] = require(load.metadata.globals[g]);
                            }

                            var exportName = load.metadata.exports;

                            if (exportName)
                                load.source += '\n' + __globalName + '["' + exportName + '"] = ' + exportName + ';';

                            var retrieveGlobal = loader.get('@@global-helpers').prepareGlobal(module.id, exportName, globals, !!load.metadata.encapsulateGlobal);
                            __exec.call(loader, load);

                            return retrieveGlobal();
                        }
                    }
                    return instantiate.call(this, load);
                };
            });


            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 && !(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 = getGlobalValue(load.metadata.exports);
                    entry.execute = function() {
                        return globalValue;
                    };
                };
            });

            hookConstructor(function(constructor) {
                return function() {
                    var loader = this;
                    constructor.call(loader);

                    var hasOwnProperty = Object.prototype.hasOwnProperty;

                    // bare minimum ignores
                    var ignoredGlobalProps = ['_g', 'sessionStorage', 'localStorage', 'clipboardData', 'frames', 'frameElement', 'external',
                        'mozAnimationStartTime', 'webkitStorageInfo', 'webkitIndexedDB', 'mozInnerScreenY', 'mozInnerScreenX'];

                    var globalSnapshot;

                    function forEachGlobal(callback) {
                        if (Object.keys)
                            Object.keys(__global).forEach(callback);
                        else
                            for (var g in __global) {
                                if (!hasOwnProperty.call(__global, g))
                                    continue;
                                callback(g);
                            }
                    }

                    function forEachGlobalValue(callback) {
                        forEachGlobal(function(globalName) {
                            if (indexOf.call(ignoredGlobalProps, globalName) != -1)
                                return;
                            try {
                                var value = __global[globalName];
                            }
                            catch (e) {
                                ignoredGlobalProps.push(globalName);
                            }
                            callback(globalName, value);
                        });
                    }

                    loader.set('@@global-helpers', loader.newModule({
                        prepareGlobal: function(moduleName, exports, globals, encapsulate) {
                            // disable module detection
                            var curDefine = __global.define;

                            __global.define = undefined;

                            // set globals
                            var oldGlobals;
                            if (globals) {
                                oldGlobals = {};
                                for (var g in globals) {
                                    oldGlobals[g] = __global[g];
                                    __global[g] = globals[g];
                                }
                            }

                            // store a complete copy of the global object in order to detect changes
                            if (!exports) {
                                globalSnapshot = {};

                                forEachGlobalValue(function(name, value) {
                                    globalSnapshot[name] = value;
                                });
                            }

                            // return function to retrieve global
                            return function() {
                                var globalValue = exports ? getGlobalValue(exports) : {};

                                var singleGlobal;
                                var multipleExports = !!exports;

                                if (!exports || encapsulate)
                                    forEachGlobalValue(function(name, value) {
                                        if (globalSnapshot[name] === value)
                                            return;
                                        if (typeof value == 'undefined')
                                            return;

                                        // 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 ? globalValue : singleGlobal;

                                // revert globals
                                if (oldGlobals) {
                                    for (var g in oldGlobals)
                                        __global[g] = oldGlobals[g];
                                }
                                __global.define = curDefine;

                                return globalValue;
                            };
                        }
                    }));
                };
            });
            /*
             SystemJS CommonJS Format
             */
            (function() {
                // CJS Module Format
                // require('...') || exports[''] = ... || exports.asd = ... || module.exports = ...
                var cjsExportsRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])(exports\s*(\[['"]|\.)|module(\.exports|\['exports'\]|\["exports"\])\s*(\[['"]|[=,\.]))/;
                // RegEx adjusted from https://github.com/jbrantly/yabble/blob/master/lib/yabble.js#L339
                var cjsRequireRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF."'])require\s*\(\s*("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')\s*\)/g;
                var commentRegEx = /(^|[^\\])(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;

                var stringRegEx = /("[^"\\\n\r]*(\\.[^"\\\n\r]*)*"|'[^'\\\n\r]*(\\.[^'\\\n\r]*)*')/g;

                // used to support leading #!/usr/bin/env in scripts as supported in Node
                var hashBangRegEx = /^\#\!.*/;

                function getCJSDeps(source) {
                    cjsRequireRegEx.lastIndex = commentRegEx.lastIndex = stringRegEx.lastIndex = 0;

                    var deps = [];

                    var match;

                    // track string and comment locations for unminified source
                    var stringLocations = [], commentLocations = [];

                    function inLocation(locations, match) {
                        for (var i = 0; i < locations.length; i++)
                            if (locations[i][0] < match.index && locations[i][1] > match.index)
                                return true;
                        return false;
                    }

                    if (source.length / source.split('\n').length < 200) {
                        while (match = stringRegEx.exec(source))
                            stringLocations.push([match.index, match.index + match[0].length]);

                        // TODO: track template literals here before comments

                        while (match = commentRegEx.exec(source)) {
                            // only track comments not starting in strings
                            if (!inLocation(stringLocations, match))
                                commentLocations.push([match.index + match[1].length, match.index + match[0].length - 1]);
                        }
                    }

                    while (match = cjsRequireRegEx.exec(source)) {
                        // ensure we're not within a string or comment location
                        if (!inLocation(stringLocations, match) && !inLocation(commentLocations, match)) {
                            var dep = match[1].substr(1, match[1].length - 2);
                            // skip cases like require('" + file + "')
                            if (dep.match(/"|'/))
                                continue;
                            // trailing slash requires are removed as they don't map mains in SystemJS
                            if (dep[dep.length - 1] == '/')
                                dep = dep.substr(0, dep.length - 1);
                            deps.push(dep);
                        }
                    }

                    return deps;
                }

                hook('instantiate', function(instantiate) {
                    return function(load) {
                        var loader = this;
                        if (!load.metadata.format) {
                            cjsExportsRegEx.lastIndex = 0;
                            cjsRequireRegEx.lastIndex = 0;
                            if (cjsRequireRegEx.exec(load.source) || cjsExportsRegEx.exec(load.source))
                                load.metadata.format = 'cjs';
                        }

                        if (load.metadata.format == 'cjs') {
                            var metaDeps = load.metadata.deps;
                            var deps = load.metadata.cjsRequireDetection === false ? [] : getCJSDeps(load.source);

                            for (var g in load.metadata.globals)
                                if (load.metadata.globals[g])
                                    deps.push(load.metadata.globals[g]);

                            var entry = createEntry();

                            load.metadata.entry = entry;

                            entry.deps = deps;
                            entry.executingRequire = true;
                            entry.execute = function(_require, exports, module) {
                                function require(name) {
                                    if (name[name.length - 1] == '/')
                                        name = name.substr(0, name.length - 1);
                                    return _require.apply(this, arguments);
                                }
                                require.resolve = function(name) {
                                    return loader.get('@@cjs-helpers').requireResolve(name, module.id);
                                };
                                // support module.paths ish
                                module.paths = [];
                                module.require = _require;

                                // ensure meta deps execute first
                                if (!load.metadata.cjsDeferDepsExecute)
                                    for (var i = 0; i < metaDeps.length; i++)
                                        require(metaDeps[i]);

                                var pathVars = loader.get('@@cjs-helpers').getPathVars(module.id);
                                var __cjsWrapper = {
                                    exports: exports,
                                    args: [require, exports, module, pathVars.filename, pathVars.dirname, __global, __global]
                                };

                                var cjsWrapper = "(function(require, exports, module, __filename, __dirname, global, GLOBAL";

                                // add metadata.globals to the wrapper arguments
                                if (load.metadata.globals)
                                    for (var g in load.metadata.globals) {
                                        __cjsWrapper.args.push(require(load.metadata.globals[g]));
                                        cjsWrapper += ", " + g;
                                    }

                                // disable AMD detection
                                var define = __global.define;
                                __global.define = undefined;
                                __global.__cjsWrapper = __cjsWrapper;

                                load.source = cjsWrapper + ") {" + load.source.replace(hashBangRegEx, '') + "\n}).apply(__cjsWrapper.exports, __cjsWrapper.args);";

                                __exec.call(loader, load);

                                __global.__cjsWrapper = undefined;
                                __global.define = define;
                            };
                        }

                        return instantiate.call(loader, load);
                    };
                });
            })();
            hookConstructor(function(constructor) {
                return function() {
                    var loader = this;
                    constructor.call(loader);

                    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('!');
                            var filename;
                            if (pluginIndex != -1)
                                filename = moduleId.substr(0, pluginIndex);
                            else
                                filename = moduleId;

                            var dirname = filename.split('/');
                            dirname.pop();
                            dirname = dirname.join('/');

                            return {
                                filename: stripOrigin(filename),
                                dirname: stripOrigin(dirname)
                            };
                        }
                    }))
                };
            });/*
             * AMD Helper function module
             * 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;
                    constructor.call(this);

                    var commentRegEx = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;
                    var cjsRequirePre = "(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])";
                    var cjsRequirePost = "\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)";
                    var fnBracketRegEx = /\(([^\)]*)\)/;
                    var wsRegEx = /^\s+|\s+$/g;

                    var requireRegExs = {};

                    function getCJSDeps(source, requireIndex) {

                        // remove comments
                        source = source.replace(commentRegEx, '');

                        // determine the require alias
                        var params = source.match(fnBracketRegEx);
                        var requireAlias = (params[1].split(',')[requireIndex] || 'require').replace(wsRegEx, '');

                        // find or generate the regex for this requireAlias
                        var requireRegEx = requireRegExs[requireAlias] || (requireRegExs[requireAlias] = new RegExp(cjsRequirePre + requireAlias + cjsRequirePost, 'g'));

                        requireRegEx.lastIndex = 0;

                        var deps = [];

                        var match;
                        while (match = requireRegEx.exec(source))
                            deps.push(match[2] || match[3]);

                        return deps;
                    }

                    /*
                     AMD-compatible require
                     To copy RequireJS, set window.require = window.requirejs = loader.amdRequire
                     */
                    function require(names, callback, errback, referer) {
                        // in amd, first arg can be a config object... we just ignore
                        if (typeof names == 'object' && !(names instanceof Array))
                            return require.apply(null, Array.prototype.splice.call(arguments, 1, arguments.length - 1));

                        // amd require
                        if (typeof names == 'string' && typeof callback == 'function')
                            names = [names];
                        if (names instanceof Array) {
                            var dynamicRequires = [];
                            for (var i = 0; i < names.length; i++)
                                dynamicRequires.push(loader['import'](names[i], referer));
                            Promise.all(dynamicRequires).then(function(modules) {
                                if (callback)
                                    callback.apply(null, modules);
                            }, errback);
                        }

                        // commonjs require
                        else if (typeof names == 'string') {
                            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 + '" as ' + normalized + (referer ? ' from "' + referer + '".' : '.'));
                            return module.__useDefault ? module['default'] : module;
                        }

                        else
                            throw new TypeError('Invalid require');
                    }

                    function define(name, deps, factory) {
                        if (typeof name != 'string') {
                            factory = deps;
                            deps = name;
                            name = null;
                        }
                        if (!(deps instanceof Array)) {
                            factory = deps;
                            deps = ['require', 'exports', 'module'].splice(0, factory.length);
                        }

                        if (typeof factory != 'function')
                            factory = (function(factory) {
                                return function() { return factory; }
                            })(factory);

                        // in IE8, a trailing comma becomes a trailing undefined entry
                        if (deps[deps.length - 1] === undefined)
                            deps.pop();

                        // remove system dependencies
                        var requireIndex, exportsIndex, moduleIndex;

                        if ((requireIndex = indexOf.call(deps, 'require')) != -1) {

                            deps.splice(requireIndex, 1);

                            // only trace cjs requires for non-named
                            // named defines assume the trace has already been done
                            if (!name)
                                deps = deps.concat(getCJSDeps(factory.toString(), requireIndex));
                        }

                        if ((exportsIndex = indexOf.call(deps, 'exports')) != -1)
                            deps.splice(exportsIndex, 1);

                        if ((moduleIndex = indexOf.call(deps, 'module')) != -1)
                            deps.splice(moduleIndex, 1);

                        function execute(req, exports, module) {
                            var depValues = [];
                            for (var i = 0; i < deps.length; i++)
                                depValues.push(req(deps[i]));

                            module.uri = module.id;

                            module.config = function() {};

                            // add back in system dependencies
                            if (moduleIndex != -1)
                                depValues.splice(moduleIndex, 0, module);

                            if (exportsIndex != -1)
                                depValues.splice(exportsIndex, 0, exports);

                            if (requireIndex != -1) {
                                function contextualRequire(names, callback, errback) {
                                    if (typeof names == 'string' && typeof callback != 'function')
                                        return req(names);
                                    return require.call(loader, names, callback, errback, module.id);
                                }
                                contextualRequire.toUrl = function(name) {
                                    // normalize without defaultJSExtensions
                                    var defaultJSExtension = loader.defaultJSExtensions && name.substr(name.length - 3, 3) != '.js';
                                    var url = loader.decanonicalize(name, module.id);
                                    if (defaultJSExtension && url.substr(url.length - 3, 3) == '.js')
                                        url = url.substr(0, url.length - 3);
                                    return url;
                                };
                                depValues.splice(requireIndex, 0, contextualRequire);
                            }

                            // set global require to AMD require
                            var curRequire = __global.require;
                            __global.require = require;

                            var output = factory.apply(exportsIndex == -1 ? __global : exports, depValues);

                            __global.require = curRequire;

                            if (typeof output == 'undefined' && module)
                                output = module.exports;

                            if (typeof output != 'undefined')
                                return output;
                        }

                        var entry = createEntry();
                        entry.name = name && (loader.decanonicalize || loader.normalize).call(loader, name);
                        entry.deps = deps;
                        entry.execute = execute;

                        loader.pushRegister_({
                            amd: true,
                            entry: entry
                        });
                    }
                    define.amd = {};

                    // reduction function to attach defines to a load record
                    hook('reduceRegister_', function(reduceRegister) {
                        return function(load, register) {
                            // only handle AMD registers here
                            if (!register || !register.amd)
                                return reduceRegister.call(this, load, register);

                            var curMeta = load && load.metadata;
                            var entry = register.entry;

                            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.');

                                if (curMeta.entry && !curMeta.entry.name)
                                    throw new Error('Multiple anonymous defines in module ' + load.name);

                                curMeta.entry = entry;
                            }
                            // named define
                            else {
                                // if we don't have any other defines,
                                // then let this be an anonymous define
                                // this is just to support single modules of the form:
                                // define('jquery')
                                // still loading anonymously
                                // because it is done widely enough to be useful
                                // as soon as there is more than one define, this gets removed though
                                if (curMeta) {
                                    if (!curMeta.entry && !curMeta.bundle)
                                        curMeta.entry = entry;
                                    else if (curMeta.entry && curMeta.entry.name && curMeta.entry.name != load.name)
                                        curMeta.entry = undefined;

                                    // note this is now a bundle
                                    curMeta.bundle = true;
                                }

                                // define the module through the register registry
                                if (!(entry.name in this.defined))
                                    this.defined[entry.name] = entry;
                            }
                        };
                    });

                    loader.amdDefine = define;
                    loader.amdRequire = require;
                };
            });/*
             SystemJS AMD Format
             */
            (function() {
                // AMD Module Format Detection RegEx
                // define([.., .., ..], ...)
                // define(varName); || define(function(require, exports) {}); || define({})
                var amdRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])define\s*\(\s*("[^"]+"\s*,\s*|'[^']+'\s*,\s*)?\s*(\[(\s*(("[^"]+"|'[^']+')\s*,|\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*(\s*("[^"]+"|'[^']+')\s*,?)?(\s*(\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*\s*\]|function\s*|{|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*\))/;

                hook('instantiate', function(instantiate) {
                    return function(load) {
                        var loader = this;

                        if (load.metadata.format == 'amd' || !load.metadata.format && load.source.match(amdRegEx)) {
                            load.metadata.format = 'amd';

                            if (!loader.builder && loader.execute !== false) {
                                var curDefine = __global.define;
                                __global.define = this.amdDefine;

                                try {
                                    __exec.call(loader, load);
                                }
                                finally {
                                    __global.define = curDefine;
                                }

                                if (!load.metadata.entry && !load.metadata.bundle)
                                    throw new TypeError('AMD module ' + load.name + ' did not define');
                            }
                            else {
                                load.metadata.execute = function() {
                                    return load.metadata.builderExecute.apply(this, arguments);
                                };
                            }
                        }

                        return instantiate.call(loader, load);
                    };
                });

            })();
            /*
             SystemJS Loader Plugin Support

             Supports plugin loader syntax with "!", or via metadata.loader

             The plugin name is loaded as a module itself, and can override standard loader hooks
             for the plugin resource. See the plugin section of the systemjs readme.
             */

            (function() {
                function getParentName(loader, parentName) {
                    // if parent is a plugin, normalize against the parent plugin argument only
                    if (parentName) {
                        var parentPluginIndex;
                        if (loader.pluginFirst) {
                            if ((parentPluginIndex = parentName.lastIndexOf('!')) != -1)
                                return parentName.substr(parentPluginIndex + 1);
                        }
                        else {
                            if ((parentPluginIndex = parentName.indexOf('!')) != -1)
                                return parentName.substr(0, parentPluginIndex);
                        }

                        return parentName;
                    }
                }

                function parsePlugin(loader, name) {
                    var argumentName;
                    var pluginName;

                    var pluginIndex = name.lastIndexOf('!');

                    if (pluginIndex == -1)
                        return;

                    if (loader.pluginFirst) {
                        argumentName = name.substr(pluginIndex + 1);
                        pluginName = name.substr(0, pluginIndex);
                    }
                    else {
                        argumentName = name.substr(0, pluginIndex);
                        pluginName = name.substr(pluginIndex + 1) || argumentName.substr(argumentName.lastIndexOf('.') + 1);
                    }

                    return {
                        argument: argumentName,
                        plugin: pluginName
                    };
                }

                // put name back together after parts have been normalized
                function combinePluginParts(loader, argumentName, pluginName, defaultExtension) {
                    if (defaultExtension && argumentName.substr(argumentName.length - 3, 3) == '.js')
                        argumentName = argumentName.substr(0, argumentName.length - 3);

                    if (loader.pluginFirst) {
                        return pluginName + '!' + argumentName;
                    }
                    else {
                        return argumentName + '!' + pluginName;
                    }
                }

                // note if normalize will add a default js extension
                // if so, remove for backwards compat
                // this is strange and sucks, but will be deprecated
                function checkDefaultExtension(loader, arg) {
                    return loader.defaultJSExtensions && arg.substr(arg.length - 3, 3) != '.js';
                }

                function createNormalizeSync(normalizeSync) {
                    return function(name, parentName, isPlugin) {
                        var loader = this;

                        var parsed = parsePlugin(loader, name);
                        parentName = getParentName(this, parentName);

                        if (!parsed)
                            return normalizeSync.call(this, name, parentName, isPlugin);

                        // if this is a plugin, normalize the plugin name and the argument
                        var argumentName = loader.normalizeSync(parsed.argument, parentName, true);
                        var pluginName = loader.normalizeSync(parsed.plugin, parentName, true);
                        return combinePluginParts(loader, argumentName, pluginName, checkDefaultExtension(loader, parsed.argument));
                    };
                }

                hook('decanonicalize', createNormalizeSync);
                hook('normalizeSync', createNormalizeSync);

                hook('normalize', function(normalize) {
                    return function(name, parentName, isPlugin) {
                        var loader = this;

                        parentName = getParentName(this, parentName);

                        var parsed = parsePlugin(loader, name);

                        if (!parsed)
                            return normalize.call(loader, name, parentName, isPlugin);

                        return Promise.all([
                            loader.normalize(parsed.argument, parentName, true),
                            loader.normalize(parsed.plugin, parentName, false)
                        ])
                            .then(function(normalized) {
                                return combinePluginParts(loader, normalized[0], normalized[1], checkDefaultExtension(loader, parsed.argument));
                            });
                    }
                });

                hook('locate', function(locate) {
                    return function(load) {
                        var loader = this;

                        var name = load.name;

                        // plugin syntax
                        var pluginSyntaxIndex;
                        if (loader.pluginFirst) {
                            if ((pluginSyntaxIndex = name.indexOf('!')) != -1) {
                                load.metadata.loader = name.substr(0, pluginSyntaxIndex);
                                load.name = name.substr(pluginSyntaxIndex + 1);
                            }
                        }
                        else {
                            if ((pluginSyntaxIndex = name.lastIndexOf('!')) != -1) {
                                load.metadata.loader = name.substr(pluginSyntaxIndex + 1);
                                load.name = name.substr(0, pluginSyntaxIndex);
                            }
                        }

                        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;

                                var pluginLoader = loader.pluginLoader || loader;

                                // load the plugin module and run standard locate
                                return pluginLoader['import'](plugin)
                                    .then(function(loaderModule) {
                                        // store the plugin module itself on the metadata
                                        load.metadata.loaderModule = loaderModule;

                                        load.address = address;
                                        if (loaderModule.locate)
                                            return loaderModule.locate.call(loader, load);

                                        return address;
                                    });
                            });
                    };
                });

                hook('fetch', function(fetch) {
                    return function(load) {
                        var loader = this;
                        if (load.metadata.loaderModule && load.metadata.loaderModule.fetch && load.metadata.format != 'defined') {
                            load.metadata.scriptLoad = false;
                            return load.metadata.loaderModule.fetch.call(loader, load, function(load) {
                                return fetch.call(loader, load);
                            });
                        }
                        else {
                            return fetch.call(loader, load);
                        }
                    };
                });

                hook('translate', function(translate) {
                    return function(load) {
                        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.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;
                                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.apply(loader, args);
                        }
                    };
                });

                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, 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;
                                }
                                load.metadata.entry.deps = load.metadata.deps;
                                load.metadata.format = 'defined';
                                return instantiate.call(loader, load);
                            });
                        else
                            return instantiate.call(loader, load);
                    };
                });

            })();/*
             * Conditions Extension
             *
             *   Allows a condition module to alter the resolution of an import via syntax:
             *
             *     import $ from 'jquery/#{browser}';
             *
             *   Will first load the module 'browser' via `SystemJS.import('browser')` and
             *   take the default export of that module.
             *   If the default export is not a string, an error is thrown.
             *
             *   We then substitute the string into the require to get the conditional resolution
             *   enabling environment-specific variations like:
             *
             *     import $ from 'jquery/ie'
             *     import $ from 'jquery/firefox'
             *     import $ from 'jquery/chrome'
             *     import $ from 'jquery/safari'
             *
             *   It can be useful for a condition module to define multiple conditions.
             *   This can be done via the `|` modifier to specify an export member expression:
             *
             *     import 'jquery/#{./browser.js|grade.version}'
             *
             *   Where the `grade` export `version` member in the `browser.js` module  is substituted.
             *
             *
             * Boolean Conditionals
             *
             *   For polyfill modules, that are used as imports but have no module value,
             *   a binary conditional allows a module not to be loaded at all if not needed:
             *
             *     import 'es5-shim#?./conditions.js|needs-es5shim'
             *
             *   These conditions can also be negated via:
             *
             *     import 'es5-shim#?./conditions.js|~es6'
             *
             */

            var sysConditions = ['browser', 'node', 'dev', 'build', 'production', 'default'];

            function parseCondition(condition) {
                var conditionExport, conditionModule, negation;

                var negation = condition[0] == '~';
                var conditionExportIndex = condition.lastIndexOf('|');
                if (conditionExportIndex != -1) {
                    conditionExport = condition.substr(conditionExportIndex + 1);
                    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 = 'default';
                    conditionModule = condition.substr(negation);
                    if (sysConditions.indexOf(conditionModule) != -1) {
                        conditionExport = conditionModule;
                        conditionModule = null;
                    }
                }

                return {
                    module: conditionModule || '@system-env',
                    prop: conditionExport,
                    negate: negation
                };
            }

            function serializeCondition(conditionObj) {
                return conditionObj.module + '|' + (conditionObj.negate ? '~' : '') + conditionObj.prop;
            }

            function resolveCondition(conditionObj, parentName, bool) {
                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;
                            });
                    });
            }

            var interpolationRegEx = /#\{[^\}]+\}/;
            function interpolateConditional(name, parentName) {
                // first we normalize the conditional
                var conditionalMatch = name.match(interpolationRegEx);

                if (!conditionalMatch)
                    return Promise.resolve(name);

                var conditionObj = parseCondition.call(this, conditionalMatch[0].substr(2, conditionalMatch[0].length - 3));

                // in builds, return normalized conditional
                if (this.builder)
                    return this['normalize'](conditionObj.module, parentName)
                        .then(function(conditionModule) {
                            conditionObj.module = conditionModule;
                            return name.replace(interpolationRegEx, '#{' + serializeCondition(conditionObj) + '}');
                        });

                return resolveCondition.call(this, conditionObj, parentName, false)
                    .then(function(conditionValue) {
                        if (typeof conditionValue !== 'string')
                            throw new TypeError('The condition value for ' + name + ' doesn\'t resolve to a string.');

                        if (conditionValue.indexOf('/') != -1)
                            throw new TypeError('Unabled to interpolate conditional ' + name + (parentName ? ' in ' + parentName : '') + '\n\tThe condition value ' + conditionValue + ' cannot contain a "/" separator.');

                        return name.replace(interpolationRegEx, conditionValue);
                    });
            }

            function booleanConditional(name, parentName) {
                // first we normalize the conditional
                var booleanIndex = name.lastIndexOf('#?');

                if (booleanIndex == -1)
                    return Promise.resolve(name);

                var conditionObj = parseCondition.call(this, name.substr(booleanIndex + 2));

                // in builds, return normalized conditional
                if (this.builder)
                    return this['normalize'](conditionObj.module, parentName)
                        .then(function(conditionModule) {
                            conditionObj.module = conditionModule;
                            return name.substr(0, booleanIndex) + '#?' + serializeCondition(conditionObj);
                        });

                return resolveCondition.call(this, conditionObj, parentName, true)
                    .then(function(conditionValue) {
                        return conditionValue ? name.substr(0, booleanIndex) : '@empty';
                    });
            }

            // normalizeSync does not parse conditionals at all although it could
            hook('normalize', function(normalize) {
                return function(name, parentName, skipExt) {
                    var loader = this;
                    return booleanConditional.call(loader, name, parentName)
                        .then(function(name) {
                            return normalize.call(loader, name, parentName, skipExt);
                        })
                        .then(function(normalized) {
                            return interpolateConditional.call(loader, normalized, parentName);
                        });
                };
            });
            /*
             * Alias Extension
             *
             * Allows a module to be a plain copy of another module by module name
             *
             * SystemJS.meta['mybootstrapalias'] = { alias: 'bootstrap' };
             *
             */
            (function() {
                // aliases
                hook('fetch', function(fetch) {
                    return function(load) {
                        var alias = load.metadata.alias;
                        var aliasDeps = load.metadata.deps || [];
                        if (alias) {
                            load.metadata.format = 'defined';
                            var entry = createEntry();
                            this.defined[load.name] = entry;
                            entry.declarative = true;
                            entry.deps = aliasDeps.concat([alias]);
                            entry.declare = function(_export) {
                                return {
                                    setters: [function(module) {
                                        for (var p in module)
                                            _export(p, module[p]);
                                        if (module.__useDefault)
                                            entry.module.exports.__useDefault = true;
                                    }],
                                    execute: function() {}
                                };
                            };
                            return '';
                        }

                        return fetch.call(this, load);
                    };
                });
            })();/*
             * Meta Extension
             *
             * Sets default metadata on a load record (load.metadata) from
             * loader.metadata via SystemJS.meta function.
             *
             *
             * Also provides an inline meta syntax for module meta in source.
             *
             * Eg:
             *
             * loader.meta({
             *   'my/module': { deps: ['jquery'] }
             *   'my/*': { format: 'amd' }
             * });
             *
             * Which in turn populates loader.metadata.
             *
             * load.metadata.deps and load.metadata.format will then be set
             * for 'my/module'
             *
             * The same meta could be set with a my/module.js file containing:
             *
             * my/module.js
             *   "format amd";
             *   "deps[] jquery";
             *   "globals.some value"
             *   console.log('this is my/module');
             *
             * Configuration meta always takes preference to inline meta.
             *
             * Multiple matches in wildcards are supported and ammend the meta.
             *
             *
             * The benefits of the function form is that paths are URL-normalized
             * supporting say
             *
             * loader.meta({ './app': { format: 'cjs' } });
             *
             * Instead of needing to set against the absolute URL (https://site.com/app.js)
             *
             */

            (function() {

                hookConstructor(function(constructor) {
                    return function() {
                        this.meta = {};
                        constructor.call(this);
                    };
                });

                hook('locate', function(locate) {
                    return function(load) {
                        var meta = this.meta;
                        var name = load.name;

                        // NB for perf, maybe introduce a fast-path wildcard lookup cache here
                        // which is checked first

                        // apply wildcard metas
                        var bestDepth = 0;
                        var wildcardIndex;
                        for (var module in meta) {
                            wildcardIndex = module.indexOf('*');
                            if (wildcardIndex === -1)
                                continue;
                            if (module.substr(0, wildcardIndex) === name.substr(0, wildcardIndex)
                                && module.substr(wildcardIndex + 1) === name.substr(name.length - module.length + wildcardIndex + 1)) {
                                var depth = module.split('/').length;
                                if (depth > bestDepth)
                                    bestDepth = depth;
                                extendMeta(load.metadata, meta[module], bestDepth != depth);
                            }
                        }

                        // apply exact meta
                        if (meta[name])
                            extendMeta(load.metadata, meta[name]);

                        return locate.call(this, load);
                    };
                });

                // detect any meta header syntax
                // only set if not already set
                var metaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/;
                var metaPartRegEx = /\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g;

                function setMetaProperty(target, p, value) {
                    var pParts = p.split('.');
                    var curPart;
                    while (pParts.length > 1) {
                        curPart = pParts.shift();
                        target = target[curPart] = target[curPart] || {};
                    }
                    curPart = pParts.shift();
                    if (!(curPart in target))
                        target[curPart] = value;
                }

                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) {
                            var metaParts = meta[0].match(metaPartRegEx);

                            for (var i = 0; i < metaParts.length; i++) {
                                var curPart = metaParts[i];
                                var len = curPart.length;

                                var firstChar = curPart.substr(0, 1);
                                if (curPart.substr(len - 1, 1) == ';')
                                    len--;

                                if (firstChar != '"' && firstChar != "'")
                                    continue;

                                var metaString = curPart.substr(1, curPart.length - 3);
                                var metaName = metaString.substr(0, metaString.indexOf(' '));

                                if (metaName) {
                                    var metaValue = metaString.substr(metaName.length + 1, metaString.length - metaName.length - 1);

                                    if (metaName.substr(metaName.length - 2, 2) == '[]') {
                                        metaName = metaName.substr(0, metaName.length - 2);
                                        load.metadata[metaName] = load.metadata[metaName] || [];
                                        load.metadata[metaName].push(metaValue);
                                    }
                                    else if (load.metadata[metaName] instanceof Array) {
                                        // temporary backwards compat for previous "deps" syntax
                                        warn.call(this, 'Module ' + load.name + ' contains deprecated "deps ' + metaValue + '" meta syntax.\nThis should be updated to "deps[] ' + metaValue + '" for pushing to array meta.');
                                        load.metadata[metaName].push(metaValue);
                                    }
                                    else {
                                        setMetaProperty(load.metadata, metaName, metaValue);
                                    }
                                }
                                else {
                                    load.metadata[metaString] = true;
                                }
                            }
                        }

                        return translate.apply(this, arguments);
                    };
                });
            })();
            /*
             System bundles

             Allows a bundle module to be specified which will be dynamically
             loaded before trying to load a given module.

             For example:
             SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap']

             Will result in a load to "mybundle" whenever a load to "jquery"
             or "bootstrap/js/bootstrap" is made.

             In this way, the bundle becomes the request that provides the module
             */

            (function() {
                // bundles support (just like RequireJS)
                // bundle name is module name of bundle itself
                // bundle is array of modules defined by the bundle
                // when a module in the bundle is requested, the bundle is loaded instead
                // of the form SystemJS.bundles['mybundle'] = ['jquery', 'bootstrap/js/bootstrap']
                hookConstructor(function(constructor) {
                    return function() {
                        constructor.call(this);
                        this.bundles = {};
                        this._loader.loadedBundles = {};
                    };
                });

                // assign bundle metadata for bundle loads
                hook('locate', function(locate) {
                    return function(load) {
                        var loader = this;
                        var matched = false;

                        if (!(load.name in loader.defined))
                            for (var b in loader.bundles) {
                                for (var i = 0; i < loader.bundles[b].length; i++) {
                                    var curModule = loader.bundles[b][i];

                                    if (curModule == load.name) {
                                        matched = true;
                                        break;
                                    }

                                    // wildcard in bundles does not include / boundaries
                                    if (curModule.indexOf('*') != -1) {
                                        var parts = curModule.split('*');
                                        if (parts.length != 2) {
                                            loader.bundles[b].splice(i--, 1);
                                            continue;
                                        }

                                        if (load.name.substring(0, parts[0].length) == parts[0] &&
                                            load.name.substr(load.name.length - parts[1].length, parts[1].length) == parts[1] &&
                                            load.name.substr(parts[0].length, load.name.length - parts[1].length - parts[0].length).indexOf('/') == -1) {
                                            matched = true;
                                            break;
                                        }
                                    }
                                }

                                if (matched)
                                    return loader['import'](b)
                                        .then(function() {
                                            return locate.call(loader, load);
                                        });
                            }

                        return locate.call(loader, load);
                    };
                });
            })();
            /*
             * Dependency Tree Cache
             *
             * Allows a build to pre-populate a dependency trace tree on the loader of
             * the expected dependency tree, to be loaded upfront when requesting the
             * module, avoinding the n round trips latency of module loading, where
             * n is the dependency tree depth.
             *
             * eg:
             * SystemJS.depCache = {
             *  'app': ['normalized', 'deps'],
             *  'normalized': ['another'],
             *  'deps': ['tree']
             * };
             *
             * SystemJS.import('app')
             * // simultaneously starts loading all of:
             * // 'normalized', 'deps', 'another', 'tree'
             * // before "app" source is even loaded
             *
             */

            (function() {
                hookConstructor(function(constructor) {
                    return function() {
                        constructor.call(this);
                        this.depCache = {};
                    }
                });

                hook('locate', function(locate) {
                    return function(load) {
                        var loader = this;
                        // load direct deps, in turn will pick up their trace trees
                        var deps = loader.depCache[load.name];
                        if (deps)
                            for (var i = 0; i < deps.length; i++)
                                loader['import'](deps[i], load.name);

                        return locate.call(loader, load);
                    };
                });
            })();

            System = new SystemJSLoader();

            __global.SystemJS = System;
            System.version = '0.19.38 Standard';
            if (typeof module == 'object' && module.exports && typeof exports == 'object')
                module.exports = System;

            __global.rnSystem = System;

        })(typeof self != 'undefined' ? self : global);}

// auto-load Promise polyfill if needed in the browser
    var doPolyfill = typeof Promise === 'undefined';

// document.write
    if (typeof document !== 'undefined') {
        var scripts = document.getElementsByTagName('script');
        $__curScript = scripts[scripts.length - 1];
        if ($__curScript.defer || $__curScript.async)
            $__curScript = document.currentScript;
        if (doPolyfill) {
            var curPath = $__curScript.src;
            var basePath = curPath.substr(0, curPath.lastIndexOf('/') + 1);
            window.systemJSBootstrap = bootstrap;
            document.write(
                '<' + 'script type="text/javascript" src="' + basePath + 'system-polyfills.js">' + '<' + '/script>'
            );
        }
        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();
    }


})();