-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinstantiator.js
98 lines (75 loc) · 2.48 KB
/
instantiator.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
var _ = require("lodash");
module.exports = Instantiator;
function Instantiator(modules) {
var self = this;
self.stack = [];
self.getInstance = function(name) {
var module = modules[name];
if (!module) {
return undefined;
}
var instance = module.instance;
if (!instance) {
instance = self.instantiate(module);
if (!module.options.transient) {
module.instance = instance;
}
}
return instance;
};
self.instantiate = function(module, options) {
options = options || {};
var index = _.findIndex(self.stack, function(item) {
return item === module.name;
});
if (index >= 0) {
throw new Error("Circular dependency found! " + get_dependency_chain(module.name, index));
}
self.stack.push(module.name);
function Factory(args) {
var value = module.func.apply(this, args);
if (options.wrap_return) {
value = {
return_value: value
};
}
return value;
}
Factory.prototype = module.func.prototype;
var params = get_params(module);
var instance = new Factory(params);
self.stack.pop();
return instance;
};
function get_dependency_chain(name, start) {
self.stack.push(name);
return self.stack.slice(start || 0).join(" -> ");
}
function get_params(module) {
var func = module.func;
var text = func.toString();
var open = text.indexOf("(");
var close = text.indexOf(")");
var params_text = text.substring(open + 1, close);
var param_names = _(params_text.split(","))
.map(function(param_name) {
param_name = param_name.trim();
return param_name === "" ? null : param_name;
})
.compact()
.value();
var params = _.map(param_names, function(param_name) {
var param;
if (module.options.transient && param_name === "__Owner") {
param = _.nth(self.stack, -2);
} else {
param = self.getInstance(param_name);
}
if (!param) {
throw new Error("Could not resolve '" + param_name + "'! " + get_dependency_chain(param_name));
}
return param;
});
return params;
}
}