一、$import流程图

二、doScriptImport流程图

三、JSI导入js关键代码分析
function loadDependence(data,vars){
loadScript(data[0],data[1],data[2]);
var objectMap = data[0].objectMap;
var names = data[5];
var i = names.length;
while(i--){
var name = names[i];
vars.push(name);//对于转载后依赖,我们使用重复设置了一次
vars[name] = objectMap[name];
}
}
function prepareScriptLoad(packageObject,loader){
var name = loader.name;
var deps = packageObject.dependenceMap[name];
var varText = 'this.hook=function(n){return eval(n)}';
var vars = [];
var i = deps && deps.length;
while(i--){
var dep = deps[i];
var key = dep[3] || 0; //? 0
if(dep[4]){//记录依赖,以待装载 dep[4]=> true 载入后依赖
vars.push.apply(vars,dep[5]); //把dep[5]=>
if(map){
if(map[key]){
map[key].push(dep);
}else{
map[key] = [dep]
}
}else{
//函数内只有一次赋值(申明后置,也就你JavaScript够狠!! )
var map = loader.dependenceMap = {};
loader.initialize = scriptLoaderInitialize;
map[key] = [dep]
}
}else{//直接装载(只是装载到缓存对象,没有进入装载单元),无需记录
//这里貌似有死循环的危险
loadDependence(dep,vars);
if(dep = packageObject.loaderMap[name]){
return dep;
}
}
}
if(vars.length){
loader.varMap = vars;
/**
* this.hook = function(n){
* return eval(n)
* };
* var obj1 = this.varMap.obj1, obj2 = this.varMap.obj2, obj3 = this.varMap.obj3
*/
varText += ';var '+vars.join(',').replace(/([^,]+)/g,'$1 = this.varMap.$1');
}
loader.varText = varText;
}
function doScriptLoad(packageObject,loader){
var name = loader.name;
var packageName = packageObject.name;
var cachedScript = getCachedScript(packageName,name);
packageObject.loaderMap[name] = loader;
try{
if(cachedScript instanceof Function){
//$JSI.preload(pkgName,name,'')
cachedScripts[packageName][name]='';//clear cache
return cachedScript.call(loader);
}else{
//不要清除文本缓存
return freeEval.call(loader,'eval(this.varText);'+(cachedScript || loadTextByURL(packageObject.scriptBase+name)));
}
}catch(e){
if(debugMode){
if("org.xidea.jsi.boot:$log"){
$log.error("Load Error:\n"+loader.scriptBase + name+"\n\nException:"+e);
}
}
throw e;
}finally{
delete loader.varMap ;
delete loader.varText ;
var names = packageObject.scriptObjectMap[name];
var index = names.length;
var objectMap = packageObject.objectMap;
//此处优化不知有无作用
if(index == 1){
objectMap[names = names[0]] = loader.hook(names);
}else{
var values = loader.hook('['+names.join(',')+']');
while(index--){
objectMap[names[index]] = values[index];
}
}
}
}
function doScriptImport(packageObject,fileName,target){
loadScript(packageObject,fileName);
var objectNames = packageObject.scriptObjectMap[fileName];
//null不可hack
if(target != null){
for(var i = 0; i<objectNames.length;i++){
target[objectNames[i]]=packageObject.objectMap[objectNames[i]];
}
}
}
var $import = function(freeEval,cachedScripts){
...
}(function(){eval(arguments[0]);},{});
第38行
loadDependence(dep,vars);
在这里JSI把待载入脚本[依赖]的对象存入vars,在第45赋值给了loader.varMap
第52行 对象名数组 => 对象声明语句
varText += ';var '+vars.join(',').replace(/([^,]+)/g,'$1 = this.varMap.$1');
第 16行
var varText = 'this.hook=function(n){return eval(n)}' ;
这是JSI把载入脚本在loader下执行后能够获取引用到的关键技术
第69行 后台js文件---->前台---->call(loader,hook+js文件内容)
return freeEval.call(loader,'eval(this.varText);'+(cachedScript || loadTextByURL(packageObject.scriptBase+name)));
在这里JSI把js文件从后台通过xmlhttp从后台载入,然后在loader这个scope中执行(避免命名污染),此时loader.hook被放到了与执行js的同一个上下文中
第88-91行 loader => package
var values = loader.hook('['+names.join(',')+']');
while(index--){
objectMap[names[index]] = values[index];
}
在这里JSI利用loader.hook提取出脚本在声明的对象并传给Package.objectMap
第102行
target[objectNames[i]]=packageObject.objectMap[objectNames[i]];
把对象从package.objectMap传给Import中声明的target对象,或者Import执行时的scope对象
9526

被折叠的 条评论
为什么被折叠?



