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