@navios/di 0.4.2 → 0.5.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 (120) hide show
  1. package/README.md +211 -1
  2. package/coverage/clover.xml +1912 -1277
  3. package/coverage/coverage-final.json +37 -28
  4. package/coverage/docs/examples/basic-usage.mts.html +1 -1
  5. package/coverage/docs/examples/factory-pattern.mts.html +1 -1
  6. package/coverage/docs/examples/index.html +1 -1
  7. package/coverage/docs/examples/injection-tokens.mts.html +1 -1
  8. package/coverage/docs/examples/request-scope-example.mts.html +1 -1
  9. package/coverage/docs/examples/service-lifecycle.mts.html +1 -1
  10. package/coverage/index.html +71 -41
  11. package/coverage/lib/_tsup-dts-rollup.d.mts.html +682 -43
  12. package/coverage/lib/index.d.mts.html +7 -4
  13. package/coverage/lib/index.html +5 -5
  14. package/coverage/lib/testing/index.d.mts.html +91 -0
  15. package/coverage/lib/testing/index.html +116 -0
  16. package/coverage/src/base-instance-holder-manager.mts.html +589 -0
  17. package/coverage/src/container.mts.html +257 -74
  18. package/coverage/src/decorators/factory.decorator.mts.html +1 -1
  19. package/coverage/src/decorators/index.html +1 -1
  20. package/coverage/src/decorators/index.mts.html +1 -1
  21. package/coverage/src/decorators/injectable.decorator.mts.html +20 -20
  22. package/coverage/src/enums/index.html +1 -1
  23. package/coverage/src/enums/index.mts.html +1 -1
  24. package/coverage/src/enums/injectable-scope.enum.mts.html +1 -1
  25. package/coverage/src/enums/injectable-type.enum.mts.html +1 -1
  26. package/coverage/src/errors/di-error.mts.html +292 -0
  27. package/coverage/src/errors/errors.enum.mts.html +30 -21
  28. package/coverage/src/errors/factory-not-found.mts.html +31 -22
  29. package/coverage/src/errors/factory-token-not-resolved.mts.html +29 -26
  30. package/coverage/src/errors/index.html +56 -41
  31. package/coverage/src/errors/index.mts.html +15 -9
  32. package/coverage/src/errors/instance-destroying.mts.html +31 -22
  33. package/coverage/src/errors/instance-expired.mts.html +31 -22
  34. package/coverage/src/errors/instance-not-found.mts.html +31 -22
  35. package/coverage/src/errors/unknown-error.mts.html +31 -43
  36. package/coverage/src/event-emitter.mts.html +14 -14
  37. package/coverage/src/factory-context.mts.html +1 -1
  38. package/coverage/src/index.html +121 -46
  39. package/coverage/src/index.mts.html +7 -4
  40. package/coverage/src/injection-token.mts.html +28 -28
  41. package/coverage/src/injector.mts.html +1 -1
  42. package/coverage/src/instance-resolver.mts.html +1762 -0
  43. package/coverage/src/interfaces/factory.interface.mts.html +1 -1
  44. package/coverage/src/interfaces/index.html +1 -1
  45. package/coverage/src/interfaces/index.mts.html +1 -1
  46. package/coverage/src/interfaces/on-service-destroy.interface.mts.html +1 -1
  47. package/coverage/src/interfaces/on-service-init.interface.mts.html +1 -1
  48. package/coverage/src/registry.mts.html +28 -28
  49. package/coverage/src/request-context-holder.mts.html +183 -102
  50. package/coverage/src/request-context-manager.mts.html +532 -0
  51. package/coverage/src/service-instantiator.mts.html +49 -49
  52. package/coverage/src/service-invalidator.mts.html +1372 -0
  53. package/coverage/src/service-locator-event-bus.mts.html +48 -48
  54. package/coverage/src/service-locator-instance-holder.mts.html +2 -14
  55. package/coverage/src/service-locator-manager.mts.html +71 -335
  56. package/coverage/src/service-locator.mts.html +240 -2328
  57. package/coverage/src/symbols/index.html +1 -1
  58. package/coverage/src/symbols/index.mts.html +1 -1
  59. package/coverage/src/symbols/injectable-token.mts.html +1 -1
  60. package/coverage/src/testing/index.html +131 -0
  61. package/coverage/src/testing/index.mts.html +88 -0
  62. package/coverage/src/testing/test-container.mts.html +445 -0
  63. package/coverage/src/token-processor.mts.html +607 -0
  64. package/coverage/src/utils/defer.mts.html +28 -214
  65. package/coverage/src/utils/get-injectable-token.mts.html +7 -7
  66. package/coverage/src/utils/get-injectors.mts.html +99 -99
  67. package/coverage/src/utils/index.html +15 -15
  68. package/coverage/src/utils/index.mts.html +4 -7
  69. package/coverage/src/utils/types.mts.html +1 -1
  70. package/docs/injectable.md +51 -11
  71. package/docs/scopes.md +63 -29
  72. package/lib/_tsup-dts-rollup.d.mts +376 -213
  73. package/lib/_tsup-dts-rollup.d.ts +376 -213
  74. package/lib/{chunk-3NLYPYBY.mjs → chunk-44F3LXW5.mjs} +1021 -605
  75. package/lib/chunk-44F3LXW5.mjs.map +1 -0
  76. package/lib/index.d.mts +6 -4
  77. package/lib/index.d.ts +6 -4
  78. package/lib/index.js +1192 -776
  79. package/lib/index.js.map +1 -1
  80. package/lib/index.mjs +2 -2
  81. package/lib/testing/index.js +1258 -840
  82. package/lib/testing/index.js.map +1 -1
  83. package/lib/testing/index.mjs +1 -1
  84. package/package.json +1 -1
  85. package/src/__tests__/container.spec.mts +47 -13
  86. package/src/__tests__/errors.spec.mts +53 -27
  87. package/src/__tests__/injectable.spec.mts +73 -0
  88. package/src/__tests__/request-scope.spec.mts +0 -2
  89. package/src/__tests__/service-locator-manager.spec.mts +12 -82
  90. package/src/__tests__/service-locator.spec.mts +1009 -1
  91. package/src/__type-tests__/inject.spec-d.mts +30 -7
  92. package/src/__type-tests__/injectable.spec-d.mts +76 -37
  93. package/src/base-instance-holder-manager.mts +2 -9
  94. package/src/container.mts +61 -9
  95. package/src/decorators/injectable.decorator.mts +29 -5
  96. package/src/errors/di-error.mts +69 -0
  97. package/src/errors/index.mts +9 -7
  98. package/src/injection-token.mts +1 -0
  99. package/src/injector.mts +2 -0
  100. package/src/instance-resolver.mts +559 -0
  101. package/src/request-context-holder.mts +0 -2
  102. package/src/request-context-manager.mts +149 -0
  103. package/src/service-invalidator.mts +429 -0
  104. package/src/service-locator-instance-holder.mts +0 -4
  105. package/src/service-locator-manager.mts +10 -40
  106. package/src/service-locator.mts +86 -782
  107. package/src/token-processor.mts +174 -0
  108. package/src/utils/get-injectors.mts +161 -24
  109. package/src/utils/index.mts +0 -1
  110. package/src/utils/types.mts +12 -8
  111. package/lib/chunk-3NLYPYBY.mjs.map +0 -1
  112. package/src/__tests__/defer.spec.mts +0 -166
  113. package/src/errors/errors.enum.mts +0 -8
  114. package/src/errors/factory-not-found.mts +0 -8
  115. package/src/errors/factory-token-not-resolved.mts +0 -10
  116. package/src/errors/instance-destroying.mts +0 -8
  117. package/src/errors/instance-expired.mts +0 -8
  118. package/src/errors/instance-not-found.mts +0 -8
  119. package/src/errors/unknown-error.mts +0 -15
  120. package/src/utils/defer.mts +0 -73
@@ -0,0 +1,1372 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/service-invalidator.mts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../prettify.css" />
9
+ <link rel="stylesheet" href="../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> service-invalidator.mts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">78.91% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>232/294</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">87.27% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>48/55</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">79.16% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>19/24</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">78.91% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>232/294</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line medium'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
496
+ <span class="cline-any cline-neutral">&nbsp;</span>
497
+ <span class="cline-any cline-neutral">&nbsp;</span>
498
+ <span class="cline-any cline-neutral">&nbsp;</span>
499
+ <span class="cline-any cline-neutral">&nbsp;</span>
500
+ <span class="cline-any cline-neutral">&nbsp;</span>
501
+ <span class="cline-any cline-yes">1x</span>
502
+ <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-neutral">&nbsp;</span>
506
+ <span class="cline-any cline-neutral">&nbsp;</span>
507
+ <span class="cline-any cline-neutral">&nbsp;</span>
508
+ <span class="cline-any cline-neutral">&nbsp;</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-neutral">&nbsp;</span>
512
+ <span class="cline-any cline-neutral">&nbsp;</span>
513
+ <span class="cline-any cline-neutral">&nbsp;</span>
514
+ <span class="cline-any cline-neutral">&nbsp;</span>
515
+ <span class="cline-any cline-neutral">&nbsp;</span>
516
+ <span class="cline-any cline-yes">1x</span>
517
+ <span class="cline-any cline-yes">1x</span>
518
+ <span class="cline-any cline-yes">143x</span>
519
+ <span class="cline-any cline-yes">143x</span>
520
+ <span class="cline-any cline-yes">143x</span>
521
+ <span class="cline-any cline-yes">143x</span>
522
+ <span class="cline-any cline-yes">143x</span>
523
+ <span class="cline-any cline-neutral">&nbsp;</span>
524
+ <span class="cline-any cline-neutral">&nbsp;</span>
525
+ <span class="cline-any cline-neutral">&nbsp;</span>
526
+ <span class="cline-any cline-neutral">&nbsp;</span>
527
+ <span class="cline-any cline-yes">1x</span>
528
+ <span class="cline-any cline-yes">37x</span>
529
+ <span class="cline-any cline-yes">37x</span>
530
+ <span class="cline-any cline-yes">37x</span>
531
+ <span class="cline-any cline-yes">37x</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-yes">37x</span>
534
+ <span class="cline-any cline-yes">37x</span>
535
+ <span class="cline-any cline-yes">32x</span>
536
+ <span class="cline-any cline-yes">32x</span>
537
+ <span class="cline-any cline-neutral">&nbsp;</span>
538
+ <span class="cline-any cline-neutral">&nbsp;</span>
539
+ <span class="cline-any cline-yes">37x</span>
540
+ <span class="cline-any cline-yes">37x</span>
541
+ <span class="cline-any cline-yes">6x</span>
542
+ <span class="cline-any cline-yes">6x</span>
543
+ <span class="cline-any cline-yes">2x</span>
544
+ <span class="cline-any cline-yes">2x</span>
545
+ <span class="cline-any cline-yes">2x</span>
546
+ <span class="cline-any cline-yes">2x</span>
547
+ <span class="cline-any cline-yes">2x</span>
548
+ <span class="cline-any cline-yes">2x</span>
549
+ <span class="cline-any cline-yes">2x</span>
550
+ <span class="cline-any cline-yes">6x</span>
551
+ <span class="cline-any cline-neutral">&nbsp;</span>
552
+ <span class="cline-any cline-yes">37x</span>
553
+ <span class="cline-any cline-yes">37x</span>
554
+ <span class="cline-any cline-neutral">&nbsp;</span>
555
+ <span class="cline-any cline-neutral">&nbsp;</span>
556
+ <span class="cline-any cline-neutral">&nbsp;</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-neutral">&nbsp;</span>
559
+ <span class="cline-any cline-neutral">&nbsp;</span>
560
+ <span class="cline-any cline-yes">1x</span>
561
+ <span class="cline-any cline-yes">10x</span>
562
+ <span class="cline-any cline-yes">10x</span>
563
+ <span class="cline-any cline-yes">10x</span>
564
+ <span class="cline-any cline-yes">10x</span>
565
+ <span class="cline-any cline-yes">10x</span>
566
+ <span class="cline-any cline-neutral">&nbsp;</span>
567
+ <span class="cline-any cline-yes">10x</span>
568
+ <span class="cline-any cline-yes">10x</span>
569
+ <span class="cline-any cline-yes">10x</span>
570
+ <span class="cline-any cline-neutral">&nbsp;</span>
571
+ <span class="cline-any cline-neutral">&nbsp;</span>
572
+ <span class="cline-any cline-yes">10x</span>
573
+ <span class="cline-any cline-yes">10x</span>
574
+ <span class="cline-any cline-yes">10x</span>
575
+ <span class="cline-any cline-yes">10x</span>
576
+ <span class="cline-any cline-yes">10x</span>
577
+ <span class="cline-any cline-yes">10x</span>
578
+ <span class="cline-any cline-neutral">&nbsp;</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-yes">10x</span>
581
+ <span class="cline-any cline-neutral">&nbsp;</span>
582
+ <span class="cline-any cline-yes">10x</span>
583
+ <span class="cline-any cline-yes">4x</span>
584
+ <span class="cline-any cline-yes">10x</span>
585
+ <span class="cline-any cline-yes">6x</span>
586
+ <span class="cline-any cline-yes">6x</span>
587
+ <span class="cline-any cline-yes">6x</span>
588
+ <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-neutral">&nbsp;</span>
590
+ <span class="cline-any cline-yes">6x</span>
591
+ <span class="cline-any cline-yes">6x</span>
592
+ <span class="cline-any cline-yes">6x</span>
593
+ <span class="cline-any cline-yes">6x</span>
594
+ <span class="cline-any cline-yes">6x</span>
595
+ <span class="cline-any cline-neutral">&nbsp;</span>
596
+ <span class="cline-any cline-neutral">&nbsp;</span>
597
+ <span class="cline-any cline-yes">10x</span>
598
+ <span class="cline-any cline-yes">9x</span>
599
+ <span class="cline-any cline-yes">9x</span>
600
+ <span class="cline-any cline-neutral">&nbsp;</span>
601
+ <span class="cline-any cline-yes">10x</span>
602
+ <span class="cline-any cline-yes">10x</span>
603
+ <span class="cline-any cline-neutral">&nbsp;</span>
604
+ <span class="cline-any cline-neutral">&nbsp;</span>
605
+ <span class="cline-any cline-neutral">&nbsp;</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-yes">1x</span>
608
+ <span class="cline-any cline-yes">11x</span>
609
+ <span class="cline-any cline-yes">11x</span>
610
+ <span class="cline-any cline-yes">11x</span>
611
+ <span class="cline-any cline-yes">11x</span>
612
+ <span class="cline-any cline-yes">11x</span>
613
+ <span class="cline-any cline-yes">11x</span>
614
+ <span class="cline-any cline-yes">11x</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span>
619
+ <span class="cline-any cline-yes">1x</span>
620
+ <span class="cline-any cline-yes">32x</span>
621
+ <span class="cline-any cline-yes">32x</span>
622
+ <span class="cline-any cline-yes">32x</span>
623
+ <span class="cline-any cline-yes">32x</span>
624
+ <span class="cline-any cline-yes">32x</span>
625
+ <span class="cline-any cline-yes">32x</span>
626
+ <span class="cline-any cline-yes">32x</span>
627
+ <span class="cline-any cline-yes">32x</span>
628
+ <span class="cline-any cline-no">&nbsp;</span>
629
+ <span class="cline-any cline-no">&nbsp;</span>
630
+ <span class="cline-any cline-no">&nbsp;</span>
631
+ <span class="cline-any cline-yes">32x</span>
632
+ <span class="cline-any cline-yes">32x</span>
633
+ <span class="cline-any cline-yes">32x</span>
634
+ <span class="cline-any cline-yes">32x</span>
635
+ <span class="cline-any cline-neutral">&nbsp;</span>
636
+ <span class="cline-any cline-neutral">&nbsp;</span>
637
+ <span class="cline-any cline-neutral">&nbsp;</span>
638
+ <span class="cline-any cline-neutral">&nbsp;</span>
639
+ <span class="cline-any cline-yes">1x</span>
640
+ <span class="cline-any cline-yes">2x</span>
641
+ <span class="cline-any cline-yes">2x</span>
642
+ <span class="cline-any cline-yes">2x</span>
643
+ <span class="cline-any cline-yes">2x</span>
644
+ <span class="cline-any cline-yes">2x</span>
645
+ <span class="cline-any cline-yes">2x</span>
646
+ <span class="cline-any cline-yes">2x</span>
647
+ <span class="cline-any cline-yes">2x</span>
648
+ <span class="cline-any cline-yes">2x</span>
649
+ <span class="cline-any cline-no">&nbsp;</span>
650
+ <span class="cline-any cline-no">&nbsp;</span>
651
+ <span class="cline-any cline-no">&nbsp;</span>
652
+ <span class="cline-any cline-yes">2x</span>
653
+ <span class="cline-any cline-no">&nbsp;</span>
654
+ <span class="cline-any cline-no">&nbsp;</span>
655
+ <span class="cline-any cline-no">&nbsp;</span>
656
+ <span class="cline-any cline-no">&nbsp;</span>
657
+ <span class="cline-any cline-no">&nbsp;</span>
658
+ <span class="cline-any cline-no">&nbsp;</span>
659
+ <span class="cline-any cline-yes">2x</span>
660
+ <span class="cline-any cline-yes">2x</span>
661
+ <span class="cline-any cline-yes">2x</span>
662
+ <span class="cline-any cline-yes">2x</span>
663
+ <span class="cline-any cline-neutral">&nbsp;</span>
664
+ <span class="cline-any cline-neutral">&nbsp;</span>
665
+ <span class="cline-any cline-neutral">&nbsp;</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-yes">1x</span>
668
+ <span class="cline-any cline-yes">34x</span>
669
+ <span class="cline-any cline-yes">34x</span>
670
+ <span class="cline-any cline-yes">34x</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-yes">34x</span>
678
+ <span class="cline-any cline-yes">34x</span>
679
+ <span class="cline-any cline-yes">34x</span>
680
+ <span class="cline-any cline-no">&nbsp;</span>
681
+ <span class="cline-any cline-no">&nbsp;</span>
682
+ <span class="cline-any cline-neutral">&nbsp;</span>
683
+ <span class="cline-any cline-yes">34x</span>
684
+ <span class="cline-any cline-no">&nbsp;</span>
685
+ <span class="cline-any cline-no">&nbsp;</span>
686
+ <span class="cline-any cline-no">&nbsp;</span>
687
+ <span class="cline-any cline-no">&nbsp;</span>
688
+ <span class="cline-any cline-no">&nbsp;</span>
689
+ <span class="cline-any cline-no">&nbsp;</span>
690
+ <span class="cline-any cline-no">&nbsp;</span>
691
+ <span class="cline-any cline-neutral">&nbsp;</span>
692
+ <span class="cline-any cline-yes">34x</span>
693
+ <span class="cline-any cline-yes">34x</span>
694
+ <span class="cline-any cline-yes">34x</span>
695
+ <span class="cline-any cline-yes">34x</span>
696
+ <span class="cline-any cline-yes">34x</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-yes">1x</span>
702
+ <span class="cline-any cline-yes">32x</span>
703
+ <span class="cline-any cline-yes">32x</span>
704
+ <span class="cline-any cline-yes">32x</span>
705
+ <span class="cline-any cline-yes">32x</span>
706
+ <span class="cline-any cline-yes">32x</span>
707
+ <span class="cline-any cline-yes">32x</span>
708
+ <span class="cline-any cline-yes">32x</span>
709
+ <span class="cline-any cline-yes">32x</span>
710
+ <span class="cline-any cline-yes">32x</span>
711
+ <span class="cline-any cline-yes">32x</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-neutral">&nbsp;</span>
715
+ <span class="cline-any cline-neutral">&nbsp;</span>
716
+ <span class="cline-any cline-yes">1x</span>
717
+ <span class="cline-any cline-yes">2x</span>
718
+ <span class="cline-any cline-yes">2x</span>
719
+ <span class="cline-any cline-yes">2x</span>
720
+ <span class="cline-any cline-yes">2x</span>
721
+ <span class="cline-any cline-yes">2x</span>
722
+ <span class="cline-any cline-yes">2x</span>
723
+ <span class="cline-any cline-yes">2x</span>
724
+ <span class="cline-any cline-yes">2x</span>
725
+ <span class="cline-any cline-yes">2x</span>
726
+ <span class="cline-any cline-yes">2x</span>
727
+ <span class="cline-any cline-yes">2x</span>
728
+ <span class="cline-any cline-yes">2x</span>
729
+ <span class="cline-any cline-yes">2x</span>
730
+ <span class="cline-any cline-yes">2x</span>
731
+ <span class="cline-any cline-yes">2x</span>
732
+ <span class="cline-any cline-yes">2x</span>
733
+ <span class="cline-any cline-yes">2x</span>
734
+ <span class="cline-any cline-yes">2x</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-yes">1x</span>
740
+ <span class="cline-any cline-yes">34x</span>
741
+ <span class="cline-any cline-yes">34x</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-neutral">&nbsp;</span>
745
+ <span class="cline-any cline-neutral">&nbsp;</span>
746
+ <span class="cline-any cline-neutral">&nbsp;</span>
747
+ <span class="cline-any cline-yes">34x</span>
748
+ <span class="cline-any cline-yes">34x</span>
749
+ <span class="cline-any cline-yes">34x</span>
750
+ <span class="cline-any cline-neutral">&nbsp;</span>
751
+ <span class="cline-any cline-yes">34x</span>
752
+ <span class="cline-any cline-yes">34x</span>
753
+ <span class="cline-any cline-yes">34x</span>
754
+ <span class="cline-any cline-yes">34x</span>
755
+ <span class="cline-any cline-yes">34x</span>
756
+ <span class="cline-any cline-yes">34x</span>
757
+ <span class="cline-any cline-yes">34x</span>
758
+ <span class="cline-any cline-yes">34x</span>
759
+ <span class="cline-any cline-neutral">&nbsp;</span>
760
+ <span class="cline-any cline-yes">34x</span>
761
+ <span class="cline-any cline-yes">34x</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-yes">1x</span>
767
+ <span class="cline-any cline-yes">12x</span>
768
+ <span class="cline-any cline-yes">12x</span>
769
+ <span class="cline-any cline-yes">12x</span>
770
+ <span class="cline-any cline-yes">12x</span>
771
+ <span class="cline-any cline-no">&nbsp;</span>
772
+ <span class="cline-any cline-no">&nbsp;</span>
773
+ <span class="cline-any cline-yes">12x</span>
774
+ <span class="cline-any cline-no">&nbsp;</span>
775
+ <span class="cline-any cline-no">&nbsp;</span>
776
+ <span class="cline-any cline-neutral">&nbsp;</span>
777
+ <span class="cline-any cline-yes">12x</span>
778
+ <span class="cline-any cline-yes">12x</span>
779
+ <span class="cline-any cline-yes">12x</span>
780
+ <span class="cline-any cline-yes">12x</span>
781
+ <span class="cline-any cline-yes">12x</span>
782
+ <span class="cline-any cline-neutral">&nbsp;</span>
783
+ <span class="cline-any cline-neutral">&nbsp;</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-yes">1x</span>
788
+ <span class="cline-any cline-yes">6x</span>
789
+ <span class="cline-any cline-yes">6x</span>
790
+ <span class="cline-any cline-yes">6x</span>
791
+ <span class="cline-any cline-yes">6x</span>
792
+ <span class="cline-any cline-yes">6x</span>
793
+ <span class="cline-any cline-neutral">&nbsp;</span>
794
+ <span class="cline-any cline-yes">6x</span>
795
+ <span class="cline-any cline-yes">8x</span>
796
+ <span class="cline-any cline-yes">8x</span>
797
+ <span class="cline-any cline-yes">8x</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-yes">8x</span>
801
+ <span class="cline-any cline-yes">8x</span>
802
+ <span class="cline-any cline-yes">8x</span>
803
+ <span class="cline-any cline-yes">8x</span>
804
+ <span class="cline-any cline-neutral">&nbsp;</span>
805
+ <span class="cline-any cline-yes">8x</span>
806
+ <span class="cline-any cline-neutral">&nbsp;</span>
807
+ <span class="cline-any cline-neutral">&nbsp;</span>
808
+ <span class="cline-any cline-no">&nbsp;</span>
809
+ <span class="cline-any cline-no">&nbsp;</span>
810
+ <span class="cline-any cline-no">&nbsp;</span>
811
+ <span class="cline-any cline-neutral">&nbsp;</span>
812
+ <span class="cline-any cline-no">&nbsp;</span>
813
+ <span class="cline-any cline-no">&nbsp;</span>
814
+ <span class="cline-any cline-no">&nbsp;</span>
815
+ <span class="cline-any cline-no">&nbsp;</span>
816
+ <span class="cline-any cline-no">&nbsp;</span>
817
+ <span class="cline-any cline-no">&nbsp;</span>
818
+ <span class="cline-any cline-no">&nbsp;</span>
819
+ <span class="cline-any cline-no">&nbsp;</span>
820
+ <span class="cline-any cline-no">&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">8x</span>
824
+ <span class="cline-any cline-yes">8x</span>
825
+ <span class="cline-any cline-yes">11x</span>
826
+ <span class="cline-any cline-yes">11x</span>
827
+ <span class="cline-any cline-yes">11x</span>
828
+ <span class="cline-any cline-yes">11x</span>
829
+ <span class="cline-any cline-yes">11x</span>
830
+ <span class="cline-any cline-yes">11x</span>
831
+ <span class="cline-any cline-yes">11x</span>
832
+ <span class="cline-any cline-no">&nbsp;</span>
833
+ <span class="cline-any cline-no">&nbsp;</span>
834
+ <span class="cline-any cline-no">&nbsp;</span>
835
+ <span class="cline-any cline-no">&nbsp;</span>
836
+ <span class="cline-any cline-neutral">&nbsp;</span>
837
+ <span class="cline-any cline-no">&nbsp;</span>
838
+ <span class="cline-any cline-no">&nbsp;</span>
839
+ <span class="cline-any cline-yes">11x</span>
840
+ <span class="cline-any cline-yes">8x</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-yes">8x</span>
843
+ <span class="cline-any cline-yes">8x</span>
844
+ <span class="cline-any cline-yes">8x</span>
845
+ <span class="cline-any cline-neutral">&nbsp;</span>
846
+ <span class="cline-any cline-yes">6x</span>
847
+ <span class="cline-any cline-no">&nbsp;</span>
848
+ <span class="cline-any cline-no">&nbsp;</span>
849
+ <span class="cline-any cline-no">&nbsp;</span>
850
+ <span class="cline-any cline-no">&nbsp;</span>
851
+ <span class="cline-any cline-yes">6x</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-yes">1x</span>
858
+ <span class="cline-any cline-yes">8x</span>
859
+ <span class="cline-any cline-yes">8x</span>
860
+ <span class="cline-any cline-yes">8x</span>
861
+ <span class="cline-any cline-yes">8x</span>
862
+ <span class="cline-any cline-yes">16x</span>
863
+ <span class="cline-any cline-yes">2x</span>
864
+ <span class="cline-any cline-yes">2x</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-yes">14x</span>
868
+ <span class="cline-any cline-yes">16x</span>
869
+ <span class="cline-any cline-yes">3x</span>
870
+ <span class="cline-any cline-yes">3x</span>
871
+ <span class="cline-any cline-neutral">&nbsp;</span>
872
+ <span class="cline-any cline-neutral">&nbsp;</span>
873
+ <span class="cline-any cline-yes">11x</span>
874
+ <span class="cline-any cline-yes">11x</span>
875
+ <span class="cline-any cline-yes">11x</span>
876
+ <span class="cline-any cline-neutral">&nbsp;</span>
877
+ <span class="cline-any cline-yes">11x</span>
878
+ <span class="cline-any cline-yes">8x</span>
879
+ <span class="cline-any cline-yes">8x</span>
880
+ <span class="cline-any cline-neutral">&nbsp;</span>
881
+ <span class="cline-any cline-neutral">&nbsp;</span>
882
+ <span class="cline-any cline-neutral">&nbsp;</span>
883
+ <span class="cline-any cline-neutral">&nbsp;</span>
884
+ <span class="cline-any cline-neutral">&nbsp;</span>
885
+ <span class="cline-any cline-yes">1x</span>
886
+ <span class="cline-any cline-no">&nbsp;</span>
887
+ <span class="cline-any cline-no">&nbsp;</span>
888
+ <span class="cline-any cline-neutral">&nbsp;</span>
889
+ <span class="cline-any cline-no">&nbsp;</span>
890
+ <span class="cline-any cline-no">&nbsp;</span>
891
+ <span class="cline-any cline-no">&nbsp;</span>
892
+ <span class="cline-any cline-no">&nbsp;</span>
893
+ <span class="cline-any cline-no">&nbsp;</span>
894
+ <span class="cline-any cline-no">&nbsp;</span>
895
+ <span class="cline-any cline-no">&nbsp;</span>
896
+ <span class="cline-any cline-no">&nbsp;</span>
897
+ <span class="cline-any cline-no">&nbsp;</span>
898
+ <span class="cline-any cline-no">&nbsp;</span>
899
+ <span class="cline-any cline-no">&nbsp;</span>
900
+ <span class="cline-any cline-neutral">&nbsp;</span>
901
+ <span class="cline-any cline-no">&nbsp;</span>
902
+ <span class="cline-any cline-no">&nbsp;</span>
903
+ <span class="cline-any cline-neutral">&nbsp;</span>
904
+ <span class="cline-any cline-neutral">&nbsp;</span>
905
+ <span class="cline-any cline-neutral">&nbsp;</span>
906
+ <span class="cline-any cline-neutral">&nbsp;</span>
907
+ <span class="cline-any cline-yes">1x</span>
908
+ <span class="cline-any cline-yes">10x</span>
909
+ <span class="cline-any cline-yes">10x</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-yes">1x</span>
915
+ <span class="cline-any cline-yes">34x</span>
916
+ <span class="cline-any cline-yes">34x</span>
917
+ <span class="cline-any cline-yes">34x</span>
918
+ <span class="cline-any cline-yes">34x</span>
919
+ <span class="cline-any cline-yes">34x</span>
920
+ <span class="cline-any cline-yes">34x</span>
921
+ <span class="cline-any cline-yes">34x</span>
922
+ <span class="cline-any cline-yes">34x</span>
923
+ <span class="cline-any cline-yes">1x</span>
924
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/* eslint-disable @typescript-eslint/no-explicit-any */
925
+ import type { RequestContextManager } from './request-context-manager.mjs'
926
+ import type { ServiceLocatorEventBus } from './service-locator-event-bus.mjs'
927
+ import type { ServiceLocatorInstanceHolder } from './service-locator-instance-holder.mjs'
928
+ import type { ServiceLocatorManager } from './service-locator-manager.mjs'
929
+ &nbsp;
930
+ import { ServiceLocatorInstanceHolderStatus } from './service-locator-instance-holder.mjs'
931
+ &nbsp;
932
+ export interface ClearAllOptions {
933
+ /** Whether to also clear request contexts (default: true) */
934
+ clearRequestContexts?: boolean
935
+ /** Maximum number of invalidation rounds to prevent infinite loops (default: 10) */
936
+ maxRounds?: number
937
+ /** Whether to wait for all services to settle before starting (default: true) */
938
+ waitForSettlement?: boolean
939
+ }
940
+ &nbsp;
941
+ /**
942
+ * ServiceInvalidator handles service invalidation, cleanup, and graceful clearing.
943
+ * Extracted from ServiceLocator to improve separation of concerns.
944
+ */
945
+ export class ServiceInvalidator {
946
+ constructor(
947
+ private readonly manager: ServiceLocatorManager,
948
+ private readonly requestContextManager: RequestContextManager,
949
+ private readonly eventBus: ServiceLocatorEventBus,
950
+ private readonly logger: Console | null = null,
951
+ ) {}
952
+ &nbsp;
953
+ /**
954
+ * Invalidates a service and all its dependencies.
955
+ */
956
+ invalidate(service: string, round = 1): Promise&lt;any&gt; {
957
+ this.logger?.log(
958
+ `[ServiceInvalidator] Starting invalidation process for ${service}`,
959
+ )
960
+ const [, toInvalidate] = this.manager.get(service)
961
+ &nbsp;
962
+ const promises = []
963
+ if (toInvalidate) {
964
+ promises.push(this.invalidateHolder(service, toInvalidate, round))
965
+ }
966
+ &nbsp;
967
+ // Also invalidate request-scoped instances that depend on the service or match the service name
968
+ const requestContexts = this.requestContextManager.getRequestContexts()
969
+ for (const [requestId, requestContext] of requestContexts.entries()) {
970
+ const holder = requestContext.get(service)
971
+ if (holder) {
972
+ this.logger?.log(
973
+ `[ServiceInvalidator] Invalidating request-scoped instance ${service} in request ${requestId}`,
974
+ )
975
+ promises.push(
976
+ this.invalidateRequestHolder(requestId, service, holder, round),
977
+ )
978
+ }
979
+ }
980
+ &nbsp;
981
+ return Promise.all(promises)
982
+ }
983
+ &nbsp;
984
+ /**
985
+ * Gracefully clears all services in the ServiceLocator using invalidation logic.
986
+ * This method respects service dependencies and ensures proper cleanup order.
987
+ * Services that depend on others will be invalidated first, then their dependencies.
988
+ */
989
+ async clearAll(options: ClearAllOptions = {}): Promise&lt;void&gt; {
990
+ const {
991
+ clearRequestContexts = true,
992
+ maxRounds = 10,
993
+ waitForSettlement = true,
994
+ } = options
995
+ &nbsp;
996
+ this.logger?.log(
997
+ '[ServiceInvalidator] Starting graceful clearing of all services',
998
+ )
999
+ &nbsp;
1000
+ // Wait for all services to settle if requested
1001
+ if (waitForSettlement) {
1002
+ this.logger?.log(
1003
+ '[ServiceInvalidator] Waiting for all services to settle...',
1004
+ )
1005
+ await this.ready()
1006
+ }
1007
+ &nbsp;
1008
+ // Get all service names that need to be cleared
1009
+ const allServiceNames = this.getAllServiceNames()
1010
+ &nbsp;
1011
+ if (allServiceNames.length === 0) {
1012
+ this.logger?.log('[ServiceInvalidator] No singleton services to clear')
1013
+ } else {
1014
+ this.logger?.log(
1015
+ `[ServiceInvalidator] Found ${allServiceNames.length} services to clear: ${allServiceNames.join(', ')}`,
1016
+ )
1017
+ &nbsp;
1018
+ // Clear services using dependency-aware invalidation
1019
+ await this.clearServicesWithDependencyAwareness(
1020
+ allServiceNames,
1021
+ maxRounds,
1022
+ )
1023
+ }
1024
+ &nbsp;
1025
+ // Clear request contexts if requested
1026
+ if (clearRequestContexts) {
1027
+ await this.requestContextManager.clearAllRequestContexts()
1028
+ }
1029
+ &nbsp;
1030
+ this.logger?.log('[ServiceInvalidator] Graceful clearing completed')
1031
+ }
1032
+ &nbsp;
1033
+ /**
1034
+ * Waits for all services to settle (either created, destroyed, or error state).
1035
+ */
1036
+ async ready(): Promise&lt;void&gt; {
1037
+ const holders = Array.from(this.manager.filter(() =&gt; true)).map(
1038
+ ([, holder]) =&gt; holder,
1039
+ )
1040
+ await Promise.all(
1041
+ holders.map((holder) =&gt; this.waitForHolderToSettle(holder)),
1042
+ )
1043
+ }
1044
+ &nbsp;
1045
+ /**
1046
+ * Invalidates a single holder based on its current status.
1047
+ */
1048
+ private async invalidateHolder(
1049
+ key: string,
1050
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1051
+ round: number,
1052
+ ): Promise&lt;void&gt; {
1053
+ await this.invalidateHolderByStatus(holder, round, {
1054
+ context: key,
1055
+ isRequestScoped: false,
1056
+ onCreationError: <span class="fstat-no" title="function not covered" >() =&gt;</span>
1057
+ <span class="cstat-no" title="statement not covered" > this.logger?.error(</span>
1058
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] ${key} creation triggered too many invalidation rounds`,</span>
1059
+ <span class="cstat-no" title="statement not covered" > ),</span>
1060
+ onRecursiveInvalidate: <span class="fstat-no" title="function not covered" >() =&gt; this.invalidate(key, round + 1),</span>
1061
+ onDestroy: () =&gt; this.destroyHolder(key, holder),
1062
+ })
1063
+ }
1064
+ &nbsp;
1065
+ /**
1066
+ * Invalidates a request-scoped holder based on its current status.
1067
+ */
1068
+ private async invalidateRequestHolder(
1069
+ requestId: string,
1070
+ instanceName: string,
1071
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1072
+ round: number,
1073
+ ): Promise&lt;void&gt; {
1074
+ await this.invalidateHolderByStatus(holder, round, {
1075
+ context: `Request-scoped ${instanceName} in ${requestId}`,
1076
+ isRequestScoped: true,
1077
+ onCreationError: <span class="fstat-no" title="function not covered" >() =&gt;</span>
1078
+ <span class="cstat-no" title="statement not covered" > this.logger?.error(</span>
1079
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] Request-scoped ${instanceName} in ${requestId} creation triggered too many invalidation rounds`,</span>
1080
+ <span class="cstat-no" title="statement not covered" > ),</span>
1081
+ onRecursiveInvalidate: <span class="fstat-no" title="function not covered" >() =&gt;</span>
1082
+ <span class="cstat-no" title="statement not covered" > this.invalidateRequestHolder(</span>
1083
+ <span class="cstat-no" title="statement not covered" > requestId,</span>
1084
+ <span class="cstat-no" title="statement not covered" > instanceName,</span>
1085
+ <span class="cstat-no" title="statement not covered" > holder,</span>
1086
+ <span class="cstat-no" title="statement not covered" > round + 1,</span>
1087
+ <span class="cstat-no" title="statement not covered" > ),</span>
1088
+ onDestroy: () =&gt;
1089
+ this.destroyRequestHolder(requestId, instanceName, holder),
1090
+ })
1091
+ }
1092
+ &nbsp;
1093
+ /**
1094
+ * Common invalidation logic for holders based on their status.
1095
+ */
1096
+ private async invalidateHolderByStatus(
1097
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1098
+ round: number,
1099
+ options: {
1100
+ context: string
1101
+ isRequestScoped: boolean
1102
+ onCreationError: () =&gt; void
1103
+ onRecursiveInvalidate: () =&gt; Promise&lt;void&gt;
1104
+ onDestroy: () =&gt; Promise&lt;void&gt;
1105
+ },
1106
+ ): Promise&lt;void&gt; {
1107
+ switch (holder.status) {
1108
+ <span class="branch-0 cbranch-no" title="branch not covered" > case ServiceLocatorInstanceHolderStatus.Destroying:</span>
1109
+ <span class="cstat-no" title="statement not covered" > await holder.destroyPromise</span>
1110
+ <span class="cstat-no" title="statement not covered" > break</span>
1111
+ &nbsp;
1112
+ <span class="branch-0 cbranch-no" title="branch not covered" > case ServiceLocatorInstanceHolderStatus.Creating:</span>
1113
+ <span class="cstat-no" title="statement not covered" > await holder.creationPromise</span>
1114
+ <span class="cstat-no" title="statement not covered" > if (round &gt; 3) {</span>
1115
+ <span class="cstat-no" title="statement not covered" > options.onCreationError()</span>
1116
+ <span class="cstat-no" title="statement not covered" > return</span>
1117
+ <span class="cstat-no" title="statement not covered" > }</span>
1118
+ <span class="cstat-no" title="statement not covered" > await options.onRecursiveInvalidate()</span>
1119
+ <span class="cstat-no" title="statement not covered" > break</span>
1120
+ &nbsp;
1121
+ default:
1122
+ await options.onDestroy()
1123
+ break
1124
+ }
1125
+ }
1126
+ &nbsp;
1127
+ /**
1128
+ * Destroys a holder and cleans up its resources.
1129
+ */
1130
+ private async destroyHolder(
1131
+ key: string,
1132
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1133
+ ): Promise&lt;void&gt; {
1134
+ await this.destroyHolderWithCleanup(holder, {
1135
+ context: key,
1136
+ logMessage: `[ServiceInvalidator] Invalidating ${key} and notifying listeners`,
1137
+ cleanup: () =&gt; this.manager.delete(key),
1138
+ eventName: key,
1139
+ })
1140
+ }
1141
+ &nbsp;
1142
+ /**
1143
+ * Destroys a request-scoped holder and cleans up its resources.
1144
+ */
1145
+ private async destroyRequestHolder(
1146
+ requestId: string,
1147
+ instanceName: string,
1148
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1149
+ ): Promise&lt;void&gt; {
1150
+ await this.destroyHolderWithCleanup(holder, {
1151
+ context: `Request-scoped ${instanceName} in ${requestId}`,
1152
+ logMessage: `[ServiceInvalidator] Invalidating request-scoped ${instanceName} in ${requestId} and notifying listeners`,
1153
+ cleanup: () =&gt; {
1154
+ const requestContext = this.requestContextManager
1155
+ .getRequestContexts()
1156
+ .get(requestId)
1157
+ if (requestContext) {
1158
+ requestContext.delete(instanceName)
1159
+ }
1160
+ },
1161
+ eventName: instanceName,
1162
+ })
1163
+ }
1164
+ &nbsp;
1165
+ /**
1166
+ * Common destroy logic for holders with customizable cleanup.
1167
+ */
1168
+ private async destroyHolderWithCleanup(
1169
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1170
+ options: {
1171
+ context: string
1172
+ logMessage: string
1173
+ cleanup: () =&gt; void
1174
+ eventName: string
1175
+ },
1176
+ ): Promise&lt;void&gt; {
1177
+ holder.status = ServiceLocatorInstanceHolderStatus.Destroying
1178
+ this.logger?.log(options.logMessage)
1179
+ &nbsp;
1180
+ holder.destroyPromise = Promise.all(
1181
+ holder.destroyListeners.map((listener) =&gt; listener()),
1182
+ ).then(async () =&gt; {
1183
+ holder.destroyListeners = []
1184
+ holder.deps.clear()
1185
+ options.cleanup()
1186
+ await this.emitInstanceEvent(options.eventName, 'destroy')
1187
+ })
1188
+ &nbsp;
1189
+ await holder.destroyPromise
1190
+ }
1191
+ &nbsp;
1192
+ /**
1193
+ * Waits for a holder to settle (either created, destroyed, or error state).
1194
+ */
1195
+ private async waitForHolderToSettle(
1196
+ holder: ServiceLocatorInstanceHolder&lt;any&gt;,
1197
+ ): Promise&lt;void&gt; {
1198
+ switch (holder.status) {
1199
+ <span class="branch-0 cbranch-no" title="branch not covered" > case ServiceLocatorInstanceHolderStatus.Creating:</span>
1200
+ <span class="cstat-no" title="statement not covered" > await holder.creationPromise</span>
1201
+ <span class="cstat-no" title="statement not covered" > break</span>
1202
+ <span class="branch-0 cbranch-no" title="branch not covered" > case ServiceLocatorInstanceHolderStatus.Destroying:</span>
1203
+ <span class="cstat-no" title="statement not covered" > await holder.destroyPromise</span>
1204
+ <span class="cstat-no" title="statement not covered" > break</span>
1205
+ // Already settled states
1206
+ case ServiceLocatorInstanceHolderStatus.Created:
1207
+ case ServiceLocatorInstanceHolderStatus.Error:
1208
+ break
1209
+ }
1210
+ }
1211
+ &nbsp;
1212
+ /**
1213
+ * Clears services with dependency awareness, ensuring proper cleanup order.
1214
+ * Services with no dependencies are cleared first, then services that depend on them.
1215
+ */
1216
+ private async clearServicesWithDependencyAwareness(
1217
+ serviceNames: string[],
1218
+ maxRounds: number,
1219
+ ): Promise&lt;void&gt; {
1220
+ const clearedServices = new Set&lt;string&gt;()
1221
+ let round = 1
1222
+ &nbsp;
1223
+ while (clearedServices.size &lt; serviceNames.length &amp;&amp; round &lt;= maxRounds) {
1224
+ this.logger?.log(
1225
+ `[ServiceInvalidator] Clearing round ${round}/${maxRounds}, ${clearedServices.size}/${serviceNames.length} services cleared`,
1226
+ )
1227
+ &nbsp;
1228
+ // Find services that can be cleared in this round
1229
+ const servicesToClearThisRound = this.findServicesReadyForClearing(
1230
+ serviceNames,
1231
+ clearedServices,
1232
+ )
1233
+ &nbsp;
1234
+ if (servicesToClearThisRound.length === 0) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1235
+ // If no services can be cleared, try to clear remaining services anyway
1236
+ // This handles circular dependencies or other edge cases
1237
+ <span class="cstat-no" title="statement not covered" > const remainingServices = serviceNames.filter(</span>
1238
+ <span class="cstat-no" title="statement not covered" > (name) =&gt; !clearedServices.has(name),</span>
1239
+ <span class="cstat-no" title="statement not covered" > )</span>
1240
+ &nbsp;
1241
+ <span class="cstat-no" title="statement not covered" > if (remainingServices.length &gt; 0) {</span>
1242
+ <span class="cstat-no" title="statement not covered" > this.logger?.warn(</span>
1243
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] No services ready for clearing, forcing cleanup of remaining: ${remainingServices.join(', ')}`,</span>
1244
+ <span class="cstat-no" title="statement not covered" > )</span>
1245
+ <span class="cstat-no" title="statement not covered" > await this.forceClearServices(remainingServices)</span>
1246
+ <span class="cstat-no" title="statement not covered" > remainingServices.forEach((name) =&gt; clearedServices.add(name))</span>
1247
+ <span class="cstat-no" title="statement not covered" > }</span>
1248
+ <span class="cstat-no" title="statement not covered" > break</span>
1249
+ <span class="cstat-no" title="statement not covered" > }</span>
1250
+ &nbsp;
1251
+ // Clear services in this round
1252
+ const clearPromises = servicesToClearThisRound.map(
1253
+ async (serviceName) =&gt; {
1254
+ try {
1255
+ await this.invalidate(serviceName, round)
1256
+ clearedServices.add(serviceName)
1257
+ this.logger?.log(
1258
+ `[ServiceInvalidator] Successfully cleared service: ${serviceName}`,
1259
+ )
1260
+ <span class="branch-0 cbranch-no" title="branch not covered" > } catch (error) {</span>
1261
+ <span class="cstat-no" title="statement not covered" > this.logger?.error(</span>
1262
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] Error clearing service ${serviceName}:`,</span>
1263
+ <span class="cstat-no" title="statement not covered" > error,</span>
1264
+ <span class="cstat-no" title="statement not covered" > )</span>
1265
+ // Still mark as cleared to avoid infinite loops
1266
+ <span class="cstat-no" title="statement not covered" > clearedServices.add(serviceName)</span>
1267
+ <span class="cstat-no" title="statement not covered" > }</span>
1268
+ },
1269
+ )
1270
+ &nbsp;
1271
+ await Promise.all(clearPromises)
1272
+ round++
1273
+ }
1274
+ &nbsp;
1275
+ if (clearedServices.size &lt; serviceNames.length) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1276
+ <span class="cstat-no" title="statement not covered" > this.logger?.warn(</span>
1277
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] Clearing completed after ${maxRounds} rounds, but ${serviceNames.length - clearedServices.size} services may not have been properly cleared`,</span>
1278
+ <span class="cstat-no" title="statement not covered" > )</span>
1279
+ <span class="cstat-no" title="statement not covered" > }</span>
1280
+ }
1281
+ &nbsp;
1282
+ /**
1283
+ * Finds services that are ready to be cleared in the current round.
1284
+ * A service is ready if all its dependencies have already been cleared.
1285
+ */
1286
+ private findServicesReadyForClearing(
1287
+ allServiceNames: string[],
1288
+ clearedServices: Set&lt;string&gt;,
1289
+ ): string[] {
1290
+ return allServiceNames.filter((serviceName) =&gt; {
1291
+ if (clearedServices.has(serviceName)) {
1292
+ return false // Already cleared
1293
+ }
1294
+ &nbsp;
1295
+ // Check if this service has any dependencies that haven't been cleared yet
1296
+ const [error, holder] = this.manager.get(serviceName)
1297
+ if (error) {
1298
+ return true // Service not found or in error state, can be cleared
1299
+ }
1300
+ &nbsp;
1301
+ // Check if all dependencies have been cleared
1302
+ const hasUnclearedDependencies = Array.from(holder.deps).some(
1303
+ (dep) =&gt; !clearedServices.has(dep),
1304
+ )
1305
+ &nbsp;
1306
+ return !hasUnclearedDependencies
1307
+ })
1308
+ }
1309
+ &nbsp;
1310
+ /**
1311
+ * Force clears services that couldn't be cleared through normal dependency resolution.
1312
+ * This handles edge cases like circular dependencies.
1313
+ */
1314
+ <span class="fstat-no" title="function not covered" > private async forceClearServices(serviceNames: string[]): Promise&lt;void&gt; {</span>
1315
+ <span class="cstat-no" title="statement not covered" > const promises = serviceNames.map(async (serviceName) =&gt; {</span>
1316
+ <span class="cstat-no" title="statement not covered" > try {</span>
1317
+ // Directly destroy the holder without going through normal invalidation
1318
+ <span class="cstat-no" title="statement not covered" > const [error, holder] = this.manager.get(serviceName)</span>
1319
+ <span class="cstat-no" title="statement not covered" > if (!error &amp;&amp; holder) {</span>
1320
+ <span class="cstat-no" title="statement not covered" > await this.destroyHolder(serviceName, holder)</span>
1321
+ <span class="cstat-no" title="statement not covered" > }</span>
1322
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1323
+ <span class="cstat-no" title="statement not covered" > this.logger?.error(</span>
1324
+ <span class="cstat-no" title="statement not covered" > `[ServiceInvalidator] Error force clearing service ${serviceName}:`,</span>
1325
+ <span class="cstat-no" title="statement not covered" > error,</span>
1326
+ <span class="cstat-no" title="statement not covered" > )</span>
1327
+ <span class="cstat-no" title="statement not covered" > }</span>
1328
+ <span class="cstat-no" title="statement not covered" > })</span>
1329
+ &nbsp;
1330
+ <span class="cstat-no" title="statement not covered" > await Promise.all(promises)</span>
1331
+ <span class="cstat-no" title="statement not covered" > }</span>
1332
+ &nbsp;
1333
+ /**
1334
+ * Gets all service names currently managed by the ServiceLocator.
1335
+ */
1336
+ private getAllServiceNames(): string[] {
1337
+ return this.manager.getAllNames()
1338
+ }
1339
+ &nbsp;
1340
+ /**
1341
+ * Emits events to listeners for instance lifecycle events.
1342
+ */
1343
+ private emitInstanceEvent(
1344
+ name: string,
1345
+ event: 'create' | 'destroy' = 'create',
1346
+ ) {
1347
+ this.logger?.log(
1348
+ `[ServiceInvalidator]#emitInstanceEvent() Notifying listeners for ${name} with event ${event}`,
1349
+ )
1350
+ return this.eventBus.emit(name, event)
1351
+ }
1352
+ }
1353
+ &nbsp;</pre></td></tr></table></pre>
1354
+
1355
+ <div class='push'></div><!-- for sticky footer -->
1356
+ </div><!-- /wrapper -->
1357
+ <div class='footer quiet pad2 space-top1 center small'>
1358
+ Code coverage generated by
1359
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1360
+ at 2025-09-21T17:47:07.632Z
1361
+ </div>
1362
+ <script src="../prettify.js"></script>
1363
+ <script>
1364
+ window.onload = function () {
1365
+ prettyPrint();
1366
+ };
1367
+ </script>
1368
+ <script src="../sorter.js"></script>
1369
+ <script src="../block-navigation.js"></script>
1370
+ </body>
1371
+ </html>
1372
+