##// END OF EJS Templates
tests
cin -
r41:eae7e609c38a di-typescript
parent child
Show More
@@ -0,0 +1,3
1 export class Bar {
2 name = "bar";
3 }
@@ -0,0 +1,3
1 export class Foo {
2 name = "foo";
3 }
@@ -1,22 +1,22
1 Copyright 2017-2018 Implab team
1 Copyright 2017-2019 Implab team
2
2
3 Redistribution and use in source and binary forms, with or without
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are met:
4 modification, are permitted provided that the following conditions are met:
5
5
6 1. Redistributions of source code must retain the above copyright notice, this
6 1. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
7 list of conditions and the following disclaimer.
8
8
9 2. Redistributions in binary form must reproduce the above copyright notice,
9 2. Redistributions in binary form must reproduce the above copyright notice,
10 this list of conditions and the following disclaimer in the documentation
10 this list of conditions and the following disclaimer in the documentation
11 and/or other materials provided with the distribution.
11 and/or other materials provided with the distribution.
12
12
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. No newline at end of file
22 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,449 +1,449
1 {
1 {
2 "name": "@implab/core",
2 "name": "@implab/core",
3 "version": "0.0.1-dev",
3 "version": "0.0.1-dev",
4 "lockfileVersion": 1,
4 "lockfileVersion": 1,
5 "requires": true,
5 "requires": true,
6 "dependencies": {
6 "dependencies": {
7 "@types/node": {
7 "@types/node": {
8 "version": "10.12.12",
8 "version": "10.12.12",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.12.tgz",
9 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.12.tgz",
10 "integrity": "sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==",
10 "integrity": "sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==",
11 "dev": true
11 "dev": true
12 },
12 },
13 "@types/tape": {
13 "@types/tape": {
14 "version": "4.2.32",
14 "version": "4.2.32",
15 "resolved": "http://registry.npmjs.org/@types/tape/-/tape-4.2.32.tgz",
15 "resolved": "http://registry.npmjs.org/@types/tape/-/tape-4.2.32.tgz",
16 "integrity": "sha512-xil0KO5wkPoixdBWGIGolPv9dekf6dVkjjJLAFYchfKcd4DICou67rgGCIO7wAh3i5Ff/6j9IDgZz+GU9cMaqQ==",
16 "integrity": "sha512-xil0KO5wkPoixdBWGIGolPv9dekf6dVkjjJLAFYchfKcd4DICou67rgGCIO7wAh3i5Ff/6j9IDgZz+GU9cMaqQ==",
17 "dev": true,
17 "dev": true,
18 "requires": {
18 "requires": {
19 "@types/node": "*"
19 "@types/node": "*"
20 }
20 }
21 },
21 },
22 "balanced-match": {
22 "balanced-match": {
23 "version": "1.0.0",
23 "version": "1.0.0",
24 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
24 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
25 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
25 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
26 "dev": true
26 "dev": true
27 },
27 },
28 "brace-expansion": {
28 "brace-expansion": {
29 "version": "1.1.11",
29 "version": "1.1.11",
30 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
30 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
31 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
31 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
32 "dev": true,
32 "dev": true,
33 "requires": {
33 "requires": {
34 "balanced-match": "^1.0.0",
34 "balanced-match": "^1.0.0",
35 "concat-map": "0.0.1"
35 "concat-map": "0.0.1"
36 }
36 }
37 },
37 },
38 "concat-map": {
38 "concat-map": {
39 "version": "0.0.1",
39 "version": "0.0.1",
40 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
40 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
41 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
41 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
42 "dev": true
42 "dev": true
43 },
43 },
44 "core-util-is": {
44 "core-util-is": {
45 "version": "1.0.2",
45 "version": "1.0.2",
46 "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
46 "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
47 "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
47 "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
48 "dev": true
48 "dev": true
49 },
49 },
50 "deep-equal": {
50 "deep-equal": {
51 "version": "0.1.2",
51 "version": "0.1.2",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
52 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz",
53 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
53 "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=",
54 "dev": true
54 "dev": true
55 },
55 },
56 "define-properties": {
56 "define-properties": {
57 "version": "1.1.3",
57 "version": "1.1.3",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
58 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
59 "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
59 "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
60 "dev": true,
60 "dev": true,
61 "requires": {
61 "requires": {
62 "object-keys": "^1.0.12"
62 "object-keys": "^1.0.12"
63 },
63 },
64 "dependencies": {
64 "dependencies": {
65 "object-keys": {
65 "object-keys": {
66 "version": "1.0.12",
66 "version": "1.0.12",
67 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
67 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
68 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
68 "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==",
69 "dev": true
69 "dev": true
70 }
70 }
71 }
71 }
72 },
72 },
73 "defined": {
73 "defined": {
74 "version": "0.0.0",
74 "version": "0.0.0",
75 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
75 "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz",
76 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
76 "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=",
77 "dev": true
77 "dev": true
78 },
78 },
79 "dojo": {
79 "dojo": {
80 "version": "1.13.0",
80 "version": "1.13.0",
81 "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.13.0.tgz",
81 "resolved": "https://registry.npmjs.org/dojo/-/dojo-1.13.0.tgz",
82 "integrity": "sha512-mGoGvsXAbPkUrBnxCoO7m6CFH8jvWq7rAL7fP7jrhJEOyswA/bZwWdXwEH0ovs68t8S0+xOpV/3V7addYbaiAA=="
82 "integrity": "sha512-mGoGvsXAbPkUrBnxCoO7m6CFH8jvWq7rAL7fP7jrhJEOyswA/bZwWdXwEH0ovs68t8S0+xOpV/3V7addYbaiAA=="
83 },
83 },
84 "duplexer": {
84 "duplexer": {
85 "version": "0.1.1",
85 "version": "0.1.1",
86 "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
86 "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
87 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
87 "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
88 "dev": true
88 "dev": true
89 },
89 },
90 "es-abstract": {
90 "es-abstract": {
91 "version": "1.12.0",
91 "version": "1.12.0",
92 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
92 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
93 "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
93 "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
94 "dev": true,
94 "dev": true,
95 "requires": {
95 "requires": {
96 "es-to-primitive": "^1.1.1",
96 "es-to-primitive": "^1.1.1",
97 "function-bind": "^1.1.1",
97 "function-bind": "^1.1.1",
98 "has": "^1.0.1",
98 "has": "^1.0.1",
99 "is-callable": "^1.1.3",
99 "is-callable": "^1.1.3",
100 "is-regex": "^1.0.4"
100 "is-regex": "^1.0.4"
101 }
101 }
102 },
102 },
103 "es-to-primitive": {
103 "es-to-primitive": {
104 "version": "1.2.0",
104 "version": "1.2.0",
105 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
105 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
106 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
106 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
107 "dev": true,
107 "dev": true,
108 "requires": {
108 "requires": {
109 "is-callable": "^1.1.4",
109 "is-callable": "^1.1.4",
110 "is-date-object": "^1.0.1",
110 "is-date-object": "^1.0.1",
111 "is-symbol": "^1.0.2"
111 "is-symbol": "^1.0.2"
112 }
112 }
113 },
113 },
114 "faucet": {
114 "faucet": {
115 "version": "0.0.1",
115 "version": "0.0.1",
116 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
116 "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz",
117 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
117 "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=",
118 "dev": true,
118 "dev": true,
119 "requires": {
119 "requires": {
120 "defined": "0.0.0",
120 "defined": "0.0.0",
121 "duplexer": "~0.1.1",
121 "duplexer": "~0.1.1",
122 "minimist": "0.0.5",
122 "minimist": "0.0.5",
123 "sprintf": "~0.1.3",
123 "sprintf": "~0.1.3",
124 "tap-parser": "~0.4.0",
124 "tap-parser": "~0.4.0",
125 "tape": "~2.3.2",
125 "tape": "~2.3.2",
126 "through2": "~0.2.3"
126 "through2": "~0.2.3"
127 },
127 },
128 "dependencies": {
128 "dependencies": {
129 "tape": {
129 "tape": {
130 "version": "2.3.3",
130 "version": "2.3.3",
131 "resolved": "http://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
131 "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz",
132 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
132 "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
133 "dev": true,
133 "dev": true,
134 "requires": {
134 "requires": {
135 "deep-equal": "~0.1.0",
135 "deep-equal": "~0.1.0",
136 "defined": "~0.0.0",
136 "defined": "~0.0.0",
137 "inherits": "~2.0.1",
137 "inherits": "~2.0.1",
138 "jsonify": "~0.0.0",
138 "jsonify": "~0.0.0",
139 "resumer": "~0.0.0",
139 "resumer": "~0.0.0",
140 "through": "~2.3.4"
140 "through": "~2.3.4"
141 }
141 }
142 }
142 }
143 }
143 }
144 },
144 },
145 "for-each": {
145 "for-each": {
146 "version": "0.3.3",
146 "version": "0.3.3",
147 "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
147 "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
148 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
148 "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
149 "dev": true,
149 "dev": true,
150 "requires": {
150 "requires": {
151 "is-callable": "^1.1.3"
151 "is-callable": "^1.1.3"
152 }
152 }
153 },
153 },
154 "fs.realpath": {
154 "fs.realpath": {
155 "version": "1.0.0",
155 "version": "1.0.0",
156 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
156 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
157 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
157 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
158 "dev": true
158 "dev": true
159 },
159 },
160 "function-bind": {
160 "function-bind": {
161 "version": "1.1.1",
161 "version": "1.1.1",
162 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
162 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
163 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
163 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
164 "dev": true
164 "dev": true
165 },
165 },
166 "glob": {
166 "glob": {
167 "version": "7.1.3",
167 "version": "7.1.3",
168 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
168 "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
169 "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
169 "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
170 "dev": true,
170 "dev": true,
171 "requires": {
171 "requires": {
172 "fs.realpath": "^1.0.0",
172 "fs.realpath": "^1.0.0",
173 "inflight": "^1.0.4",
173 "inflight": "^1.0.4",
174 "inherits": "2",
174 "inherits": "2",
175 "minimatch": "^3.0.4",
175 "minimatch": "^3.0.4",
176 "once": "^1.3.0",
176 "once": "^1.3.0",
177 "path-is-absolute": "^1.0.0"
177 "path-is-absolute": "^1.0.0"
178 }
178 }
179 },
179 },
180 "has": {
180 "has": {
181 "version": "1.0.3",
181 "version": "1.0.3",
182 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
182 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
183 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
183 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
184 "dev": true,
184 "dev": true,
185 "requires": {
185 "requires": {
186 "function-bind": "^1.1.1"
186 "function-bind": "^1.1.1"
187 }
187 }
188 },
188 },
189 "has-symbols": {
189 "has-symbols": {
190 "version": "1.0.0",
190 "version": "1.0.0",
191 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
191 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
192 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
192 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
193 "dev": true
193 "dev": true
194 },
194 },
195 "inflight": {
195 "inflight": {
196 "version": "1.0.6",
196 "version": "1.0.6",
197 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
197 "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
198 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
198 "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
199 "dev": true,
199 "dev": true,
200 "requires": {
200 "requires": {
201 "once": "^1.3.0",
201 "once": "^1.3.0",
202 "wrappy": "1"
202 "wrappy": "1"
203 }
203 }
204 },
204 },
205 "inherits": {
205 "inherits": {
206 "version": "2.0.3",
206 "version": "2.0.3",
207 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
207 "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
208 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
208 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
209 "dev": true
209 "dev": true
210 },
210 },
211 "is-callable": {
211 "is-callable": {
212 "version": "1.1.4",
212 "version": "1.1.4",
213 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
213 "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
214 "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
214 "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
215 "dev": true
215 "dev": true
216 },
216 },
217 "is-date-object": {
217 "is-date-object": {
218 "version": "1.0.1",
218 "version": "1.0.1",
219 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
219 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
220 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
220 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
221 "dev": true
221 "dev": true
222 },
222 },
223 "is-regex": {
223 "is-regex": {
224 "version": "1.0.4",
224 "version": "1.0.4",
225 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
225 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
226 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
226 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
227 "dev": true,
227 "dev": true,
228 "requires": {
228 "requires": {
229 "has": "^1.0.1"
229 "has": "^1.0.1"
230 }
230 }
231 },
231 },
232 "is-symbol": {
232 "is-symbol": {
233 "version": "1.0.2",
233 "version": "1.0.2",
234 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
234 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
235 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
235 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
236 "dev": true,
236 "dev": true,
237 "requires": {
237 "requires": {
238 "has-symbols": "^1.0.0"
238 "has-symbols": "^1.0.0"
239 }
239 }
240 },
240 },
241 "isarray": {
241 "isarray": {
242 "version": "0.0.1",
242 "version": "0.0.1",
243 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
243 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
244 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
244 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
245 "dev": true
245 "dev": true
246 },
246 },
247 "jsonify": {
247 "jsonify": {
248 "version": "0.0.0",
248 "version": "0.0.0",
249 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
249 "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
250 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
250 "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
251 "dev": true
251 "dev": true
252 },
252 },
253 "minimatch": {
253 "minimatch": {
254 "version": "3.0.4",
254 "version": "3.0.4",
255 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
255 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
256 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
256 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
257 "dev": true,
257 "dev": true,
258 "requires": {
258 "requires": {
259 "brace-expansion": "^1.1.7"
259 "brace-expansion": "^1.1.7"
260 }
260 }
261 },
261 },
262 "minimist": {
262 "minimist": {
263 "version": "0.0.5",
263 "version": "0.0.5",
264 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
264 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz",
265 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
265 "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=",
266 "dev": true
266 "dev": true
267 },
267 },
268 "object-inspect": {
268 "object-inspect": {
269 "version": "1.6.0",
269 "version": "1.6.0",
270 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
270 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
271 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
271 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
272 "dev": true
272 "dev": true
273 },
273 },
274 "object-keys": {
274 "object-keys": {
275 "version": "0.4.0",
275 "version": "0.4.0",
276 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
276 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
277 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
277 "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=",
278 "dev": true
278 "dev": true
279 },
279 },
280 "once": {
280 "once": {
281 "version": "1.4.0",
281 "version": "1.4.0",
282 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
282 "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
283 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
283 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
284 "dev": true,
284 "dev": true,
285 "requires": {
285 "requires": {
286 "wrappy": "1"
286 "wrappy": "1"
287 }
287 }
288 },
288 },
289 "path-is-absolute": {
289 "path-is-absolute": {
290 "version": "1.0.1",
290 "version": "1.0.1",
291 "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
291 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
292 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
292 "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
293 "dev": true
293 "dev": true
294 },
294 },
295 "path-parse": {
295 "path-parse": {
296 "version": "1.0.6",
296 "version": "1.0.6",
297 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
297 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
298 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
298 "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
299 "dev": true
299 "dev": true
300 },
300 },
301 "readable-stream": {
301 "readable-stream": {
302 "version": "1.1.14",
302 "version": "1.1.14",
303 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
303 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
304 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
304 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
305 "dev": true,
305 "dev": true,
306 "requires": {
306 "requires": {
307 "core-util-is": "~1.0.0",
307 "core-util-is": "~1.0.0",
308 "inherits": "~2.0.1",
308 "inherits": "~2.0.1",
309 "isarray": "0.0.1",
309 "isarray": "0.0.1",
310 "string_decoder": "~0.10.x"
310 "string_decoder": "~0.10.x"
311 }
311 }
312 },
312 },
313 "requirejs": {
313 "requirejs": {
314 "version": "2.3.6",
314 "version": "2.3.6",
315 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
315 "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz",
316 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
316 "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==",
317 "dev": true
317 "dev": true
318 },
318 },
319 "resolve": {
319 "resolve": {
320 "version": "1.7.1",
320 "version": "1.7.1",
321 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
321 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
322 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
322 "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
323 "dev": true,
323 "dev": true,
324 "requires": {
324 "requires": {
325 "path-parse": "^1.0.5"
325 "path-parse": "^1.0.5"
326 }
326 }
327 },
327 },
328 "resumer": {
328 "resumer": {
329 "version": "0.0.0",
329 "version": "0.0.0",
330 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
330 "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
331 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
331 "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
332 "dev": true,
332 "dev": true,
333 "requires": {
333 "requires": {
334 "through": "~2.3.4"
334 "through": "~2.3.4"
335 }
335 }
336 },
336 },
337 "sprintf": {
337 "sprintf": {
338 "version": "0.1.5",
338 "version": "0.1.5",
339 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
339 "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz",
340 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
340 "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=",
341 "dev": true
341 "dev": true
342 },
342 },
343 "string.prototype.trim": {
343 "string.prototype.trim": {
344 "version": "1.1.2",
344 "version": "1.1.2",
345 "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
345 "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
346 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
346 "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
347 "dev": true,
347 "dev": true,
348 "requires": {
348 "requires": {
349 "define-properties": "^1.1.2",
349 "define-properties": "^1.1.2",
350 "es-abstract": "^1.5.0",
350 "es-abstract": "^1.5.0",
351 "function-bind": "^1.0.2"
351 "function-bind": "^1.0.2"
352 }
352 }
353 },
353 },
354 "string_decoder": {
354 "string_decoder": {
355 "version": "0.10.31",
355 "version": "0.10.31",
356 "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
356 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
357 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
357 "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
358 "dev": true
358 "dev": true
359 },
359 },
360 "tap-parser": {
360 "tap-parser": {
361 "version": "0.4.3",
361 "version": "0.4.3",
362 "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz",
362 "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz",
363 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
363 "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
364 "dev": true,
364 "dev": true,
365 "requires": {
365 "requires": {
366 "inherits": "~2.0.1",
366 "inherits": "~2.0.1",
367 "readable-stream": "~1.1.11"
367 "readable-stream": "~1.1.11"
368 }
368 }
369 },
369 },
370 "tape": {
370 "tape": {
371 "version": "4.9.1",
371 "version": "4.9.1",
372 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
372 "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz",
373 "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==",
373 "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==",
374 "dev": true,
374 "dev": true,
375 "requires": {
375 "requires": {
376 "deep-equal": "~1.0.1",
376 "deep-equal": "~1.0.1",
377 "defined": "~1.0.0",
377 "defined": "~1.0.0",
378 "for-each": "~0.3.3",
378 "for-each": "~0.3.3",
379 "function-bind": "~1.1.1",
379 "function-bind": "~1.1.1",
380 "glob": "~7.1.2",
380 "glob": "~7.1.2",
381 "has": "~1.0.3",
381 "has": "~1.0.3",
382 "inherits": "~2.0.3",
382 "inherits": "~2.0.3",
383 "minimist": "~1.2.0",
383 "minimist": "~1.2.0",
384 "object-inspect": "~1.6.0",
384 "object-inspect": "~1.6.0",
385 "resolve": "~1.7.1",
385 "resolve": "~1.7.1",
386 "resumer": "~0.0.0",
386 "resumer": "~0.0.0",
387 "string.prototype.trim": "~1.1.2",
387 "string.prototype.trim": "~1.1.2",
388 "through": "~2.3.8"
388 "through": "~2.3.8"
389 },
389 },
390 "dependencies": {
390 "dependencies": {
391 "deep-equal": {
391 "deep-equal": {
392 "version": "1.0.1",
392 "version": "1.0.1",
393 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
393 "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
394 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
394 "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
395 "dev": true
395 "dev": true
396 },
396 },
397 "defined": {
397 "defined": {
398 "version": "1.0.0",
398 "version": "1.0.0",
399 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
399 "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
400 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
400 "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
401 "dev": true
401 "dev": true
402 },
402 },
403 "minimist": {
403 "minimist": {
404 "version": "1.2.0",
404 "version": "1.2.0",
405 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
405 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
406 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
406 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
407 "dev": true
407 "dev": true
408 }
408 }
409 }
409 }
410 },
410 },
411 "through": {
411 "through": {
412 "version": "2.3.8",
412 "version": "2.3.8",
413 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
413 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
414 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
414 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
415 "dev": true
415 "dev": true
416 },
416 },
417 "through2": {
417 "through2": {
418 "version": "0.2.3",
418 "version": "0.2.3",
419 "resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
419 "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
420 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
420 "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
421 "dev": true,
421 "dev": true,
422 "requires": {
422 "requires": {
423 "readable-stream": "~1.1.9",
423 "readable-stream": "~1.1.9",
424 "xtend": "~2.1.1"
424 "xtend": "~2.1.1"
425 }
425 }
426 },
426 },
427 "typescript": {
427 "typescript": {
428 "version": "3.2.1",
428 "version": "3.2.1",
429 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.1.tgz",
429 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.1.tgz",
430 "integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==",
430 "integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==",
431 "dev": true
431 "dev": true
432 },
432 },
433 "wrappy": {
433 "wrappy": {
434 "version": "1.0.2",
434 "version": "1.0.2",
435 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
435 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
436 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
436 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
437 "dev": true
437 "dev": true
438 },
438 },
439 "xtend": {
439 "xtend": {
440 "version": "2.1.2",
440 "version": "2.1.2",
441 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
441 "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
442 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
442 "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
443 "dev": true,
443 "dev": true,
444 "requires": {
444 "requires": {
445 "object-keys": "~0.4.0"
445 "object-keys": "~0.4.0"
446 }
446 }
447 }
447 }
448 }
448 }
449 }
449 }
@@ -1,134 +1,132
1 import { TraceSource } from "../log/TraceSource";
1 import { TraceSource } from "../log/TraceSource";
2 import { argumentNotNull, argumentNotEmptyString, isPrimitive, each, isNull } from "../safe";
2 import { argumentNotNull, argumentNotEmptyString, isPrimitive, each, isNull } from "../safe";
3 import { Descriptor, ServiceMap, isDescriptor } from "./interfaces";
3 import { Descriptor, ServiceMap, isDescriptor } from "./interfaces";
4 import { Container } from "./Container";
4 import { Container } from "./Container";
5
5
6 const trace = TraceSource.get("@implab/core/di/ActivationContext");
6 const trace = TraceSource.get("@implab/core/di/ActivationContext");
7
7
8 export interface ActivationContextInfo {
8 export interface ActivationContextInfo {
9 name: string;
9 name: string;
10
10
11 service: Descriptor;
11 service: string;
12
12
13 scope: ServiceMap;
13 scope: ServiceMap;
14 }
14 }
15
15
16 export class ActivationContext {
16 export class ActivationContext {
17 _cache: object;
17 _cache: object;
18
18
19 _services: ServiceMap;
19 _services: ServiceMap;
20
20
21 _stack: ActivationContextInfo[];
21 _stack: ActivationContextInfo[];
22
22
23 _visited: object;
23 _visited: object;
24
24
25 _name: string;
26
27 _localized: boolean;
28
25 container: Container;
29 container: Container;
26
30
27 constructor(container: Container, services: ServiceMap, cache?: object, visited?) {
31 constructor(container: Container, services: ServiceMap, name?: string, cache?: object, visited?) {
28 argumentNotNull(container, "container");
32 argumentNotNull(container, "container");
29 argumentNotNull(services, "services");
33 argumentNotNull(services, "services");
30
34
35 this._name = name;
31 this._visited = visited || {};
36 this._visited = visited || {};
32 this._stack = [];
37 this._stack = [];
33 this._cache = cache || {};
38 this._cache = cache || {};
34 this._services = services;
39 this._services = services;
35 this.container = container;
40 this.container = container;
36 }
41 }
37
42
38 getService(name, def?): any {
43 getName() {
44 return this._name;
45 }
46
47 resolve(name, def?): any {
39 const d = this._services[name];
48 const d = this._services[name];
40
49
41 if (!d)
50 if (!d)
42 if (arguments.length > 1)
51 if (arguments.length > 1)
43 return def;
52 return def;
44 else
53 else
45 throw new Error(`Service ${name} not found`);
54 throw new Error(`Service ${name} not found`);
46
55
47 return isDescriptor(d) ? d.activate(this, name) : d;
56 return this.activate(d, name);
48 }
57 }
49
58
50 /**
59 /**
51 * registers services local to the the activation context
60 * registers services local to the the activation context
52 *
61 *
53 * @name{string} the name of the service
62 * @name{string} the name of the service
54 * @service{string} the service descriptor to register
63 * @service{string} the service descriptor to register
55 */
64 */
56 register(name: string, service: Descriptor) {
65 register(name: string, service: Descriptor) {
57 argumentNotEmptyString(name, "name");
66 argumentNotEmptyString(name, "name");
58
67
59 this._services[name] = service;
68 this._services[name] = service;
60 }
69 }
61
70
62 clone() {
71 clone() {
63 return new ActivationContext(
72 return new ActivationContext(
64 this.container,
73 this.container,
65 Object.create(this._services),
74 this._services,
75 this._name,
66 this._cache,
76 this._cache,
67 this._visited
77 this._visited
68 );
78 );
69 }
79 }
70
80
71 has(id: string) {
81 has(id: string) {
72 return id in this._cache;
82 return id in this._cache;
73 }
83 }
74
84
75 get(id: string) {
85 get(id: string) {
76 return this._cache[id];
86 return this._cache[id];
77 }
87 }
78
88
79 store(id: string, value) {
89 store(id: string, value) {
80 return (this._cache[id] = value);
90 return (this._cache[id] = value);
81 }
91 }
82
92
83 parse(data, name: string) {
93 activate(d: Descriptor, name: string) {
84 if (isPrimitive(data))
94 if (trace.isLogEnabled())
85 return data;
95 trace.log(`enter ${name} ${d}`);
86
96
87 if (isDescriptor(data)) {
97 this.enter(name, d.toString());
88 return data.activate(this, name);
98 const v = d.activate(this);
89 } else if (data instanceof Array) {
99 this.leave();
90 this.enter(name);
100
91 const v = data.map( (x, i) => this.parse(x, `[${i}]`));
101 if (trace.isLogEnabled())
92 this.leave();
102 trace.log(`leave ${name}`);
93 return v;
103
94 } else {
104 return v;
95 this.enter(name);
96 const result = {};
97 for (const p in data)
98 result[p] = this.parse(data[p], "." + p);
99 this.leave();
100 return result;
101 }
102 }
105 }
103
106
104 visit(id: string) {
107 visit(id: string) {
105 const count = this._visited[id] || 0;
108 const count = this._visited[id] || 0;
106 this._visited[id] = count + 1;
109 this._visited[id] = count + 1;
107 return count;
110 return count;
108 }
111 }
109
112
110 getStack() {
113 getStack() {
111 return this._stack.slice().reverse();
114 return this._stack.slice().reverse();
112 }
115 }
113
116
114 enter(name: string, d?: Descriptor, localize?: boolean) {
117 private enter(name: string, service: string) {
115 if (trace.isLogEnabled())
116 trace.log("enter " + name + " " + (d || "") +
117 (localize ? " localize" : ""));
118 this._stack.push({
118 this._stack.push({
119 name,
119 name,
120 service: d,
120 service,
121 scope: this._services
121 scope: this._services
122 });
122 });
123 if (localize)
123 this._name = name;
124 this._services = Object.create(this._services);
124 this._services = Object.create(this._services);
125 }
125 }
126
126
127 leave() {
127 private leave() {
128 const ctx = this._stack.pop();
128 const ctx = this._stack.pop();
129 this._services = ctx.scope;
129 this._services = ctx.scope;
130
130 this._name = ctx.name;
131 if (trace.isLogEnabled())
132 trace.log("leave " + ctx.name + " " + (ctx.service || ""));
133 }
131 }
134 }
132 }
@@ -1,36 +1,36
1 import { ActivationContextInfo } from "./ActivationContext";
1 import { ActivationContextInfo } from "./ActivationContext";
2
2
3 export class ActivationError {
3 export class ActivationError {
4 activationStack: ActivationContextInfo[];
4 activationStack: ActivationContextInfo[];
5
5
6 service: string;
6 service: string;
7
7
8 innerException: any;
8 innerException: any;
9
9
10 message: string;
10 message: string;
11
11
12 constructor(service: string, activationStack: ActivationContextInfo[], innerException) {
12 constructor(service: string, activationStack: ActivationContextInfo[], innerException) {
13 this.message = "Failed to activate the service";
13 this.message = "Failed to activate the service";
14 this.activationStack = activationStack;
14 this.activationStack = activationStack;
15 this.service = service;
15 this.service = service;
16 this.innerException = innerException;
16 this.innerException = innerException;
17 }
17 }
18
18
19 toString() {
19 toString() {
20 const parts = [this.message];
20 const parts = [this.message];
21 if (this.service)
21 if (this.service)
22 parts.push("when activating: " + this.service.toString());
22 parts.push("when activating: " + this.service.toString());
23
23
24 if (this.innerException)
24 if (this.innerException)
25 parts.push("caused by: " + this.innerException.toString());
25 parts.push("caused by: " + this.innerException.toString());
26
26
27 if (this.activationStack) {
27 if (this.activationStack) {
28 parts.push("at");
28 parts.push("at");
29 this.activationStack
29 this.activationStack
30 .forEach(x => parts.push(` ${x.name} ${x.service ? x.service.toString() : ""}`));
30 .forEach(x => parts.push(` ${x.name} ${x.service}`));
31
31
32 }
32 }
33
33
34 return parts.join("\n");
34 return parts.join("\n");
35 }
35 }
36 }
36 }
@@ -1,24 +1,37
1 import { Descriptor } from "./interfaces";
1 import { Descriptor, isDescriptor } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { isPrimitive } from "util";
3
4
4 export class AggregateDescriptor implements Descriptor {
5 export class AggregateDescriptor implements Descriptor {
5 _value: object;
6 _value: object;
6
7
7 constructor(value: object) {
8 constructor(value: object) {
8 this._value = value;
9 this._value = value;
9 }
10 }
10
11
11 activate(context: ActivationContext, name: string) {
12 activate(context: ActivationContext) {
12 context.enter(name);
13 return this._parse(this._value, context, "$value");
13 const v = context.parse(this._value, ".params");
14 context.leave();
15 return v;
16 }
14 }
17
15
18 isInstanceCreated(): boolean {
16 // TODO: make async
19 return false;
17 _parse(value, context: ActivationContext, path: string) {
18 if (isPrimitive(value))
19 return value;
20
21 if (isDescriptor(value))
22 return context.activate(value, path);
23
24 if (value instanceof Array)
25 return value.map((x, i) => this._parse(x, context, `${path}[${i}]`));
26
27 const t = {};
28 for (const p of Object.keys(value))
29 t[p] = this._parse(value[p], context, `${path}.${p}`);
30 return t;
31
20 }
32 }
21 getInstance(): any {
33
22 throw new Error("Not supported");
34 toString() {
35 return "@walk";
23 }
36 }
24 }
37 }
@@ -1,260 +1,279
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { ValueDescriptor } from "./ValueDescriptor";
2 import { ValueDescriptor } from "./ValueDescriptor";
3 import { ActivationError } from "./ActivationError";
3 import { ActivationError } from "./ActivationError";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration } from "./interfaces";
4 import { isDescriptor, ActivationType, ServiceMap, isDependencyRegistration, isValueRegistration, ServiceRegistration, DependencyRegistration } from "./interfaces";
5 import { AggregateDescriptor } from "./AggregateDescriptor";
5 import { AggregateDescriptor } from "./AggregateDescriptor";
6 import { isPrimitive } from "../safe";
6 import { isPrimitive, pmap } from "../safe";
7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
7 import { ReferenceDescriptor } from "./ReferenceDescriptor";
8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
8 import { ServiceDescriptor, ServiceDescriptorParams } from "./ServiceDescriptor";
9 import { ModuleResolverBase } from "./ModuleResolverBase";
9 import { ModuleResolverBase } from "./ModuleResolverBase";
10 import format = require("../text/format");
10 import format = require("../text/format");
11 import { throws } from "assert";
11
12
12 export class Container {
13 export class Container {
13 _services: ServiceMap;
14 _services: ServiceMap;
14
15
15 _cache: object;
16 _cache: object;
16
17
17 _cleanup: (() => void)[];
18 _cleanup: (() => void)[];
18
19
19 _root: Container;
20 _root: Container;
20
21
21 _parent: Container;
22 _parent: Container;
22
23
23 _resolver: ModuleResolverBase;
24 _resolver: ModuleResolverBase;
24
25
25 constructor(parent?: Container) {
26 constructor(parent?: Container) {
26 this._parent = parent;
27 this._parent = parent;
27 this._services = parent ? Object.create(parent._services) : {};
28 this._services = parent ? Object.create(parent._services) : {};
28 this._cache = {};
29 this._cache = {};
29 this._cleanup = [];
30 this._cleanup = [];
30 this._root = parent ? parent.getRootContainer() : this;
31 this._root = parent ? parent.getRootContainer() : this;
31 this._services.container = new ValueDescriptor(this);
32 this._services.container = new ValueDescriptor(this);
32 }
33 }
33
34
34 getRootContainer() {
35 getRootContainer() {
35 return this._root;
36 return this._root;
36 }
37 }
37
38
38 getParent() {
39 getParent() {
39 return this._parent;
40 return this._parent;
40 }
41 }
41
42
42 getService(name: string, def?) {
43 resolve(name: string, def?) {
43 const d = this._services[name];
44 const d = this._services[name];
44 if (!d)
45 if (d === undefined) {
45 if (arguments.length > 1)
46 if (arguments.length > 1)
46 return def;
47 return def;
47 else
48 else
48 throw new Error("Service '" + name + "' isn't found");
49 throw new Error("Service '" + name + "' isn't found");
49
50 }
50 if (!isDescriptor(d))
51 return d;
52
53 if (d.isInstanceCreated())
54 return d.getInstance();
55
51
56 const context = new ActivationContext(this, this._services);
52 const context = new ActivationContext(this, this._services);
57
58 try {
53 try {
59 return d.activate(context, name);
54 return context.activate(d, name);
60 } catch (error) {
55 } catch (error) {
61 throw new ActivationError(name, context.getStack(), error);
56 throw new ActivationError(name, context.getStack(), error);
62 }
57 }
63 }
58 }
64
59
60 getService(name: string, def?) {
61 return this.resolve.apply(this, arguments);
62 }
63
65 register(nameOrCollection, service?) {
64 register(nameOrCollection, service?) {
66 if (arguments.length === 1) {
65 if (arguments.length === 1) {
67 const data = nameOrCollection;
66 const data = nameOrCollection;
68 for (const name in data)
67 for (const name in data)
69 this.register(name, data[name]);
68 this.register(name, data[name]);
70 } else {
69 } else {
70 if (!isDescriptor(service))
71 throw new Error("The service parameter must be a descriptor");
72
71 this._services[nameOrCollection] = service;
73 this._services[nameOrCollection] = service;
72 }
74 }
73 return this;
75 return this;
74 }
76 }
75
77
76 onDispose(callback) {
78 onDispose(callback) {
77 if (!(callback instanceof Function))
79 if (!(callback instanceof Function))
78 throw new Error("The callback must be a function");
80 throw new Error("The callback must be a function");
79 this._cleanup.push(callback);
81 this._cleanup.push(callback);
80 }
82 }
81
83
82 dispose() {
84 dispose() {
83 if (this._cleanup) {
85 if (this._cleanup) {
84 for (const f of this._cleanup)
86 for (const f of this._cleanup)
85 f();
87 f();
86 this._cleanup = null;
88 this._cleanup = null;
87 }
89 }
88 }
90 }
89
91
90 /**
92 /**
91 * @param{String|Object} config
93 * @param{String|Object} config
92 * The configuration of the contaier. Can be either a string or an object,
94 * The configuration of the contaier. Can be either a string or an object,
93 * if the configuration is an object it's treated as a collection of
95 * if the configuration is an object it's treated as a collection of
94 * services which will be registed in the contaier.
96 * services which will be registed in the contaier.
95 *
97 *
96 * @param{Function} opts.contextRequire
98 * @param{Function} opts.contextRequire
97 * The function which will be used to load a configuration or types for services.
99 * The function which will be used to load a configuration or types for services.
98 *
100 *
99 */
101 */
100 async configure(config: string | object, opts?: object) {
102 async configure(config: string | object, opts?: object) {
101 if (typeof (config) === "string") {
103 if (typeof (config) === "string") {
102 const resolver = await this._resolver.createResolver(config, opts);
104 const resolver = await this._resolver.createResolver(config, opts);
103 const data = await this._resolver.loadModule(config);
105 const data = await this._resolver.loadModule(config);
104 return this._configure(data, { resolver });
106 return this._configure(data, { resolver });
105 } else {
107 } else {
106 return this._configure(config);
108 return this._configure(config);
107 }
109 }
108 }
110 }
109
111
110 createChildContainer() {
112 createChildContainer() {
111 return new Container(this);
113 return new Container(this);
112 }
114 }
113
115
114 has(id) {
116 has(id) {
115 return id in this._cache;
117 return id in this._cache;
116 }
118 }
117
119
118 get(id) {
120 get(id) {
119 return this._cache[id];
121 return this._cache[id];
120 }
122 }
121
123
122 store(id, value) {
124 store(id, value) {
123 return (this._cache[id] = value);
125 return (this._cache[id] = value);
124 }
126 }
125
127
126 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
128 async _configure(data: object, opts?: { resolver: ModuleResolverBase }) {
127 const resolver = (opts && opts.resolver) || this._resolver;
129 const resolver = (opts && opts.resolver) || this._resolver;
128
130
129 const services: ServiceMap = {};
131 const services = await this._parseRegistrations(data, resolver);
130
131 resolver.beginBatch();
132
133 async function parse(k) {
134 services[k] = await this._parse(data[k], resolver);
135 }
136
137 const batch = Object.keys(data).map(parse);
138
139 resolver.completeBatch();
140
141 await Promise.all(batch);
142
132
143 this.register(services);
133 this.register(services);
144 }
134 }
145
135
146 async _parse(registration: any, resolver: ModuleResolverBase) {
136 async _parse(registration: any, resolver: ModuleResolverBase) {
147 if (isPrimitive(registration) || isDescriptor(registration))
137 if (isPrimitive(registration) || isDescriptor(registration))
148 return registration;
138 return registration;
149
139
150 if (isDependencyRegistration(registration)) {
140 if (isDependencyRegistration(registration)) {
151
141 return this._paseReference(registration, resolver);
152 return new ReferenceDescriptor({
153 name: registration.$dependency,
154 lazy: registration.lazy,
155 optional: registration.optional,
156 default: registration.default,
157 services: registration.services && this._parseObject(registration.services, resolver)
158 });
159
160 } else if (isValueRegistration(registration)) {
142 } else if (isValueRegistration(registration)) {
161
162 return !registration.parse ?
143 return !registration.parse ?
163 new ValueDescriptor(registration.$value) :
144 new ValueDescriptor(registration.$value) :
164 new AggregateDescriptor(this._parse(registration.$value, resolver));
145 new AggregateDescriptor(this._parse(registration.$value, resolver));
165
146
166 } else if (registration.$type || registration.$factory) {
147 } else if (registration.$type || registration.$factory) {
167 return this._parseService(registration, resolver);
148 return this._parseService(registration, resolver);
168 } else if (registration instanceof Array) {
149 } else if (registration instanceof Array) {
169 return this._parseArray(registration, resolver);
150 return this._parseArray(registration, resolver);
170 }
151 }
171
152
172 return this._parseObject(registration, resolver);
153 return this._parseObject(registration, resolver);
173 }
154 }
174
155
156 async _paseReference(registration: DependencyRegistration, resolver: ModuleResolverBase) {
157 return new ReferenceDescriptor({
158 name: registration.$dependency,
159 lazy: registration.lazy,
160 optional: registration.optional,
161 default: registration.default,
162 services: registration.services && await this._parseRegistrations(registration.services, resolver)
163 });
164 }
165
175 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
166 async _parseService(data: ServiceRegistration, resolver: ModuleResolverBase) {
176 const opts: ServiceDescriptorParams = {
167 const opts: ServiceDescriptorParams = {
177 owner: this
168 owner: this
178 };
169 };
179
170
180 if (data.$type) {
171 if (data.$type) {
181 if (data.$type instanceof Function)
172 if (data.$type instanceof Function)
182 opts.type = data.$type;
173 opts.type = data.$type;
183 else if (typeof data.$type === "string")
174 else if (typeof data.$type === "string")
184 opts.type = await resolver.resolve(data.$type);
175 opts.type = await resolver.resolve(data.$type);
185 else
176 else
186 throw new Error(format("Unsupported type specification: {0:json}", data.$type));
177 throw new Error(format("Unsupported type specification: {0:json}", data.$type));
187 } else {
178 } else {
188 if (data.$factory instanceof Function)
179 if (data.$factory instanceof Function)
189 opts.factory = data.$factory;
180 opts.factory = data.$factory;
190 else if (typeof data.$factory === "string")
181 else if (typeof data.$factory === "string")
191 opts.factory = await resolver.resolve(data.$factory);
182 opts.factory = await resolver.resolve(data.$factory);
192 else
183 else
193 throw new Error(format("Unsupported factory specification: {0:json}", data.$factory));
184 throw new Error(format("Unsupported factory specification: {0:json}", data.$factory));
194 }
185 }
195
186
196 if (data.services)
187 if (data.services)
197 opts.services = await this._parseObject(data.services, resolver);
188 opts.services = await this._parseRegistrations(data.services, resolver);
198
189
199 if (data.inject instanceof Array)
190 if (data.inject) {
200 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
191 if (data.inject instanceof Array)
201 else
192 opts.inject = await Promise.all(data.inject.map(x => this._parseObject(x, resolver)));
202 opts.inject = [await this._parseObject(data.inject, resolver)];
193 else
194 opts.inject = [await this._parseObject(data.inject, resolver)];
195 }
203
196
204 if (data.params)
197 if (data.params)
205 opts.params = this._parse(data.params, resolver);
198 opts.params = this._parse(data.params, resolver);
206
199
207 if (data.activation) {
200 if (data.activation) {
208 if (typeof (data.activation) === "string") {
201 if (typeof (data.activation) === "string") {
209 switch (data.activation.toLowerCase()) {
202 switch (data.activation.toLowerCase()) {
210 case "singleton":
203 case "singleton":
211 opts.activation = ActivationType.Singleton;
204 opts.activation = ActivationType.Singleton;
212 break;
205 break;
213 case "container":
206 case "container":
214 opts.activation = ActivationType.Container;
207 opts.activation = ActivationType.Container;
215 break;
208 break;
216 case "hierarchy":
209 case "hierarchy":
217 opts.activation = ActivationType.Hierarchy;
210 opts.activation = ActivationType.Hierarchy;
218 break;
211 break;
219 case "context":
212 case "context":
220 opts.activation = ActivationType.Context;
213 opts.activation = ActivationType.Context;
221 break;
214 break;
222 case "call":
215 case "call":
223 opts.activation = ActivationType.Call;
216 opts.activation = ActivationType.Call;
224 break;
217 break;
225 default:
218 default:
226 throw new Error("Unknown activation type: " +
219 throw new Error("Unknown activation type: " +
227 data.activation);
220 data.activation);
228 }
221 }
229 } else {
222 } else {
230 opts.activation = Number(data.activation);
223 opts.activation = Number(data.activation);
231 }
224 }
232 }
225 }
233
226
234 if (data.cleanup)
227 if (data.cleanup)
235 opts.cleanup = data.cleanup;
228 opts.cleanup = data.cleanup;
236
229
237 return new ServiceDescriptor(opts);
230 return new ServiceDescriptor(opts);
238 }
231 }
239
232
240 _parseObject(data: object, resolver: ModuleResolverBase) {
233 async _parseObject(data: object, resolver: ModuleResolverBase) {
241 if (data.constructor &&
234 if (data.constructor &&
242 data.constructor.prototype !== Object.prototype)
235 data.constructor.prototype !== Object.prototype)
243 return new ValueDescriptor(data);
236 return new ValueDescriptor(data);
244
237
245 const o = {};
238 const o = {};
246
239
247 for (const p in data)
240 for (const p in data)
248 o[p] = this._parse(data[p], resolver);
241 o[p] = await this._parse(data[p], resolver);
242
243 // TODO: handle inline descriptors properly
244 // const ex = {
245 // activate(ctx) {
246 // const value = ctx.activate(this.prop, "prop");
247 // // some code
248 // },
249
250 // // will be turned to ReferenceDescriptor
251 // prop: { $dependency: "depName" }
252 // };
249
253
250 return o;
254 return o;
251 }
255 }
252
256
253 _parseArray(data: Array<any>, resolver: ModuleResolverBase) {
257 async _parseArray(data: Array<any>, resolver: ModuleResolverBase) {
254 if (data.constructor &&
258 if (data.constructor &&
255 data.constructor.prototype !== Array.prototype)
259 data.constructor.prototype !== Array.prototype)
256 return new ValueDescriptor(data);
260 return new ValueDescriptor(data);
257
261
258 return data.map(x => this._parse(x, resolver));
262 return pmap(data, x => this._parse(x, resolver));
263 }
264
265 async _parseRegistrations(data: object, resolver: ModuleResolverBase) {
266 if (data.constructor &&
267 data.constructor.prototype !== Object.prototype)
268 throw new Error("Registrations must be a simple object");
269
270 const o: ServiceMap = {};
271
272 for (const p of Object.keys(data)) {
273 const v = await this._parse(data[p], resolver);
274 o[p] = isDescriptor(v) ? v : new AggregateDescriptor(v);
275 }
276
277 return o;
259 }
278 }
260 }
279 }
@@ -1,114 +1,100
1 import { isNull, argumentNotEmptyString, each } from "../safe";
1 import { isNull, argumentNotEmptyString, each } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { ServiceMap, Descriptor } from "./interfaces";
3 import { ServiceMap, Descriptor } from "./interfaces";
4 import { ActivationError } from "./ActivationError";
4 import { ActivationError } from "./ActivationError";
5
5
6 export interface ReferenceDescriptorParams {
6 export interface ReferenceDescriptorParams {
7 name: string;
7 name: string;
8 lazy?: boolean;
8 lazy?: boolean;
9 optional?: boolean;
9 optional?: boolean;
10 default?;
10 default?;
11 services?: ServiceMap;
11 services?: ServiceMap;
12 }
12 }
13
13
14 export class ReferenceDescriptor implements Descriptor {
14 export class ReferenceDescriptor implements Descriptor {
15 _name: string;
15 _name: string;
16
16
17 _lazy = false;
17 _lazy = false;
18
18
19 _optional = false;
19 _optional = false;
20
20
21 _default: any;
21 _default: any;
22
22
23 _services: ServiceMap;
23 _services: ServiceMap;
24
24
25 constructor(opts: ReferenceDescriptorParams) {
25 constructor(opts: ReferenceDescriptorParams) {
26 argumentNotEmptyString(opts && opts.name, "opts.name");
26 argumentNotEmptyString(opts && opts.name, "opts.name");
27 this._name = opts.name;
27 this._name = opts.name;
28 this._lazy = !!opts.lazy;
28 this._lazy = !!opts.lazy;
29 this._optional = !!opts.optional;
29 this._optional = !!opts.optional;
30 this._default = !!opts.default;
30 this._default = opts.default;
31 this._services = opts.services;
31 this._services = opts.services;
32 }
32 }
33
33
34 activate(context: ActivationContext, name: string) {
34 activate(context: ActivationContext, name: string) {
35 // добавляем сервисы
36 if (this._services) {
37 for (const p of Object.keys(this._services))
38 context.register(p, this._services[p]);
39 }
35
40
36 if (this._lazy) {
41 if (this._lazy) {
37 // сохраняем контекст активации
42 const saved = context.clone();
38 context = context.clone();
39
40 // добавляем сервисы
41 if (this._services) {
42 for (const p of Object.keys(this._services))
43 context.register(p, this._services[p]);
44 }
45
43
46 return (cfg: ServiceMap) => {
44 return (cfg: ServiceMap) => {
47 // защищаем контекст на случай исключения в процессе
45 // защищаем контекст на случай исключения в процессе
48 // активации
46 // активации
49 const ct = context.clone();
47 const ct = saved.clone();
50 try {
48 try {
51 if (cfg) {
49 if (cfg) {
52 for (const k in cfg)
50 for (const k in cfg)
53 ct.register(k, cfg[k]);
51 ct.register(k, cfg[k]);
54 }
52 }
55
53
56 return this._optional ? ct.getService(this._name, this._default) : ct
54 return this._optional ? ct.resolve(this._name, this._default) : ct
57 .getService(this._name);
55 .resolve(this._name);
58 } catch (error) {
56 } catch (error) {
59 throw new ActivationError(this._name, ct.getStack(), error);
57 throw new ActivationError(this._name, ct.getStack(), error);
60 }
58 }
61 };
59 };
62 } else {
60 } else {
63 context.enter(name, this, !!this._services);
64
65 // добавляем сервисы
61 // добавляем сервисы
66 if (this._services) {
62 if (this._services) {
67 for (const p of Object.keys(this._services))
63 for (const p of Object.keys(this._services))
68 context.register(p, this._services[p]);
64 context.register(p, this._services[p]);
69 }
65 }
70
66
71 const v = this._optional ?
67 const v = this._optional ?
72 context.getService(this._name, this._default) :
68 context.resolve(this._name, this._default) :
73 context.getService(this._name);
69 context.resolve(this._name);
74
75 context.leave();
76
70
77 return v;
71 return v;
78 }
72 }
79 }
73 }
80
74
81 isInstanceCreated() {
82 return false;
83 }
84
85 getInstance() {
86 throw new Error("The reference descriptor doesn't allowed to hold an instance");
87 }
88
89 toString() {
75 toString() {
90 const opts = [];
76 const opts = [];
91 if (this._optional)
77 if (this._optional)
92 opts.push("optional");
78 opts.push("optional");
93 if (this._lazy)
79 if (this._lazy)
94 opts.push("lazy");
80 opts.push("lazy");
95
81
96 const parts = [
82 const parts = [
97 "@ref "
83 "@ref "
98 ];
84 ];
99 if (opts.length) {
85 if (opts.length) {
100 parts.push("{");
86 parts.push("{");
101 parts.push(opts.join());
87 parts.push(opts.join());
102 parts.push("} ");
88 parts.push("} ");
103 }
89 }
104
90
105 parts.push(this._name);
91 parts.push(this._name);
106
92
107 if (!isNull(this._default)) {
93 if (!isNull(this._default)) {
108 parts.push(" = ");
94 parts.push(" = ");
109 parts.push(this._default);
95 parts.push(this._default);
110 }
96 }
111
97
112 return parts.join("");
98 return parts.join("");
113 }
99 }
114 }
100 }
@@ -1,273 +1,286
1 import { ActivationContext } from "./ActivationContext";
1 import { ActivationContext } from "./ActivationContext";
2 import { Descriptor, ActivationType, ServiceMap } from "./interfaces";
2 import { Descriptor, ActivationType, ServiceMap, isDescriptor } from "./interfaces";
3 import { Container } from "./Container";
3 import { Container } from "./Container";
4 import { argumentNotNull, isPrimitive, oid, isPromise } from "../safe";
4 import { argumentNotNull, isPrimitive, oid, isPromise } from "../safe";
5 import { Constructor, Factory } from "../interfaces";
5 import { Constructor, Factory } from "../interfaces";
6 import { TraceSource } from "../log/TraceSource";
6
7
7 let cacheId = 0;
8 let cacheId = 0;
8
9
10 const trace = TraceSource.get("@implab/core/di/ActivationContext");
11
9 function injectMethod(target, method, context, args) {
12 function injectMethod(target, method, context, args) {
10 const m = target[method];
13 const m = target[method];
11 if (!m)
14 if (!m)
12 throw new Error("Method '" + method + "' not found");
15 throw new Error("Method '" + method + "' not found");
13
16
14 if (args instanceof Array)
17 if (args instanceof Array)
15 return m.apply(target, context.parse(args, "." + method));
18 return m.apply(target, context.parse(args, "." + method));
16 else
19 else
17 return m.call(target, context.parse(args, "." + method));
20 return m.call(target, context.parse(args, "." + method));
18 }
21 }
19
22
20 function makeClenupCallback(target, method: ((instance) => void) | string) {
23 function makeClenupCallback(target, method: ((instance) => void) | string) {
21 if (typeof (method) === "string") {
24 if (typeof (method) === "string") {
22 return () => {
25 return () => {
23 target[method]();
26 target[method]();
24 };
27 };
25 } else {
28 } else {
26 return () => {
29 return () => {
27 method(target);
30 method(target);
28 };
31 };
29 }
32 }
30 }
33 }
31
34
35 // TODO: make async
36 function _parse(value, context: ActivationContext, path: string) {
37 if (isPrimitive(value))
38 return value;
39
40 if (isDescriptor(value))
41 return context.activate(value, path);
42
43 if (value instanceof Array)
44 return value.map((x, i) => this._parse(x, context, `${path}[${i}]`));
45
46 const t = {};
47 for (const p of Object.keys(value))
48 t[p] = this._parse(value[p], context, `${path}.${p}`);
49 return t;
50
51 }
52
32 export interface ServiceDescriptorParams {
53 export interface ServiceDescriptorParams {
33 activation?: ActivationType;
54 activation?: ActivationType;
34
55
35 owner: Container;
56 owner: Container;
36
57
37 type?: Constructor;
58 type?: Constructor;
38
59
39 factory?: Factory;
60 factory?: Factory;
40
61
41 params?;
62 params?;
42
63
43 inject?: object[];
64 inject?: object[];
44
65
45 services?: ServiceMap;
66 services?: ServiceMap;
46
67
47 cleanup?: ((x) => void) | string;
68 cleanup?: ((x) => void) | string;
48 }
69 }
49
70
50 export class ServiceDescriptor implements Descriptor {
71 export class ServiceDescriptor implements Descriptor {
51 _instance;
72 _instance;
52
73
53 _hasInstance = false;
74 _hasInstance = false;
54
75
55 _activationType = ActivationType.Call;
76 _activationType = ActivationType.Call;
56
77
57 _services: ServiceMap;
78 _services: ServiceMap;
58
79
59 _type: Constructor = null;
80 _type: Constructor = null;
60
81
61 _factory: Factory = null;
82 _factory: Factory = null;
62
83
63 _params;
84 _params;
64
85
65 _inject: object[];
86 _inject: object[];
66
87
67 _cleanup: ((x) => void) | string;
88 _cleanup: ((x) => void) | string;
68
89
69 _cacheId: any;
90 _cacheId: any;
70
91
71 _owner: Container;
92 _owner: Container;
72
93
73 constructor(opts: ServiceDescriptorParams) {
94 constructor(opts: ServiceDescriptorParams) {
74 argumentNotNull(opts, "opts");
95 argumentNotNull(opts, "opts");
75 argumentNotNull(opts.owner, "owner");
96 argumentNotNull(opts.owner, "owner");
76
97
77 this._owner = opts.owner;
98 this._owner = opts.owner;
78
99
79 if (!(opts.type || opts.factory))
100 if (!(opts.type || opts.factory))
80 throw new Error(
101 throw new Error(
81 "Either a type or a factory must be specified");
102 "Either a type or a factory must be specified");
82
103
83 if (opts.activation)
104 if (opts.activation)
84 this._activationType = opts.activation;
105 this._activationType = opts.activation;
85
106
86 if (opts.type)
107 if (opts.type)
87 this._type = opts.type;
108 this._type = opts.type;
88
109
89 if (opts.params)
110 if (opts.params)
90 this._params = opts.params;
111 this._params = opts.params;
91
112
92 if (opts.inject)
113 if (opts.inject)
93 this._inject = opts.inject;
114 this._inject = opts.inject;
94
115
95 if (opts.services)
116 if (opts.services)
96 this._services = opts.services;
117 this._services = opts.services;
97
118
98 if (opts.factory)
119 if (opts.factory)
99 this._factory = opts.factory;
120 this._factory = opts.factory;
100
121
101 if (opts.cleanup) {
122 if (opts.cleanup) {
102 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
123 if (!(typeof (opts.cleanup) === "string" || opts.cleanup instanceof Function))
103 throw new Error(
124 throw new Error(
104 "The cleanup parameter must be either a function or a function name");
125 "The cleanup parameter must be either a function or a function name");
105
126
106 this._cleanup = opts.cleanup;
127 this._cleanup = opts.cleanup;
107 }
128 }
108
129
109 if (this._activationType === ActivationType.Singleton) {
130 if (this._activationType === ActivationType.Singleton) {
110 const tof = this._type || this._factory;
131 const tof = this._type || this._factory;
111
132
112 // create the persistent cache identifier for the type
133 // create the persistent cache identifier for the type
113 if (isPrimitive(tof))
134 if (isPrimitive(tof))
114 this._cacheId = tof;
135 this._cacheId = tof;
115 else
136 else
116 this._cacheId = oid(tof);
137 this._cacheId = oid(tof);
117 } else {
138 } else {
118 this._cacheId = ++cacheId;
139 this._cacheId = ++cacheId;
119 }
140 }
120 }
141 }
121
142
122 activate(context: ActivationContext, name: string) {
143 activate(context: ActivationContext) {
123 // if we have a local service records, register them first
144 // if we have a local service records, register them first
124 let instance;
145 let instance;
125
146
126 switch (this._activationType) {
147 switch (this._activationType) {
127 case ActivationType.Singleton: // SINGLETON
148 case ActivationType.Singleton: // SINGLETON
128 // if the value is cached return it
149 // if the value is cached return it
129 if (this._hasInstance)
150 if (this._hasInstance)
130 return this._instance;
151 return this._instance;
131
152
132 // singletons are bound to the root container
153 // singletons are bound to the root container
133 const container = context.container.getRootContainer();
154 const container = context.container.getRootContainer();
134
155
135 if (container.has(this._cacheId)) {
156 if (container.has(this._cacheId)) {
136 instance = container.get(this._cacheId);
157 instance = container.get(this._cacheId);
137 } else {
158 } else {
138 instance = this._create(context, name);
159 instance = this._create(context);
139 container.store(this._cacheId, instance);
160 container.store(this._cacheId, instance);
140 if (this._cleanup)
161 if (this._cleanup)
141 container.onDispose(
162 container.onDispose(
142 makeClenupCallback(instance, this._cleanup));
163 makeClenupCallback(instance, this._cleanup));
143 }
164 }
144
165
145 this._hasInstance = true;
166 this._hasInstance = true;
146 return (this._instance = instance);
167 return (this._instance = instance);
147
168
148 case ActivationType.Container: // CONTAINER
169 case ActivationType.Container: // CONTAINER
149 // return a cached value
170 // return a cached value
150
171
151 if (this._hasInstance)
172 if (this._hasInstance)
152 return this._instance;
173 return this._instance;
153
174
154 // create an instance
175 // create an instance
155 instance = this._create(context, name);
176 instance = this._create(context);
156
177
157 // the instance is bound to the container
178 // the instance is bound to the container
158 if (this._cleanup)
179 if (this._cleanup)
159 this._owner.onDispose(
180 this._owner.onDispose(
160 makeClenupCallback(instance, this._cleanup));
181 makeClenupCallback(instance, this._cleanup));
161
182
162 // cache and return the instance
183 // cache and return the instance
163 this._hasInstance = true;
184 this._hasInstance = true;
164 return (this._instance = instance);
185 return (this._instance = instance);
165 case ActivationType.Context: // CONTEXT
186 case ActivationType.Context: // CONTEXT
166 // return a cached value if one exists
187 // return a cached value if one exists
167
188
168 if (context.has(this._cacheId))
189 if (context.has(this._cacheId))
169 return context.get(this._cacheId);
190 return context.get(this._cacheId);
170 // context context activated instances are controlled by callers
191 // context context activated instances are controlled by callers
171 return context.store(this._cacheId, this._create(
192 return context.store(this._cacheId, this._create(context));
172 context,
173 name));
174 case ActivationType.Call: // CALL
193 case ActivationType.Call: // CALL
175 // per-call created instances are controlled by callers
194 // per-call created instances are controlled by callers
176 return this._create(context, name);
195 return this._create(context);
177 case ActivationType.Hierarchy: // HIERARCHY
196 case ActivationType.Hierarchy: // HIERARCHY
178 // hierarchy activated instances are behave much like container activated
197 // hierarchy activated instances are behave much like container activated
179 // except they are created and bound to the child container
198 // except they are created and bound to the child container
180
199
181 // return a cached value
200 // return a cached value
182 if (context.container.has(this._cacheId))
201 if (context.container.has(this._cacheId))
183 return context.container.get(this._cacheId);
202 return context.container.get(this._cacheId);
184
203
185 instance = this._create(context, name);
204 instance = this._create(context);
186
205
187 if (this._cleanup)
206 if (this._cleanup)
188 context.container.onDispose(makeClenupCallback(
207 context.container.onDispose(makeClenupCallback(
189 instance,
208 instance,
190 this._cleanup));
209 this._cleanup));
191
210
192 return context.container.store(this._cacheId, instance);
211 return context.container.store(this._cacheId, instance);
193 default:
212 default:
194 throw new Error("Invalid activation type: " + this._activationType);
213 throw new Error("Invalid activation type: " + this._activationType);
195 }
214 }
196 }
215 }
197
216
198 isInstanceCreated() {
217 isInstanceCreated() {
199 return this._hasInstance;
218 return this._hasInstance;
200 }
219 }
201
220
202 getInstance() {
221 getInstance() {
203 return this._instance;
222 return this._instance;
204 }
223 }
205
224
206 _create(context, name) {
225 _create(context: ActivationContext) {
207 context.enter(name, this, Boolean(this._services));
226 trace.debug(`constructing ${context._name}`);
208
227
209 if (this._activationType !== ActivationType.Call &&
228 if (this._activationType !== ActivationType.Call &&
210 context.visit(this._cacheId) > 0)
229 context.visit(this._cacheId) > 0)
211 throw new Error("Recursion detected");
230 throw new Error("Recursion detected");
212
231
213 if (this._services) {
232 if (this._services) {
214 for (const p in this._services)
233 for (const p in this._services)
215 context.register(p, this._services[p]);
234 context.register(p, this._services[p]);
216 }
235 }
217
236
218 let instance;
237 let instance;
219
238
220 if (!this._factory) {
239 if (!this._factory) {
221 const ctor = this._type;
240 const ctor = this._type;
222 if (this._params && this._params.length) {
241 if (this._params && this._params.length) {
223 this._factory = (...args) => {
242 this._factory = (...args) => {
224 const t = Object.create(ctor.prototype);
243 const t = Object.create(ctor.prototype);
225 const inst = ctor.apply(t, args);
244 const inst = ctor.apply(t, args);
226 return isPrimitive(inst) ? t : inst;
245 return isPrimitive(inst) ? t : inst;
227 };
246 };
228 } else {
247 } else {
229 this._factory = () => {
248 this._factory = () => {
230 return new ctor();
249 return new ctor();
231 };
250 };
232 }
251 }
233 }
252 }
234
253
235 if (this._params === undefined) {
254 if (this._params === undefined) {
236 instance = this._factory();
255 instance = this._factory();
237 } else if (this._params instanceof Array) {
256 } else if (this._params instanceof Array) {
238 instance = this._factory.apply(this, context.parse(
257 instance = this._factory.apply(this, _parse(this._params, context, "args"));
239 this._params,
240 ".params"));
241 } else {
258 } else {
242 instance = this._factory(context.parse(
259 instance = this._factory(_parse(this._params, context, "args"));
243 this._params,
244 ".params"));
245 }
260 }
246
261
247 if (this._inject) {
262 if (this._inject) {
248 this._inject.forEach(spec => {
263 this._inject.forEach(spec => {
249 for (const m in spec)
264 for (const m in spec)
250 injectMethod(instance, m, context, spec[m]);
265 injectMethod(instance, m, context, spec[m]);
251 });
266 });
252 }
267 }
253
268
254 context.leave();
255
256 return instance;
269 return instance;
257 }
270 }
258
271
259 // @constructor {singleton} foo/bar/Baz
272 // @constructor {singleton} foo/bar/Baz
260 // @factory {singleton}
273 // @factory {singleton}
261 toString() {
274 toString() {
262 const parts = [];
275 const parts = [];
263
276
264 parts.push(this._type ? "@constructor" : "@factory");
277 parts.push(this._type ? "@constructor" : "@factory");
265
278
266 parts.push(ActivationType[this._activationType]);
279 parts.push(ActivationType[this._activationType]);
267
280
268 if (typeof (this._type) === "string")
281 if (typeof (this._type) === "string")
269 parts.push(this._type);
282 parts.push(this._type);
270
283
271 return parts.join(" ");
284 return parts.join(" ");
272 }
285 }
273 }
286 }
@@ -1,23 +1,17
1 import { Descriptor } from "./interfaces";
1 import { Descriptor } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
3
2
4 export class ValueDescriptor implements Descriptor {
3 export class ValueDescriptor implements Descriptor {
5 _value;
4 _value;
6
5
7 constructor(value) {
6 constructor(value) {
8 this._value = value;
7 this._value = value;
9 }
8 }
10
9
11 activate(context: ActivationContext, name: string) {
10 activate() {
12 context.enter(name);
13 const v = this._value;
14 context.leave();
15 return v;
16 }
17 isInstanceCreated(): boolean {
18 return true;
19 }
20 getInstance() {
21 return this._value;
11 return this._value;
22 }
12 }
13
14 toString() {
15 return `@type=${typeof this._value}`;
16 }
23 }
17 }
@@ -1,68 +1,66
1 import { isNull, isPrimitive } from "../safe";
1 import { isNull, isPrimitive } from "../safe";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { Constructor, Factory } from "../interfaces";
3 import { Constructor, Factory } from "../interfaces";
4
4
5 export interface Descriptor {
5 export interface Descriptor {
6 activate(context: ActivationContext, name?: string);
6 activate(context: ActivationContext, name?: string);
7 isInstanceCreated(): boolean;
8 getInstance();
9 }
7 }
10
8
11 export function isDescriptor(x): x is Descriptor {
9 export function isDescriptor(x): x is Descriptor {
12 return (!isPrimitive(x)) &&
10 return (!isPrimitive(x)) &&
13 (x.activate instanceof Function);
11 (x.activate instanceof Function);
14 }
12 }
15
13
16 export interface ServiceMap {
14 export interface ServiceMap {
17 [s: string]: any;
15 [s: string]: Descriptor;
18 }
16 }
19
17
20 export enum ActivationType {
18 export enum ActivationType {
21 Singleton,
19 Singleton,
22 Container,
20 Container,
23 Hierarchy,
21 Hierarchy,
24 Context,
22 Context,
25 Call
23 Call
26 }
24 }
27
25
28 export interface RegistrationWithServices {
26 export interface RegistrationWithServices {
29 services?: object;
27 services?: object;
30 }
28 }
31
29
32 export interface ServiceRegistration extends RegistrationWithServices {
30 export interface ServiceRegistration extends RegistrationWithServices {
33 $type?: string | Constructor;
31 $type?: string | Constructor;
34
32
35 $factory?: string | Factory;
33 $factory?: string | Factory;
36
34
37 activation?: "singleton" | "container" | "hierarchy" | "context" | "call";
35 activation?: "singleton" | "container" | "hierarchy" | "context" | "call";
38
36
39 params?;
37 params?;
40
38
41 inject?: object | object[];
39 inject?: object | object[];
42
40
43 cleanup: (instance) => void | string;
41 cleanup: (instance) => void | string;
44 }
42 }
45
43
46 export interface ValueRegistration {
44 export interface ValueRegistration {
47 $value;
45 $value;
48 parse?: boolean;
46 parse?: boolean;
49 }
47 }
50
48
51 export interface DependencyRegistration extends RegistrationWithServices {
49 export interface DependencyRegistration extends RegistrationWithServices {
52 $dependency: string;
50 $dependency: string;
53 lazy?: boolean;
51 lazy?: boolean;
54 optional?: boolean;
52 optional?: boolean;
55 default?;
53 default?;
56 }
54 }
57
55
58 export function isServiceRegistration(x): x is ServiceRegistration {
56 export function isServiceRegistration(x): x is ServiceRegistration {
59 return (!isPrimitive(x)) && ("$type" in x || "$factory" in x);
57 return (!isPrimitive(x)) && ("$type" in x || "$factory" in x);
60 }
58 }
61
59
62 export function isValueRegistration(x): x is ValueRegistration {
60 export function isValueRegistration(x): x is ValueRegistration {
63 return (!isPrimitive(x)) && ("$value" in x);
61 return (!isPrimitive(x)) && ("$value" in x);
64 }
62 }
65
63
66 export function isDependencyRegistration(x): x is DependencyRegistration {
64 export function isDependencyRegistration(x): x is DependencyRegistration {
67 return (!isPrimitive(x)) && ("$depdendency" in x);
65 return (!isPrimitive(x)) && ("$depdendency" in x);
68 }
66 }
@@ -1,306 +1,306
1 let _nextOid = 0;
1 let _nextOid = 0;
2 const _oid = Symbol("__oid");
2 const _oid = typeof Symbol === "function" ? Symbol("__oid") : "__oid";
3
3
4 export function oid(instance: object): string {
4 export function oid(instance: object): string {
5 if (isNull(instance))
5 if (isNull(instance))
6 return null;
6 return null;
7
7
8 if (_oid in instance)
8 if (_oid in instance)
9 return instance[_oid];
9 return instance[_oid];
10 else
10 else
11 return (instance[_oid] = "oid_" + (++_nextOid));
11 return (instance[_oid] = "oid_" + (++_nextOid));
12 }
12 }
13
13
14 export function argumentNotNull(arg, name) {
14 export function argumentNotNull(arg, name) {
15 if (arg === null || arg === undefined)
15 if (arg === null || arg === undefined)
16 throw new Error("The argument " + name + " can't be null or undefined");
16 throw new Error("The argument " + name + " can't be null or undefined");
17 }
17 }
18
18
19 export function argumentNotEmptyString(arg, name) {
19 export function argumentNotEmptyString(arg, name) {
20 if (typeof (arg) !== "string" || !arg.length)
20 if (typeof (arg) !== "string" || !arg.length)
21 throw new Error("The argument '" + name + "' must be a not empty string");
21 throw new Error("The argument '" + name + "' must be a not empty string");
22 }
22 }
23
23
24 export function argumentNotEmptyArray(arg, name) {
24 export function argumentNotEmptyArray(arg, name) {
25 if (!(arg instanceof Array) || !arg.length)
25 if (!(arg instanceof Array) || !arg.length)
26 throw new Error("The argument '" + name + "' must be a not empty array");
26 throw new Error("The argument '" + name + "' must be a not empty array");
27 }
27 }
28
28
29 export function argumentOfType(arg, type, name) {
29 export function argumentOfType(arg, type, name) {
30 if (!(arg instanceof type))
30 if (!(arg instanceof type))
31 throw new Error("The argument '" + name + "' type doesn't match");
31 throw new Error("The argument '" + name + "' type doesn't match");
32 }
32 }
33
33
34 export function isNull(arg) {
34 export function isNull(arg) {
35 return (arg === null || arg === undefined);
35 return (arg === null || arg === undefined);
36 }
36 }
37
37
38 export function isPrimitive(arg) {
38 export function isPrimitive(arg) {
39 return (arg === null || arg === undefined || typeof (arg) === "string" ||
39 return (arg === null || arg === undefined || typeof (arg) === "string" ||
40 typeof (arg) === "number" || typeof (arg) === "boolean");
40 typeof (arg) === "number" || typeof (arg) === "boolean");
41 }
41 }
42
42
43 export function isInteger(arg) {
43 export function isInteger(arg) {
44 return parseInt(arg, 10) === arg;
44 return parseInt(arg, 10) === arg;
45 }
45 }
46
46
47 export function isNumber(arg) {
47 export function isNumber(arg) {
48 return parseFloat(arg) === arg;
48 return parseFloat(arg) === arg;
49 }
49 }
50
50
51 export function isString(val) {
51 export function isString(val) {
52 return typeof (val) === "string" || val instanceof String;
52 return typeof (val) === "string" || val instanceof String;
53 }
53 }
54
54
55 export function isPromise(val): val is PromiseLike<any> {
55 export function isPromise(val): val is PromiseLike<any> {
56 return "then" in val && val.then instanceof Function;
56 return "then" in val && val.then instanceof Function;
57 }
57 }
58
58
59 export function isNullOrEmptyString(str) {
59 export function isNullOrEmptyString(str) {
60 if (str === null || str === undefined ||
60 if (str === null || str === undefined ||
61 ((typeof (str) === "string" || str instanceof String) && str.length === 0))
61 ((typeof (str) === "string" || str instanceof String) && str.length === 0))
62 return true;
62 return true;
63 }
63 }
64
64
65 export function isNotEmptyArray(arg): arg is Array<any> {
65 export function isNotEmptyArray(arg): arg is Array<any> {
66 return (arg instanceof Array && arg.length > 0);
66 return (arg instanceof Array && arg.length > 0);
67 }
67 }
68
68
69 export function getGlobal() {
69 export function getGlobal() {
70 return this;
70 return this;
71 }
71 }
72
72
73 export function get(member: string, context?: object) {
73 export function get(member: string, context?: object) {
74 argumentNotEmptyString(member, "member");
74 argumentNotEmptyString(member, "member");
75 let that = context || getGlobal();
75 let that = context || getGlobal();
76 const parts = member.split(".");
76 const parts = member.split(".");
77 for (const m of parts) {
77 for (const m of parts) {
78 if (!m)
78 if (!m)
79 continue;
79 continue;
80 if (isNull(that = that[m]))
80 if (isNull(that = that[m]))
81 break;
81 break;
82 }
82 }
83 return that;
83 return that;
84 }
84 }
85
85
86 /**
86 /**
87 * Выполняет метод для каждого элемента массива, останавливается, когда
87 * Выполняет метод для каждого элемента массива, останавливается, когда
88 * либо достигнут конец массива, либо функция <c>cb</c> вернула
88 * либо достигнут конец массива, либо функция <c>cb</c> вернула
89 * значение.
89 * значение.
90 *
90 *
91 * @param {Array | Object} obj массив элементов для просмотра
91 * @param {Array | Object} obj массив элементов для просмотра
92 * @param {Function} cb функция, вызываемая для каждого элемента
92 * @param {Function} cb функция, вызываемая для каждого элемента
93 * @param {Object} thisArg значение, которое будет передано в качестве
93 * @param {Object} thisArg значение, которое будет передано в качестве
94 * <c>this</c> в <c>cb</c>.
94 * <c>this</c> в <c>cb</c>.
95 * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c>
95 * @returns Результат вызова функции <c>cb</c>, либо <c>undefined</c>
96 * если достигнут конец массива.
96 * если достигнут конец массива.
97 */
97 */
98 export function each(obj, cb, thisArg?) {
98 export function each(obj, cb, thisArg?) {
99 argumentNotNull(cb, "cb");
99 argumentNotNull(cb, "cb");
100 if (obj instanceof Array) {
100 if (obj instanceof Array) {
101 for (let i = 0; i < obj.length; i++) {
101 for (let i = 0; i < obj.length; i++) {
102 const x = cb.call(thisArg, obj[i], i);
102 const x = cb.call(thisArg, obj[i], i);
103 if (x !== undefined)
103 if (x !== undefined)
104 return x;
104 return x;
105 }
105 }
106 } else {
106 } else {
107 const keys = Object.keys(obj);
107 const keys = Object.keys(obj);
108 for (const k of keys) {
108 for (const k of keys) {
109 const x = cb.call(thisArg, obj[k], k);
109 const x = cb.call(thisArg, obj[k], k);
110 if (x !== undefined)
110 if (x !== undefined)
111 return x;
111 return x;
112 }
112 }
113 }
113 }
114 }
114 }
115
115
116 /** Copies property values from a source object to the destination and returns
116 /** Copies property values from a source object to the destination and returns
117 * the destination onject.
117 * the destination onject.
118 *
118 *
119 * @param dest The destination object into which properties from the source
119 * @param dest The destination object into which properties from the source
120 * object will be copied.
120 * object will be copied.
121 * @param source The source of values which will be copied to the destination
121 * @param source The source of values which will be copied to the destination
122 * object.
122 * object.
123 * @param template An optional parameter specifies which properties should be
123 * @param template An optional parameter specifies which properties should be
124 * copied from the source and how to map them to the destination. If the
124 * copied from the source and how to map them to the destination. If the
125 * template is an array it contains the list of property names to copy from the
125 * template is an array it contains the list of property names to copy from the
126 * source to the destination. In case of object the templates contains the map
126 * source to the destination. In case of object the templates contains the map
127 * where keys are property names in the source and the values are property
127 * where keys are property names in the source and the values are property
128 * names in the destination object. If the template isn't specified then the
128 * names in the destination object. If the template isn't specified then the
129 * own properties of the source are entirely copied to the destination.
129 * own properties of the source are entirely copied to the destination.
130 *
130 *
131 */
131 */
132 export function mixin<T, S>(dest: T, source: S, template?: string[] | object): T & S {
132 export function mixin<T, S>(dest: T, source: S, template?: string[] | object): T & S {
133 argumentNotNull(dest, "to");
133 argumentNotNull(dest, "to");
134 const _res = dest as T & S;
134 const _res = dest as T & S;
135
135
136 if (template instanceof Array) {
136 if (template instanceof Array) {
137 for (const p of template) {
137 for (const p of template) {
138 if (p in source)
138 if (p in source)
139 _res[p] = source[p];
139 _res[p] = source[p];
140 }
140 }
141 } else if (template) {
141 } else if (template) {
142 const keys = Object.keys(source);
142 const keys = Object.keys(source);
143 for (const p of keys) {
143 for (const p of keys) {
144 if (p in template)
144 if (p in template)
145 _res[template[p]] = source[p];
145 _res[template[p]] = source[p];
146 }
146 }
147 } else {
147 } else {
148 const keys = Object.keys(source);
148 const keys = Object.keys(source);
149 for (const p of keys)
149 for (const p of keys)
150 _res[p] = source[p];
150 _res[p] = source[p];
151 }
151 }
152
152
153 return _res;
153 return _res;
154 }
154 }
155
155
156 /** Wraps the specified function to emulate an asynchronous execution.
156 /** Wraps the specified function to emulate an asynchronous execution.
157 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
157 * @param{Object} thisArg [Optional] Object which will be passed as 'this' to the function.
158 * @param{Function|String} fn [Required] Function wich will be wrapped.
158 * @param{Function|String} fn [Required] Function wich will be wrapped.
159 */
159 */
160 export function async(_fn: (...args: any[]) => any, thisArg): (...args: any[]) => PromiseLike<any> {
160 export function async(_fn: (...args: any[]) => any, thisArg): (...args: any[]) => PromiseLike<any> {
161 let fn = _fn;
161 let fn = _fn;
162
162
163 if (arguments.length === 2 && !(fn instanceof Function))
163 if (arguments.length === 2 && !(fn instanceof Function))
164 fn = thisArg[fn];
164 fn = thisArg[fn];
165
165
166 if (fn == null)
166 if (fn == null)
167 throw new Error("The function must be specified");
167 throw new Error("The function must be specified");
168
168
169 function wrapresult(x, e?): PromiseLike<any> {
169 function wrapresult(x, e?): PromiseLike<any> {
170 if (e) {
170 if (e) {
171 return {
171 return {
172 then(cb, eb) {
172 then(cb, eb) {
173 try {
173 try {
174 return eb ? wrapresult(eb(e)) : this;
174 return eb ? wrapresult(eb(e)) : this;
175 } catch (e2) {
175 } catch (e2) {
176 return wrapresult(null, e2);
176 return wrapresult(null, e2);
177 }
177 }
178 }
178 }
179 };
179 };
180 } else {
180 } else {
181 if (x && x.then)
181 if (x && x.then)
182 return x;
182 return x;
183 return {
183 return {
184 then(cb) {
184 then(cb) {
185 try {
185 try {
186 return cb ? wrapresult(cb(x)) : this;
186 return cb ? wrapresult(cb(x)) : this;
187 } catch (e2) {
187 } catch (e2) {
188 return wrapresult(e2);
188 return wrapresult(e2);
189 }
189 }
190 }
190 }
191 };
191 };
192 }
192 }
193 }
193 }
194
194
195 return (...args) => {
195 return (...args) => {
196 try {
196 try {
197 return wrapresult(fn.apply(thisArg, args));
197 return wrapresult(fn.apply(thisArg, args));
198 } catch (e) {
198 } catch (e) {
199 return wrapresult(null, e);
199 return wrapresult(null, e);
200 }
200 }
201 };
201 };
202 }
202 }
203
203
204 type _AnyFn = (...args) => any;
204 type _AnyFn = (...args) => any;
205
205
206 export function delegate<T, K extends keyof T>(target: T, _method: (K | _AnyFn)) {
206 export function delegate<T, K extends keyof T>(target: T, _method: (K | _AnyFn)) {
207 let method;
207 let method;
208
208
209 if (!(_method instanceof Function)) {
209 if (!(_method instanceof Function)) {
210 argumentNotNull(target, "target");
210 argumentNotNull(target, "target");
211 method = target[_method];
211 method = target[_method];
212 if (!(method instanceof Function))
212 if (!(method instanceof Function))
213 throw new Error("'method' argument must be a Function or a method name");
213 throw new Error("'method' argument must be a Function or a method name");
214 } else {
214 } else {
215 method = _method;
215 method = _method;
216 }
216 }
217
217
218 return (...args) => {
218 return (...args) => {
219 return method.apply(target, args);
219 return method.apply(target, args);
220 };
220 };
221 }
221 }
222
222
223 /**
223 /**
224 * Для каждого элемента массива вызывает указанную функцию и сохраняет
224 * Для каждого элемента массива вызывает указанную функцию и сохраняет
225 * возвращенное значение в массиве результатов.
225 * возвращенное значение в массиве результатов.
226 *
226 *
227 * @remarks cb может выполняться асинхронно, при этом одновременно будет
227 * @remarks cb может выполняться асинхронно, при этом одновременно будет
228 * только одна операция.
228 * только одна операция.
229 *
229 *
230 * @async
230 * @async
231 */
231 */
232 export function pmap(items, cb) {
232 export function pmap(items, cb) {
233 argumentNotNull(cb, "cb");
233 argumentNotNull(cb, "cb");
234
234
235 if (items && items.then instanceof Function)
235 if (isPromise(items))
236 return items.then(data => pmap(data, cb));
236 return items.then(data => pmap(data, cb));
237
237
238 if (isNull(items) || !items.length)
238 if (isNull(items) || !items.length)
239 return items;
239 return items;
240
240
241 let i = 0;
241 let i = 0;
242 const result = [];
242 const result = [];
243
243
244 function next() {
244 function next() {
245 let r;
245 let r;
246 let ri;
246 let ri;
247
247
248 function chain(x) {
248 function chain(x) {
249 result[ri] = x;
249 result[ri] = x;
250 return next();
250 return next();
251 }
251 }
252
252
253 while (i < items.length) {
253 while (i < items.length) {
254 r = cb(items[i], i);
254 r = cb(items[i], i);
255 ri = i;
255 ri = i;
256 i++;
256 i++;
257 if (isPromise(r)) {
257 if (isPromise(r)) {
258 return r.then(chain);
258 return r.then(chain);
259 } else {
259 } else {
260 result[ri] = r;
260 result[ri] = r;
261 }
261 }
262 }
262 }
263 return result;
263 return result;
264 }
264 }
265
265
266 return next();
266 return next();
267 }
267 }
268
268
269 /**
269 /**
270 * Выбирает первый элемент из последовательности, или обещания, если в
270 * Выбирает первый элемент из последовательности, или обещания, если в
271 * качестве параметра используется обещание, оно должно вернуть массив.
271 * качестве параметра используется обещание, оно должно вернуть массив.
272 *
272 *
273 * @param {Function} cb обработчик результата, ему будет передан первый
273 * @param {Function} cb обработчик результата, ему будет передан первый
274 * элемент последовательности в случае успеха
274 * элемент последовательности в случае успеха
275 * @param {Function} err обработчик исключения, если массив пустой, либо
275 * @param {Function} err обработчик исключения, если массив пустой, либо
276 * не массив
276 * не массив
277 *
277 *
278 * @remarks Если не указаны ни cb ни err, тогда функция вернет либо
278 * @remarks Если не указаны ни cb ни err, тогда функция вернет либо
279 * обещание, либо первый элемент.
279 * обещание, либо первый элемент.
280 * @async
280 * @async
281 */
281 */
282 export function first(sequence, cb: (x) => any, err: (x) => any) {
282 export function first(sequence, cb: (x) => any, err: (x) => any) {
283 if (sequence) {
283 if (sequence) {
284 if (isPromise(sequence)) {
284 if (isPromise(sequence)) {
285 return sequence.then(res => first(res, cb, err));
285 return sequence.then(res => first(res, cb, err));
286 } else if (sequence && "length" in sequence) {
286 } else if (sequence && "length" in sequence) {
287 if (sequence.length === 0) {
287 if (sequence.length === 0) {
288 if (err)
288 if (err)
289 return err(new Error("The sequence is empty"));
289 return err(new Error("The sequence is empty"));
290 else
290 else
291 throw new Error("The sequence is empty");
291 throw new Error("The sequence is empty");
292 }
292 }
293 return cb ? cb(sequence[0]) : sequence[0];
293 return cb ? cb(sequence[0]) : sequence[0];
294 }
294 }
295 }
295 }
296
296
297 if (err)
297 if (err)
298 return err(new Error("The sequence is required"));
298 return err(new Error("The sequence is required"));
299 else
299 else
300 throw new Error("The sequence is required");
300 throw new Error("The sequence is required");
301 }
301 }
302
302
303 export function destroy(d) {
303 export function destroy(d) {
304 if (d && "destroy" in d)
304 if (d && "destroy" in d)
305 d.destroy();
305 d.destroy();
306 }
306 }
@@ -1,26 +1,74
1 import { test } from "./TestTraits";
1 import { test, TapeWriter } from "./TestTraits";
2 import { Container } from "@implab/core/di/Container";
2 import { Container } from "@implab/core/di/Container";
3 import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor";
3 import { ReferenceDescriptor } from "@implab/core/di/ReferenceDescriptor";
4 import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor";
4 import { AggregateDescriptor } from "@implab/core/di/AggregateDescriptor";
5 import { ValueDescriptor } from "@implab/core/di/ValueDescriptor";
6 import { TraceSource, DebugLevel } from "@implab/core/log/TraceSource";
7 import { Foo } from "./mock/Foo";
8 import { Bar } from "./mock/Bar";
9 import { isNull } from "@implab/core/safe";
5
10
6 test("Container register/getService tests", async t => {
11 test("Container register/resolve tests", async t => {
12 const writer = new TapeWriter(t);
13
14 TraceSource.on(ts => {
15 ts.level = DebugLevel;
16 writer.writeEvents(ts.events);
17 });
18
7 const container = new Container();
19 const container = new Container();
8
20
9 const connection1 = "db://localhost";
21 const connection1 = "db://localhost";
10
22
11 container.register("connection", connection1);
23 container.register("connection", new ValueDescriptor(connection1));
12
24
13 t.equals(container.getService("connection"), connection1);
25 t.equals(container.getService("connection"), connection1);
14
26
15 container.register(
27 container.register(
16 "dbParams",
28 "dbParams",
17 new AggregateDescriptor({
29 new AggregateDescriptor({
18 timeout: 10,
30 timeout: 10,
19 connection: new ReferenceDescriptor({name: "connection"})
31 connection: new ReferenceDescriptor({ name: "connection" })
20 })
32 })
21 );
33 );
22
34
23 const dbParams = container.getService("dbParams");
35 const dbParams = container.getService("dbParams");
24 t.equals(dbParams.connection, connection1);
36 t.equals(dbParams.connection, connection1, "should get connection");
37
38 writer.destroy();
39 });
40
41 test("Container configure/resolve tests", async t => {
42 const writer = new TapeWriter(t);
43
44 TraceSource.on(ts => {
45 ts.level = DebugLevel;
46 writer.writeEvents(ts.events);
47 });
48
49 const container = new Container();
50
51 await container.configure({
52 foo: {
53 $type: Foo
54 },
25
55
56 bar: {
57 $type: Bar,
58 params: {
59 db: {
60 provider: {
61 $dependency: "db"
62 }
63 }
64 }
65 }
66 });
67
68 const f1 = container.resolve("foo");
69 t.assert(!isNull(f1), "foo should be not null");
70
71 const b1 = container.resolve("bar");
72
73 writer.destroy();
26 });
74 });
@@ -1,75 +1,79
1 import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces";
1 import { IObservable, ICancellation, IDestroyable } from "@implab/core/interfaces";
2 import { Cancellation } from "@implab/core/Cancellation";
2 import { Cancellation } from "@implab/core/Cancellation";
3 import { TraceEvent, LogLevel, WarnLevel } from "@implab/core/log/TraceSource";
3 import { TraceEvent, LogLevel, WarnLevel } from "@implab/core/log/TraceSource";
4 import * as tape from "tape";
4 import * as tape from "tape";
5 import { argumentNotNull } from "@implab/core/safe";
5 import { argumentNotNull } from "@implab/core/safe";
6
6
7 export class TapeWriter implements IDestroyable {
7 export class TapeWriter implements IDestroyable {
8 readonly _tape: tape.Test;
8 readonly _tape: tape.Test;
9
9
10 _subscriptions = new Array<IDestroyable>();
10 _subscriptions = new Array<IDestroyable>();
11
11
12 constructor(t: tape.Test) {
12 constructor(t: tape.Test) {
13 argumentNotNull(t, "tape");
13 argumentNotNull(t, "tape");
14 this._tape = t;
14 this._tape = t;
15 }
15 }
16
16
17 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
17 writeEvents(source: IObservable<TraceEvent>, ct: ICancellation = Cancellation.none) {
18 const subscription = source.on(this.writeEvent.bind(this));
18 const subscription = source.on(this.writeEvent.bind(this));
19 if (ct.isSupported()) {
19 if (ct.isSupported()) {
20 ct.register(subscription.destroy.bind(subscription));
20 ct.register(subscription.destroy.bind(subscription));
21 }
21 }
22 this._subscriptions.push(subscription);
22 this._subscriptions.push(subscription);
23 }
23 }
24
24
25 writeEvent(next: TraceEvent) {
25 writeEvent(next: TraceEvent) {
26 if (next.level >= LogLevel) {
26 if (next.level >= LogLevel) {
27 this._tape.comment("LOG " + next.arg);
27 this._tape.comment("LOG " + next.arg);
28 } else if (next.level >= WarnLevel) {
28 } else if (next.level >= WarnLevel) {
29 this._tape.comment("WARN " + next.arg);
29 this._tape.comment("WARN " + next.arg);
30 } else {
30 } else {
31 this._tape.comment("ERROR " + next.arg);
31 this._tape.comment("ERROR " + next.arg);
32 }
32 }
33 }
33 }
34
34
35 destroy() {
35 destroy() {
36 this._subscriptions.forEach(x => x.destroy());
36 this._subscriptions.forEach(x => x.destroy());
37 }
37 }
38 }
38 }
39
39
40 export async function delay(timeout: number, ct: ICancellation = Cancellation.none) {
40 export async function delay(timeout: number, ct: ICancellation = Cancellation.none) {
41 let un: IDestroyable;
41 let un: IDestroyable;
42
42
43 try {
43 try {
44 await new Promise((resolve, reject) => {
44 await new Promise((resolve, reject) => {
45 if (ct.isRequested()) {
45 if (ct.isRequested()) {
46 un = ct.register(reject);
46 un = ct.register(reject);
47 } else {
47 } else {
48 const ht = setTimeout(() => {
48 const ht = setTimeout(() => {
49 resolve();
49 resolve();
50 }, timeout);
50 }, timeout);
51
51
52 un = ct.register(e => {
52 un = ct.register(e => {
53 clearTimeout(ht);
53 clearTimeout(ht);
54 reject(e);
54 reject(e);
55 });
55 });
56 }
56 }
57 });
57 });
58 } finally {
58 } finally {
59 if (un)
59 if (un)
60 un.destroy();
60 un.destroy();
61 }
61 }
62 }
62 }
63
63
64 export function test(name: string, cb: (t: tape.Test) => any) {
64 export function test(name: string, cb: (t: tape.Test) => any) {
65 tape(name, async t => {
65 tape(name, async t => {
66 try {
66 try {
67 await cb(t);
67 await cb(t);
68 } catch (e) {
68 } catch (e) {
69
70 // verbose error information
71 // tslint:disable-next-line
69 console.error(e);
72 console.error(e);
70 t.fail(e);
73 t.fail(e);
74
71 } finally {
75 } finally {
72 t.end();
76 t.end();
73 }
77 }
74 });
78 });
75 }
79 }
@@ -1,15 +1,17
1 {
1 {
2 "compilerOptions": {
2 "compilerOptions": {
3 "target": "es3",
3 "target": "es3",
4 "module": "amd",
4 "module": "amd",
5 "sourceMap": true,
5 "sourceMap": true,
6 "outDir" : "build/dist",
6 "outDir" : "build/dist",
7 "declaration": true,
7 "declaration": true,
8 "lib": [
8 "lib": [
9 "es2015"
9 "es5",
10 "es2015.promise",
11 "es2015.symbol"
10 ]
12 ]
11 },
13 },
12 "include" : [
14 "include" : [
13 "src/ts/**/*.ts"
15 "src/ts/**/*.ts"
14 ]
16 ]
15 } No newline at end of file
17 }
General Comments 0
You need to be logged in to leave comments. Login now