bkjxxxw/WebContent/static/echarts-2.2.7/doc/asset/js/esl/esl.js

1654 lines
46 KiB
JavaScript
Raw Normal View History

2024-03-18 10:04:33 +08:00
/**
* 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);