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

1654 lines
46 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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