| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653 | /** * ESL (Enterprise Standard Loader) * Copyright 2013 Baidu Inc. All rights reserved. * * @file Browser端标准加载器,符合AMD规范 * @author errorrik(errorrik@gmail.com) *         Firede(firede@firede.us) *//* jshint ignore:start */var define;var require;var esl;/* jshint ignore:end */(function (global) {    // "mod"开头的变量或函数为内部模块管理函数    // 为提高压缩率,不使用function或object包装    /**     * 模块容器     *     * @inner     * @type {Object}     */    var modModules = {};    /**     * 自动定义的模块表     *     * 模块define factory是用到时才执行,但是以下几种情况需要自动马上执行:     * 1. require( [moduleId], callback )     * 2. plugin module: require( 'plugin!resource' )     *     * @inner     * @type {Object}     */    var autoDefineModules = {};    // 模块状态枚举量    var MODULE_PRE_DEFINED = 1;    var MODULE_ANALYZED = 2;    var MODULE_PREPARED = 3;    var MODULE_DEFINED = 4;    /**     * 内建module名称集合     *     * @inner     * @type {Object}     */    var BUILDIN_MODULE = {        require: globalRequire,        exports: 1,        module: 1    };    /**     * 全局require函数     *     * @inner     * @type {Function}     */    var actualGlobalRequire = createLocalRequire();    // #begin-ignore    /**     * 超时提醒定时器     *     * @inner     * @type {number}     */    var waitTimeout;    // #end-ignore    /* eslint-disable fecs-key-spacing */    /* eslint-disable key-spacing */    /**     * require配置     *     * @inner     * @type {Object}     */    var requireConf = {        baseUrl    : './',        paths      : {},        config     : {},        map        : {},        packages   : [],        // #begin-ignore        waitSeconds: 0,        // #end-ignore        noRequests : {},        urlArgs    : {}    };    /* eslint-enable key-spacing */    /**     * 加载模块     *     * @param {string|Array} requireId 模块id或模块id数组,     * @param {Function=} callback 加载完成的回调函数     * @return {*} requireId为string时返回模块暴露对象     */    function globalRequire(requireId, callback) {        // #begin-ignore        // #begin assertNotContainRelativeId        // 确定require的模块id不包含相对id。用于global require,提前预防难以跟踪的错误出现        var invalidIds = [];        /**         * 监测模块id是否relative id         *         * @inner         * @param {string} id 模块id         */        function monitor(id) {            if (id.indexOf('.') === 0) {                invalidIds.push(id);            }        }        if (typeof requireId === 'string') {            monitor(requireId);        }        else {            each(                requireId,                function (id) {                    monitor(id);                }            );        }        // 包含相对id时,直接抛出错误        if (invalidIds.length > 0) {            throw new Error(                '[REQUIRE_FATAL]Relative ID is not allowed in global require: '                + invalidIds.join(', ')            );        }        // #end assertNotContainRelativeId        // 超时提醒        var timeout = requireConf.waitSeconds;        if (timeout && (requireId instanceof Array)) {            if (waitTimeout) {                clearTimeout(waitTimeout);            }            waitTimeout = setTimeout(waitTimeoutNotice, timeout * 1000);        }        // #end-ignore        return actualGlobalRequire(requireId, callback);    }    /**     * 版本号     *     * @type {string}     */    globalRequire.version = '1.8.8';    /**     * loader名称     *     * @type {string}     */    globalRequire.loader = 'esl';    /**     * 将模块标识转换成相对的url     *     * @param {string} id 模块标识     * @return {string}     */    globalRequire.toUrl = actualGlobalRequire.toUrl;    // #begin-ignore    /**     * 超时提醒函数     *     * @inner     */    function waitTimeoutNotice() {        var hangModules = [];        var missModules = [];        var hangModulesMap = {};        var missModulesMap = {};        var visited = {};        /**         * 检查模块的加载错误         *         * @inner         * @param {string} id 模块id         * @param {boolean} hard 是否装载时依赖         */        function checkError(id, hard) {            if (visited[id] || modIs(id, MODULE_DEFINED)) {                return;            }            visited[id] = 1;            if (!modIs(id, MODULE_PREPARED)) {                // HACK: 为gzip后体积优化,不做抽取                if (!hangModulesMap[id]) {                    hangModulesMap[id] = 1;                    hangModules.push(id);                }            }            var mod = modModules[id];            if (!mod) {                if (!missModulesMap[id]) {                    missModulesMap[id] = 1;                    missModules.push(id);                }            }            else if (hard) {                if (!hangModulesMap[id]) {                    hangModulesMap[id] = 1;                    hangModules.push(id);                }                each(                    mod.depMs,                    function (dep) {                        checkError(dep.absId, dep.hard);                    }                );            }        }        /* eslint-disable guard-for-in */        for (var id in autoDefineModules) {            checkError(id, 1);        }        /* eslint-enable guard-for-in */        if (hangModules.length || missModules.length) {            throw new Error(                '[MODULE_TIMEOUT]Hang( '                + (hangModules.join(', ') || 'none')                + ' ) Miss( '                + (missModules.join(', ') || 'none')                + ' )'            );        }    }    // #end-ignore    /**     * 未预定义的模块集合     * 主要存储匿名方式define的模块     *     * @inner     * @type {Array}     */    var wait4PreDefine = [];    /**     * 完成模块预定义,此时处理的模块是匿名define的模块     *     * @inner     * @param {string} currentId 匿名define的模块的id     */    function completePreDefine(currentId) {        // HACK: 这里在IE下有个性能陷阱,不能使用任何变量。        //       否则貌似会形成变量引用和修改的读写锁,导致wait4PreDefine释放困难        each(wait4PreDefine, function (mod) {            modPreDefine(                currentId,                mod.deps,                mod.factory            );        });        wait4PreDefine.length = 0;        modAnalyse(currentId);    }    /**     * 定义模块     *     * @param {string=} id 模块标识     * @param {Array=} dependencies 依赖模块列表     * @param {Function=} factory 创建模块的工厂方法     */    function globalDefine(id, dependencies, factory) {        // define(factory)        // define(dependencies, factory)        // define(id, factory)        // define(id, dependencies, factory)        if (factory == null) {            if (dependencies == null) {                factory = id;                id = null;            }            else {                factory = dependencies;                dependencies = null;                if (id instanceof Array) {                    dependencies = id;                    id = null;                }            }        }        if (factory == null) {            return;        }        var opera = window.opera;        // IE下通过current script的data-require-id获取当前id        if (            !id            && document.attachEvent            && (!(opera && opera.toString() === '[object Opera]'))        ) {            var currentScript = getCurrentScript();            id = currentScript && currentScript.getAttribute('data-require-id');        }        if (id) {            modPreDefine(id, dependencies, factory);        }        else {            // 纪录到共享变量中,在load或readystatechange中处理            // 标准浏览器下,使用匿名define时,将进入这个分支            wait4PreDefine[0] = {                deps: dependencies,                factory: factory            };        }    }    globalDefine.amd = {};    /**     * 模块配置获取函数     *     * @inner     * @return {Object} 模块配置对象     */    function moduleConfigGetter() {        var conf = requireConf.config[this.id];        if (conf && typeof conf === 'object') {            return conf;        }        return {};    }    /**     * 预定义模块     *     * @inner     * @param {string} id 模块标识     * @param {Array.<string>} dependencies 显式声明的依赖模块列表     * @param {*} factory 模块定义函数或模块对象     */    function modPreDefine(id, dependencies, factory) {        // 将模块存入容器        //        // 模块内部信息包括        // -----------------------------------        // id: module id        // depsDec: 模块定义时声明的依赖        // deps: 模块依赖,默认为['require', 'exports', 'module']        // factory: 初始化函数或对象        // factoryDeps: 初始化函数的参数依赖        // exports: 模块的实际暴露对象(AMD定义)        // config: 用于获取模块配置信息的函数(AMD定义)        // state: 模块当前状态        // require: local require函数        // depMs: 实际依赖的模块集合,数组形式        // depMkv: 实际依赖的模块集合,表形式,便于查找        // depRs: 实际依赖的资源集合        // depPMs: 用于加载资源的模块集合,key是模块名,value是1,仅用于快捷查找        // ------------------------------------        if (!modModules[id]) {            /* eslint-disable key-spacing */            modModules[id] = {                id          : id,                depsDec     : dependencies,                deps        : dependencies || ['require', 'exports', 'module'],                factoryDeps : [],                factory     : factory,                exports     : {},                config      : moduleConfigGetter,                state       : MODULE_PRE_DEFINED,                require     : createLocalRequire(id),                depMs       : [],                depMkv      : {},                depRs       : [],                depPMs      : []            };            /* eslint-enable key-spacing */        }    }    /**     * 预分析模块     *     * 首先,完成对factory中声明依赖的分析提取     * 然后,尝试加载"资源加载所需模块"     *     * 需要先加载模块的原因是:如果模块不存在,无法进行resourceId normalize化     * modAnalyse完成后续的依赖分析处理,并进行依赖模块的加载     *     * @inner     * @param {string} id 模块id     */    function modAnalyse(id) {        var mod = modModules[id];        if (!mod || modIs(id, MODULE_ANALYZED)) {            return;        }        var deps = mod.deps;        var factory = mod.factory;        var hardDependsCount = 0;        // 分析function body中的require        // 如果包含显式依赖声明,根据AMD规定和性能考虑,可以不分析factoryBody        if (typeof factory === 'function') {            hardDependsCount = Math.min(factory.length, deps.length);            // If the dependencies argument is present, the module loader            // SHOULD NOT scan for dependencies within the factory function.            !mod.depsDec && factory.toString()                .replace(/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, '')                .replace(/require\(\s*(['"'])([^'"]+)\1\s*\)/g,                    function ($0, $1, depId) {                        deps.push(depId);                    }                );        }        var requireModules = [];        each(deps, function (depId, index) {            var idInfo = parseId(depId);            var absId = normalize(idInfo.mod, id);            var moduleInfo;            var resInfo;            if (absId && !BUILDIN_MODULE[absId]) {                // 如果依赖是一个资源,将其信息添加到module.depRs                //                // module.depRs中的项有可能是重复的。                // 在这个阶段,加载resource的module可能还未defined,                // 导致此时resource id无法被normalize。                //                // 比如对a/b/c而言,下面几个resource可能指的是同一个资源:                // - js!../name.js                // - js!a/name.js                // - ../../js!../name.js                //                // 所以加载资源的module ready时,需要遍历module.depRs进行处理                if (idInfo.res) {                    resInfo = {                        id: depId,                        mod: absId,                        res: idInfo.res                    };                    autoDefineModules[absId] = 1;                    mod.depPMs.push(absId);                    mod.depRs.push(resInfo);                }                // 对依赖模块的id normalize能保证正确性,在此处进行去重                moduleInfo = mod.depMkv[absId];                if (!moduleInfo) {                    moduleInfo = {                        id: idInfo.mod,                        absId: absId,                        hard: index < hardDependsCount                    };                    mod.depMs.push(moduleInfo);                    mod.depMkv[absId] = moduleInfo;                    requireModules.push(absId);                }            }            else {                moduleInfo = {absId: absId};            }            // 如果当前正在分析的依赖项是define中声明的,            // 则记录到module.factoryDeps中            // 在factory invoke前将用于生成invoke arguments            if (index < hardDependsCount) {                mod.factoryDeps.push(resInfo || moduleInfo);            }        });        mod.state = MODULE_ANALYZED;        modInitFactoryInvoker(id);        nativeRequire(requireModules);    }    /**     * 对一些需要自动定义的模块进行自动定义     *     * @inner     */    function modAutoInvoke() {        /* eslint-disable guard-for-in */        for (var id in autoDefineModules) {            modUpdatePreparedState(id);            modTryInvokeFactory(id);        }        /* eslint-enable guard-for-in */    }    /**     * 更新模块的准备状态     *     * @inner     * @param {string} id 模块id     */    function modUpdatePreparedState(id) {        var visited = {};        update(id);        function update(id) {            if (!modIs(id, MODULE_ANALYZED)) {                return false;            }            if (modIs(id, MODULE_PREPARED) || visited[id]) {                return true;            }            visited[id] = 1;            var mod = modModules[id];            var prepared = true;            each(                mod.depMs,                function (dep) {                    return (prepared = update(dep.absId));                }            );            // 判断resource是否加载完成。如果resource未加载完成,则认为未准备好            /* jshint ignore:start */            prepared && each(                mod.depRs,                function (dep) {                    prepared = !!(dep.absId && modIs(dep.absId, MODULE_DEFINED));                    return prepared;                }            );            /* jshint ignore:end */            if (prepared) {                mod.state = MODULE_PREPARED;            }            return prepared;        }    }    /**     * 初始化模块定义时所需的factory执行器     *     * @inner     * @param {string} id 模块id     */    function modInitFactoryInvoker(id) {        var mod = modModules[id];        var invoking;        mod.invokeFactory = invokeFactory;        /* eslint-disable max-nested-callbacks */        each(            mod.depPMs,            function (pluginModuleId) {                modAddDefinedListener(                    pluginModuleId,                    function () {                        each(mod.depRs, function (res) {                            if (!res.absId && res.mod === pluginModuleId) {                                res.absId = normalize(res.id, id);                                nativeRequire([res.absId], modAutoInvoke);                            }                        });                    }                );            }        );        /* eslint-enable max-nested-callbacks */        /**         * 初始化模块         *         * @inner         */        function invokeFactory() {            if (invoking || mod.state !== MODULE_PREPARED) {                return;            }            invoking = 1;            // 拼接factory invoke所需的arguments            var factoryReady = 1;            var factoryDeps = [];            each(                mod.factoryDeps,                function (dep) {                    var depId = dep.absId;                    if (!BUILDIN_MODULE[depId]) {                        modTryInvokeFactory(depId);                        if (!modIs(depId, MODULE_DEFINED)) {                            factoryReady = 0;                            return false;                        }                    }                    factoryDeps.push(depId);                }            );            if (factoryReady) {                try {                    var args = modGetModulesExports(                        factoryDeps,                        {                            require: mod.require,                            exports: mod.exports,                            module: mod                        }                    );                    // 调用factory函数初始化module                    var factory = mod.factory;                    var exports = typeof factory === 'function'                        ? factory.apply(global, args)                        : factory;                    if (exports != null) {                        mod.exports = exports;                    }                    mod.invokeFactory = null;                    delete autoDefineModules[id];                }                catch (ex) {                    invoking = 0;                    if (/^\[MODULE_MISS\]"([^"]+)/.test(ex.message)) {                        // 出错,则说明在factory的运行中,该require的模块是需要的                        // 所以把它加入强依赖中                        var hardCirclurDep = mod.depMkv[RegExp.$1];                        hardCirclurDep && (hardCirclurDep.hard = 1);                        return;                    }                    throw ex;                }                // 完成define                // 不放在try里,避免后续的运行错误被这里吞掉                modDefined(id);            }        }    }    /**     * 判断模块是否完成相应的状态     *     * @inner     * @param {string} id 模块标识     * @param {number} state 状态码,使用时传入相应的枚举变量,比如`MODULE_DEFINED`     * @return {boolean} 是否完成相应的状态     */    function modIs(id, state) {        return modModules[id] && modModules[id].state >= state;    }    /**     * 尝试执行模块factory函数,进行模块初始化     *     * @inner     * @param {string} id 模块id     */    function modTryInvokeFactory(id) {        var mod = modModules[id];        if (mod && mod.invokeFactory) {            mod.invokeFactory();        }    }    /**     * 根据模块id数组,获取其的exports数组     * 用于模块初始化的factory参数或require的callback参数生成     *     * @inner     * @param {Array} modules 模块id数组     * @param {Object} buildinModules 内建模块对象     * @return {Array} 模块exports数组     */    function modGetModulesExports(modules, buildinModules) {        var args = [];        each(            modules,            function (id, index) {                args[index] = buildinModules[id] || modGetModuleExports(id);            }        );        return args;    }    /**     * 模块定义完成事件监听器容器     *     * @inner     * @type {Object}     */    var modDefinedListeners = {};    /**     * 添加模块定义完成时间的监听器     *     * @inner     * @param {string} id 模块标识     * @param {Function} listener 监听函数     */    function modAddDefinedListener(id, listener) {        if (modIs(id, MODULE_DEFINED)) {            listener();            return;        }        var listeners = modDefinedListeners[id];        if (!listeners) {            listeners = modDefinedListeners[id] = [];        }        listeners.push(listener);    }    /**     * 模块状态切换为定义完成     * 因为需要触发事件,MODULE_DEFINED状态切换通过该函数     *     * @inner     * @param {string} id 模块标识     */    function modDefined(id) {        var listeners = modDefinedListeners[id] || [];        var mod = modModules[id];        mod.state = MODULE_DEFINED;        var len = listeners.length;        while (len--) {            // 这里不做function类型的检测            // 因为listener都是通过modOn传入的,modOn为内部调用            listeners[len]();        }        // 清理listeners        listeners.length = 0;        delete modDefinedListeners[id];    }    /**     * 获取模块的exports     *     * @inner     * @param {string} id 模块标识     * @return {*} 模块的exports     */    function modGetModuleExports(id) {        if (modIs(id, MODULE_DEFINED)) {            return modModules[id].exports;        }        return null;    }    /**     * 获取模块     *     * @param {string|Array} ids 模块名称或模块名称列表     * @param {Function=} callback 获取模块完成时的回调函数     * @param {string} baseId 基础id,用于当ids是relative id时的normalize     * @param {Object} noRequests 无需发起请求的模块集合     * @return {Object} 模块对象     */    function nativeRequire(ids, callback, baseId, noRequests) {        // 根据 https://github.com/amdjs/amdjs-api/wiki/require        // It MUST throw an error if the module has not        // already been loaded and evaluated.        if (typeof ids === 'string') {            modTryInvokeFactory(ids);            if (!modIs(ids, MODULE_DEFINED)) {                throw new Error('[MODULE_MISS]"' + ids + '" is not exists!');            }            return modGetModuleExports(ids);        }        noRequests = noRequests || {};        var isCallbackCalled = 0;        if (ids instanceof Array) {            tryFinishRequire();            if (!isCallbackCalled) {                each(ids, function (id) {                    if (!(BUILDIN_MODULE[id] || modIs(id, MODULE_DEFINED))) {                        modAddDefinedListener(id, tryFinishRequire);                        if (!noRequests[id]) {                            (id.indexOf('!') > 0                                ? loadResource                                : loadModule                            )(id, baseId);                        }                        modAnalyse(id);                    }                });                modAutoInvoke();            }        }        /**         * 尝试完成require,调用callback         * 在模块与其依赖模块都加载完时调用         *         * @inner         */        function tryFinishRequire() {            if (!isCallbackCalled) {                var isAllCompleted = 1;                each(ids, function (id) {                    if (!BUILDIN_MODULE[id]) {                        return (isAllCompleted = !!modIs(id, MODULE_DEFINED));                    }                });                // 检测并调用callback                if (isAllCompleted) {                    isCallbackCalled = 1;                    (typeof callback === 'function') && callback.apply(                        global,                        modGetModulesExports(ids, BUILDIN_MODULE)                    );                }            }        }    }    /**     * 正在加载的模块列表     *     * @inner     * @type {Object}     */    var loadingModules = {};    /**     * 加载模块     *     * @inner     * @param {string} moduleId 模块标识     */    function loadModule(moduleId) {        if (loadingModules[moduleId] || modModules[moduleId]) {            return;        }        loadingModules[moduleId] = 1;        // 创建script标签        //        // 这里不挂接onerror的错误处理        // 因为高级浏览器在devtool的console面板会报错        // 再throw一个Error多此一举了        var script = document.createElement('script');        script.setAttribute('data-require-id', moduleId);        script.src = toUrl(moduleId + '.js');        script.async = true;        if (script.readyState) {            script.onreadystatechange = loadedListener;        }        else {            script.onload = loadedListener;        }        appendScript(script);        /**         * script标签加载完成的事件处理函数         *         * @inner         */        function loadedListener() {            var readyState = script.readyState;            if (                typeof readyState === 'undefined'                || /^(loaded|complete)$/.test(readyState)            ) {                script.onload = script.onreadystatechange = null;                script = null;                completePreDefine(moduleId);                /* eslint-disable guard-for-in */                for (var key in autoDefineModules) {                    modAnalyse(key);                }                /* eslint-enable guard-for-in */                modAutoInvoke();            }        }    }    /**     * 加载资源     *     * @inner     * @param {string} pluginAndResource 插件与资源标识     * @param {string} baseId 当前环境的模块标识     */    function loadResource(pluginAndResource, baseId) {        if (modModules[pluginAndResource]) {            return;        }        var idInfo = parseId(pluginAndResource);        var resource = {            id: pluginAndResource,            state: MODULE_ANALYZED        };        modModules[pluginAndResource] = resource;        /**         * plugin加载完成的回调函数         *         * @inner         * @param {*} value resource的值         */        function pluginOnload(value) {            resource.exports = value || true;            modDefined(pluginAndResource);        }        /* jshint ignore:start */        /**         * 该方法允许plugin使用加载的资源声明模块         *         * @param {string} id 模块id         * @param {string} text 模块声明字符串         */        pluginOnload.fromText = function (id, text) {            autoDefineModules[id] = 1;            new Function(text)();            completePreDefine(id);        };        /* jshint ignore:end */        /**         * 加载资源         *         * @inner         * @param {Object} plugin 用于加载资源的插件模块         */        function load(plugin) {            var pluginRequire = baseId                ? modModules[baseId].require                : actualGlobalRequire;            plugin.load(                idInfo.res,                pluginRequire,                pluginOnload,                moduleConfigGetter.call({id: pluginAndResource})            );        }        load(modGetModuleExports(idInfo.mod));    }    /**     * 配置require     *     * @param {Object} conf 配置对象     */    globalRequire.config = function (conf) {        if (conf) {            /* eslint-disable guard-for-in */            for (var key in requireConf) {                var newValue = conf[key];                var oldValue = requireConf[key];                if (!newValue) {                    continue;                }                if (key === 'urlArgs' && typeof newValue === 'string') {                    requireConf.urlArgs['*'] = newValue;                }                else {                    // 简单的多处配置还是需要支持,所以配置实现为支持二级mix                    if (oldValue instanceof Array) {                        oldValue.push.apply(oldValue, newValue);                    }                    else if (typeof oldValue === 'object') {                        for (var k in newValue) {                            oldValue[k] = newValue[k];                        }                    }                    else {                        requireConf[key] = newValue;                    }                }            }            /* eslint-enable guard-for-in */            createConfIndex();        }        // 配置信息对象clone返回,避免返回结果对象被用户程序修改可能导致的问题        // return clone(requireConf);    };    /**     * 对象克隆,支持raw type, Array, raw Object     *     * @inner     * @param {*} source 要克隆的对象     * @return {*}     */    // function clone(source) {    //     var result = source;    //     if (source instanceof Array) {    //         result = [];    //         each(source, function (item, i) {    //             result[i] = clone(item);    //         });    //     }    //     else if (typeof source === 'object') {    //         result = {};    //         for (var key in source) {    //             if (source.hasOwnProperty(key)) {    //                 result[key] = clone(source[key]);    //             }    //         }    //     }    //     return result;    // }    // 初始化时需要创建配置索引    createConfIndex();    /**     * paths内部索引     *     * @inner     * @type {Array}     */    var pathsIndex;    /**     * packages内部索引     *     * @inner     * @type {Array}     */    var packagesIndex;    /**     * mapping内部索引     *     * @inner     * @type {Array}     */    var mappingIdIndex;    /**     * urlArgs内部索引     *     * @inner     * @type {Array}     */    var urlArgsIndex;    /**     * noRequests内部索引     *     * @inner     * @type {Array}     */    var noRequestsIndex;    /**     * 将key为module id prefix的Object,生成数组形式的索引,并按照长度和字面排序     *     * @inner     * @param {Object} value 源值     * @param {boolean} allowAsterisk 是否允许*号表示匹配所有     * @return {Array} 索引对象     */    function createKVSortedIndex(value, allowAsterisk) {        var index = kv2List(value, 1, allowAsterisk);        index.sort(descSorterByKOrName);        return index;    }    /**     * 创建配置信息内部索引     *     * @inner     */    function createConfIndex() {        requireConf.baseUrl = requireConf.baseUrl.replace(/\/$/, '') + '/';        // create paths index        pathsIndex = createKVSortedIndex(requireConf.paths);        // create mappingId index        mappingIdIndex = createKVSortedIndex(requireConf.map, 1);        each(            mappingIdIndex,            function (item) {                item.v = createKVSortedIndex(item.v);            }        );        // create packages index        packagesIndex = [];        each(            requireConf.packages,            function (packageConf) {                var pkg = packageConf;                if (typeof packageConf === 'string') {                    pkg = {                        name: packageConf.split('/')[0],                        location: packageConf,                        main: 'main'                    };                }                pkg.location = pkg.location || pkg.name;                pkg.main = (pkg.main || 'main').replace(/\.js$/i, '');                pkg.reg = createPrefixRegexp(pkg.name);                packagesIndex.push(pkg);            }        );        packagesIndex.sort(descSorterByKOrName);        // create urlArgs index        urlArgsIndex = createKVSortedIndex(requireConf.urlArgs, 1);        // create noRequests index        noRequestsIndex = createKVSortedIndex(requireConf.noRequests);        each(noRequestsIndex, function (item) {            var value = item.v;            var mapIndex = {};            item.v = mapIndex;            if (!(value instanceof Array)) {                value = [value];            }            each(value, function (meetId) {                mapIndex[meetId] = 1;            });        });    }    /**     * 对配置信息的索引进行检索     *     * @inner     * @param {string} value 要检索的值     * @param {Array} index 索引对象     * @param {Function} hitBehavior 索引命中的行为函数     */    function indexRetrieve(value, index, hitBehavior) {        each(index, function (item) {            if (item.reg.test(value)) {                hitBehavior(item.v, item.k, item);                return false;            }        });    }    /**     * 将`模块标识+'.extension'`形式的字符串转换成相对的url     *     * @inner     * @param {string} source 源字符串     * @return {string} url     */    function toUrl(source) {        // 分离 模块标识 和 .extension        var extReg = /(\.[a-z0-9]+)$/i;        var queryReg = /(\?[^#]*)$/;        var extname = '';        var id = source;        var query = '';        if (queryReg.test(source)) {            query = RegExp.$1;            source = source.replace(queryReg, '');        }        if (extReg.test(source)) {            extname = RegExp.$1;            id = source.replace(extReg, '');        }        var url = id;        // paths处理和匹配        var isPathMap;        indexRetrieve(id, pathsIndex, function (value, key) {            url = url.replace(key, value);            isPathMap = 1;        });        // packages处理和匹配        if (!isPathMap) {            indexRetrieve(id, packagesIndex, function (value, key, item) {                url = url.replace(item.name, item.location);            });        }        // 相对路径时,附加baseUrl        if (!/^([a-z]{2,10}:\/)?\//i.test(url)) {            url = requireConf.baseUrl + url;        }        // 附加 .extension 和 query        url += extname + query;        // urlArgs处理和匹配        indexRetrieve(id, urlArgsIndex, function (value) {            url += (url.indexOf('?') > 0 ? '&' : '?') + value;        });        return url;    }    /**     * 创建local require函数     *     * @inner     * @param {number} baseId 当前module id     * @return {Function} local require函数     */    function createLocalRequire(baseId) {        var requiredCache = {};        function req(requireId, callback) {            if (typeof requireId === 'string') {                if (!requiredCache[requireId]) {                    requiredCache[requireId] =                        nativeRequire(normalize(requireId, baseId));                }                return requiredCache[requireId];            }            else if (requireId instanceof Array) {                // 分析是否有resource,取出pluginModule先                var pluginModules = [];                var pureModules = [];                var normalizedIds = [];                each(                    requireId,                    function (id, i) {                        var idInfo = parseId(id);                        var absId = normalize(idInfo.mod, baseId);                        pureModules.push(absId);                        autoDefineModules[absId] = 1;                        if (idInfo.res) {                            pluginModules.push(absId);                            normalizedIds[i] = null;                        }                        else {                            normalizedIds[i] = absId;                        }                    }                );                var noRequestModules = {};                each(                    pureModules,                    function (id) {                        var meet;                        indexRetrieve(                            id,                            noRequestsIndex,                            function (value) {                                meet = value;                            }                        );                        if (meet) {                            if (meet['*']) {                                noRequestModules[id] = 1;                            }                            else {                                each(pureModules, function (meetId) {                                    if (meet[meetId]) {                                        noRequestModules[id] = 1;                                        return false;                                    }                                });                            }                        }                    }                );                // 加载模块                nativeRequire(                    pureModules,                    function () {                        /* jshint ignore:start */                        each(normalizedIds, function (id, i) {                            if (id == null) {                                normalizedIds[i] = normalize(requireId[i], baseId);                            }                        });                        /* jshint ignore:end */                        nativeRequire(normalizedIds, callback, baseId);                    },                    baseId,                    noRequestModules                );            }        }        /**         * 将[module ID] + '.extension'格式的字符串转换成url         *         * @inner         * @param {string} id 符合描述格式的源字符串         * @return {string} url         */        req.toUrl = function (id) {            return toUrl(normalize(id, baseId));        };        return req;    }    /**     * id normalize化     *     * @inner     * @param {string} id 需要normalize的模块标识     * @param {string} baseId 当前环境的模块标识     * @return {string} normalize结果     */    function normalize(id, baseId) {        if (!id) {            return '';        }        baseId = baseId || '';        var idInfo = parseId(id);        if (!idInfo) {            return id;        }        var resourceId = idInfo.res;        var moduleId = relative2absolute(idInfo.mod, baseId);        each(            packagesIndex,            function (packageConf) {                var name = packageConf.name;                if (name === moduleId) {                    moduleId = name + '/' + packageConf.main;                    return false;                }            }        );        // 根据config中的map配置进行module id mapping        indexRetrieve(            baseId,            mappingIdIndex,            function (value) {                indexRetrieve(                    moduleId,                    value,                    function (mdValue, mdKey) {                        moduleId = moduleId.replace(mdKey, mdValue);                    }                );            }        );        if (resourceId) {            var mod = modGetModuleExports(moduleId);            resourceId = mod.normalize                ? mod.normalize(                    resourceId,                    function (resId) {                        return normalize(resId, baseId);                    }                  )                : normalize(resourceId, baseId);            moduleId += '!' + resourceId;        }        return moduleId;    }    /**     * 相对id转换成绝对id     *     * @inner     * @param {string} id 要转换的相对id     * @param {string} baseId 当前所在环境id     * @return {string} 绝对id     */    function relative2absolute(id, baseId) {        if (id.indexOf('.') === 0) {            var basePath = baseId.split('/');            var namePath = id.split('/');            var baseLen = basePath.length - 1;            var nameLen = namePath.length;            var cutBaseTerms = 0;            var cutNameTerms = 0;            /* eslint-disable block-scoped-var */            pathLoop: for (var i = 0; i < nameLen; i++) {                switch (namePath[i]) {                    case '..':                        if (cutBaseTerms < baseLen) {                            cutBaseTerms++;                            cutNameTerms++;                        }                        else {                            break pathLoop;                        }                        break;                    case '.':                        cutNameTerms++;                        break;                    default:                        break pathLoop;                }            }            /* eslint-enable block-scoped-var */            basePath.length = baseLen - cutBaseTerms;            namePath = namePath.slice(cutNameTerms);            return basePath.concat(namePath).join('/');        }        return id;    }    /**     * 解析id,返回带有module和resource属性的Object     *     * @inner     * @param {string} id 标识     * @return {Object} id解析结果对象     */    function parseId(id) {        var segs = id.split('!');        if (segs[0]) {            return {                mod: segs[0],                res: segs[1]            };        }        return null;    }    /**     * 将对象数据转换成数组,数组每项是带有k和v的Object     *     * @inner     * @param {Object} source 对象数据     * @param {boolean} keyMatchable key是否允许被前缀匹配     * @param {boolean} allowAsterisk 是否支持*匹配所有     * @return {Array.<Object>} 对象转换数组     */    function kv2List(source, keyMatchable, allowAsterisk) {        var list = [];        for (var key in source) {            if (source.hasOwnProperty(key)) {                var item = {                    k: key,                    v: source[key]                };                list.push(item);                if (keyMatchable) {                    item.reg = key === '*' && allowAsterisk                        ? /^/                        : createPrefixRegexp(key);                }            }        }        return list;    }    // 感谢requirejs,通过currentlyAddingScript兼容老旧ie    //    // For some cache cases in IE 6-8, the script executes before the end    // of the appendChild execution, so to tie an anonymous define    // call to the module name (which is stored on the node), hold on    // to a reference to this node, but clear after the DOM insertion.    var currentlyAddingScript;    var interactiveScript;    /**     * 获取当前script标签     * 用于ie下define未指定module id时获取id     *     * @inner     * @return {HTMLScriptElement} 当前script标签     */    function getCurrentScript() {        if (currentlyAddingScript) {            return currentlyAddingScript;        }        else if (            interactiveScript            && interactiveScript.readyState === 'interactive'        ) {            return interactiveScript;        }        var scripts = document.getElementsByTagName('script');        var scriptLen = scripts.length;        while (scriptLen--) {            var script = scripts[scriptLen];            if (script.readyState === 'interactive') {                interactiveScript = script;                return script;            }        }    }    var headElement = document.getElementsByTagName('head')[0];    var baseElement = document.getElementsByTagName('base')[0];    if (baseElement) {        headElement = baseElement.parentNode;    }    /**     * 向页面中插入script标签     *     * @inner     * @param {HTMLScriptElement} script script标签     */    function appendScript(script) {        currentlyAddingScript = script;        // If BASE tag is in play, using appendChild is a problem for IE6.        // See: http://dev.jquery.com/ticket/2709        baseElement            ? headElement.insertBefore(script, baseElement)            : headElement.appendChild(script);        currentlyAddingScript = null;    }    /**     * 创建id前缀匹配的正则对象     *     * @inner     * @param {string} prefix id前缀     * @return {RegExp} 前缀匹配的正则对象     */    function createPrefixRegexp(prefix) {        return new RegExp('^' + prefix + '(/|$)');    }    /**     * 循环遍历数组集合     *     * @inner     * @param {Array} source 数组源     * @param {function(Array,Number):boolean} iterator 遍历函数     */    function each(source, iterator) {        if (source instanceof Array) {            for (var i = 0, len = source.length; i < len; i++) {                if (iterator(source[i], i) === false) {                    break;                }            }        }    }    /**     * 根据元素的k或name项进行数组字符数逆序的排序函数     *     * @inner     * @param {Object} a 要比较的对象a     * @param {Object} b 要比较的对象b     * @return {number} 比较结果     */    function descSorterByKOrName(a, b) {        var aValue = a.k || a.name;        var bValue = b.k || b.name;        if (bValue === '*') {            return -1;        }        if (aValue === '*') {            return 1;        }        return bValue.length - aValue.length;    }    // 暴露全局对象    if (!define) {        define = globalDefine;        // 可能碰到其他形式的loader,所以,不要覆盖人家        if (!require) {            require = globalRequire;        }        // 如果存在其他版本的esl,在define那里就判断过了,不会进入这个分支        // 所以这里就不判断了,直接写        esl = globalRequire;    }})(this);
 |