forked from ObjectJS/object
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefaultloader.js
943 lines (799 loc) · 21.8 KB
/
defaultloader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
;(function(object) {
/**
* 将name中的“.”换成id形式的“/”
*/
function name2id(name) {
return name.replace(/\./g, '/');
}
/**
* 模块
*/
function Module(name) {
this.__name__ = name;
}
Module.prototype.toString = function() {
return '<module \'' + this.__name__ + '\'>';
};
/**
* 找不到模块Error
*/
function NoModuleError(id) {
this.message = 'no module named ' + id;
};
NoModuleError.prototype = new Error();
/**
* 未对模块进行依赖
*/
function ModuleRequiredError(id) {
this.message = 'module ' + id + ' required';
};
ModuleRequiredError.prototype = new Error();
/**
* 循环依赖Error
*/
function CyclicDependencyError(stack) {
this.runStack = stack;
var msg = '';
stack.forEach(function(m, i) {
msg += m.id;
if (i != stack.length - 1) {
msg += '-->';
}
});
this.message = msg + ' cyclic dependency.';
}
CyclicDependencyError.prototype = new Error();
/**
* 普通Package
*/
function CommonJSPackage(id, deps, factory) {
Package.apply(this, arguments);
}
CommonJSPackage.prototype = new Package();
CommonJSPackage.prototype.constructor = CommonJSPackage;
/**
* 执行一个package,返回其exports
*/
CommonJSPackage.prototype.execute = function(name, runtime) {
var exports = runtime.modules[name] || new Module(name);
var returnExports = this.factory.call(exports, this.createRequire(name, runtime), exports, this);
if (returnExports) {
returnExports.__name__ = exports.__name__;
exports = returnExports;
}
return exports;
};
CommonJSPackage.prototype.createRequire = function(name, runtime) {
var loader = runtime.loader;
var module = this;
function require(id) {
var dep = module.getDep(id);
if (!dep) {
throw new ModuleRequiredError(id);
}
var exports = dep.getRef(runtime);
// 有依赖却没有获取到,说明是由于循环依赖
if (!exports && module.dependencies.indexOf(id) != -1) {
throw new CyclicDependencyError(runtime.stack);
}
return exports;
}
require.async = function(deps, callback) {
deps = module.parseDeps(deps);
var pkg = new CommonJSPackage(module.id, deps, function(require) {
var args = [];
deps.forEach(function(dep) {
args.push(require(dep));
});
callback.apply(null, args);
});
pkg.load(name, runtime);
};
return require;
};
/**
* 文艺 Package
*/
function ObjectPackage(id, deps, factory) {
Package.apply(this, arguments);
};
ObjectPackage.prototype = new Package();
ObjectPackage.prototype.constructor = ObjectPackage;
/**
* 执行一个package,返回其exports
*/
ObjectPackage.prototype.execute = function(name, runtime) {
var exports = runtime.modules[name] || new Module(name);
var args = [exports];
this.dependencies.forEach(function(depId) {
var depExports = this.getDep(depId).getRef(runtime);
if (args.indexOf(depExports) == -1) {
args.push(depExports);
}
}, this);
var returnExports = this.factory.apply(exports, args);
if (returnExports) {
// 检测是否有子模块引用了本模块
if (exports.__empty_refs__) {
exports.__empty_refs__.forEach(function(ref) {
if (typeof console != 'undefined') {
console.warn(ref + '无法正确获得' + name + '模块的引用。因为该模块是通过return返回模块实例的。');
}
});
}
returnExports.__name__ = exports.__name__;
exports = returnExports;
} else {
delete exports.__empty_refs__;
}
return exports;
};
ObjectPackage.prototype.handleCyclicDependency = function(dep, pkg, runtime, next) {
var exports = runtime.modules[dep.id] || new Module(dep.id);
runtime.modules[dep.id] = exports;
if (!exports.__empty_refs__) exports.__empty_refs__ = [];
exports.__empty_refs__.push(pkg.id);
next(exports);
};
/**
* XX Package
*/
function Package(id, deps, factory) {
if (!id) return;
this.id = id;
this.dependencies = this.parseDeps(deps);
this.factory = factory;
this.deps = {};
this.initDeps();
}
Package.prototype.initDeps = function() {
this.dependencies.forEach(function(depId) {
var dep;
if (depId.indexOf('/') != -1) {
dep = new CommonJSDependency(depId, this);
} else {
dep = new ObjectDependency(depId, this);
}
this.deps[depId] = dep;
}, this);
};
Package.prototype.execute = function(name, runtime) {
return new Module(name);
};
Package.prototype.load = function(name, runtime, callback) {
var currentUse = -1;
var pkg = this;
/**
* 顺序执行pkg中的dependencies
* @param pExports 上一个nextDep返回的模块实例
*/
function nextDep(pExports) {
var deps = pkg.dependencies;
var factory = pkg.factory;
var dep, depPkg;
if (pExports) {
// 模块获取完毕,去除循环依赖检测
runtime.stack.pop();
}
currentUse++;
// 模块获取完毕,执行factory,将exports通过callback传回去。
// 已经处理到最后一个
if (currentUse == deps.length) {
doneDep();
} else {
dep = pkg.getDep(deps[currentUse]);
depPkg = dep.getModule(runtime);
// 记录开始获取当前模块
runtime.stack.push(depPkg);
// 刚刚push过,应该在最后一个,如果不在,说明循环依赖了
if (runtime.stack.indexOf(depPkg) != runtime.stack.length - 1) {
depPkg.handleCyclicDependency(dep, pkg, runtime, nextDep);
} else {
dep.load(runtime, nextDep);
}
}
}
/**
* 已执行完毕最后一个dependency
*/
function doneDep() {
if (!name) name = pkg.id; // 没有指定name,则使用全名
var exports = pkg.execute(name, runtime);
runtime.addModule(name, exports);
// sys.modules
if (exports.__name__ === 'sys') exports.modules = runtime.modules;
if (callback) callback(exports);
}
nextDep();
};
Package.prototype.handleCyclicDependency = function(dep, pkg, runtime, next) {
// 但并不立刻报错,而是当作此模块没有获取到,继续获取下一个
next();
};
Package.prototype.getDep = function(id) {
return this.deps[id];
};
/**
* 处理传入的deps参数
* 在parseDeps阶段不需要根据名称判断去重(比如自己use自己),因为并不能避免所有冲突,还有循环引用的问题(比如 core use dom, dom use core)
* @param {String} deps 输入
*/
Package.prototype.parseDeps = function(deps) {
if (Array.isArray(deps)) return deps;
if (!deps) {
return [];
}
deps = deps.trim().replace(/^,*|,*$/g, '').split(/\s*,\s*/ig);
return deps;
};
function Dependency(name, owner) {
if (!name) return;
this.name = name;
this.owner = owner;
}
Dependency.prototype.getModule = function(runtime) {
var pkg = runtime.loader.getModule(this.id);
return pkg;
};
/**
* @param name
* @param module
*/
function CommonJSDependency(name, owner) {
var pParts, parts;
if (name.indexOf('/') == 0) { // root
} else if (name.indexOf('./') == 0 || name.indexOf('../') == 0) { // relative
pParts = owner.id.split('/');
pParts.pop();
parts = name.split(/\//ig);
parts.forEach(function(part) {
if (part == '.') {
} else if (part == '..') {
pParts.pop();
} else {
pParts.push(part);
}
});
this.id = pParts.join('/');
} else { // top level
this.id = name2id(name);
}
Dependency.call(this, name, owner);
};
CommonJSDependency.prototype = new Dependency();
CommonJSDependency.prototype.constructor = CommonJSDependency;
/**
* 处理当前模块
* @param callback 异步方法,模块获取完毕后通过callback的唯一参数传回
*/
CommonJSDependency.prototype.load = function(runtime, callback) {
runtime.loadModule(this.id, runtime.getName(this.id), callback);
};
/**
* 获取此依赖的引用
*/
CommonJSDependency.prototype.getRef = function(runtime) {
var root = runtime.getName(this.id);
return runtime.modules[root];
};
ObjectDependency = function(name, owner) {
this.nameParts = name.split('.');
this.root = this.nameParts[0];
this.id = name2id(name);
Dependency.call(this, name, owner);
};
ObjectDependency.prototype = new Dependency();
ObjectDependency.prototype.constructor = ObjectDependency;
ObjectDependency.prototype.load = function(runtime, callback) {
var dep = this;
var pName, part, name, currentPart = -1;
/**
* 依次获取当前模块的每个部分
* 如a.b.c,依次获取a、a.b、a.b.c
* @param pExprorts 上一部分的模块实例,如果是初次调用,为空
* @param name 截止到当前部分的包含context前缀的名字
*/
function nextPart(pExports) {
var depModule;
if (pExports) {
runtime.setModule(name, pExports);
// 生成对象链
runtime.setMemberTo(pName, part, pExports);
}
pName = name;
currentPart++;
if (currentPart == dep.nameParts.length) {
callback(runtime.modules[dep.root]);
} else {
part = dep.nameParts[currentPart];
name = (pName? pName + '.' : '') + part;
runtime.loadModule(name2id(name), runtime.getName(name), nextPart);
};
}
nextPart();
};
/**
* 获取此依赖的引用
*/
ObjectDependency.prototype.getRef = function(runtime) {
var root = runtime.getName(this.root);
return runtime.modules[root];
};
/**
* Loader运行时,每一个use、execute产生一个
*/
function LoaderRuntime(root) {
/**
* 此次use运行过程中用到的所有module
*/
this.modules = {};
/**
* 模块的依赖路径的栈,检测循环依赖
*/
this.stack = [];
/**
* 当使用相对依赖时,子模块被处理完毕时,其父模块可能还未处理完毕
* 导致无法立刻将此子模块的引用赋予其父模块
* 此变量用于存储父模块与其子模块的映射关系,在父模块初始化完毕后再将自模块赋予自己。
*/
this.members = {};
/**
* 运行入口模块的名字
*/
this.root = root;
}
LoaderRuntime.prototype = {
/**
* 加入一个module
*/
addModule: function(name, exports) {
exports = exports || new Module(name);
this.modules[name] = exports;
// 已获取到了此host的引用,将其子模块都注册上去。
var members = this.members[name];
if (members) {
members.forEach(function(member) {
this.modules[name][member.id] = member.value;
}, this);
}
return exports;
},
/**
* 设置一个已存在的module
*/
setModule: function(name, exports) {
this.modules[name] = exports;
},
/**
* 加载一个module
*/
loadModule: function(id, name, callback) {
var loader = this.loader;
var exports = this.modules[name];
// 使用缓存中的
if (exports) {
callback(exports);
} else {
loader.load(id, name, this, callback);
}
},
/**
* 加上root前缀的完整id
*/
getId: function(name) {
return this.root + '.' + name;
},
/**
* 去掉root前缀的模块名
*/
getName: function(id) {
var root = this.root;
if (id == root || id.indexOf(root + '/') == 0) {
id = id.slice(root.length + 1);
}
return id.replace(/\//g, '.');
},
/**
* 为名为host的module设置member成员为value
*/
setMemberTo: function(host, member, value) {
// 向host添加member成员
if (host) {
// 已存在host
if (this.modules[host]) {
this.modules[host][member] = value;
}
// host不存在,记录在members对象中
else {
if (!this.members[host]) this.members[host] = [];
this.members[host].push({
id: member,
value: value
});
}
}
}
};
/**
* object的包管理器
* 这个class依赖于object._lib ,且会修改它
*/
var Loader = new Class(function() {
// 计算当前引用objectjs的页面文件的目录路径
function calculatePageDir() {
var loc = window['location'];
var pageUrl = loc.protocol + '//' + loc.host + (loc.pathname.charAt(0) !== '/' ? '/' : '') + loc.pathname;
// IE 下文件系统是以\为分隔符,统一改为/
if (pageUrl.indexOf('\\') != -1) {
pageUrl = pageUrl.replace(/\\/g, '/');
}
var pageDir = './';
if (pageUrl.indexOf('/') != -1) {
// 去除文件,留下目录path
pageDir = pageUrl.substring(0, pageUrl.lastIndexOf('/') + 1);
}
return pageDir;
}
// global pageDir
var pageDir;
// 用于保存url与script节点的键值对
this._urlNodeMap = {};
this.initialize = function(self) {
self.useCache = true;
self.lib = {
'sys': new Package('sys', [], function() {})
};
self.fileLib = {};
self.prefixLib = {};
self.anonymousModuleCount = 0;
self.scripts = document.getElementsByTagName('script');
};
/**
* 加载一个module
*
* @param pkg 被执行的module
* @param name 执行时的name
* @param {LoaderRuntime} runtime
* @param callback 异步方法,执行完毕后调用,传入模块实例及名字
*/
this.load = function(self, id, name, runtime, callback) {
var pkg = self.getModule(id);
// No module
if (!pkg) {
throw new NoModuleError(id);
}
// file
else if (pkg.file) {
// TODO 加入预处理过程,跑出所有需要加载的文件并行加载,在此执行useScript而不是loadScript
self.loadScript(pkg.file, function() {
var id = pkg.id;
var file = pkg.file;
// 重新读取pkg,之前的pkg只是个fileLib中的占位
pkg = self.lib[id];
// 加载进来的脚本没有替换掉相应的模块,文件有问题。
if (!pkg) {
throw new Error(file + ' do not add ' + id);
}
pkg.load(name, runtime, callback);
}, true);
// Already define
} else {
pkg.load(name, runtime, callback);
}
};
/**
* 查找页面中的标记script标签,更新 self.fileLib
*/
this.buildFileLib = function(self) {
var scripts = self.scripts;
for (var i = 0, script, names, src, l = scripts.length; i < l; i++) {
script = scripts[i];
src = script.getAttribute('data-src');
names = script.getAttribute('data-module');
if (!names || !src) continue;
names.split(/\s+/ig).forEach(function(name) {
self.defineFile(name2id(name), src);
});
}
};
/**
* 通过一个src,获取对应文件的绝对路径
* 例如:http://hg.xnimg.cn/a.js -> http://hg.xnimg.cn/a.js
* file:///dir/a.js -> file:///dir/a.js
* in http://host/b/c/d/e/f.html, load ../g.js -> http://host/a/b/d/g.js
* in file:///dir/b/c/d/e/f.html, load ../g.js -> file:///dir/a/b/d/g.js
*
* @param src 地址
*/
this._getAbsolutePath = staticmethod(function(src) {
/**
* 清理路径url,去除相对寻址符号
*/
function cleanPath(path) {
// 去除多余的/
path = path.replace(/([^:\/])\/+/g, '$1\/');
// 如果没有相对寻址,直接返回path
if (path.indexOf('.') === -1) {
return path;
}
var parts = path.split('/');
// 把所有的普通var变量都写在一行,便于压缩
var result = [];
for (var i = 0, part, len = parts.length; i < len; i++) {
part = parts[i];
if (part === '..') {
if (result.length === 0) {
throw new Error('invalid path: ' + path);
}
result.pop();
} else if (part !== '.') {
result.push(part);
}
}
// 去除尾部的#号
return result.join('/').replace(/#$/, '');
}
// 如果本身是绝对路径,则返回src的清理版本
if (src.indexOf('://') != -1 || src.indexOf('//') === 0) {
return cleanPath(src);
}
if (typeof pageDir == 'undefined') {
pageDir = calculatePageDir();
}
return cleanPath(pageDir + src);
});
/**
* TODO
*/
this.useScript = function(self, src, callback) {
};
/**
* 加载一个script, 执行callback
* 有冲突检测,如果连续调用两次loadScript同一src的话,则第二个调用会等第一个完毕后直接执行callback,不会加载两次。
*
* @param src 地址
* @param callback callback函数
*/
this.loadScript = classmethod(function(cls, src, callback, useCache) {
if (!src || typeof src != 'string') {
throw new Error('src should be string');
}
src = src.trim();
var absPath = cls._getAbsolutePath(src);
if (useCache) {
var urlNodeMap = cls.get('_urlNodeMap'), scriptNode = urlNodeMap[absPath];
if (scriptNode) {
if (scriptNode.loading) {
// 增加一个回调即可
scriptNode.callbacks.push(callback);
} else {
callback(scriptNode);
}
return;
}
}
var ele = document.createElement('script');
ele.type = "text/javascript";
ele.src = src;
ele.async = true;
ele.loading = true;
ele.callbacks = [];
var doCallback = function() {
ele.loading = null;
ele.callbacks.forEach(function(callback) {
callback(ele);
});
for (var i = 0, l = ele.callbacks.length; i < l; i++) {
ele.callbacks[i] = null;
}
ele.callbacks = null;
};
ele.callbacks.push(callback);
if (window.ActiveXObject) { // IE
ele.onreadystatechange = function() {
var rs = this.readyState;
if ('loaded' === rs || 'complete' === rs) {
ele.onreadystatechange = null;
doCallback();
}
};
} else if (ele.addEventListener) { // Standard
ele.addEventListener('load', doCallback, false);
ele.addEventListener('error', doCallback, false);
} else { // Old browser
ele.onload = ele.onerror = doCallback;
}
document.getElementsByTagName('head')[0].insertBefore(ele, null);
if (useCache) {
// 利用绝对路径来存键值对,key为绝对路径,value为script节点
urlNodeMap[absPath] = ele;
}
});
/**
* 根据src属性,删除一个script标签,并且清除对应的键值对缓存记录
* 目前只供单元测试还原测试环境使用
* @param src 路径
*/
this.removeScript = classmethod(function(cls, src) {
if (!src || typeof src != 'string') {
throw new Error('src should be string');
}
src = src.trim();
// 转换为绝对路径
var absPath = cls._getAbsolutePath(src);
// 获取节点
var urlNodeMap = cls.get('_urlNodeMap'), scriptNode = urlNodeMap[absPath];
// 如果节点存在,则删除script,并从缓存中清空
if (scriptNode) {
delete urlNodeMap[absPath];
if (scriptNode.parentNode) {
scriptNode.parentNode.removeChild(scriptNode);
}
scriptNode = null;
}
});
/**
* 建立一个runtime
*/
this.createRuntime = function(self, id) {
var runtime = new LoaderRuntime(id);
runtime.loader = self;
return runtime;
};
/**
* 建立前缀模块
* 比如 a/b/c/d ,会建立 a a/b a/b/c 三个空模块,最后一个模块为目标模块
*/
this.definePrefixFor = function(self, id) {
if (!id || typeof id != 'string') return;
if (arguments.length < 2) return;
var idParts = id.split('/');
for (var i = 0, prefix, pkg, l = idParts.length - 1; i < l; i++) {
prefix = idParts.slice(0, i + 1).join('/');
self.definePrefix(prefix);
}
};
/**
* 定义一个prefix module
*/
this.definePrefix = function(self, id) {
if (!id || typeof id != 'string') return;
if (arguments.length < 2) return;
if (id in self.lib || id in self.prefixLib) return;
self.prefixLib[id] = new Package(id, [], function(){});
};
/**
* 定义一个file module,供异步加载
*/
this.defineFile = function(self, id, src) {
if (!id || typeof id != 'string') return;
if (arguments.length < 2) return;
if (self.fileLib[id]) return;
// prefix已注册
if (id in self.prefixLib) {
delete self.prefixLib[id];
}
// 添加前缀module到prefixLib
else {
self.definePrefixFor(id);
}
self.fileLib[id] = {
id: id,
file: src
};
};
/**
* 定义一个普通module
*/
this.defineModule = function(self, constructor, id, deps, factory) {
if (arguments.length < 5) return;
// 不允许重复添加。
if (id in self.lib) return;
// prefix已注册
if (id in self.prefixLib) {
delete self.prefixLib[id];
}
// file已注册
else if (id in self.fileLib) {
delete self.fileLib[id];
}
// 添加前缀module到prefixLib
else {
self.definePrefixFor(id);
}
var pkg = new constructor(id, deps, factory);
self.lib[id] = pkg;
};
/**
* @param name
* @param deps
* @param factory
*/
this.define = function(self, name, deps, factory) {
if (typeof name != 'string') return;
if (typeof deps == 'function') {
factory = deps;
deps = [];
}
self.defineModule(CommonJSPackage, name2id(name), deps, factory);
};
/**
* @param name
* @param deps
* @param factory
*/
this.add = function(self, name, deps, factory) {
if (typeof name != 'string') return;
if (typeof deps == 'function') {
factory = deps;
deps = [];
}
self.defineModule(ObjectPackage, name2id(name), deps, factory);
};
/**
* @param id
*/
this.getModule = function(self, id) {
return self.lib[id] || self.fileLib[id] || self.prefixLib[id];
};
/**
* 移除模块的定义
* @param id 需要移除模块的id
* @param all 是否移除其所有子模块
*/
this.remove = function(self, id, all) {
delete self.lib[id];
if (all) {
Object.keys(self.lib).forEach(function(key) {
if (key.indexOf(id + '/') == 0) delete self.lib[key];
});
}
};
/**
* execute
* @param id 执行的入口模块名称
*/
this.execute = function(self, id) {
if (!id || typeof id != 'string') {
return;
}
self.buildFileLib();
var runtime = self.createRuntime(id);
runtime.loadModule(id.replace(/\./g, '/'), '__main__');
};
/**
* use
* @param deps 用逗号分隔开的模块名称列表
* @param factory deps加载后调用,将module通过参数传入factory,第一个参数为exports,后面的参数为每个module的不重复引用,顺序排列
*/
this.use = function(self, deps, factory) {
if (!factory || typeof factory != 'function') {
return;
}
self.buildFileLib();
var id = '__anonymous_' + self.anonymousModuleCount + '__';
self.anonymousModuleCount++;
object.define(id, deps, function(require, exports, module) {
var args = [];
module.dependencies.forEach(function(dep) {
dep = require(dep);
if (args.indexOf(dep) == -1) {
args.push(dep);
}
});
if (factory.length == args.length + 1) {
if (typeof console != 'undefined') {
console.warn('object.use即将不再支持第一个exports参数,请尽快删除。');
}
args.unshift(exports);
}
factory.apply(null, args);
});
var runtime = self.createRuntime(id);
runtime.loadModule(id.replace(/\./g, '/'), '__main__', function() {});
};
});
object.Loader = Loader;
object.NoModuleError = NoModuleError;
object.ModuleRequiredError = ModuleRequiredError;
})(object);