esl.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653
  1. /**
  2. * ESL (Enterprise Standard Loader)
  3. * Copyright 2013 Baidu Inc. All rights reserved.
  4. *
  5. * @file Browser端标准加载器,符合AMD规范
  6. * @author errorrik(errorrik@gmail.com)
  7. * Firede(firede@firede.us)
  8. */
  9. /* jshint ignore:start */
  10. var define;
  11. var require;
  12. var esl;
  13. /* jshint ignore:end */
  14. (function (global) {
  15. // "mod"开头的变量或函数为内部模块管理函数
  16. // 为提高压缩率,不使用function或object包装
  17. /**
  18. * 模块容器
  19. *
  20. * @inner
  21. * @type {Object}
  22. */
  23. var modModules = {};
  24. /**
  25. * 自动定义的模块表
  26. *
  27. * 模块define factory是用到时才执行,但是以下几种情况需要自动马上执行:
  28. * 1. require( [moduleId], callback )
  29. * 2. plugin module: require( 'plugin!resource' )
  30. *
  31. * @inner
  32. * @type {Object}
  33. */
  34. var autoDefineModules = {};
  35. // 模块状态枚举量
  36. var MODULE_PRE_DEFINED = 1;
  37. var MODULE_ANALYZED = 2;
  38. var MODULE_PREPARED = 3;
  39. var MODULE_DEFINED = 4;
  40. /**
  41. * 内建module名称集合
  42. *
  43. * @inner
  44. * @type {Object}
  45. */
  46. var BUILDIN_MODULE = {
  47. require: globalRequire,
  48. exports: 1,
  49. module: 1
  50. };
  51. /**
  52. * 全局require函数
  53. *
  54. * @inner
  55. * @type {Function}
  56. */
  57. var actualGlobalRequire = createLocalRequire();
  58. // #begin-ignore
  59. /**
  60. * 超时提醒定时器
  61. *
  62. * @inner
  63. * @type {number}
  64. */
  65. var waitTimeout;
  66. // #end-ignore
  67. /* eslint-disable fecs-key-spacing */
  68. /* eslint-disable key-spacing */
  69. /**
  70. * require配置
  71. *
  72. * @inner
  73. * @type {Object}
  74. */
  75. var requireConf = {
  76. baseUrl : './',
  77. paths : {},
  78. config : {},
  79. map : {},
  80. packages : [],
  81. // #begin-ignore
  82. waitSeconds: 0,
  83. // #end-ignore
  84. noRequests : {},
  85. urlArgs : {}
  86. };
  87. /* eslint-enable key-spacing */
  88. /**
  89. * 加载模块
  90. *
  91. * @param {string|Array} requireId 模块id或模块id数组,
  92. * @param {Function=} callback 加载完成的回调函数
  93. * @return {*} requireId为string时返回模块暴露对象
  94. */
  95. function globalRequire(requireId, callback) {
  96. // #begin-ignore
  97. // #begin assertNotContainRelativeId
  98. // 确定require的模块id不包含相对id。用于global require,提前预防难以跟踪的错误出现
  99. var invalidIds = [];
  100. /**
  101. * 监测模块id是否relative id
  102. *
  103. * @inner
  104. * @param {string} id 模块id
  105. */
  106. function monitor(id) {
  107. if (id.indexOf('.') === 0) {
  108. invalidIds.push(id);
  109. }
  110. }
  111. if (typeof requireId === 'string') {
  112. monitor(requireId);
  113. }
  114. else {
  115. each(
  116. requireId,
  117. function (id) {
  118. monitor(id);
  119. }
  120. );
  121. }
  122. // 包含相对id时,直接抛出错误
  123. if (invalidIds.length > 0) {
  124. throw new Error(
  125. '[REQUIRE_FATAL]Relative ID is not allowed in global require: '
  126. + invalidIds.join(', ')
  127. );
  128. }
  129. // #end assertNotContainRelativeId
  130. // 超时提醒
  131. var timeout = requireConf.waitSeconds;
  132. if (timeout && (requireId instanceof Array)) {
  133. if (waitTimeout) {
  134. clearTimeout(waitTimeout);
  135. }
  136. waitTimeout = setTimeout(waitTimeoutNotice, timeout * 1000);
  137. }
  138. // #end-ignore
  139. return actualGlobalRequire(requireId, callback);
  140. }
  141. /**
  142. * 版本号
  143. *
  144. * @type {string}
  145. */
  146. globalRequire.version = '1.8.8';
  147. /**
  148. * loader名称
  149. *
  150. * @type {string}
  151. */
  152. globalRequire.loader = 'esl';
  153. /**
  154. * 将模块标识转换成相对的url
  155. *
  156. * @param {string} id 模块标识
  157. * @return {string}
  158. */
  159. globalRequire.toUrl = actualGlobalRequire.toUrl;
  160. // #begin-ignore
  161. /**
  162. * 超时提醒函数
  163. *
  164. * @inner
  165. */
  166. function waitTimeoutNotice() {
  167. var hangModules = [];
  168. var missModules = [];
  169. var hangModulesMap = {};
  170. var missModulesMap = {};
  171. var visited = {};
  172. /**
  173. * 检查模块的加载错误
  174. *
  175. * @inner
  176. * @param {string} id 模块id
  177. * @param {boolean} hard 是否装载时依赖
  178. */
  179. function checkError(id, hard) {
  180. if (visited[id] || modIs(id, MODULE_DEFINED)) {
  181. return;
  182. }
  183. visited[id] = 1;
  184. if (!modIs(id, MODULE_PREPARED)) {
  185. // HACK: 为gzip后体积优化,不做抽取
  186. if (!hangModulesMap[id]) {
  187. hangModulesMap[id] = 1;
  188. hangModules.push(id);
  189. }
  190. }
  191. var mod = modModules[id];
  192. if (!mod) {
  193. if (!missModulesMap[id]) {
  194. missModulesMap[id] = 1;
  195. missModules.push(id);
  196. }
  197. }
  198. else if (hard) {
  199. if (!hangModulesMap[id]) {
  200. hangModulesMap[id] = 1;
  201. hangModules.push(id);
  202. }
  203. each(
  204. mod.depMs,
  205. function (dep) {
  206. checkError(dep.absId, dep.hard);
  207. }
  208. );
  209. }
  210. }
  211. /* eslint-disable guard-for-in */
  212. for (var id in autoDefineModules) {
  213. checkError(id, 1);
  214. }
  215. /* eslint-enable guard-for-in */
  216. if (hangModules.length || missModules.length) {
  217. throw new Error(
  218. '[MODULE_TIMEOUT]Hang( '
  219. + (hangModules.join(', ') || 'none')
  220. + ' ) Miss( '
  221. + (missModules.join(', ') || 'none')
  222. + ' )'
  223. );
  224. }
  225. }
  226. // #end-ignore
  227. /**
  228. * 未预定义的模块集合
  229. * 主要存储匿名方式define的模块
  230. *
  231. * @inner
  232. * @type {Array}
  233. */
  234. var wait4PreDefine = [];
  235. /**
  236. * 完成模块预定义,此时处理的模块是匿名define的模块
  237. *
  238. * @inner
  239. * @param {string} currentId 匿名define的模块的id
  240. */
  241. function completePreDefine(currentId) {
  242. // HACK: 这里在IE下有个性能陷阱,不能使用任何变量。
  243. // 否则貌似会形成变量引用和修改的读写锁,导致wait4PreDefine释放困难
  244. each(wait4PreDefine, function (mod) {
  245. modPreDefine(
  246. currentId,
  247. mod.deps,
  248. mod.factory
  249. );
  250. });
  251. wait4PreDefine.length = 0;
  252. modAnalyse(currentId);
  253. }
  254. /**
  255. * 定义模块
  256. *
  257. * @param {string=} id 模块标识
  258. * @param {Array=} dependencies 依赖模块列表
  259. * @param {Function=} factory 创建模块的工厂方法
  260. */
  261. function globalDefine(id, dependencies, factory) {
  262. // define(factory)
  263. // define(dependencies, factory)
  264. // define(id, factory)
  265. // define(id, dependencies, factory)
  266. if (factory == null) {
  267. if (dependencies == null) {
  268. factory = id;
  269. id = null;
  270. }
  271. else {
  272. factory = dependencies;
  273. dependencies = null;
  274. if (id instanceof Array) {
  275. dependencies = id;
  276. id = null;
  277. }
  278. }
  279. }
  280. if (factory == null) {
  281. return;
  282. }
  283. var opera = window.opera;
  284. // IE下通过current script的data-require-id获取当前id
  285. if (
  286. !id
  287. && document.attachEvent
  288. && (!(opera && opera.toString() === '[object Opera]'))
  289. ) {
  290. var currentScript = getCurrentScript();
  291. id = currentScript && currentScript.getAttribute('data-require-id');
  292. }
  293. if (id) {
  294. modPreDefine(id, dependencies, factory);
  295. }
  296. else {
  297. // 纪录到共享变量中,在load或readystatechange中处理
  298. // 标准浏览器下,使用匿名define时,将进入这个分支
  299. wait4PreDefine[0] = {
  300. deps: dependencies,
  301. factory: factory
  302. };
  303. }
  304. }
  305. globalDefine.amd = {};
  306. /**
  307. * 模块配置获取函数
  308. *
  309. * @inner
  310. * @return {Object} 模块配置对象
  311. */
  312. function moduleConfigGetter() {
  313. var conf = requireConf.config[this.id];
  314. if (conf && typeof conf === 'object') {
  315. return conf;
  316. }
  317. return {};
  318. }
  319. /**
  320. * 预定义模块
  321. *
  322. * @inner
  323. * @param {string} id 模块标识
  324. * @param {Array.<string>} dependencies 显式声明的依赖模块列表
  325. * @param {*} factory 模块定义函数或模块对象
  326. */
  327. function modPreDefine(id, dependencies, factory) {
  328. // 将模块存入容器
  329. //
  330. // 模块内部信息包括
  331. // -----------------------------------
  332. // id: module id
  333. // depsDec: 模块定义时声明的依赖
  334. // deps: 模块依赖,默认为['require', 'exports', 'module']
  335. // factory: 初始化函数或对象
  336. // factoryDeps: 初始化函数的参数依赖
  337. // exports: 模块的实际暴露对象(AMD定义)
  338. // config: 用于获取模块配置信息的函数(AMD定义)
  339. // state: 模块当前状态
  340. // require: local require函数
  341. // depMs: 实际依赖的模块集合,数组形式
  342. // depMkv: 实际依赖的模块集合,表形式,便于查找
  343. // depRs: 实际依赖的资源集合
  344. // depPMs: 用于加载资源的模块集合,key是模块名,value是1,仅用于快捷查找
  345. // ------------------------------------
  346. if (!modModules[id]) {
  347. /* eslint-disable key-spacing */
  348. modModules[id] = {
  349. id : id,
  350. depsDec : dependencies,
  351. deps : dependencies || ['require', 'exports', 'module'],
  352. factoryDeps : [],
  353. factory : factory,
  354. exports : {},
  355. config : moduleConfigGetter,
  356. state : MODULE_PRE_DEFINED,
  357. require : createLocalRequire(id),
  358. depMs : [],
  359. depMkv : {},
  360. depRs : [],
  361. depPMs : []
  362. };
  363. /* eslint-enable key-spacing */
  364. }
  365. }
  366. /**
  367. * 预分析模块
  368. *
  369. * 首先,完成对factory中声明依赖的分析提取
  370. * 然后,尝试加载"资源加载所需模块"
  371. *
  372. * 需要先加载模块的原因是:如果模块不存在,无法进行resourceId normalize化
  373. * modAnalyse完成后续的依赖分析处理,并进行依赖模块的加载
  374. *
  375. * @inner
  376. * @param {string} id 模块id
  377. */
  378. function modAnalyse(id) {
  379. var mod = modModules[id];
  380. if (!mod || modIs(id, MODULE_ANALYZED)) {
  381. return;
  382. }
  383. var deps = mod.deps;
  384. var factory = mod.factory;
  385. var hardDependsCount = 0;
  386. // 分析function body中的require
  387. // 如果包含显式依赖声明,根据AMD规定和性能考虑,可以不分析factoryBody
  388. if (typeof factory === 'function') {
  389. hardDependsCount = Math.min(factory.length, deps.length);
  390. // If the dependencies argument is present, the module loader
  391. // SHOULD NOT scan for dependencies within the factory function.
  392. !mod.depsDec && factory.toString()
  393. .replace(/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, '')
  394. .replace(/require\(\s*(['"'])([^'"]+)\1\s*\)/g,
  395. function ($0, $1, depId) {
  396. deps.push(depId);
  397. }
  398. );
  399. }
  400. var requireModules = [];
  401. each(deps, function (depId, index) {
  402. var idInfo = parseId(depId);
  403. var absId = normalize(idInfo.mod, id);
  404. var moduleInfo;
  405. var resInfo;
  406. if (absId && !BUILDIN_MODULE[absId]) {
  407. // 如果依赖是一个资源,将其信息添加到module.depRs
  408. //
  409. // module.depRs中的项有可能是重复的。
  410. // 在这个阶段,加载resource的module可能还未defined,
  411. // 导致此时resource id无法被normalize。
  412. //
  413. // 比如对a/b/c而言,下面几个resource可能指的是同一个资源:
  414. // - js!../name.js
  415. // - js!a/name.js
  416. // - ../../js!../name.js
  417. //
  418. // 所以加载资源的module ready时,需要遍历module.depRs进行处理
  419. if (idInfo.res) {
  420. resInfo = {
  421. id: depId,
  422. mod: absId,
  423. res: idInfo.res
  424. };
  425. autoDefineModules[absId] = 1;
  426. mod.depPMs.push(absId);
  427. mod.depRs.push(resInfo);
  428. }
  429. // 对依赖模块的id normalize能保证正确性,在此处进行去重
  430. moduleInfo = mod.depMkv[absId];
  431. if (!moduleInfo) {
  432. moduleInfo = {
  433. id: idInfo.mod,
  434. absId: absId,
  435. hard: index < hardDependsCount
  436. };
  437. mod.depMs.push(moduleInfo);
  438. mod.depMkv[absId] = moduleInfo;
  439. requireModules.push(absId);
  440. }
  441. }
  442. else {
  443. moduleInfo = {absId: absId};
  444. }
  445. // 如果当前正在分析的依赖项是define中声明的,
  446. // 则记录到module.factoryDeps中
  447. // 在factory invoke前将用于生成invoke arguments
  448. if (index < hardDependsCount) {
  449. mod.factoryDeps.push(resInfo || moduleInfo);
  450. }
  451. });
  452. mod.state = MODULE_ANALYZED;
  453. modInitFactoryInvoker(id);
  454. nativeRequire(requireModules);
  455. }
  456. /**
  457. * 对一些需要自动定义的模块进行自动定义
  458. *
  459. * @inner
  460. */
  461. function modAutoInvoke() {
  462. /* eslint-disable guard-for-in */
  463. for (var id in autoDefineModules) {
  464. modUpdatePreparedState(id);
  465. modTryInvokeFactory(id);
  466. }
  467. /* eslint-enable guard-for-in */
  468. }
  469. /**
  470. * 更新模块的准备状态
  471. *
  472. * @inner
  473. * @param {string} id 模块id
  474. */
  475. function modUpdatePreparedState(id) {
  476. var visited = {};
  477. update(id);
  478. function update(id) {
  479. if (!modIs(id, MODULE_ANALYZED)) {
  480. return false;
  481. }
  482. if (modIs(id, MODULE_PREPARED) || visited[id]) {
  483. return true;
  484. }
  485. visited[id] = 1;
  486. var mod = modModules[id];
  487. var prepared = true;
  488. each(
  489. mod.depMs,
  490. function (dep) {
  491. return (prepared = update(dep.absId));
  492. }
  493. );
  494. // 判断resource是否加载完成。如果resource未加载完成,则认为未准备好
  495. /* jshint ignore:start */
  496. prepared && each(
  497. mod.depRs,
  498. function (dep) {
  499. prepared = !!(dep.absId && modIs(dep.absId, MODULE_DEFINED));
  500. return prepared;
  501. }
  502. );
  503. /* jshint ignore:end */
  504. if (prepared) {
  505. mod.state = MODULE_PREPARED;
  506. }
  507. return prepared;
  508. }
  509. }
  510. /**
  511. * 初始化模块定义时所需的factory执行器
  512. *
  513. * @inner
  514. * @param {string} id 模块id
  515. */
  516. function modInitFactoryInvoker(id) {
  517. var mod = modModules[id];
  518. var invoking;
  519. mod.invokeFactory = invokeFactory;
  520. /* eslint-disable max-nested-callbacks */
  521. each(
  522. mod.depPMs,
  523. function (pluginModuleId) {
  524. modAddDefinedListener(
  525. pluginModuleId,
  526. function () {
  527. each(mod.depRs, function (res) {
  528. if (!res.absId && res.mod === pluginModuleId) {
  529. res.absId = normalize(res.id, id);
  530. nativeRequire([res.absId], modAutoInvoke);
  531. }
  532. });
  533. }
  534. );
  535. }
  536. );
  537. /* eslint-enable max-nested-callbacks */
  538. /**
  539. * 初始化模块
  540. *
  541. * @inner
  542. */
  543. function invokeFactory() {
  544. if (invoking || mod.state !== MODULE_PREPARED) {
  545. return;
  546. }
  547. invoking = 1;
  548. // 拼接factory invoke所需的arguments
  549. var factoryReady = 1;
  550. var factoryDeps = [];
  551. each(
  552. mod.factoryDeps,
  553. function (dep) {
  554. var depId = dep.absId;
  555. if (!BUILDIN_MODULE[depId]) {
  556. modTryInvokeFactory(depId);
  557. if (!modIs(depId, MODULE_DEFINED)) {
  558. factoryReady = 0;
  559. return false;
  560. }
  561. }
  562. factoryDeps.push(depId);
  563. }
  564. );
  565. if (factoryReady) {
  566. try {
  567. var args = modGetModulesExports(
  568. factoryDeps,
  569. {
  570. require: mod.require,
  571. exports: mod.exports,
  572. module: mod
  573. }
  574. );
  575. // 调用factory函数初始化module
  576. var factory = mod.factory;
  577. var exports = typeof factory === 'function'
  578. ? factory.apply(global, args)
  579. : factory;
  580. if (exports != null) {
  581. mod.exports = exports;
  582. }
  583. mod.invokeFactory = null;
  584. delete autoDefineModules[id];
  585. }
  586. catch (ex) {
  587. invoking = 0;
  588. if (/^\[MODULE_MISS\]"([^"]+)/.test(ex.message)) {
  589. // 出错,则说明在factory的运行中,该require的模块是需要的
  590. // 所以把它加入强依赖中
  591. var hardCirclurDep = mod.depMkv[RegExp.$1];
  592. hardCirclurDep && (hardCirclurDep.hard = 1);
  593. return;
  594. }
  595. throw ex;
  596. }
  597. // 完成define
  598. // 不放在try里,避免后续的运行错误被这里吞掉
  599. modDefined(id);
  600. }
  601. }
  602. }
  603. /**
  604. * 判断模块是否完成相应的状态
  605. *
  606. * @inner
  607. * @param {string} id 模块标识
  608. * @param {number} state 状态码,使用时传入相应的枚举变量,比如`MODULE_DEFINED`
  609. * @return {boolean} 是否完成相应的状态
  610. */
  611. function modIs(id, state) {
  612. return modModules[id] && modModules[id].state >= state;
  613. }
  614. /**
  615. * 尝试执行模块factory函数,进行模块初始化
  616. *
  617. * @inner
  618. * @param {string} id 模块id
  619. */
  620. function modTryInvokeFactory(id) {
  621. var mod = modModules[id];
  622. if (mod && mod.invokeFactory) {
  623. mod.invokeFactory();
  624. }
  625. }
  626. /**
  627. * 根据模块id数组,获取其的exports数组
  628. * 用于模块初始化的factory参数或require的callback参数生成
  629. *
  630. * @inner
  631. * @param {Array} modules 模块id数组
  632. * @param {Object} buildinModules 内建模块对象
  633. * @return {Array} 模块exports数组
  634. */
  635. function modGetModulesExports(modules, buildinModules) {
  636. var args = [];
  637. each(
  638. modules,
  639. function (id, index) {
  640. args[index] = buildinModules[id] || modGetModuleExports(id);
  641. }
  642. );
  643. return args;
  644. }
  645. /**
  646. * 模块定义完成事件监听器容器
  647. *
  648. * @inner
  649. * @type {Object}
  650. */
  651. var modDefinedListeners = {};
  652. /**
  653. * 添加模块定义完成时间的监听器
  654. *
  655. * @inner
  656. * @param {string} id 模块标识
  657. * @param {Function} listener 监听函数
  658. */
  659. function modAddDefinedListener(id, listener) {
  660. if (modIs(id, MODULE_DEFINED)) {
  661. listener();
  662. return;
  663. }
  664. var listeners = modDefinedListeners[id];
  665. if (!listeners) {
  666. listeners = modDefinedListeners[id] = [];
  667. }
  668. listeners.push(listener);
  669. }
  670. /**
  671. * 模块状态切换为定义完成
  672. * 因为需要触发事件,MODULE_DEFINED状态切换通过该函数
  673. *
  674. * @inner
  675. * @param {string} id 模块标识
  676. */
  677. function modDefined(id) {
  678. var listeners = modDefinedListeners[id] || [];
  679. var mod = modModules[id];
  680. mod.state = MODULE_DEFINED;
  681. var len = listeners.length;
  682. while (len--) {
  683. // 这里不做function类型的检测
  684. // 因为listener都是通过modOn传入的,modOn为内部调用
  685. listeners[len]();
  686. }
  687. // 清理listeners
  688. listeners.length = 0;
  689. delete modDefinedListeners[id];
  690. }
  691. /**
  692. * 获取模块的exports
  693. *
  694. * @inner
  695. * @param {string} id 模块标识
  696. * @return {*} 模块的exports
  697. */
  698. function modGetModuleExports(id) {
  699. if (modIs(id, MODULE_DEFINED)) {
  700. return modModules[id].exports;
  701. }
  702. return null;
  703. }
  704. /**
  705. * 获取模块
  706. *
  707. * @param {string|Array} ids 模块名称或模块名称列表
  708. * @param {Function=} callback 获取模块完成时的回调函数
  709. * @param {string} baseId 基础id,用于当ids是relative id时的normalize
  710. * @param {Object} noRequests 无需发起请求的模块集合
  711. * @return {Object} 模块对象
  712. */
  713. function nativeRequire(ids, callback, baseId, noRequests) {
  714. // 根据 https://github.com/amdjs/amdjs-api/wiki/require
  715. // It MUST throw an error if the module has not
  716. // already been loaded and evaluated.
  717. if (typeof ids === 'string') {
  718. modTryInvokeFactory(ids);
  719. if (!modIs(ids, MODULE_DEFINED)) {
  720. throw new Error('[MODULE_MISS]"' + ids + '" is not exists!');
  721. }
  722. return modGetModuleExports(ids);
  723. }
  724. noRequests = noRequests || {};
  725. var isCallbackCalled = 0;
  726. if (ids instanceof Array) {
  727. tryFinishRequire();
  728. if (!isCallbackCalled) {
  729. each(ids, function (id) {
  730. if (!(BUILDIN_MODULE[id] || modIs(id, MODULE_DEFINED))) {
  731. modAddDefinedListener(id, tryFinishRequire);
  732. if (!noRequests[id]) {
  733. (id.indexOf('!') > 0
  734. ? loadResource
  735. : loadModule
  736. )(id, baseId);
  737. }
  738. modAnalyse(id);
  739. }
  740. });
  741. modAutoInvoke();
  742. }
  743. }
  744. /**
  745. * 尝试完成require,调用callback
  746. * 在模块与其依赖模块都加载完时调用
  747. *
  748. * @inner
  749. */
  750. function tryFinishRequire() {
  751. if (!isCallbackCalled) {
  752. var isAllCompleted = 1;
  753. each(ids, function (id) {
  754. if (!BUILDIN_MODULE[id]) {
  755. return (isAllCompleted = !!modIs(id, MODULE_DEFINED));
  756. }
  757. });
  758. // 检测并调用callback
  759. if (isAllCompleted) {
  760. isCallbackCalled = 1;
  761. (typeof callback === 'function') && callback.apply(
  762. global,
  763. modGetModulesExports(ids, BUILDIN_MODULE)
  764. );
  765. }
  766. }
  767. }
  768. }
  769. /**
  770. * 正在加载的模块列表
  771. *
  772. * @inner
  773. * @type {Object}
  774. */
  775. var loadingModules = {};
  776. /**
  777. * 加载模块
  778. *
  779. * @inner
  780. * @param {string} moduleId 模块标识
  781. */
  782. function loadModule(moduleId) {
  783. if (loadingModules[moduleId] || modModules[moduleId]) {
  784. return;
  785. }
  786. loadingModules[moduleId] = 1;
  787. // 创建script标签
  788. //
  789. // 这里不挂接onerror的错误处理
  790. // 因为高级浏览器在devtool的console面板会报错
  791. // 再throw一个Error多此一举了
  792. var script = document.createElement('script');
  793. script.setAttribute('data-require-id', moduleId);
  794. script.src = toUrl(moduleId + '.js');
  795. script.async = true;
  796. if (script.readyState) {
  797. script.onreadystatechange = loadedListener;
  798. }
  799. else {
  800. script.onload = loadedListener;
  801. }
  802. appendScript(script);
  803. /**
  804. * script标签加载完成的事件处理函数
  805. *
  806. * @inner
  807. */
  808. function loadedListener() {
  809. var readyState = script.readyState;
  810. if (
  811. typeof readyState === 'undefined'
  812. || /^(loaded|complete)$/.test(readyState)
  813. ) {
  814. script.onload = script.onreadystatechange = null;
  815. script = null;
  816. completePreDefine(moduleId);
  817. /* eslint-disable guard-for-in */
  818. for (var key in autoDefineModules) {
  819. modAnalyse(key);
  820. }
  821. /* eslint-enable guard-for-in */
  822. modAutoInvoke();
  823. }
  824. }
  825. }
  826. /**
  827. * 加载资源
  828. *
  829. * @inner
  830. * @param {string} pluginAndResource 插件与资源标识
  831. * @param {string} baseId 当前环境的模块标识
  832. */
  833. function loadResource(pluginAndResource, baseId) {
  834. if (modModules[pluginAndResource]) {
  835. return;
  836. }
  837. var idInfo = parseId(pluginAndResource);
  838. var resource = {
  839. id: pluginAndResource,
  840. state: MODULE_ANALYZED
  841. };
  842. modModules[pluginAndResource] = resource;
  843. /**
  844. * plugin加载完成的回调函数
  845. *
  846. * @inner
  847. * @param {*} value resource的值
  848. */
  849. function pluginOnload(value) {
  850. resource.exports = value || true;
  851. modDefined(pluginAndResource);
  852. }
  853. /* jshint ignore:start */
  854. /**
  855. * 该方法允许plugin使用加载的资源声明模块
  856. *
  857. * @param {string} id 模块id
  858. * @param {string} text 模块声明字符串
  859. */
  860. pluginOnload.fromText = function (id, text) {
  861. autoDefineModules[id] = 1;
  862. new Function(text)();
  863. completePreDefine(id);
  864. };
  865. /* jshint ignore:end */
  866. /**
  867. * 加载资源
  868. *
  869. * @inner
  870. * @param {Object} plugin 用于加载资源的插件模块
  871. */
  872. function load(plugin) {
  873. var pluginRequire = baseId
  874. ? modModules[baseId].require
  875. : actualGlobalRequire;
  876. plugin.load(
  877. idInfo.res,
  878. pluginRequire,
  879. pluginOnload,
  880. moduleConfigGetter.call({id: pluginAndResource})
  881. );
  882. }
  883. load(modGetModuleExports(idInfo.mod));
  884. }
  885. /**
  886. * 配置require
  887. *
  888. * @param {Object} conf 配置对象
  889. */
  890. globalRequire.config = function (conf) {
  891. if (conf) {
  892. /* eslint-disable guard-for-in */
  893. for (var key in requireConf) {
  894. var newValue = conf[key];
  895. var oldValue = requireConf[key];
  896. if (!newValue) {
  897. continue;
  898. }
  899. if (key === 'urlArgs' && typeof newValue === 'string') {
  900. requireConf.urlArgs['*'] = newValue;
  901. }
  902. else {
  903. // 简单的多处配置还是需要支持,所以配置实现为支持二级mix
  904. if (oldValue instanceof Array) {
  905. oldValue.push.apply(oldValue, newValue);
  906. }
  907. else if (typeof oldValue === 'object') {
  908. for (var k in newValue) {
  909. oldValue[k] = newValue[k];
  910. }
  911. }
  912. else {
  913. requireConf[key] = newValue;
  914. }
  915. }
  916. }
  917. /* eslint-enable guard-for-in */
  918. createConfIndex();
  919. }
  920. // 配置信息对象clone返回,避免返回结果对象被用户程序修改可能导致的问题
  921. // return clone(requireConf);
  922. };
  923. /**
  924. * 对象克隆,支持raw type, Array, raw Object
  925. *
  926. * @inner
  927. * @param {*} source 要克隆的对象
  928. * @return {*}
  929. */
  930. // function clone(source) {
  931. // var result = source;
  932. // if (source instanceof Array) {
  933. // result = [];
  934. // each(source, function (item, i) {
  935. // result[i] = clone(item);
  936. // });
  937. // }
  938. // else if (typeof source === 'object') {
  939. // result = {};
  940. // for (var key in source) {
  941. // if (source.hasOwnProperty(key)) {
  942. // result[key] = clone(source[key]);
  943. // }
  944. // }
  945. // }
  946. // return result;
  947. // }
  948. // 初始化时需要创建配置索引
  949. createConfIndex();
  950. /**
  951. * paths内部索引
  952. *
  953. * @inner
  954. * @type {Array}
  955. */
  956. var pathsIndex;
  957. /**
  958. * packages内部索引
  959. *
  960. * @inner
  961. * @type {Array}
  962. */
  963. var packagesIndex;
  964. /**
  965. * mapping内部索引
  966. *
  967. * @inner
  968. * @type {Array}
  969. */
  970. var mappingIdIndex;
  971. /**
  972. * urlArgs内部索引
  973. *
  974. * @inner
  975. * @type {Array}
  976. */
  977. var urlArgsIndex;
  978. /**
  979. * noRequests内部索引
  980. *
  981. * @inner
  982. * @type {Array}
  983. */
  984. var noRequestsIndex;
  985. /**
  986. * 将key为module id prefix的Object,生成数组形式的索引,并按照长度和字面排序
  987. *
  988. * @inner
  989. * @param {Object} value 源值
  990. * @param {boolean} allowAsterisk 是否允许*号表示匹配所有
  991. * @return {Array} 索引对象
  992. */
  993. function createKVSortedIndex(value, allowAsterisk) {
  994. var index = kv2List(value, 1, allowAsterisk);
  995. index.sort(descSorterByKOrName);
  996. return index;
  997. }
  998. /**
  999. * 创建配置信息内部索引
  1000. *
  1001. * @inner
  1002. */
  1003. function createConfIndex() {
  1004. requireConf.baseUrl = requireConf.baseUrl.replace(/\/$/, '') + '/';
  1005. // create paths index
  1006. pathsIndex = createKVSortedIndex(requireConf.paths);
  1007. // create mappingId index
  1008. mappingIdIndex = createKVSortedIndex(requireConf.map, 1);
  1009. each(
  1010. mappingIdIndex,
  1011. function (item) {
  1012. item.v = createKVSortedIndex(item.v);
  1013. }
  1014. );
  1015. // create packages index
  1016. packagesIndex = [];
  1017. each(
  1018. requireConf.packages,
  1019. function (packageConf) {
  1020. var pkg = packageConf;
  1021. if (typeof packageConf === 'string') {
  1022. pkg = {
  1023. name: packageConf.split('/')[0],
  1024. location: packageConf,
  1025. main: 'main'
  1026. };
  1027. }
  1028. pkg.location = pkg.location || pkg.name;
  1029. pkg.main = (pkg.main || 'main').replace(/\.js$/i, '');
  1030. pkg.reg = createPrefixRegexp(pkg.name);
  1031. packagesIndex.push(pkg);
  1032. }
  1033. );
  1034. packagesIndex.sort(descSorterByKOrName);
  1035. // create urlArgs index
  1036. urlArgsIndex = createKVSortedIndex(requireConf.urlArgs, 1);
  1037. // create noRequests index
  1038. noRequestsIndex = createKVSortedIndex(requireConf.noRequests);
  1039. each(noRequestsIndex, function (item) {
  1040. var value = item.v;
  1041. var mapIndex = {};
  1042. item.v = mapIndex;
  1043. if (!(value instanceof Array)) {
  1044. value = [value];
  1045. }
  1046. each(value, function (meetId) {
  1047. mapIndex[meetId] = 1;
  1048. });
  1049. });
  1050. }
  1051. /**
  1052. * 对配置信息的索引进行检索
  1053. *
  1054. * @inner
  1055. * @param {string} value 要检索的值
  1056. * @param {Array} index 索引对象
  1057. * @param {Function} hitBehavior 索引命中的行为函数
  1058. */
  1059. function indexRetrieve(value, index, hitBehavior) {
  1060. each(index, function (item) {
  1061. if (item.reg.test(value)) {
  1062. hitBehavior(item.v, item.k, item);
  1063. return false;
  1064. }
  1065. });
  1066. }
  1067. /**
  1068. * 将`模块标识+'.extension'`形式的字符串转换成相对的url
  1069. *
  1070. * @inner
  1071. * @param {string} source 源字符串
  1072. * @return {string} url
  1073. */
  1074. function toUrl(source) {
  1075. // 分离 模块标识 和 .extension
  1076. var extReg = /(\.[a-z0-9]+)$/i;
  1077. var queryReg = /(\?[^#]*)$/;
  1078. var extname = '';
  1079. var id = source;
  1080. var query = '';
  1081. if (queryReg.test(source)) {
  1082. query = RegExp.$1;
  1083. source = source.replace(queryReg, '');
  1084. }
  1085. if (extReg.test(source)) {
  1086. extname = RegExp.$1;
  1087. id = source.replace(extReg, '');
  1088. }
  1089. var url = id;
  1090. // paths处理和匹配
  1091. var isPathMap;
  1092. indexRetrieve(id, pathsIndex, function (value, key) {
  1093. url = url.replace(key, value);
  1094. isPathMap = 1;
  1095. });
  1096. // packages处理和匹配
  1097. if (!isPathMap) {
  1098. indexRetrieve(id, packagesIndex, function (value, key, item) {
  1099. url = url.replace(item.name, item.location);
  1100. });
  1101. }
  1102. // 相对路径时,附加baseUrl
  1103. if (!/^([a-z]{2,10}:\/)?\//i.test(url)) {
  1104. url = requireConf.baseUrl + url;
  1105. }
  1106. // 附加 .extension 和 query
  1107. url += extname + query;
  1108. // urlArgs处理和匹配
  1109. indexRetrieve(id, urlArgsIndex, function (value) {
  1110. url += (url.indexOf('?') > 0 ? '&' : '?') + value;
  1111. });
  1112. return url;
  1113. }
  1114. /**
  1115. * 创建local require函数
  1116. *
  1117. * @inner
  1118. * @param {number} baseId 当前module id
  1119. * @return {Function} local require函数
  1120. */
  1121. function createLocalRequire(baseId) {
  1122. var requiredCache = {};
  1123. function req(requireId, callback) {
  1124. if (typeof requireId === 'string') {
  1125. if (!requiredCache[requireId]) {
  1126. requiredCache[requireId] =
  1127. nativeRequire(normalize(requireId, baseId));
  1128. }
  1129. return requiredCache[requireId];
  1130. }
  1131. else if (requireId instanceof Array) {
  1132. // 分析是否有resource,取出pluginModule先
  1133. var pluginModules = [];
  1134. var pureModules = [];
  1135. var normalizedIds = [];
  1136. each(
  1137. requireId,
  1138. function (id, i) {
  1139. var idInfo = parseId(id);
  1140. var absId = normalize(idInfo.mod, baseId);
  1141. pureModules.push(absId);
  1142. autoDefineModules[absId] = 1;
  1143. if (idInfo.res) {
  1144. pluginModules.push(absId);
  1145. normalizedIds[i] = null;
  1146. }
  1147. else {
  1148. normalizedIds[i] = absId;
  1149. }
  1150. }
  1151. );
  1152. var noRequestModules = {};
  1153. each(
  1154. pureModules,
  1155. function (id) {
  1156. var meet;
  1157. indexRetrieve(
  1158. id,
  1159. noRequestsIndex,
  1160. function (value) {
  1161. meet = value;
  1162. }
  1163. );
  1164. if (meet) {
  1165. if (meet['*']) {
  1166. noRequestModules[id] = 1;
  1167. }
  1168. else {
  1169. each(pureModules, function (meetId) {
  1170. if (meet[meetId]) {
  1171. noRequestModules[id] = 1;
  1172. return false;
  1173. }
  1174. });
  1175. }
  1176. }
  1177. }
  1178. );
  1179. // 加载模块
  1180. nativeRequire(
  1181. pureModules,
  1182. function () {
  1183. /* jshint ignore:start */
  1184. each(normalizedIds, function (id, i) {
  1185. if (id == null) {
  1186. normalizedIds[i] = normalize(requireId[i], baseId);
  1187. }
  1188. });
  1189. /* jshint ignore:end */
  1190. nativeRequire(normalizedIds, callback, baseId);
  1191. },
  1192. baseId,
  1193. noRequestModules
  1194. );
  1195. }
  1196. }
  1197. /**
  1198. * 将[module ID] + '.extension'格式的字符串转换成url
  1199. *
  1200. * @inner
  1201. * @param {string} id 符合描述格式的源字符串
  1202. * @return {string} url
  1203. */
  1204. req.toUrl = function (id) {
  1205. return toUrl(normalize(id, baseId));
  1206. };
  1207. return req;
  1208. }
  1209. /**
  1210. * id normalize化
  1211. *
  1212. * @inner
  1213. * @param {string} id 需要normalize的模块标识
  1214. * @param {string} baseId 当前环境的模块标识
  1215. * @return {string} normalize结果
  1216. */
  1217. function normalize(id, baseId) {
  1218. if (!id) {
  1219. return '';
  1220. }
  1221. baseId = baseId || '';
  1222. var idInfo = parseId(id);
  1223. if (!idInfo) {
  1224. return id;
  1225. }
  1226. var resourceId = idInfo.res;
  1227. var moduleId = relative2absolute(idInfo.mod, baseId);
  1228. each(
  1229. packagesIndex,
  1230. function (packageConf) {
  1231. var name = packageConf.name;
  1232. if (name === moduleId) {
  1233. moduleId = name + '/' + packageConf.main;
  1234. return false;
  1235. }
  1236. }
  1237. );
  1238. // 根据config中的map配置进行module id mapping
  1239. indexRetrieve(
  1240. baseId,
  1241. mappingIdIndex,
  1242. function (value) {
  1243. indexRetrieve(
  1244. moduleId,
  1245. value,
  1246. function (mdValue, mdKey) {
  1247. moduleId = moduleId.replace(mdKey, mdValue);
  1248. }
  1249. );
  1250. }
  1251. );
  1252. if (resourceId) {
  1253. var mod = modGetModuleExports(moduleId);
  1254. resourceId = mod.normalize
  1255. ? mod.normalize(
  1256. resourceId,
  1257. function (resId) {
  1258. return normalize(resId, baseId);
  1259. }
  1260. )
  1261. : normalize(resourceId, baseId);
  1262. moduleId += '!' + resourceId;
  1263. }
  1264. return moduleId;
  1265. }
  1266. /**
  1267. * 相对id转换成绝对id
  1268. *
  1269. * @inner
  1270. * @param {string} id 要转换的相对id
  1271. * @param {string} baseId 当前所在环境id
  1272. * @return {string} 绝对id
  1273. */
  1274. function relative2absolute(id, baseId) {
  1275. if (id.indexOf('.') === 0) {
  1276. var basePath = baseId.split('/');
  1277. var namePath = id.split('/');
  1278. var baseLen = basePath.length - 1;
  1279. var nameLen = namePath.length;
  1280. var cutBaseTerms = 0;
  1281. var cutNameTerms = 0;
  1282. /* eslint-disable block-scoped-var */
  1283. pathLoop: for (var i = 0; i < nameLen; i++) {
  1284. switch (namePath[i]) {
  1285. case '..':
  1286. if (cutBaseTerms < baseLen) {
  1287. cutBaseTerms++;
  1288. cutNameTerms++;
  1289. }
  1290. else {
  1291. break pathLoop;
  1292. }
  1293. break;
  1294. case '.':
  1295. cutNameTerms++;
  1296. break;
  1297. default:
  1298. break pathLoop;
  1299. }
  1300. }
  1301. /* eslint-enable block-scoped-var */
  1302. basePath.length = baseLen - cutBaseTerms;
  1303. namePath = namePath.slice(cutNameTerms);
  1304. return basePath.concat(namePath).join('/');
  1305. }
  1306. return id;
  1307. }
  1308. /**
  1309. * 解析id,返回带有module和resource属性的Object
  1310. *
  1311. * @inner
  1312. * @param {string} id 标识
  1313. * @return {Object} id解析结果对象
  1314. */
  1315. function parseId(id) {
  1316. var segs = id.split('!');
  1317. if (segs[0]) {
  1318. return {
  1319. mod: segs[0],
  1320. res: segs[1]
  1321. };
  1322. }
  1323. return null;
  1324. }
  1325. /**
  1326. * 将对象数据转换成数组,数组每项是带有k和v的Object
  1327. *
  1328. * @inner
  1329. * @param {Object} source 对象数据
  1330. * @param {boolean} keyMatchable key是否允许被前缀匹配
  1331. * @param {boolean} allowAsterisk 是否支持*匹配所有
  1332. * @return {Array.<Object>} 对象转换数组
  1333. */
  1334. function kv2List(source, keyMatchable, allowAsterisk) {
  1335. var list = [];
  1336. for (var key in source) {
  1337. if (source.hasOwnProperty(key)) {
  1338. var item = {
  1339. k: key,
  1340. v: source[key]
  1341. };
  1342. list.push(item);
  1343. if (keyMatchable) {
  1344. item.reg = key === '*' && allowAsterisk
  1345. ? /^/
  1346. : createPrefixRegexp(key);
  1347. }
  1348. }
  1349. }
  1350. return list;
  1351. }
  1352. // 感谢requirejs,通过currentlyAddingScript兼容老旧ie
  1353. //
  1354. // For some cache cases in IE 6-8, the script executes before the end
  1355. // of the appendChild execution, so to tie an anonymous define
  1356. // call to the module name (which is stored on the node), hold on
  1357. // to a reference to this node, but clear after the DOM insertion.
  1358. var currentlyAddingScript;
  1359. var interactiveScript;
  1360. /**
  1361. * 获取当前script标签
  1362. * 用于ie下define未指定module id时获取id
  1363. *
  1364. * @inner
  1365. * @return {HTMLScriptElement} 当前script标签
  1366. */
  1367. function getCurrentScript() {
  1368. if (currentlyAddingScript) {
  1369. return currentlyAddingScript;
  1370. }
  1371. else if (
  1372. interactiveScript
  1373. && interactiveScript.readyState === 'interactive'
  1374. ) {
  1375. return interactiveScript;
  1376. }
  1377. var scripts = document.getElementsByTagName('script');
  1378. var scriptLen = scripts.length;
  1379. while (scriptLen--) {
  1380. var script = scripts[scriptLen];
  1381. if (script.readyState === 'interactive') {
  1382. interactiveScript = script;
  1383. return script;
  1384. }
  1385. }
  1386. }
  1387. var headElement = document.getElementsByTagName('head')[0];
  1388. var baseElement = document.getElementsByTagName('base')[0];
  1389. if (baseElement) {
  1390. headElement = baseElement.parentNode;
  1391. }
  1392. /**
  1393. * 向页面中插入script标签
  1394. *
  1395. * @inner
  1396. * @param {HTMLScriptElement} script script标签
  1397. */
  1398. function appendScript(script) {
  1399. currentlyAddingScript = script;
  1400. // If BASE tag is in play, using appendChild is a problem for IE6.
  1401. // See: http://dev.jquery.com/ticket/2709
  1402. baseElement
  1403. ? headElement.insertBefore(script, baseElement)
  1404. : headElement.appendChild(script);
  1405. currentlyAddingScript = null;
  1406. }
  1407. /**
  1408. * 创建id前缀匹配的正则对象
  1409. *
  1410. * @inner
  1411. * @param {string} prefix id前缀
  1412. * @return {RegExp} 前缀匹配的正则对象
  1413. */
  1414. function createPrefixRegexp(prefix) {
  1415. return new RegExp('^' + prefix + '(/|$)');
  1416. }
  1417. /**
  1418. * 循环遍历数组集合
  1419. *
  1420. * @inner
  1421. * @param {Array} source 数组源
  1422. * @param {function(Array,Number):boolean} iterator 遍历函数
  1423. */
  1424. function each(source, iterator) {
  1425. if (source instanceof Array) {
  1426. for (var i = 0, len = source.length; i < len; i++) {
  1427. if (iterator(source[i], i) === false) {
  1428. break;
  1429. }
  1430. }
  1431. }
  1432. }
  1433. /**
  1434. * 根据元素的k或name项进行数组字符数逆序的排序函数
  1435. *
  1436. * @inner
  1437. * @param {Object} a 要比较的对象a
  1438. * @param {Object} b 要比较的对象b
  1439. * @return {number} 比较结果
  1440. */
  1441. function descSorterByKOrName(a, b) {
  1442. var aValue = a.k || a.name;
  1443. var bValue = b.k || b.name;
  1444. if (bValue === '*') {
  1445. return -1;
  1446. }
  1447. if (aValue === '*') {
  1448. return 1;
  1449. }
  1450. return bValue.length - aValue.length;
  1451. }
  1452. // 暴露全局对象
  1453. if (!define) {
  1454. define = globalDefine;
  1455. // 可能碰到其他形式的loader,所以,不要覆盖人家
  1456. if (!require) {
  1457. require = globalRequire;
  1458. }
  1459. // 如果存在其他版本的esl,在define那里就判断过了,不会进入这个分支
  1460. // 所以这里就不判断了,直接写
  1461. esl = globalRequire;
  1462. }
  1463. })(this);