@navios/di 0.9.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +28 -0
  3. package/coverage/block-navigation.js +1 -1
  4. package/coverage/clover.xml +1463 -3174
  5. package/coverage/coverage-final.json +56 -54
  6. package/coverage/index.html +179 -104
  7. package/coverage/sorter.js +21 -7
  8. package/coverage/src/{request-context-manager.mts.html → __tests__/gc/gc-test-utils.mts.html} +192 -231
  9. package/coverage/{lib → src/__tests__/gc}/index.html +25 -40
  10. package/coverage/src/container/abstract-container.mts.html +1066 -0
  11. package/coverage/src/container/container.mts.html +958 -0
  12. package/coverage/src/container/index.html +161 -0
  13. package/coverage/src/{testing → container}/index.mts.html +12 -9
  14. package/coverage/src/container/scoped-container.mts.html +907 -0
  15. package/coverage/src/decorators/factory.decorator.mts.html +68 -53
  16. package/coverage/src/decorators/index.html +34 -34
  17. package/coverage/src/decorators/index.mts.html +10 -10
  18. package/coverage/src/decorators/injectable.decorator.mts.html +144 -60
  19. package/coverage/src/enums/index.html +21 -21
  20. package/coverage/src/enums/index.mts.html +12 -12
  21. package/coverage/src/enums/injectable-scope.enum.mts.html +11 -8
  22. package/coverage/src/enums/injectable-type.enum.mts.html +10 -7
  23. package/coverage/src/errors/di-error.mts.html +380 -71
  24. package/coverage/src/errors/index.html +22 -127
  25. package/coverage/src/errors/index.mts.html +9 -33
  26. package/coverage/src/event-emitter.mts.html +35 -107
  27. package/coverage/src/index.html +14 -254
  28. package/coverage/src/index.mts.html +23 -50
  29. package/coverage/src/interfaces/container.interface.mts.html +370 -0
  30. package/coverage/src/interfaces/factory.interface.mts.html +12 -12
  31. package/coverage/src/interfaces/index.html +45 -30
  32. package/coverage/src/interfaces/index.mts.html +16 -13
  33. package/coverage/src/interfaces/on-service-destroy.interface.mts.html +1 -1
  34. package/coverage/src/interfaces/on-service-init.interface.mts.html +1 -1
  35. package/coverage/src/internal/context/async-local-storage.browser.mts.html +142 -0
  36. package/coverage/src/internal/context/async-local-storage.mts.html +292 -0
  37. package/coverage/src/{factory-context.mts.html → internal/context/async-local-storage.types.mts.html} +17 -17
  38. package/coverage/src/internal/context/factory-context.mts.html +142 -0
  39. package/coverage/src/internal/context/index.html +221 -0
  40. package/coverage/src/internal/context/index.mts.html +100 -0
  41. package/coverage/src/{service-locator-instance-holder.mts.html → internal/context/resolution-context.mts.html} +114 -78
  42. package/coverage/src/internal/context/service-initialization-context.mts.html +214 -0
  43. package/coverage/src/internal/context/sync-local-storage.mts.html +244 -0
  44. package/coverage/src/internal/core/index.html +206 -0
  45. package/coverage/src/internal/core/index.mts.html +103 -0
  46. package/coverage/src/internal/core/instance-resolver.mts.html +2533 -0
  47. package/coverage/src/{request-context-holder.mts.html → internal/core/name-resolver.mts.html} +245 -260
  48. package/coverage/src/{container.mts.html → internal/core/scope-tracker.mts.html} +352 -310
  49. package/coverage/src/{service-instantiator.mts.html → internal/core/service-initializer.mts.html} +254 -176
  50. package/coverage/src/internal/core/service-invalidator.mts.html +955 -0
  51. package/coverage/src/internal/core/token-resolver.mts.html +451 -0
  52. package/coverage/src/internal/holder/holder-storage.interface.mts.html +451 -0
  53. package/coverage/src/internal/holder/index.html +161 -0
  54. package/coverage/src/internal/holder/index.mts.html +94 -0
  55. package/coverage/src/internal/holder/instance-holder.mts.html +406 -0
  56. package/coverage/src/{service-locator.mts.html → internal/holder/unified-storage.mts.html} +376 -379
  57. package/coverage/{lib/testing → src/internal}/index.html +26 -11
  58. package/coverage/src/internal/index.mts.html +100 -0
  59. package/coverage/src/internal/lifecycle/circular-detector.mts.html +364 -0
  60. package/coverage/src/internal/lifecycle/index.html +146 -0
  61. package/coverage/src/internal/lifecycle/index.mts.html +91 -0
  62. package/coverage/src/{service-locator-event-bus.mts.html → internal/lifecycle/lifecycle-event-bus.mts.html} +104 -80
  63. package/coverage/src/internal/stub-factory-class.mts.html +133 -0
  64. package/coverage/src/symbols/index.html +14 -14
  65. package/coverage/src/symbols/index.mts.html +9 -9
  66. package/coverage/src/symbols/injectable-token.mts.html +9 -3
  67. package/coverage/src/testing/index.html +32 -32
  68. package/coverage/src/testing/test-container.mts.html +1576 -139
  69. package/coverage/src/testing/unit-test-container.mts.html +1888 -0
  70. package/coverage/src/token/index.html +146 -0
  71. package/coverage/{lib/testing/index.d.mts.html → src/token/index.mts.html} +11 -11
  72. package/coverage/src/{injection-token.mts.html → token/injection-token.mts.html} +225 -111
  73. package/coverage/src/{base-instance-holder-manager.mts.html → token/registry.mts.html} +188 -269
  74. package/coverage/src/{injector.mts.html → utils/default-injectors.mts.html} +31 -31
  75. package/coverage/src/utils/get-injectable-token.mts.html +19 -22
  76. package/coverage/src/utils/get-injectors.mts.html +684 -177
  77. package/coverage/src/utils/index.html +36 -36
  78. package/coverage/src/utils/index.mts.html +18 -12
  79. package/coverage/src/utils/types.mts.html +26 -11
  80. package/docs/examples/basic-usage.mts +1 -1
  81. package/docs/examples/factory-pattern.mts +3 -3
  82. package/docs/examples/request-scope-example.mts +1 -1
  83. package/docs/examples/service-lifecycle.mts +1 -1
  84. package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -1
  85. package/lib/browser/internal/core/instance-resolver.mjs.map +1 -1
  86. package/lib/{container-D-0Ho3qL.d.cts → container-D3j3KuD9.d.mts} +5 -289
  87. package/lib/container-D3j3KuD9.d.mts.map +1 -0
  88. package/lib/{container-Bi0huFQX.mjs → container-qgHMgGNG.mjs} +3 -227
  89. package/lib/container-qgHMgGNG.mjs.map +1 -0
  90. package/lib/{container-CNiqesCL.d.mts → container-r1KP4F-n.d.cts} +5 -289
  91. package/lib/container-r1KP4F-n.d.cts.map +1 -0
  92. package/lib/{container-pmGNCZL_.cjs → container-ycYJgTq7.cjs} +41 -319
  93. package/lib/container-ycYJgTq7.cjs.map +1 -0
  94. package/lib/factory.decorator-D4mem6YQ.cjs +21 -0
  95. package/lib/factory.decorator-D4mem6YQ.cjs.map +1 -0
  96. package/lib/factory.decorator-_IPWcwQn.mjs +16 -0
  97. package/lib/factory.decorator-_IPWcwQn.mjs.map +1 -0
  98. package/lib/index.cjs +14 -24
  99. package/lib/index.cjs.map +1 -1
  100. package/lib/index.d.cts +3 -52
  101. package/lib/index.d.cts.map +1 -1
  102. package/lib/index.d.mts +3 -52
  103. package/lib/index.d.mts.map +1 -1
  104. package/lib/index.mjs +3 -13
  105. package/lib/index.mjs.map +1 -1
  106. package/lib/injectable.decorator-BNfWpjr_.d.cts +56 -0
  107. package/lib/injectable.decorator-BNfWpjr_.d.cts.map +1 -0
  108. package/lib/injectable.decorator-Bc05hRQU.d.mts +56 -0
  109. package/lib/injectable.decorator-Bc05hRQU.d.mts.map +1 -0
  110. package/lib/injectable.decorator-CyPrBzBN.mjs +227 -0
  111. package/lib/injectable.decorator-CyPrBzBN.mjs.map +1 -0
  112. package/lib/injectable.decorator-DbpiDrg-.cjs +281 -0
  113. package/lib/injectable.decorator-DbpiDrg-.cjs.map +1 -0
  114. package/lib/legacy-compat/index.cjs +114 -0
  115. package/lib/legacy-compat/index.cjs.map +1 -0
  116. package/lib/legacy-compat/index.d.cts +63 -0
  117. package/lib/legacy-compat/index.d.cts.map +1 -0
  118. package/lib/legacy-compat/index.d.mts +63 -0
  119. package/lib/legacy-compat/index.d.mts.map +1 -0
  120. package/lib/legacy-compat/index.mjs +111 -0
  121. package/lib/legacy-compat/index.mjs.map +1 -0
  122. package/lib/registry-DKbKWFvJ.d.cts +290 -0
  123. package/lib/registry-DKbKWFvJ.d.cts.map +1 -0
  124. package/lib/registry-n8JhJoxm.d.mts +290 -0
  125. package/lib/registry-n8JhJoxm.d.mts.map +1 -0
  126. package/lib/testing/index.cjs +23 -22
  127. package/lib/testing/index.cjs.map +1 -1
  128. package/lib/testing/index.d.cts +2 -1
  129. package/lib/testing/index.d.cts.map +1 -1
  130. package/lib/testing/index.d.mts +2 -1
  131. package/lib/testing/index.d.mts.map +1 -1
  132. package/lib/testing/index.mjs +2 -1
  133. package/lib/testing/index.mjs.map +1 -1
  134. package/package.json +11 -1
  135. package/project.json +8 -0
  136. package/src/__tests__/gc/basic-container.spec.mts +358 -0
  137. package/src/__tests__/gc/circular-dependencies.spec.mts +501 -0
  138. package/src/__tests__/gc/gc-test-utils.mts +136 -0
  139. package/src/__tests__/gc/memory-pressure.spec.mts +542 -0
  140. package/src/__tests__/gc/scoped-container.spec.mts +444 -0
  141. package/src/__tests__/gc/transient-services.spec.mts +326 -0
  142. package/src/__tests__/scope-upgrade.spec.mts +0 -18
  143. package/src/internal/core/instance-resolver.mts +0 -1
  144. package/src/legacy-compat/context-compat.mts +95 -0
  145. package/src/legacy-compat/factory.decorator.mts +37 -0
  146. package/src/legacy-compat/index.mts +16 -0
  147. package/src/legacy-compat/injectable.decorator.mts +41 -0
  148. package/tsdown.config.mts +1 -1
  149. package/vitest.config.mts +3 -7
  150. package/coverage/docs/examples/basic-usage.mts.html +0 -376
  151. package/coverage/docs/examples/factory-pattern.mts.html +0 -1039
  152. package/coverage/docs/examples/index.html +0 -176
  153. package/coverage/docs/examples/injection-tokens.mts.html +0 -760
  154. package/coverage/docs/examples/request-scope-example.mts.html +0 -847
  155. package/coverage/docs/examples/service-lifecycle.mts.html +0 -1162
  156. package/coverage/lib/_tsup-dts-rollup.d.mts.html +0 -3445
  157. package/coverage/lib/index.d.mts.html +0 -313
  158. package/coverage/src/errors/errors.enum.mts.html +0 -118
  159. package/coverage/src/errors/factory-not-found.mts.html +0 -118
  160. package/coverage/src/errors/factory-token-not-resolved.mts.html +0 -118
  161. package/coverage/src/errors/instance-destroying.mts.html +0 -118
  162. package/coverage/src/errors/instance-expired.mts.html +0 -118
  163. package/coverage/src/errors/instance-not-found.mts.html +0 -118
  164. package/coverage/src/errors/unknown-error.mts.html +0 -118
  165. package/coverage/src/instance-resolver.mts.html +0 -1762
  166. package/coverage/src/registry.mts.html +0 -247
  167. package/coverage/src/service-invalidator.mts.html +0 -1372
  168. package/coverage/src/service-locator-manager.mts.html +0 -340
  169. package/coverage/src/token-processor.mts.html +0 -607
  170. package/coverage/src/utils/defer.mts.html +0 -118
  171. package/lib/container-Bi0huFQX.mjs.map +0 -1
  172. package/lib/container-CNiqesCL.d.mts.map +0 -1
  173. package/lib/container-D-0Ho3qL.d.cts.map +0 -1
  174. package/lib/container-pmGNCZL_.cjs.map +0 -1
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">96.77% </span>
26
+ <span class="strong">76.78% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>60/62</span>
28
+ <span class='fraction'>129/168</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">88.88% </span>
33
+ <span class="strong">52.8% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>8/9</span>
35
+ <span class='fraction'>47/89</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">100% </span>
40
+ <span class="strong">84.09% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>8/8</span>
42
+ <span class='fraction'>37/44</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">96.77% </span>
47
+ <span class="strong">77.63% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>60/62</span>
49
+ <span class='fraction'>125/161</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line high'></div>
64
+ <div class='status-line medium'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -183,93 +183,1018 @@
183
183
  <a name='L118'></a><a href='#L118'>118</a>
184
184
  <a name='L119'></a><a href='#L119'>119</a>
185
185
  <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a>
657
+ <a name='L592'></a><a href='#L592'>592</a>
658
+ <a name='L593'></a><a href='#L593'>593</a>
659
+ <a name='L594'></a><a href='#L594'>594</a>
660
+ <a name='L595'></a><a href='#L595'>595</a>
661
+ <a name='L596'></a><a href='#L596'>596</a>
662
+ <a name='L597'></a><a href='#L597'>597</a>
663
+ <a name='L598'></a><a href='#L598'>598</a>
664
+ <a name='L599'></a><a href='#L599'>599</a>
665
+ <a name='L600'></a><a href='#L600'>600</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-neutral">&nbsp;</span>
668
+ <span class="cline-any cline-neutral">&nbsp;</span>
669
+ <span class="cline-any cline-neutral">&nbsp;</span>
670
+ <span class="cline-any cline-neutral">&nbsp;</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-neutral">&nbsp;</span>
673
+ <span class="cline-any cline-neutral">&nbsp;</span>
674
+ <span class="cline-any cline-neutral">&nbsp;</span>
675
+ <span class="cline-any cline-neutral">&nbsp;</span>
676
+ <span class="cline-any cline-neutral">&nbsp;</span>
677
+ <span class="cline-any cline-neutral">&nbsp;</span>
678
+ <span class="cline-any cline-neutral">&nbsp;</span>
679
+ <span class="cline-any cline-neutral">&nbsp;</span>
680
+ <span class="cline-any cline-neutral">&nbsp;</span>
681
+ <span class="cline-any cline-neutral">&nbsp;</span>
682
+ <span class="cline-any cline-neutral">&nbsp;</span>
683
+ <span class="cline-any cline-neutral">&nbsp;</span>
684
+ <span class="cline-any cline-neutral">&nbsp;</span>
685
+ <span class="cline-any cline-neutral">&nbsp;</span>
686
+ <span class="cline-any cline-neutral">&nbsp;</span>
687
+ <span class="cline-any cline-neutral">&nbsp;</span>
688
+ <span class="cline-any cline-neutral">&nbsp;</span>
689
+ <span class="cline-any cline-neutral">&nbsp;</span>
690
+ <span class="cline-any cline-neutral">&nbsp;</span>
691
+ <span class="cline-any cline-neutral">&nbsp;</span>
692
+ <span class="cline-any cline-neutral">&nbsp;</span>
693
+ <span class="cline-any cline-neutral">&nbsp;</span>
694
+ <span class="cline-any cline-neutral">&nbsp;</span>
695
+ <span class="cline-any cline-neutral">&nbsp;</span>
696
+ <span class="cline-any cline-neutral">&nbsp;</span>
697
+ <span class="cline-any cline-neutral">&nbsp;</span>
698
+ <span class="cline-any cline-neutral">&nbsp;</span>
699
+ <span class="cline-any cline-neutral">&nbsp;</span>
700
+ <span class="cline-any cline-neutral">&nbsp;</span>
701
+ <span class="cline-any cline-neutral">&nbsp;</span>
702
+ <span class="cline-any cline-neutral">&nbsp;</span>
703
+ <span class="cline-any cline-neutral">&nbsp;</span>
704
+ <span class="cline-any cline-neutral">&nbsp;</span>
705
+ <span class="cline-any cline-neutral">&nbsp;</span>
706
+ <span class="cline-any cline-neutral">&nbsp;</span>
707
+ <span class="cline-any cline-neutral">&nbsp;</span>
708
+ <span class="cline-any cline-neutral">&nbsp;</span>
709
+ <span class="cline-any cline-neutral">&nbsp;</span>
710
+ <span class="cline-any cline-neutral">&nbsp;</span>
711
+ <span class="cline-any cline-neutral">&nbsp;</span>
712
+ <span class="cline-any cline-neutral">&nbsp;</span>
713
+ <span class="cline-any cline-neutral">&nbsp;</span>
714
+ <span class="cline-any cline-yes">21x</span>
715
+ <span class="cline-any cline-yes">21x</span>
716
+ <span class="cline-any cline-yes">21x</span>
717
+ <span class="cline-any cline-yes">21x</span>
718
+ <span class="cline-any cline-neutral">&nbsp;</span>
719
+ <span class="cline-any cline-neutral">&nbsp;</span>
720
+ <span class="cline-any cline-neutral">&nbsp;</span>
721
+ <span class="cline-any cline-neutral">&nbsp;</span>
722
+ <span class="cline-any cline-neutral">&nbsp;</span>
723
+ <span class="cline-any cline-neutral">&nbsp;</span>
724
+ <span class="cline-any cline-neutral">&nbsp;</span>
725
+ <span class="cline-any cline-neutral">&nbsp;</span>
726
+ <span class="cline-any cline-neutral">&nbsp;</span>
727
+ <span class="cline-any cline-neutral">&nbsp;</span>
728
+ <span class="cline-any cline-neutral">&nbsp;</span>
729
+ <span class="cline-any cline-neutral">&nbsp;</span>
730
+ <span class="cline-any cline-neutral">&nbsp;</span>
731
+ <span class="cline-any cline-neutral">&nbsp;</span>
732
+ <span class="cline-any cline-neutral">&nbsp;</span>
733
+ <span class="cline-any cline-neutral">&nbsp;</span>
734
+ <span class="cline-any cline-neutral">&nbsp;</span>
735
+ <span class="cline-any cline-neutral">&nbsp;</span>
736
+ <span class="cline-any cline-neutral">&nbsp;</span>
737
+ <span class="cline-any cline-neutral">&nbsp;</span>
738
+ <span class="cline-any cline-neutral">&nbsp;</span>
739
+ <span class="cline-any cline-neutral">&nbsp;</span>
740
+ <span class="cline-any cline-yes">21x</span>
741
+ <span class="cline-any cline-yes">21x</span>
742
+ <span class="cline-any cline-neutral">&nbsp;</span>
743
+ <span class="cline-any cline-neutral">&nbsp;</span>
744
+ <span class="cline-any cline-yes">21x</span>
745
+ <span class="cline-any cline-yes">21x</span>
746
+ <span class="cline-any cline-neutral">&nbsp;</span>
747
+ <span class="cline-any cline-neutral">&nbsp;</span>
748
+ <span class="cline-any cline-neutral">&nbsp;</span>
749
+ <span class="cline-any cline-neutral">&nbsp;</span>
750
+ <span class="cline-any cline-neutral">&nbsp;</span>
751
+ <span class="cline-any cline-neutral">&nbsp;</span>
752
+ <span class="cline-any cline-neutral">&nbsp;</span>
753
+ <span class="cline-any cline-neutral">&nbsp;</span>
754
+ <span class="cline-any cline-neutral">&nbsp;</span>
755
+ <span class="cline-any cline-neutral">&nbsp;</span>
756
+ <span class="cline-any cline-neutral">&nbsp;</span>
757
+ <span class="cline-any cline-neutral">&nbsp;</span>
758
+ <span class="cline-any cline-neutral">&nbsp;</span>
759
+ <span class="cline-any cline-neutral">&nbsp;</span>
760
+ <span class="cline-any cline-neutral">&nbsp;</span>
761
+ <span class="cline-any cline-neutral">&nbsp;</span>
762
+ <span class="cline-any cline-neutral">&nbsp;</span>
763
+ <span class="cline-any cline-neutral">&nbsp;</span>
764
+ <span class="cline-any cline-neutral">&nbsp;</span>
765
+ <span class="cline-any cline-neutral">&nbsp;</span>
766
+ <span class="cline-any cline-neutral">&nbsp;</span>
767
+ <span class="cline-any cline-neutral">&nbsp;</span>
768
+ <span class="cline-any cline-neutral">&nbsp;</span>
769
+ <span class="cline-any cline-yes">13x</span>
770
+ <span class="cline-any cline-yes">13x</span>
771
+ <span class="cline-any cline-neutral">&nbsp;</span>
772
+ <span class="cline-any cline-yes">13x</span>
773
+ <span class="cline-any cline-neutral">&nbsp;</span>
774
+ <span class="cline-any cline-yes">7x</span>
775
+ <span class="cline-any cline-yes">7x</span>
776
+ <span class="cline-any cline-neutral">&nbsp;</span>
777
+ <span class="cline-any cline-neutral">&nbsp;</span>
778
+ <span class="cline-any cline-yes">5x</span>
779
+ <span class="cline-any cline-yes">5x</span>
780
+ <span class="cline-any cline-neutral">&nbsp;</span>
781
+ <span class="cline-any cline-neutral">&nbsp;</span>
782
+ <span class="cline-any cline-yes">1x</span>
783
+ <span class="cline-any cline-yes">1x</span>
784
+ <span class="cline-any cline-neutral">&nbsp;</span>
785
+ <span class="cline-any cline-neutral">&nbsp;</span>
786
+ <span class="cline-any cline-neutral">&nbsp;</span>
787
+ <span class="cline-any cline-neutral">&nbsp;</span>
788
+ <span class="cline-any cline-neutral">&nbsp;</span>
789
+ <span class="cline-any cline-neutral">&nbsp;</span>
790
+ <span class="cline-any cline-neutral">&nbsp;</span>
791
+ <span class="cline-any cline-neutral">&nbsp;</span>
792
+ <span class="cline-any cline-yes">1x</span>
793
+ <span class="cline-any cline-yes">1x</span>
794
+ <span class="cline-any cline-yes">1x</span>
795
+ <span class="cline-any cline-yes">1x</span>
796
+ <span class="cline-any cline-yes">1x</span>
797
+ <span class="cline-any cline-neutral">&nbsp;</span>
798
+ <span class="cline-any cline-neutral">&nbsp;</span>
799
+ <span class="cline-any cline-neutral">&nbsp;</span>
800
+ <span class="cline-any cline-neutral">&nbsp;</span>
801
+ <span class="cline-any cline-neutral">&nbsp;</span>
802
+ <span class="cline-any cline-neutral">&nbsp;</span>
803
+ <span class="cline-any cline-neutral">&nbsp;</span>
804
+ <span class="cline-any cline-neutral">&nbsp;</span>
805
+ <span class="cline-any cline-neutral">&nbsp;</span>
806
+ <span class="cline-any cline-neutral">&nbsp;</span>
807
+ <span class="cline-any cline-yes">3x</span>
808
+ <span class="cline-any cline-yes">3x</span>
809
+ <span class="cline-any cline-yes">3x</span>
810
+ <span class="cline-any cline-yes">5x</span>
811
+ <span class="cline-any cline-neutral">&nbsp;</span>
812
+ <span class="cline-any cline-yes">3x</span>
813
+ <span class="cline-any cline-yes">1x</span>
814
+ <span class="cline-any cline-neutral">&nbsp;</span>
815
+ <span class="cline-any cline-neutral">&nbsp;</span>
816
+ <span class="cline-any cline-neutral">&nbsp;</span>
817
+ <span class="cline-any cline-neutral">&nbsp;</span>
818
+ <span class="cline-any cline-neutral">&nbsp;</span>
819
+ <span class="cline-any cline-neutral">&nbsp;</span>
820
+ <span class="cline-any cline-neutral">&nbsp;</span>
821
+ <span class="cline-any cline-neutral">&nbsp;</span>
822
+ <span class="cline-any cline-neutral">&nbsp;</span>
823
+ <span class="cline-any cline-yes">3x</span>
824
+ <span class="cline-any cline-yes">3x</span>
825
+ <span class="cline-any cline-yes">3x</span>
826
+ <span class="cline-any cline-yes">3x</span>
827
+ <span class="cline-any cline-neutral">&nbsp;</span>
828
+ <span class="cline-any cline-yes">3x</span>
829
+ <span class="cline-any cline-yes">1x</span>
830
+ <span class="cline-any cline-neutral">&nbsp;</span>
831
+ <span class="cline-any cline-neutral">&nbsp;</span>
832
+ <span class="cline-any cline-neutral">&nbsp;</span>
833
+ <span class="cline-any cline-neutral">&nbsp;</span>
834
+ <span class="cline-any cline-neutral">&nbsp;</span>
835
+ <span class="cline-any cline-neutral">&nbsp;</span>
836
+ <span class="cline-any cline-neutral">&nbsp;</span>
837
+ <span class="cline-any cline-neutral">&nbsp;</span>
838
+ <span class="cline-any cline-neutral">&nbsp;</span>
839
+ <span class="cline-any cline-yes">1x</span>
840
+ <span class="cline-any cline-yes">1x</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-yes">1x</span>
843
+ <span class="cline-any cline-no">&nbsp;</span>
844
+ <span class="cline-any cline-neutral">&nbsp;</span>
845
+ <span class="cline-any cline-neutral">&nbsp;</span>
846
+ <span class="cline-any cline-neutral">&nbsp;</span>
847
+ <span class="cline-any cline-neutral">&nbsp;</span>
848
+ <span class="cline-any cline-yes">1x</span>
849
+ <span class="cline-any cline-yes">1x</span>
850
+ <span class="cline-any cline-no">&nbsp;</span>
851
+ <span class="cline-any cline-neutral">&nbsp;</span>
852
+ <span class="cline-any cline-neutral">&nbsp;</span>
853
+ <span class="cline-any cline-neutral">&nbsp;</span>
854
+ <span class="cline-any cline-neutral">&nbsp;</span>
855
+ <span class="cline-any cline-neutral">&nbsp;</span>
856
+ <span class="cline-any cline-neutral">&nbsp;</span>
857
+ <span class="cline-any cline-neutral">&nbsp;</span>
858
+ <span class="cline-any cline-neutral">&nbsp;</span>
859
+ <span class="cline-any cline-neutral">&nbsp;</span>
860
+ <span class="cline-any cline-yes">1x</span>
861
+ <span class="cline-any cline-yes">1x</span>
862
+ <span class="cline-any cline-neutral">&nbsp;</span>
863
+ <span class="cline-any cline-yes">1x</span>
864
+ <span class="cline-any cline-no">&nbsp;</span>
865
+ <span class="cline-any cline-neutral">&nbsp;</span>
866
+ <span class="cline-any cline-neutral">&nbsp;</span>
867
+ <span class="cline-any cline-neutral">&nbsp;</span>
868
+ <span class="cline-any cline-neutral">&nbsp;</span>
869
+ <span class="cline-any cline-yes">1x</span>
870
+ <span class="cline-any cline-yes">1x</span>
871
+ <span class="cline-any cline-no">&nbsp;</span>
872
+ <span class="cline-any cline-neutral">&nbsp;</span>
873
+ <span class="cline-any cline-neutral">&nbsp;</span>
874
+ <span class="cline-any cline-neutral">&nbsp;</span>
875
+ <span class="cline-any cline-neutral">&nbsp;</span>
876
+ <span class="cline-any cline-neutral">&nbsp;</span>
877
+ <span class="cline-any cline-neutral">&nbsp;</span>
187
878
  <span class="cline-any cline-neutral">&nbsp;</span>
188
879
  <span class="cline-any cline-neutral">&nbsp;</span>
189
880
  <span class="cline-any cline-neutral">&nbsp;</span>
190
881
  <span class="cline-any cline-yes">1x</span>
191
882
  <span class="cline-any cline-yes">1x</span>
883
+ <span class="cline-any cline-neutral">&nbsp;</span>
884
+ <span class="cline-any cline-yes">1x</span>
885
+ <span class="cline-any cline-no">&nbsp;</span>
886
+ <span class="cline-any cline-neutral">&nbsp;</span>
887
+ <span class="cline-any cline-neutral">&nbsp;</span>
888
+ <span class="cline-any cline-neutral">&nbsp;</span>
889
+ <span class="cline-any cline-neutral">&nbsp;</span>
890
+ <span class="cline-any cline-yes">1x</span>
891
+ <span class="cline-any cline-yes">1x</span>
892
+ <span class="cline-any cline-no">&nbsp;</span>
893
+ <span class="cline-any cline-neutral">&nbsp;</span>
894
+ <span class="cline-any cline-neutral">&nbsp;</span>
895
+ <span class="cline-any cline-neutral">&nbsp;</span>
896
+ <span class="cline-any cline-neutral">&nbsp;</span>
897
+ <span class="cline-any cline-neutral">&nbsp;</span>
898
+ <span class="cline-any cline-neutral">&nbsp;</span>
899
+ <span class="cline-any cline-neutral">&nbsp;</span>
900
+ <span class="cline-any cline-neutral">&nbsp;</span>
901
+ <span class="cline-any cline-neutral">&nbsp;</span>
902
+ <span class="cline-any cline-yes">1x</span>
903
+ <span class="cline-any cline-yes">1x</span>
904
+ <span class="cline-any cline-neutral">&nbsp;</span>
905
+ <span class="cline-any cline-yes">1x</span>
906
+ <span class="cline-any cline-no">&nbsp;</span>
907
+ <span class="cline-any cline-no">&nbsp;</span>
908
+ <span class="cline-any cline-neutral">&nbsp;</span>
909
+ <span class="cline-any cline-neutral">&nbsp;</span>
910
+ <span class="cline-any cline-neutral">&nbsp;</span>
911
+ <span class="cline-any cline-neutral">&nbsp;</span>
912
+ <span class="cline-any cline-neutral">&nbsp;</span>
913
+ <span class="cline-any cline-neutral">&nbsp;</span>
914
+ <span class="cline-any cline-neutral">&nbsp;</span>
915
+ <span class="cline-any cline-neutral">&nbsp;</span>
916
+ <span class="cline-any cline-neutral">&nbsp;</span>
917
+ <span class="cline-any cline-yes">1x</span>
918
+ <span class="cline-any cline-yes">1x</span>
919
+ <span class="cline-any cline-neutral">&nbsp;</span>
920
+ <span class="cline-any cline-yes">1x</span>
921
+ <span class="cline-any cline-no">&nbsp;</span>
922
+ <span class="cline-any cline-no">&nbsp;</span>
923
+ <span class="cline-any cline-neutral">&nbsp;</span>
924
+ <span class="cline-any cline-neutral">&nbsp;</span>
925
+ <span class="cline-any cline-neutral">&nbsp;</span>
926
+ <span class="cline-any cline-neutral">&nbsp;</span>
927
+ <span class="cline-any cline-neutral">&nbsp;</span>
928
+ <span class="cline-any cline-neutral">&nbsp;</span>
929
+ <span class="cline-any cline-neutral">&nbsp;</span>
930
+ <span class="cline-any cline-neutral">&nbsp;</span>
931
+ <span class="cline-any cline-neutral">&nbsp;</span>
932
+ <span class="cline-any cline-neutral">&nbsp;</span>
933
+ <span class="cline-any cline-neutral">&nbsp;</span>
934
+ <span class="cline-any cline-neutral">&nbsp;</span>
935
+ <span class="cline-any cline-neutral">&nbsp;</span>
936
+ <span class="cline-any cline-no">&nbsp;</span>
937
+ <span class="cline-any cline-no">&nbsp;</span>
938
+ <span class="cline-any cline-no">&nbsp;</span>
939
+ <span class="cline-any cline-neutral">&nbsp;</span>
940
+ <span class="cline-any cline-no">&nbsp;</span>
941
+ <span class="cline-any cline-no">&nbsp;</span>
942
+ <span class="cline-any cline-neutral">&nbsp;</span>
943
+ <span class="cline-any cline-neutral">&nbsp;</span>
944
+ <span class="cline-any cline-neutral">&nbsp;</span>
945
+ <span class="cline-any cline-neutral">&nbsp;</span>
946
+ <span class="cline-any cline-neutral">&nbsp;</span>
947
+ <span class="cline-any cline-neutral">&nbsp;</span>
948
+ <span class="cline-any cline-neutral">&nbsp;</span>
949
+ <span class="cline-any cline-neutral">&nbsp;</span>
950
+ <span class="cline-any cline-neutral">&nbsp;</span>
951
+ <span class="cline-any cline-no">&nbsp;</span>
952
+ <span class="cline-any cline-no">&nbsp;</span>
953
+ <span class="cline-any cline-no">&nbsp;</span>
954
+ <span class="cline-any cline-neutral">&nbsp;</span>
955
+ <span class="cline-any cline-no">&nbsp;</span>
956
+ <span class="cline-any cline-no">&nbsp;</span>
957
+ <span class="cline-any cline-neutral">&nbsp;</span>
958
+ <span class="cline-any cline-neutral">&nbsp;</span>
959
+ <span class="cline-any cline-neutral">&nbsp;</span>
960
+ <span class="cline-any cline-neutral">&nbsp;</span>
961
+ <span class="cline-any cline-neutral">&nbsp;</span>
962
+ <span class="cline-any cline-neutral">&nbsp;</span>
963
+ <span class="cline-any cline-neutral">&nbsp;</span>
964
+ <span class="cline-any cline-neutral">&nbsp;</span>
965
+ <span class="cline-any cline-neutral">&nbsp;</span>
966
+ <span class="cline-any cline-no">&nbsp;</span>
967
+ <span class="cline-any cline-no">&nbsp;</span>
968
+ <span class="cline-any cline-no">&nbsp;</span>
969
+ <span class="cline-any cline-neutral">&nbsp;</span>
970
+ <span class="cline-any cline-no">&nbsp;</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-neutral">&nbsp;</span>
973
+ <span class="cline-any cline-neutral">&nbsp;</span>
974
+ <span class="cline-any cline-neutral">&nbsp;</span>
975
+ <span class="cline-any cline-neutral">&nbsp;</span>
976
+ <span class="cline-any cline-neutral">&nbsp;</span>
977
+ <span class="cline-any cline-neutral">&nbsp;</span>
978
+ <span class="cline-any cline-neutral">&nbsp;</span>
979
+ <span class="cline-any cline-neutral">&nbsp;</span>
980
+ <span class="cline-any cline-neutral">&nbsp;</span>
981
+ <span class="cline-any cline-neutral">&nbsp;</span>
982
+ <span class="cline-any cline-neutral">&nbsp;</span>
983
+ <span class="cline-any cline-neutral">&nbsp;</span>
984
+ <span class="cline-any cline-neutral">&nbsp;</span>
985
+ <span class="cline-any cline-neutral">&nbsp;</span>
986
+ <span class="cline-any cline-neutral">&nbsp;</span>
987
+ <span class="cline-any cline-neutral">&nbsp;</span>
988
+ <span class="cline-any cline-neutral">&nbsp;</span>
989
+ <span class="cline-any cline-neutral">&nbsp;</span>
990
+ <span class="cline-any cline-neutral">&nbsp;</span>
991
+ <span class="cline-any cline-neutral">&nbsp;</span>
992
+ <span class="cline-any cline-yes">8x</span>
993
+ <span class="cline-any cline-yes">8x</span>
994
+ <span class="cline-any cline-yes">8x</span>
995
+ <span class="cline-any cline-neutral">&nbsp;</span>
996
+ <span class="cline-any cline-neutral">&nbsp;</span>
997
+ <span class="cline-any cline-neutral">&nbsp;</span>
998
+ <span class="cline-any cline-neutral">&nbsp;</span>
999
+ <span class="cline-any cline-neutral">&nbsp;</span>
1000
+ <span class="cline-any cline-neutral">&nbsp;</span>
1001
+ <span class="cline-any cline-yes">8x</span>
1002
+ <span class="cline-any cline-neutral">&nbsp;</span>
1003
+ <span class="cline-any cline-neutral">&nbsp;</span>
1004
+ <span class="cline-any cline-neutral">&nbsp;</span>
1005
+ <span class="cline-any cline-neutral">&nbsp;</span>
1006
+ <span class="cline-any cline-neutral">&nbsp;</span>
1007
+ <span class="cline-any cline-neutral">&nbsp;</span>
1008
+ <span class="cline-any cline-neutral">&nbsp;</span>
1009
+ <span class="cline-any cline-neutral">&nbsp;</span>
1010
+ <span class="cline-any cline-neutral">&nbsp;</span>
1011
+ <span class="cline-any cline-neutral">&nbsp;</span>
1012
+ <span class="cline-any cline-yes">7x</span>
1013
+ <span class="cline-any cline-yes">7x</span>
1014
+ <span class="cline-any cline-yes">7x</span>
1015
+ <span class="cline-any cline-neutral">&nbsp;</span>
1016
+ <span class="cline-any cline-neutral">&nbsp;</span>
1017
+ <span class="cline-any cline-neutral">&nbsp;</span>
1018
+ <span class="cline-any cline-neutral">&nbsp;</span>
1019
+ <span class="cline-any cline-yes">7x</span>
1020
+ <span class="cline-any cline-neutral">&nbsp;</span>
1021
+ <span class="cline-any cline-yes">7x</span>
1022
+ <span class="cline-any cline-yes">7x</span>
1023
+ <span class="cline-any cline-yes">7x</span>
1024
+ <span class="cline-any cline-neutral">&nbsp;</span>
1025
+ <span class="cline-any cline-neutral">&nbsp;</span>
1026
+ <span class="cline-any cline-neutral">&nbsp;</span>
1027
+ <span class="cline-any cline-neutral">&nbsp;</span>
1028
+ <span class="cline-any cline-neutral">&nbsp;</span>
1029
+ <span class="cline-any cline-neutral">&nbsp;</span>
1030
+ <span class="cline-any cline-neutral">&nbsp;</span>
192
1031
  <span class="cline-any cline-yes">1x</span>
193
1032
  <span class="cline-any cline-yes">1x</span>
194
1033
  <span class="cline-any cline-yes">1x</span>
195
1034
  <span class="cline-any cline-neutral">&nbsp;</span>
1035
+ <span class="cline-any cline-yes">1x</span>
1036
+ <span class="cline-any cline-no">&nbsp;</span>
1037
+ <span class="cline-any cline-neutral">&nbsp;</span>
1038
+ <span class="cline-any cline-neutral">&nbsp;</span>
1039
+ <span class="cline-any cline-neutral">&nbsp;</span>
1040
+ <span class="cline-any cline-neutral">&nbsp;</span>
1041
+ <span class="cline-any cline-neutral">&nbsp;</span>
1042
+ <span class="cline-any cline-neutral">&nbsp;</span>
1043
+ <span class="cline-any cline-neutral">&nbsp;</span>
1044
+ <span class="cline-any cline-neutral">&nbsp;</span>
1045
+ <span class="cline-any cline-neutral">&nbsp;</span>
1046
+ <span class="cline-any cline-neutral">&nbsp;</span>
1047
+ <span class="cline-any cline-neutral">&nbsp;</span>
1048
+ <span class="cline-any cline-neutral">&nbsp;</span>
1049
+ <span class="cline-any cline-neutral">&nbsp;</span>
1050
+ <span class="cline-any cline-yes">1x</span>
1051
+ <span class="cline-any cline-yes">1x</span>
1052
+ <span class="cline-any cline-yes">1x</span>
1053
+ <span class="cline-any cline-yes">1x</span>
1054
+ <span class="cline-any cline-neutral">&nbsp;</span>
1055
+ <span class="cline-any cline-neutral">&nbsp;</span>
1056
+ <span class="cline-any cline-yes">1x</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-neutral">&nbsp;</span>
1059
+ <span class="cline-any cline-neutral">&nbsp;</span>
1060
+ <span class="cline-any cline-neutral">&nbsp;</span>
1061
+ <span class="cline-any cline-neutral">&nbsp;</span>
1062
+ <span class="cline-any cline-neutral">&nbsp;</span>
1063
+ <span class="cline-any cline-neutral">&nbsp;</span>
1064
+ <span class="cline-any cline-neutral">&nbsp;</span>
1065
+ <span class="cline-any cline-neutral">&nbsp;</span>
1066
+ <span class="cline-any cline-neutral">&nbsp;</span>
1067
+ <span class="cline-any cline-yes">1x</span>
1068
+ <span class="cline-any cline-yes">1x</span>
1069
+ <span class="cline-any cline-yes">3x</span>
1070
+ <span class="cline-any cline-neutral">&nbsp;</span>
1071
+ <span class="cline-any cline-yes">1x</span>
1072
+ <span class="cline-any cline-no">&nbsp;</span>
1073
+ <span class="cline-any cline-neutral">&nbsp;</span>
1074
+ <span class="cline-any cline-neutral">&nbsp;</span>
1075
+ <span class="cline-any cline-neutral">&nbsp;</span>
1076
+ <span class="cline-any cline-neutral">&nbsp;</span>
1077
+ <span class="cline-any cline-neutral">&nbsp;</span>
1078
+ <span class="cline-any cline-neutral">&nbsp;</span>
1079
+ <span class="cline-any cline-neutral">&nbsp;</span>
1080
+ <span class="cline-any cline-neutral">&nbsp;</span>
1081
+ <span class="cline-any cline-neutral">&nbsp;</span>
1082
+ <span class="cline-any cline-yes">2x</span>
1083
+ <span class="cline-any cline-yes">2x</span>
1084
+ <span class="cline-any cline-neutral">&nbsp;</span>
1085
+ <span class="cline-any cline-neutral">&nbsp;</span>
1086
+ <span class="cline-any cline-neutral">&nbsp;</span>
1087
+ <span class="cline-any cline-neutral">&nbsp;</span>
1088
+ <span class="cline-any cline-neutral">&nbsp;</span>
1089
+ <span class="cline-any cline-neutral">&nbsp;</span>
1090
+ <span class="cline-any cline-yes">2x</span>
1091
+ <span class="cline-any cline-yes">2x</span>
1092
+ <span class="cline-any cline-neutral">&nbsp;</span>
1093
+ <span class="cline-any cline-neutral">&nbsp;</span>
1094
+ <span class="cline-any cline-neutral">&nbsp;</span>
1095
+ <span class="cline-any cline-neutral">&nbsp;</span>
1096
+ <span class="cline-any cline-neutral">&nbsp;</span>
1097
+ <span class="cline-any cline-neutral">&nbsp;</span>
1098
+ <span class="cline-any cline-neutral">&nbsp;</span>
1099
+ <span class="cline-any cline-neutral">&nbsp;</span>
1100
+ <span class="cline-any cline-neutral">&nbsp;</span>
1101
+ <span class="cline-any cline-neutral">&nbsp;</span>
1102
+ <span class="cline-any cline-yes">1x</span>
1103
+ <span class="cline-any cline-neutral">&nbsp;</span>
196
1104
  <span class="cline-any cline-neutral">&nbsp;</span>
197
1105
  <span class="cline-any cline-neutral">&nbsp;</span>
198
1106
  <span class="cline-any cline-neutral">&nbsp;</span>
1107
+ <span class="cline-any cline-neutral">&nbsp;</span>
1108
+ <span class="cline-any cline-neutral">&nbsp;</span>
1109
+ <span class="cline-any cline-neutral">&nbsp;</span>
1110
+ <span class="cline-any cline-neutral">&nbsp;</span>
1111
+ <span class="cline-any cline-neutral">&nbsp;</span>
1112
+ <span class="cline-any cline-neutral">&nbsp;</span>
1113
+ <span class="cline-any cline-neutral">&nbsp;</span>
1114
+ <span class="cline-any cline-yes">1x</span>
199
1115
  <span class="cline-any cline-yes">1x</span>
200
1116
  <span class="cline-any cline-yes">1x</span>
201
- <span class="cline-any cline-yes">11x</span>
202
- <span class="cline-any cline-yes">11x</span>
203
- <span class="cline-any cline-yes">11x</span>
204
1117
  <span class="cline-any cline-neutral">&nbsp;</span>
1118
+ <span class="cline-any cline-yes">1x</span>
1119
+ <span class="cline-any cline-yes">3x</span>
1120
+ <span class="cline-any cline-yes">3x</span>
205
1121
  <span class="cline-any cline-neutral">&nbsp;</span>
1122
+ <span class="cline-any cline-yes">3x</span>
206
1123
  <span class="cline-any cline-neutral">&nbsp;</span>
207
1124
  <span class="cline-any cline-neutral">&nbsp;</span>
208
1125
  <span class="cline-any cline-neutral">&nbsp;</span>
209
1126
  <span class="cline-any cline-neutral">&nbsp;</span>
210
- <span class="cline-any cline-yes">1x</span>
211
- <span class="cline-any cline-yes">5x</span>
212
- <span class="cline-any cline-yes">5x</span>
213
- <span class="cline-any cline-yes">5x</span>
214
- <span class="cline-any cline-yes">5x</span>
215
- <span class="cline-any cline-yes">5x</span>
216
- <span class="cline-any cline-yes">5x</span>
217
- <span class="cline-any cline-yes">5x</span>
218
- <span class="cline-any cline-yes">5x</span>
219
- <span class="cline-any cline-yes">5x</span>
220
- <span class="cline-any cline-yes">5x</span>
221
- <span class="cline-any cline-yes">5x</span>
222
- <span class="cline-any cline-yes">5x</span>
223
- <span class="cline-any cline-yes">5x</span>
224
- <span class="cline-any cline-yes">5x</span>
225
1127
  <span class="cline-any cline-neutral">&nbsp;</span>
226
1128
  <span class="cline-any cline-neutral">&nbsp;</span>
227
1129
  <span class="cline-any cline-neutral">&nbsp;</span>
228
1130
  <span class="cline-any cline-neutral">&nbsp;</span>
1131
+ <span class="cline-any cline-yes">3x</span>
1132
+ <span class="cline-any cline-yes">3x</span>
1133
+ <span class="cline-any cline-neutral">&nbsp;</span>
1134
+ <span class="cline-any cline-neutral">&nbsp;</span>
229
1135
  <span class="cline-any cline-neutral">&nbsp;</span>
230
- <span class="cline-any cline-yes">1x</span>
231
- <span class="cline-any cline-yes">5x</span>
232
- <span class="cline-any cline-yes">5x</span>
233
- <span class="cline-any cline-yes">5x</span>
234
- <span class="cline-any cline-yes">5x</span>
235
- <span class="cline-any cline-yes">5x</span>
236
- <span class="cline-any cline-yes">5x</span>
237
- <span class="cline-any cline-yes">5x</span>
238
- <span class="cline-any cline-yes">5x</span>
239
1136
  <span class="cline-any cline-yes">1x</span>
240
1137
  <span class="cline-any cline-neutral">&nbsp;</span>
241
1138
  <span class="cline-any cline-neutral">&nbsp;</span>
242
1139
  <span class="cline-any cline-neutral">&nbsp;</span>
243
1140
  <span class="cline-any cline-neutral">&nbsp;</span>
244
1141
  <span class="cline-any cline-neutral">&nbsp;</span>
1142
+ <span class="cline-any cline-neutral">&nbsp;</span>
1143
+ <span class="cline-any cline-neutral">&nbsp;</span>
245
1144
  <span class="cline-any cline-yes">1x</span>
246
1145
  <span class="cline-any cline-yes">1x</span>
1146
+ <span class="cline-any cline-neutral">&nbsp;</span>
247
1147
  <span class="cline-any cline-yes">1x</span>
248
- <span class="cline-any cline-yes">13x</span>
249
- <span class="cline-any cline-yes">13x</span>
250
- <span class="cline-any cline-yes">13x</span>
251
- <span class="cline-any cline-yes">13x</span>
252
- <span class="cline-any cline-yes">13x</span>
253
- <span class="cline-any cline-yes">13x</span>
1148
+ <span class="cline-any cline-yes">2x</span>
1149
+ <span class="cline-any cline-yes">2x</span>
1150
+ <span class="cline-any cline-neutral">&nbsp;</span>
1151
+ <span class="cline-any cline-yes">2x</span>
1152
+ <span class="cline-any cline-yes">2x</span>
254
1153
  <span class="cline-any cline-neutral">&nbsp;</span>
255
1154
  <span class="cline-any cline-neutral">&nbsp;</span>
1155
+ <span class="cline-any cline-yes">2x</span>
1156
+ <span class="cline-any cline-no">&nbsp;</span>
1157
+ <span class="cline-any cline-no">&nbsp;</span>
1158
+ <span class="cline-any cline-no">&nbsp;</span>
1159
+ <span class="cline-any cline-no">&nbsp;</span>
256
1160
  <span class="cline-any cline-neutral">&nbsp;</span>
257
1161
  <span class="cline-any cline-neutral">&nbsp;</span>
258
1162
  <span class="cline-any cline-neutral">&nbsp;</span>
259
1163
  <span class="cline-any cline-neutral">&nbsp;</span>
260
1164
  <span class="cline-any cline-neutral">&nbsp;</span>
1165
+ <span class="cline-any cline-yes">1x</span>
1166
+ <span class="cline-any cline-yes">2x</span>
261
1167
  <span class="cline-any cline-neutral">&nbsp;</span>
262
1168
  <span class="cline-any cline-neutral">&nbsp;</span>
263
1169
  <span class="cline-any cline-yes">1x</span>
264
- <span class="cline-any cline-yes">11x</span>
265
- <span class="cline-any cline-yes">11x</span>
1170
+ <span class="cline-any cline-neutral">&nbsp;</span>
1171
+ <span class="cline-any cline-neutral">&nbsp;</span>
1172
+ <span class="cline-any cline-neutral">&nbsp;</span>
1173
+ <span class="cline-any cline-neutral">&nbsp;</span>
1174
+ <span class="cline-any cline-neutral">&nbsp;</span>
1175
+ <span class="cline-any cline-neutral">&nbsp;</span>
1176
+ <span class="cline-any cline-neutral">&nbsp;</span>
1177
+ <span class="cline-any cline-yes">44x</span>
1178
+ <span class="cline-any cline-yes">7x</span>
1179
+ <span class="cline-any cline-neutral">&nbsp;</span>
1180
+ <span class="cline-any cline-yes">37x</span>
266
1181
  <span class="cline-any cline-no">&nbsp;</span>
1182
+ <span class="cline-any cline-neutral">&nbsp;</span>
1183
+ <span class="cline-any cline-yes">37x</span>
1184
+ <span class="cline-any cline-neutral">&nbsp;</span>
1185
+ <span class="cline-any cline-neutral">&nbsp;</span>
1186
+ <span class="cline-any cline-neutral">&nbsp;</span>
1187
+ <span class="cline-any cline-neutral">&nbsp;</span>
1188
+ <span class="cline-any cline-neutral">&nbsp;</span>
1189
+ <span class="cline-any cline-neutral">&nbsp;</span>
1190
+ <span class="cline-any cline-neutral">&nbsp;</span>
1191
+ <span class="cline-any cline-yes">7x</span>
1192
+ <span class="cline-any cline-neutral">&nbsp;</span>
267
1193
  <span class="cline-any cline-no">&nbsp;</span>
268
- <span class="cline-any cline-yes">11x</span>
269
- <span class="cline-any cline-yes">11x</span>
270
1194
  <span class="cline-any cline-neutral">&nbsp;</span>
271
1195
  <span class="cline-any cline-neutral">&nbsp;</span>
272
1196
  <span class="cline-any cline-neutral">&nbsp;</span>
1197
+ <span class="cline-any cline-yes">7x</span>
273
1198
  <span class="cline-any cline-neutral">&nbsp;</span>
274
1199
  <span class="cline-any cline-neutral">&nbsp;</span>
275
1200
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -277,150 +1202,662 @@
277
1202
  <span class="cline-any cline-neutral">&nbsp;</span>
278
1203
  <span class="cline-any cline-neutral">&nbsp;</span>
279
1204
  <span class="cline-any cline-neutral">&nbsp;</span>
280
- <span class="cline-any cline-yes">1x</span>
281
- <span class="cline-any cline-yes">3x</span>
282
- <span class="cline-any cline-yes">3x</span>
283
1205
  <span class="cline-any cline-neutral">&nbsp;</span>
1206
+ <span class="cline-any cline-yes">7x</span>
1207
+ <span class="cline-any cline-yes">7x</span>
1208
+ <span class="cline-any cline-neutral">&nbsp;</span>
1209
+ <span class="cline-any cline-neutral">&nbsp;</span>
1210
+ <span class="cline-any cline-neutral">&nbsp;</span>
1211
+ <span class="cline-any cline-neutral">&nbsp;</span>
1212
+ <span class="cline-any cline-neutral">&nbsp;</span>
1213
+ <span class="cline-any cline-yes">7x</span>
1214
+ <span class="cline-any cline-yes">7x</span>
284
1215
  <span class="cline-any cline-neutral">&nbsp;</span>
285
1216
  <span class="cline-any cline-neutral">&nbsp;</span>
286
1217
  <span class="cline-any cline-neutral">&nbsp;</span>
287
1218
  <span class="cline-any cline-neutral">&nbsp;</span>
288
1219
  <span class="cline-any cline-neutral">&nbsp;</span>
289
1220
  <span class="cline-any cline-neutral">&nbsp;</span>
1221
+ <span class="cline-any cline-yes">5x</span>
1222
+ <span class="cline-any cline-neutral">&nbsp;</span>
1223
+ <span class="cline-any cline-neutral">&nbsp;</span>
1224
+ <span class="cline-any cline-neutral">&nbsp;</span>
1225
+ <span class="cline-any cline-neutral">&nbsp;</span>
1226
+ <span class="cline-any cline-neutral">&nbsp;</span>
1227
+ <span class="cline-any cline-neutral">&nbsp;</span>
1228
+ <span class="cline-any cline-neutral">&nbsp;</span>
1229
+ <span class="cline-any cline-neutral">&nbsp;</span>
1230
+ <span class="cline-any cline-neutral">&nbsp;</span>
1231
+ <span class="cline-any cline-neutral">&nbsp;</span>
1232
+ <span class="cline-any cline-neutral">&nbsp;</span>
1233
+ <span class="cline-any cline-neutral">&nbsp;</span>
1234
+ <span class="cline-any cline-neutral">&nbsp;</span>
1235
+ <span class="cline-any cline-yes">1x</span>
1236
+ <span class="cline-any cline-yes">1x</span>
1237
+ <span class="cline-any cline-neutral">&nbsp;</span>
1238
+ <span class="cline-any cline-yes">1x</span>
290
1239
  <span class="cline-any cline-neutral">&nbsp;</span>
291
1240
  <span class="cline-any cline-neutral">&nbsp;</span>
292
1241
  <span class="cline-any cline-neutral">&nbsp;</span>
293
1242
  <span class="cline-any cline-yes">1x</span>
294
- <span class="cline-any cline-yes">4x</span>
295
- <span class="cline-any cline-yes">4x</span>
296
1243
  <span class="cline-any cline-neutral">&nbsp;</span>
297
1244
  <span class="cline-any cline-neutral">&nbsp;</span>
298
1245
  <span class="cline-any cline-neutral">&nbsp;</span>
299
1246
  <span class="cline-any cline-neutral">&nbsp;</span>
300
1247
  <span class="cline-any cline-neutral">&nbsp;</span>
301
1248
  <span class="cline-any cline-neutral">&nbsp;</span>
1249
+ <span class="cline-any cline-neutral">&nbsp;</span>
1250
+ <span class="cline-any cline-neutral">&nbsp;</span>
1251
+ <span class="cline-any cline-neutral">&nbsp;</span>
1252
+ <span class="cline-any cline-yes">1x</span>
1253
+ <span class="cline-any cline-no">&nbsp;</span>
1254
+ <span class="cline-any cline-neutral">&nbsp;</span>
302
1255
  <span class="cline-any cline-yes">1x</span>
303
1256
  <span class="cline-any cline-yes">1x</span>
304
1257
  <span class="cline-any cline-yes">1x</span>
1258
+ <span class="cline-any cline-no">&nbsp;</span>
1259
+ <span class="cline-any cline-neutral">&nbsp;</span>
305
1260
  <span class="cline-any cline-yes">1x</span>
306
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { ClassType, InjectionToken } from '../injection-token.mjs'
307
- import type { Registry } from '../registry.mjs'
308
- import type { Injectors } from '../utils/index.mjs'
1261
+ <span class="cline-any cline-neutral">&nbsp;</span>
1262
+ <span class="cline-any cline-neutral">&nbsp;</span>
1263
+ <span class="cline-any cline-neutral">&nbsp;</span>
1264
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type {
1265
+ BindingBuilder,
1266
+ DependencyGraph,
1267
+ DependencyNode,
1268
+ LifecycleRecord,
1269
+ MethodCallRecord,
1270
+ MockServiceStats,
1271
+ TestContainerOptions,
1272
+ } from './types.mjs'
309
1273
  &nbsp;
310
- import { Container } from '../container.mjs'
311
- import { Injectable } from '../decorators/injectable.decorator.mjs'
1274
+ import { Container } from '../container/container.mjs'
312
1275
  import { InjectableScope, InjectableType } from '../enums/index.mjs'
313
- import { globalRegistry } from '../registry.mjs'
314
- import { getInjectableToken } from '../utils/index.mjs'
1276
+ import {
1277
+ BoundInjectionToken,
1278
+ InjectionToken,
1279
+ } from '../token/injection-token.mjs'
1280
+ import { globalRegistry, Registry } from '../token/registry.mjs'
1281
+ import { getInjectableToken } from '../utils/get-injectable-token.mjs'
1282
+ import { defaultInjectors } from '../utils/index.mjs'
1283
+ &nbsp;
1284
+ type AnyToken =
1285
+ | InjectionToken&lt;any, any&gt;
1286
+ | BoundInjectionToken&lt;any, any&gt;
1287
+ | (new (...args: any[]) =&gt; any)
315
1288
  &nbsp;
316
1289
  /**
317
- * A binding builder for the TestContainer that allows chaining binding operations.
1290
+ * TestContainer extends Container with testing utilities.
1291
+ *
1292
+ * Provides simple value/class binding for integration/e2e tests,
1293
+ * plus assertion helpers and dependency graph inspection.
1294
+ *
1295
+ * @example
1296
+ * ```ts
1297
+ * const container = new TestContainer()
1298
+ *
1299
+ * // Bind mock values
1300
+ * container.bind(DatabaseToken).toValue(mockDatabase)
1301
+ * container.bind(UserService).toClass(MockUserService)
1302
+ *
1303
+ * // Use container normally
1304
+ * const service = await container.get(MyService)
1305
+ *
1306
+ * // Assert on container state
1307
+ * container.expectResolved(MyService)
1308
+ * container.expectSingleton(MyService)
1309
+ * ```
318
1310
  */
319
- export class TestBindingBuilder&lt;T&gt; {
320
- constructor(
321
- private readonly container: TestContainer,
322
- private readonly token: InjectionToken&lt;T, any&gt;,
323
- ) {}
1311
+ export class TestContainer extends Container {
1312
+ private readonly testRegistry: Registry
1313
+ private readonly methodCalls = new Map&lt;string, MethodCallRecord[]&gt;()
1314
+ private readonly lifecycleEvents = new Map&lt;string, LifecycleRecord[]&gt;()
1315
+ private readonly instanceCounts = new Map&lt;string, number&gt;()
1316
+ private readonly boundTokens = new Set&lt;string&gt;()
1317
+ &nbsp;
1318
+ /**
1319
+ * Creates a new TestContainer.
1320
+ *
1321
+ * @param options - Configuration options
1322
+ * @param options.parentRegistry - Parent registry. Defaults to globalRegistry.
1323
+ * Pass `null` for a completely isolated container.
1324
+ * @param options.logger - Optional logger for debugging.
1325
+ *
1326
+ * @example
1327
+ * ```ts
1328
+ * // Uses globalRegistry as parent (default)
1329
+ * const container = new TestContainer()
1330
+ *
1331
+ * // Isolated container (no access to @Injectable classes)
1332
+ * const isolated = new TestContainer({ parentRegistry: null })
1333
+ *
1334
+ * // Custom parent registry
1335
+ * const custom = new TestContainer({ parentRegistry: myRegistry })
1336
+ * ```
1337
+ */
1338
+ constructor(options: TestContainerOptions = {}) {
1339
+ const { parentRegistry = globalRegistry, logger = null } = options
1340
+ const testRegistry = parentRegistry
1341
+ ? new Registry(parentRegistry)
1342
+ : <span class="branch-1 cbranch-no" title="branch not covered" >new Registry()</span>
1343
+ super(testRegistry, logger, defaultInjectors)
1344
+ this.testRegistry = testRegistry
1345
+ }
1346
+ &nbsp;
1347
+ // ============================================================================
1348
+ // BINDING API
1349
+ // ============================================================================
1350
+ &nbsp;
1351
+ /**
1352
+ * Creates a binding builder for the given token.
1353
+ *
1354
+ * @example
1355
+ * ```ts
1356
+ * container.bind(UserService).toValue(mockUserService)
1357
+ * container.bind(DatabaseToken).toClass(MockDatabase)
1358
+ * container.bind(ConfigToken).toFactory(() =&gt; ({ apiKey: 'test' }))
1359
+ * container.bind(BOUND_CONFIG_TOKEN).toValue(overrideValue)
1360
+ * ```
1361
+ */
1362
+ bind&lt;T&gt;(
1363
+ token:
1364
+ | InjectionToken&lt;T, any&gt;
1365
+ | BoundInjectionToken&lt;T, any&gt;
1366
+ | (new (...args: any[]) =&gt; T),
1367
+ ): BindingBuilder&lt;T&gt; {
1368
+ const realToken = this.resolveToken(token)
1369
+ const tokenId = realToken.id
1370
+ &nbsp;
1371
+ return {
1372
+ toValue: (value: T) =&gt; {
1373
+ this.boundTokens.add(tokenId)
1374
+ this.registerValueBinding(realToken, value)
1375
+ },
1376
+ toClass: &lt;C extends new (...args: any[]) =&gt; T&gt;(cls: C) =&gt; {
1377
+ this.boundTokens.add(tokenId)
1378
+ this.registerClassBinding(realToken, cls)
1379
+ },
1380
+ toFactory: (factory: () =&gt; T | Promise&lt;T&gt;) =&gt; {
1381
+ this.boundTokens.add(tokenId)
1382
+ this.registerFactoryBinding(realToken, factory)
1383
+ },
1384
+ }
1385
+ }
1386
+ &nbsp;
1387
+ /**
1388
+ * Clears all bindings and resets container state.
1389
+ */
1390
+ async clear(): Promise&lt;void&gt; {
1391
+ await this.dispose()
1392
+ this.methodCalls.clear()
1393
+ this.lifecycleEvents.clear()
1394
+ this.instanceCounts.clear()
1395
+ this.boundTokens.clear()
1396
+ }
1397
+ &nbsp;
1398
+ // ============================================================================
1399
+ // ASSERTION HELPERS
1400
+ // ============================================================================
1401
+ &nbsp;
1402
+ /**
1403
+ * Asserts that a service has been resolved at least once.
1404
+ */
1405
+ expectResolved(token: AnyToken): void {
1406
+ const realToken = this.resolveToken(token)
1407
+ const storage = this.getStorage()
1408
+ const names = storage.getAllNames()
1409
+ const found = names.some((name) =&gt; name.includes(realToken.id))
1410
+ &nbsp;
1411
+ if (!found) {
1412
+ throw new Error(
1413
+ `Expected ${realToken.toString()} to be resolved, but it was not`,
1414
+ )
1415
+ }
1416
+ }
324
1417
  &nbsp;
325
1418
  /**
326
- * Binds the token to a specific value.
327
- * This is useful for testing with mock values or constants.
328
- * @param value The value to bind to the token
1419
+ * Asserts that a service has NOT been resolved.
329
1420
  */
330
- toValue(value: T): TestContainer {
331
- const instanceName = this.container
332
- .getServiceLocator()
333
- .getInstanceIdentifier(this.token)
334
- this.container
335
- .getServiceLocator()
336
- .getManager()
337
- .storeCreatedHolder(
338
- instanceName,
339
- value,
340
- InjectableType.Class,
341
- InjectableScope.Singleton,
1421
+ expectNotResolved(token: AnyToken): void {
1422
+ const realToken = this.resolveToken(token)
1423
+ const storage = this.getStorage()
1424
+ const names = storage.getAllNames()
1425
+ const found = names.some((name) =&gt; name.includes(realToken.id))
1426
+ &nbsp;
1427
+ if (found) {
1428
+ throw new Error(
1429
+ `Expected ${realToken.toString()} to NOT be resolved, but it was`,
342
1430
  )
343
- return this.container
1431
+ }
344
1432
  }
345
1433
  &nbsp;
346
1434
  /**
347
- * Binds the token to a class constructor.
348
- * @param target The class constructor to bind to
1435
+ * Asserts that a service is registered as singleton scope.
349
1436
  */
350
- toClass(target: ClassType): TestContainer {
351
- this.container['registry'].set(
352
- this.token,
353
- InjectableScope.Singleton,
354
- target,
355
- InjectableType.Class,
1437
+ expectSingleton(token: AnyToken): void {
1438
+ const realToken = this.resolveToken(token)
1439
+ const registry = this.getRegistry()
1440
+ &nbsp;
1441
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!registry.has(realToken)) {
1442
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1443
+ `Expected ${realToken.toString()} to be registered, but it was not`,
1444
+ )
1445
+ }
1446
+ &nbsp;
1447
+ const record = registry.get(realToken)
1448
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (record.scope !== InjectableScope.Singleton) {
1449
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1450
+ `Expected ${realToken.toString()} to be Singleton scope, but it was ${record.scope}`,
1451
+ )
1452
+ }
1453
+ }
1454
+ &nbsp;
1455
+ /**
1456
+ * Asserts that a service is registered as transient scope.
1457
+ */
1458
+ expectTransient(token: AnyToken): void {
1459
+ const realToken = this.resolveToken(token)
1460
+ const registry = this.getRegistry()
1461
+ &nbsp;
1462
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!registry.has(realToken)) {
1463
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1464
+ `Expected ${realToken.toString()} to be registered, but it was not`,
1465
+ )
1466
+ }
1467
+ &nbsp;
1468
+ const record = registry.get(realToken)
1469
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (record.scope !== InjectableScope.Transient) {
1470
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1471
+ `Expected ${realToken.toString()} to be Transient scope, but it was ${record.scope}`,
1472
+ )
1473
+ }
1474
+ }
1475
+ &nbsp;
1476
+ /**
1477
+ * Asserts that a service is registered as request scope.
1478
+ */
1479
+ expectRequestScoped(token: AnyToken): void {
1480
+ const realToken = this.resolveToken(token)
1481
+ const registry = this.getRegistry()
1482
+ &nbsp;
1483
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!registry.has(realToken)) {
1484
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1485
+ `Expected ${realToken.toString()} to be registered, but it was not`,
1486
+ )
1487
+ }
1488
+ &nbsp;
1489
+ const record = registry.get(realToken)
1490
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (record.scope !== InjectableScope.Request) {
1491
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1492
+ `Expected ${realToken.toString()} to be Request scope, but it was ${record.scope}`,
1493
+ )
1494
+ }
1495
+ }
1496
+ &nbsp;
1497
+ /**
1498
+ * Asserts that two service resolutions return the same instance.
1499
+ */
1500
+ async expectSameInstance(token: AnyToken): Promise&lt;void&gt; {
1501
+ const instance1 = await this.get(token as any)
1502
+ const instance2 = await this.get(token as any)
1503
+ &nbsp;
1504
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (instance1 !== instance2) {
1505
+ const realToken = <span class="cstat-no" title="statement not covered" >this.resolveToken(token)</span>
1506
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1507
+ `Expected ${realToken.toString()} to return same instance, but got different instances`,
1508
+ )
1509
+ }
1510
+ }
1511
+ &nbsp;
1512
+ /**
1513
+ * Asserts that two service resolutions return different instances.
1514
+ */
1515
+ async expectDifferentInstances(token: AnyToken): Promise&lt;void&gt; {
1516
+ const instance1 = await this.get(token as any)
1517
+ const instance2 = await this.get(token as any)
1518
+ &nbsp;
1519
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (instance1 === instance2) {
1520
+ const realToken = <span class="cstat-no" title="statement not covered" >this.resolveToken(token)</span>
1521
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1522
+ `Expected ${realToken.toString()} to return different instances, but got same instance`,
1523
+ )
1524
+ }
1525
+ }
1526
+ &nbsp;
1527
+ // ============================================================================
1528
+ // LIFECYCLE ASSERTIONS
1529
+ // ============================================================================
1530
+ &nbsp;
1531
+ /**
1532
+ * Asserts that a service's onServiceInit was called.
1533
+ */
1534
+ <span class="fstat-no" title="function not covered" > expectInitialized(t</span>oken: AnyToken): void {
1535
+ const realToken = <span class="cstat-no" title="statement not covered" >this.resolveToken(token)</span>
1536
+ const events = <span class="cstat-no" title="statement not covered" >this.lifecycleEvents.get(realToken.id) || []</span>
1537
+ const initialized = <span class="cstat-no" title="statement not covered" >events.some(<span class="fstat-no" title="function not covered" >(e</span>) =&gt; <span class="cstat-no" title="statement not covered" >e.event === 'initialized')</span></span>
1538
+ &nbsp;
1539
+ <span class="cstat-no" title="statement not covered" > if (!initialized) {</span>
1540
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1541
+ `Expected ${realToken.toString()} to be initialized, but onServiceInit was not called`,
1542
+ )
1543
+ }
1544
+ }
1545
+ &nbsp;
1546
+ /**
1547
+ * Asserts that a service's onServiceDestroy was called.
1548
+ */
1549
+ <span class="fstat-no" title="function not covered" > expectDestroyed(t</span>oken: AnyToken): void {
1550
+ const realToken = <span class="cstat-no" title="statement not covered" >this.resolveToken(token)</span>
1551
+ const events = <span class="cstat-no" title="statement not covered" >this.lifecycleEvents.get(realToken.id) || []</span>
1552
+ const destroyed = <span class="cstat-no" title="statement not covered" >events.some(<span class="fstat-no" title="function not covered" >(e</span>) =&gt; <span class="cstat-no" title="statement not covered" >e.event === 'destroyed')</span></span>
1553
+ &nbsp;
1554
+ <span class="cstat-no" title="statement not covered" > if (!destroyed) {</span>
1555
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1556
+ `Expected ${realToken.toString()} to be destroyed, but onServiceDestroy was not called`,
1557
+ )
1558
+ }
1559
+ }
1560
+ &nbsp;
1561
+ /**
1562
+ * Asserts that a service has NOT been destroyed.
1563
+ */
1564
+ <span class="fstat-no" title="function not covered" > expectNotDestroyed(t</span>oken: AnyToken): void {
1565
+ const realToken = <span class="cstat-no" title="statement not covered" >this.resolveToken(token)</span>
1566
+ const events = <span class="cstat-no" title="statement not covered" >this.lifecycleEvents.get(realToken.id) || []</span>
1567
+ const destroyed = <span class="cstat-no" title="statement not covered" >events.some(<span class="fstat-no" title="function not covered" >(e</span>) =&gt; <span class="cstat-no" title="statement not covered" >e.event === 'destroyed')</span></span>
1568
+ &nbsp;
1569
+ <span class="cstat-no" title="statement not covered" > if (destroyed) {</span>
1570
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1571
+ `Expected ${realToken.toString()} to NOT be destroyed, but onServiceDestroy was called`,
1572
+ )
1573
+ }
1574
+ }
1575
+ &nbsp;
1576
+ // ============================================================================
1577
+ // CALL TRACKING
1578
+ // ============================================================================
1579
+ &nbsp;
1580
+ /**
1581
+ * Records a method call for tracking.
1582
+ * Call this from your mock implementations.
1583
+ */
1584
+ recordMethodCall(
1585
+ token: AnyToken,
1586
+ method: string,
1587
+ args: unknown[],
1588
+ result?: unknown,
1589
+ error?: Error,
1590
+ ): void {
1591
+ const realToken = this.resolveToken(token)
1592
+ const calls = this.methodCalls.get(realToken.id) || []
1593
+ calls.push({
1594
+ method,
1595
+ args,
1596
+ timestamp: Date.now(),
1597
+ result,
1598
+ error,
1599
+ })
1600
+ this.methodCalls.set(realToken.id, calls)
1601
+ }
1602
+ &nbsp;
1603
+ /**
1604
+ * Records a lifecycle event for tracking.
1605
+ */
1606
+ recordLifecycleEvent(
1607
+ token: AnyToken,
1608
+ event: 'created' | 'initialized' | 'destroyed',
1609
+ instanceName: string,
1610
+ ): void {
1611
+ const realToken = this.resolveToken(token)
1612
+ const events = this.lifecycleEvents.get(realToken.id) || []
1613
+ events.push({
1614
+ event,
1615
+ timestamp: Date.now(),
1616
+ instanceName,
1617
+ })
1618
+ this.lifecycleEvents.set(realToken.id, events)
1619
+ &nbsp;
1620
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (event === 'created') {
1621
+ const count = this.instanceCounts.get(realToken.id) || 0
1622
+ this.instanceCounts.set(realToken.id, count + 1)
1623
+ }
1624
+ }
1625
+ &nbsp;
1626
+ /**
1627
+ * Asserts that a method was called on a service.
1628
+ */
1629
+ expectCalled(token: AnyToken, method: string): void {
1630
+ const realToken = this.resolveToken(token)
1631
+ const calls = this.methodCalls.get(realToken.id) || <span class="branch-1 cbranch-no" title="branch not covered" >[]</span>
1632
+ const found = calls.some((c) =&gt; c.method === method)
1633
+ &nbsp;
1634
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!found) {
1635
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1636
+ `Expected ${realToken.toString()}.${method}() to be called, but it was not`,
1637
+ )
1638
+ }
1639
+ }
1640
+ &nbsp;
1641
+ /**
1642
+ * Asserts that a method was called with specific arguments.
1643
+ */
1644
+ expectCalledWith(
1645
+ token: AnyToken,
1646
+ method: string,
1647
+ expectedArgs: unknown[],
1648
+ ): void {
1649
+ const realToken = this.resolveToken(token)
1650
+ const calls = this.methodCalls.get(realToken.id) || <span class="branch-1 cbranch-no" title="branch not covered" >[]</span>
1651
+ const found = calls.some(
1652
+ (c) =&gt; c.method === method &amp;&amp; this.argsMatch(c.args, expectedArgs),
356
1653
  )
357
- return this.container
1654
+ &nbsp;
1655
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!found) {
1656
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1657
+ `Expected ${realToken.toString()}.${method}() to be called with ${JSON.stringify(expectedArgs)}, but it was not`,
1658
+ )
1659
+ }
358
1660
  }
359
- }
360
1661
  &nbsp;
361
- /**
362
- * TestContainer extends the base Container with additional methods useful for testing.
363
- * It provides a simplified API for binding values and classes during test setup.
364
- */
365
- @Injectable()
366
- export class TestContainer extends Container {
367
- constructor(
368
- registry: Registry = globalRegistry,
369
- logger: Console | null = null,
370
- injectors: Injectors = undefined as any,
371
- ) {
372
- super(registry, logger, injectors)
1662
+ /**
1663
+ * Asserts that a method was called a specific number of times.
1664
+ */
1665
+ expectCallCount(token: AnyToken, method: string, count: number): void {
1666
+ const realToken = this.resolveToken(token)
1667
+ const calls = this.methodCalls.get(realToken.id) || <span class="branch-1 cbranch-no" title="branch not covered" >[]</span>
1668
+ const actualCount = calls.filter((c) =&gt; c.method === method).length
1669
+ &nbsp;
1670
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (actualCount !== count) {
1671
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1672
+ `Expected ${realToken.toString()}.${method}() to be called ${count} times, but was called ${actualCount} times`,
1673
+ )
1674
+ }
373
1675
  }
374
1676
  &nbsp;
375
1677
  /**
376
- * Creates a binding builder for the given token.
377
- * This allows chaining binding operations like bind(Token).toValue(value).
378
- * @param token The injection token to bind
379
- * @returns A TestBindingBuilder for chaining binding operations
1678
+ * Gets all recorded method calls for a service.
1679
+ */
1680
+ getMethodCalls(token: AnyToken): MethodCallRecord[] {
1681
+ const realToken = this.resolveToken(token)
1682
+ return this.methodCalls.get(realToken.id) || []
1683
+ }
1684
+ &nbsp;
1685
+ /**
1686
+ * Gets statistics about a mocked service.
380
1687
  */
381
- bind&lt;T&gt;(token: ClassType): TestBindingBuilder&lt;T&gt;
382
- bind&lt;T&gt;(token: InjectionToken&lt;T, any&gt;): TestBindingBuilder&lt;T&gt;
383
- bind(token: any): TestBindingBuilder&lt;any&gt; {
384
- let realToken = token
385
- if (typeof token === 'function') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
386
- <span class="cstat-no" title="statement not covered" > realToken = getInjectableToken(token)</span>
387
- <span class="cstat-no" title="statement not covered" > }</span>
388
- return new TestBindingBuilder(this, realToken)
1688
+ getServiceStats(token: AnyToken): MockServiceStats {
1689
+ const realToken = this.resolveToken(token)
1690
+ return {
1691
+ instanceCount: this.instanceCounts.get(realToken.id) || <span class="branch-1 cbranch-no" title="branch not covered" >0,</span>
1692
+ methodCalls: this.methodCalls.get(realToken.id) || [],
1693
+ lifecycleEvents: this.lifecycleEvents.get(realToken.id) || <span class="branch-1 cbranch-no" title="branch not covered" >[],</span>
1694
+ }
389
1695
  }
390
1696
  &nbsp;
391
1697
  /**
392
- * Binds a value directly to a token.
393
- * This is a convenience method equivalent to bind(token).toValue(value).
394
- * @param token The injection token to bind
395
- * @param value The value to bind to the token
396
- * @returns The TestContainer instance for chaining
1698
+ * Clears all recorded method calls.
397
1699
  */
398
- bindValue&lt;T&gt;(token: ClassType, value: T): TestContainer
399
- bindValue&lt;T&gt;(token: InjectionToken&lt;T, any&gt;, value: T): TestContainer
400
- bindValue(token: any, value: any): TestContainer {
401
- return this.bind(token).toValue(value)
1700
+ clearMethodCalls(): void {
1701
+ this.methodCalls.clear()
402
1702
  }
1703
+ &nbsp;
1704
+ // ============================================================================
1705
+ // DEPENDENCY GRAPH
1706
+ // ============================================================================
403
1707
  &nbsp;
404
1708
  /**
405
- * Binds a class to a token.
406
- * This is a convenience method equivalent to bind(token).toClass(target).
407
- * @param token The injection token to bind
408
- * @param target The class constructor to bind to
409
- * @returns The TestContainer instance for chaining
1709
+ * Gets the dependency graph for snapshot testing.
1710
+ * Returns a serializable structure that can be used with vitest snapshots.
410
1711
  */
411
- bindClass(token: ClassType, target: ClassType): TestContainer
412
- bindClass&lt;T&gt;(token: InjectionToken&lt;T, any&gt;, target: ClassType): TestContainer
413
- bindClass(token: any, target: any): TestContainer {
414
- return this.bind(token).toClass(target)
1712
+ getDependencyGraph(): DependencyGraph {
1713
+ const storage = this.getStorage()
1714
+ const nodes: Record&lt;string, DependencyNode&gt; = {}
1715
+ const rootTokens: string[] = []
1716
+ &nbsp;
1717
+ storage.forEach((name, holder) =&gt; {
1718
+ const tokenMatch = name.match(/^([^:]+)/)
1719
+ const tokenId = tokenMatch ? tokenMatch[1] : <span class="branch-1 cbranch-no" title="branch not covered" >name</span>
1720
+ &nbsp;
1721
+ nodes[name] = {
1722
+ token: tokenId,
1723
+ instanceName: name,
1724
+ scope: holder.scope,
1725
+ dependencies: Array.from(holder.deps),
1726
+ dependents: storage.findDependents(name),
1727
+ }
1728
+ &nbsp;
1729
+ // Root tokens have no dependents
1730
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (storage.findDependents(name).length === 0) {
1731
+ rootTokens.push(name)
1732
+ }
1733
+ })
1734
+ &nbsp;
1735
+ return { nodes, rootTokens }
415
1736
  }
416
1737
  &nbsp;
417
1738
  /**
418
- * Creates a new TestContainer instance with the same configuration.
419
- * This is useful for creating isolated test containers.
420
- * @returns A new TestContainer instance
1739
+ * Gets a simplified dependency graph showing only token relationships.
1740
+ * Useful for cleaner snapshot comparisons.
421
1741
  */
422
- createChild(): TestContainer {
423
- return new TestContainer(this.registry, this.logger, this.injectors)
1742
+ getSimplifiedDependencyGraph(): Record&lt;string, string[]&gt; {
1743
+ const storage = this.getStorage()
1744
+ const graph: Record&lt;string, string[]&gt; = {}
1745
+ &nbsp;
1746
+ storage.forEach((name, holder) =&gt; {
1747
+ const tokenMatch = name.match(/^([^:]+)/)
1748
+ const tokenId = tokenMatch ? tokenMatch[1] : <span class="branch-1 cbranch-no" title="branch not covered" >name</span>
1749
+ &nbsp;
1750
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (!graph[tokenId]) {
1751
+ graph[tokenId] = []
1752
+ }
1753
+ &nbsp;
1754
+ for (const dep of holder.deps) {
1755
+ const depTokenMatch = <span class="cstat-no" title="statement not covered" >dep.match(/^([^:]+)/)</span>
1756
+ const depTokenId = <span class="cstat-no" title="statement not covered" >depTokenMatch ? depTokenMatch[1] : dep</span>
1757
+ <span class="cstat-no" title="statement not covered" > if (!graph[tokenId].includes(depTokenId)) {</span>
1758
+ <span class="cstat-no" title="statement not covered" > graph[tokenId].push(depTokenId)</span>
1759
+ }
1760
+ }
1761
+ })
1762
+ &nbsp;
1763
+ // Sort for consistent snapshots
1764
+ for (const key of Object.keys(graph)) {
1765
+ graph[key].sort()
1766
+ }
1767
+ &nbsp;
1768
+ return graph
1769
+ }
1770
+ &nbsp;
1771
+ // ============================================================================
1772
+ // INTERNAL HELPERS
1773
+ // ============================================================================
1774
+ &nbsp;
1775
+ private resolveToken(token: AnyToken): InjectionToken&lt;any, any&gt; {
1776
+ if (typeof token === 'function') {
1777
+ return getInjectableToken(token)
1778
+ }
1779
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (token instanceof BoundInjectionToken) {
1780
+ <span class="cstat-no" title="statement not covered" > return token.token</span>
1781
+ }
1782
+ return token
1783
+ }
1784
+ &nbsp;
1785
+ private registerValueBinding&lt;T&gt;(
1786
+ token: InjectionToken&lt;T, any&gt;,
1787
+ value: T,
1788
+ ): void {
1789
+ // Create a simple class that returns the value
1790
+ const ValueHolder = class {
1791
+ <span class="fstat-no" title="function not covered" > create(): T {</span>
1792
+ <span class="cstat-no" title="statement not covered" > return value</span>
1793
+ }
1794
+ }
1795
+ &nbsp;
1796
+ this.testRegistry.set(
1797
+ token,
1798
+ InjectableScope.Singleton,
1799
+ ValueHolder,
1800
+ InjectableType.Factory,
1801
+ 1000, // Higher priority for test overrides
1802
+ )
1803
+ &nbsp;
1804
+ // Store the instance directly
1805
+ const nameResolver = this.getNameResolver()
1806
+ const instanceName = nameResolver.generateInstanceName(
1807
+ token,
1808
+ undefined,
1809
+ undefined,
1810
+ InjectableScope.Singleton,
1811
+ )
1812
+ this.getStorage().storeInstance(instanceName, value)
1813
+ this.recordLifecycleEvent(token, 'created', instanceName)
1814
+ }
1815
+ &nbsp;
1816
+ private registerClassBinding&lt;T&gt;(
1817
+ token: InjectionToken&lt;T, any&gt;,
1818
+ cls: new (...args: any[]) =&gt; T,
1819
+ ): void {
1820
+ this.testRegistry.set(
1821
+ token,
1822
+ InjectableScope.Singleton,
1823
+ cls,
1824
+ InjectableType.Class,
1825
+ 1000, // Higher priority for test overrides
1826
+ )
1827
+ }
1828
+ &nbsp;
1829
+ private registerFactoryBinding&lt;T&gt;(
1830
+ token: InjectionToken&lt;T, any&gt;,
1831
+ factory: () =&gt; T | Promise&lt;T&gt;,
1832
+ ): void {
1833
+ // Create a factory class wrapper
1834
+ const FactoryWrapper = class {
1835
+ static factory = factory
1836
+ async create(): Promise&lt;T&gt; {
1837
+ return await factory()
1838
+ }
1839
+ }
1840
+ &nbsp;
1841
+ this.testRegistry.set(
1842
+ token,
1843
+ InjectableScope.Singleton,
1844
+ FactoryWrapper,
1845
+ InjectableType.Factory,
1846
+ 1000, // Higher priority for test overrides
1847
+ )
1848
+ }
1849
+ &nbsp;
1850
+ private argsMatch(actual: unknown[], expected: unknown[]): boolean {
1851
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (actual.length !== expected.length) {
1852
+ <span class="cstat-no" title="statement not covered" > return false</span>
1853
+ }
1854
+ return actual.every((arg, index) =&gt; {
1855
+ const exp = expected[index]
1856
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (typeof exp === 'object' &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >exp !== null) {</span>
1857
+ <span class="cstat-no" title="statement not covered" > return JSON.stringify(arg) === JSON.stringify(exp)</span>
1858
+ }
1859
+ return arg === exp
1860
+ })
424
1861
  }
425
1862
  }
426
1863
  &nbsp;</pre></td></tr></table></pre>
@@ -430,7 +1867,7 @@ export class TestContainer extends Container {
430
1867
  <div class='footer quiet pad2 space-top1 center small'>
431
1868
  Code coverage generated by
432
1869
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
433
- at 2025-09-21T17:47:07.632Z
1870
+ at 2026-01-08T12:15:46.476Z
434
1871
  </div>
435
1872
  <script src="../../prettify.js"></script>
436
1873
  <script>