@codefast/di 0.11.0 → 0.13.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 (79) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/README.md +128 -31
  3. package/dist/container/{binding-builders.d.ts → binding-chain.d.ts} +21 -28
  4. package/dist/container/{binding-builders.js → binding-chain.js} +53 -163
  5. package/dist/container/container.d.ts +11 -3
  6. package/dist/container/container.js +176 -102
  7. package/dist/core/binding-builders.d.ts +117 -0
  8. package/dist/core/binding-declaration.d.ts +9 -2
  9. package/dist/core/binding-declaration.js +5 -4
  10. package/dist/core/binding.d.ts +21 -149
  11. package/dist/core/binding.js +15 -25
  12. package/dist/core/module.d.ts +1 -1
  13. package/dist/core/registry.d.ts +9 -24
  14. package/dist/core/registry.js +30 -155
  15. package/dist/core/tag.js +1 -1
  16. package/dist/decorators/inject.d.ts +3 -1
  17. package/dist/decorators/inject.js +5 -5
  18. package/dist/decorators/injectable.js +2 -2
  19. package/dist/decorators/lifecycle.d.ts +20 -0
  20. package/dist/decorators/{lifecycle-decorators.js → lifecycle.js} +7 -3
  21. package/dist/decorators/{decorator-metadata.js → metadata-record.js} +1 -1
  22. package/dist/{errors/errors.d.ts → errors.d.ts} +29 -19
  23. package/dist/{errors/errors.js → errors.js} +43 -25
  24. package/dist/index.d.ts +12 -10
  25. package/dist/index.js +6 -6
  26. package/dist/injection/descriptor.d.ts +1 -1
  27. package/dist/introspection/dependency-graph.d.ts +1 -1
  28. package/dist/introspection/dependency-graph.js +3 -4
  29. package/dist/introspection/explanation.d.ts +101 -0
  30. package/dist/introspection/explanation.js +169 -0
  31. package/dist/introspection/inspector.d.ts +9 -2
  32. package/dist/introspection/inspector.js +25 -20
  33. package/dist/lifecycle/{lifecycle-manager.d.ts → hooks.d.ts} +11 -2
  34. package/dist/lifecycle/{lifecycle-manager.js → hooks.js} +51 -28
  35. package/dist/lifecycle/{scope-manager.d.ts → scopes.d.ts} +23 -6
  36. package/dist/lifecycle/{scope-manager.js → scopes.js} +93 -20
  37. package/dist/metadata/{metadata-keys.d.ts → keys.d.ts} +1 -1
  38. package/dist/metadata/{metadata-keys.js → keys.js} +1 -1
  39. package/dist/metadata/{metadata-reader-token.d.ts → reader-token.d.ts} +1 -1
  40. package/dist/metadata/{symbol-metadata-reader.d.ts → symbol-reader.d.ts} +1 -1
  41. package/dist/metadata/{symbol-metadata-reader.js → symbol-reader.js} +1 -1
  42. package/dist/metadata/{metadata-types.d.ts → types.d.ts} +1 -1
  43. package/dist/metadata/types.js +1 -0
  44. package/dist/metadata/verify.d.ts +43 -0
  45. package/dist/metadata/verify.js +133 -0
  46. package/dist/metadata/{verifying-metadata-reader.d.ts → verifying-reader.d.ts} +1 -1
  47. package/dist/metadata/{verifying-metadata-reader.js → verifying-reader.js} +2 -2
  48. package/dist/resolution/cache/activation-need.d.ts +1 -1
  49. package/dist/resolution/cache/activation-need.js +5 -1
  50. package/dist/resolution/cache/class-introspector.d.ts +27 -36
  51. package/dist/resolution/cache/class-introspector.js +61 -159
  52. package/dist/resolution/cache/{binding-lookup-cache.d.ts → lookup.d.ts} +7 -2
  53. package/dist/resolution/cache/{binding-lookup-cache.js → lookup.js} +40 -8
  54. package/dist/resolution/context.d.ts +1 -1
  55. package/dist/resolution/context.js +1 -1
  56. package/dist/resolution/{path/resolution-path.d.ts → path.d.ts} +12 -2
  57. package/dist/resolution/{path/resolution-path.js → path.js} +23 -3
  58. package/dist/resolution/plan/{plan-codegen.d.ts → codegen.d.ts} +2 -4
  59. package/dist/resolution/plan/{plan-codegen.js → codegen.js} +2 -4
  60. package/dist/resolution/plan/{instantiation-plan.d.ts → compiler.d.ts} +1 -1
  61. package/dist/resolution/plan/{instantiation-plan.js → compiler.js} +4 -4
  62. package/dist/resolution/resolver.d.ts +19 -7
  63. package/dist/resolution/resolver.js +343 -125
  64. package/dist/resolution/select/{binding-select.d.ts → candidates.d.ts} +30 -0
  65. package/dist/resolution/select/{binding-select.js → candidates.js} +51 -10
  66. package/dist/resolution/select/constraints.js +1 -1
  67. package/package.json +80 -72
  68. package/dist/core/binding-scope.d.ts +0 -12
  69. package/dist/core/binding-scope.js +0 -12
  70. package/dist/decorators/lifecycle-decorators.d.ts +0 -14
  71. /package/dist/{ambient/active-container.d.ts → ambient-container.d.ts} +0 -0
  72. /package/dist/{ambient/active-container.js → ambient-container.js} +0 -0
  73. /package/dist/{metadata/metadata-types.js → core/binding-builders.js} +0 -0
  74. /package/dist/decorators/{decorator-metadata.d.ts → metadata-record.d.ts} +0 -0
  75. /package/dist/injection/{resolve-options.d.ts → dependency-slot.d.ts} +0 -0
  76. /package/dist/injection/{resolve-options.js → dependency-slot.js} +0 -0
  77. /package/dist/{errors → introspection}/diagnostics.d.ts +0 -0
  78. /package/dist/{errors → introspection}/diagnostics.js +0 -0
  79. /package/dist/metadata/{metadata-reader-token.js → reader-token.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_BINDING_SLOT, withSlotCriterion } from "#core/binding";
2
2
  import { slotName } from "#core/tag";
3
3
  import { tokenName } from "#core/token";
4
- import { InvalidBindingDeclarationError, ManyBindingSlotError, SelfBindingRequiresClassError } from "#errors/errors";
4
+ import { InvalidBindingDeclarationError, ManyBindingSlotError, SelfBindingRequiresClassError } from "#errors";
5
5
  import { normalizeToDescriptor } from "#injection/descriptor";
6
6
  // Only this module can mint the symbol, so an entry carrying it was made by `binding()`.
7
7
  const declarationBrand = Symbol("di:binding-declaration");
@@ -83,8 +83,9 @@ function slotOf(definition) {
83
83
  }
84
84
  return slot;
85
85
  }
86
- // The value type is erased here, once: the overloads above are what a caller is checked against.
87
86
  /**
87
+ * Implements both overloads with the value type erased once, since a caller is checked against the overloads above.
88
+ *
88
89
  * @since 0.11.0
89
90
  */
90
91
  export function binding(key, definition) {
@@ -156,8 +157,8 @@ export function binding(key, definition) {
156
157
  if (kind === "alias" && (onActivation !== undefined || onDeactivation !== undefined)) {
157
158
  throw new InvalidBindingDeclarationError(name, "`toAlias` takes no lifecycle hook");
158
159
  }
159
- if (onDeactivation !== undefined && kind !== "constant" && scope !== "singleton") {
160
- throw new InvalidBindingDeclarationError(name, '`onDeactivation` needs `scope: "singleton"`');
160
+ if (onDeactivation !== undefined && kind !== "constant" && scope === "transient") {
161
+ throw new InvalidBindingDeclarationError(name, '`onDeactivation` needs `scope: "singleton"` or `scope: "scoped"`');
161
162
  }
162
163
  if (definition.many !== undefined && definition.many !== true) {
163
164
  throw new InvalidBindingDeclarationError(name, "`many` takes `true`");
@@ -1,7 +1,7 @@
1
1
  import type { BindingTag, TagKeyMask } from "#core/tag";
2
2
  import type { Token } from "#core/token";
3
- import type { ActivationHandler, BindingIdentifier, BindingScope, Constructor, DeactivationHandler, ResolutionContext, ResolutionFrame, BindingConstraint } from "#core/types";
4
- import type { InjectableDependency, InjectionDescriptor, ResolvedDependencyValue } from "#injection/descriptor";
3
+ import type { BindingConstraint, BindingIdentifier, BindingScope, Constructor, ResolutionContext, ResolutionFrame } from "#core/types";
4
+ import type { InjectionDescriptor } from "#injection/descriptor";
5
5
  /**
6
6
  * The criterion set a binding registers under and a request matches against.
7
7
  *
@@ -106,13 +106,6 @@ interface BindingBase<Value> {
106
106
  * container resolving each binding once would build and never read again.
107
107
  */
108
108
  activationStamp: number;
109
- /**
110
- * Where the binding stands in registration order, or {@link UNREGISTERED_ORDER} before its first add.
111
- *
112
- * @remarks Registry-owned: stamped by the first `add` and kept through every re-slot and restore, so a
113
- * binding taken out and put back returns to its place rather than behind later registrations.
114
- */
115
- registrationOrder: number;
116
109
  /**
117
110
  * Cached singleton instance, or {@link NO_INSTANCE}.
118
111
  *
@@ -120,6 +113,13 @@ interface BindingBase<Value> {
120
113
  * a field read replaces a keyed lookup on the hottest resolve shape there is.
121
114
  */
122
115
  instance: unknown;
116
+ /**
117
+ * The key every container's scoped cache files this binding's instance under.
118
+ *
119
+ * @remarks Chain-owned. It starts as the binding's id, and a scope verb that changes the scope mints a new one, so
120
+ * a scoped instance any child cached under an earlier scope is never found again. The id itself stays stable.
121
+ */
122
+ scopedCacheKey: BindingIdentifier;
123
123
  readonly token: Token<Value> | Constructor<Value>;
124
124
  readonly slot: BindingSlot;
125
125
  readonly predicate?: BindingConstraint | undefined;
@@ -228,40 +228,21 @@ export interface AliasBinding<Value> extends BindingBase<Value> {
228
228
  */
229
229
  export type Binding<Value = unknown> = ClassBinding<Value> | DynamicBinding<Value> | DynamicAsyncBinding<Value> | ResolvedBinding<Value> | ResolvedAsyncBinding<Value> | ConstantBinding<Value> | AliasBinding<Value>;
230
230
  /**
231
- * Returns a process-unique identifier for a new binding.
231
+ * The scope a binding resolves under.
232
232
  *
233
- * @since 0.3.16-canary.0
234
- */
235
- export declare function generateBindingId(): BindingIdentifier;
236
- /**
237
- * Writable view of the one selection field a chain may refine without re-registering: nothing
238
- * indexes on the predicate, so the registry rewrites it in place and re-homes the binding itself.
239
- *
240
- * @since 0.10.0
241
- */
242
- export interface PredicateField {
243
- predicate: BindingConstraint | undefined;
244
- }
245
- /**
246
- * Narrows a registered binding to its predicate for the registry to rewrite.
233
+ * @remarks Every kind declares one — an alias declares `transient`, since it defers scoping to the
234
+ * binding it points at — so this is a field read, kept as a named function because it is the
235
+ * vocabulary validation and introspection speak.
247
236
  *
248
- * @since 0.10.0
237
+ * @since 0.3.16-canary.0
249
238
  */
250
- export declare function writablePredicate(binding: Binding): PredicateField;
239
+ export declare function effectiveBindingScope(binding: Binding): BindingScope;
251
240
  /**
252
- * Writable view of collection membership, which the registry sets because it decides the binding's map.
253
- *
254
- * @since 0.10.0
255
- */
256
- export interface MembershipField {
257
- isMany: boolean;
258
- }
259
- /**
260
- * Narrows a registered binding to its membership flag for the registry to set.
241
+ * Returns a process-unique identifier for a new binding.
261
242
  *
262
- * @since 0.10.0
243
+ * @since 0.3.16-canary.0
263
244
  */
264
- export declare function writableMembership(binding: Binding): MembershipField;
245
+ export declare function generateBindingId(): BindingIdentifier;
265
246
  /**
266
247
  * The stamp of a binding whose activation need has not been computed under the current versions.
267
248
  *
@@ -269,121 +250,12 @@ export declare function writableMembership(binding: Binding): MembershipField;
269
250
  */
270
251
  export declare const NO_ACTIVATION_STAMP = -1;
271
252
  /**
272
- * The registration order of a binding no registry has added yet.
253
+ * Drops the memoized resolution frame, for a scope change that alters what the frame reports.
273
254
  *
274
- * @since 0.11.0
275
- */
276
- export declare const UNREGISTERED_ORDER = -1;
277
- /**
278
- * Drops the memoized resolution frame, for a refinement that changes what the frame reports.
279
- *
280
- * @remarks The frame derives from `scope` and `slot`, both of which a chain now writes in place on
281
- * the registered object, so every such refinement clears it.
255
+ * @remarks The frame derives from `scope` and `slot`; the slot is final once the binding registers, so
256
+ * only a scope written in place on the registered object clears it.
282
257
  *
283
258
  * @since 0.5.0-canary.9
284
259
  */
285
260
  export declare function clearBindingFrame<Value>(binding: Binding<Value>): void;
286
- /**
287
- * Common slot-constraint + id methods shared by all concrete binding builders.
288
- *
289
- * @since 0.3.16-canary.0
290
- */
291
- export interface SlotConstrainedBuilder<Names extends string = string> {
292
- /** Narrows the binding to requests the predicate accepts, evaluated on every resolve. */
293
- when(predicate: BindingConstraint): this;
294
- /** Declares the binding's slot name, one of the names the token declares. */
295
- whenNamed(name: Names): this;
296
- /** Declares one criterion of the binding's slot, replacing any earlier criterion of the same key. */
297
- whenTagged(criterion: BindingTag): this;
298
- /** Keeps the binding on the default slot, the one an unconstrained request selects. */
299
- whenDefault(): this;
300
- /**
301
- * Makes the binding a collection member: one of several the token's `resolveAll` returns, never
302
- * what a single `resolve` selects, and outside slot last-wins. It keeps the default slot.
303
- */
304
- many(): this;
305
- /** The identifier this binding is registered under. */
306
- id(): BindingIdentifier;
307
- }
308
- /**
309
- * The `to*` step of the fluent chain, choosing what a token resolves to.
310
- *
311
- * @since 0.3.16-canary.0
312
- */
313
- export interface BindToBuilder<Value, Names extends string = string> {
314
- to(type: Constructor<Value>): BindingBuilder<Value, Names>;
315
- toSelf(): BindingBuilder<Value, Names>;
316
- toConstantValue(value: Value): ConstantBindingBuilder<Value, Names>;
317
- toDynamic(factory: (ctx: ResolutionContext) => Value): BindingBuilder<Value, Names>;
318
- toDynamicAsync(factory: (ctx: ResolutionContext) => Promise<Value>): BindingBuilder<Value, Names>;
319
- toResolved<const Deps extends ReadonlyArray<InjectableDependency>>(factory: (...args: {
320
- [K in keyof Deps]: ResolvedDependencyValue<NoInfer<Deps>[K]>;
321
- }) => Value, deps: Deps): BindingBuilder<Value, Names>;
322
- toResolvedAsync<const Deps extends ReadonlyArray<InjectableDependency>>(factory: (...args: {
323
- [K in keyof Deps]: ResolvedDependencyValue<NoInfer<Deps>[K]>;
324
- }) => Promise<Value>, deps: Deps): BindingBuilder<Value, Names>;
325
- toAlias(target: Token<Value> | Constructor<Value>): AliasBindingBuilder<Names>;
326
- }
327
- /**
328
- * The scope-selection step of the fluent chain.
329
- *
330
- * @since 0.3.16-canary.0
331
- */
332
- export interface BindingBuilder<Value, Names extends string = string> extends SlotConstrainedBuilder<Names> {
333
- singleton(): SingletonBindingBuilder<Value>;
334
- transient(): TransientBindingBuilder<Value>;
335
- scoped(): ScopedBindingBuilder<Value>;
336
- }
337
- /**
338
- * The fluent chain for a constant — lifecycle hooks only, since the scope is fixed.
339
- *
340
- * @since 0.3.16-canary.0
341
- */
342
- export interface ConstantBindingBuilder<Value, Names extends string = string> extends SlotConstrainedBuilder<Names> {
343
- onActivation(fn: ActivationHandler<Value>): SingletonLifecycleBuilder<Value>;
344
- onDeactivation(fn: DeactivationHandler<Value>): SingletonLifecycleBuilder<Value>;
345
- }
346
- /**
347
- * The fluent chain for an alias — slot constraints only, since scoping belongs to the target.
348
- *
349
- * @since 0.3.16-canary.0
350
- */
351
- export interface AliasBindingBuilder<Names extends string = string> extends SlotConstrainedBuilder<Names> {
352
- }
353
- /**
354
- * The fluent chain after `singleton()`, where both lifecycle hooks stay available.
355
- *
356
- * @since 0.3.16-canary.0
357
- */
358
- export interface SingletonBindingBuilder<Value> {
359
- onActivation(fn: ActivationHandler<Value>): this;
360
- onDeactivation(fn: DeactivationHandler<Value>): this;
361
- id(): BindingIdentifier;
362
- }
363
- /**
364
- * The fluent chain after `transient()`, where activation is the one lifecycle hook offered.
365
- *
366
- * @since 0.3.16-canary.0
367
- */
368
- export interface TransientBindingBuilder<Value> {
369
- onActivation(fn: ActivationHandler<Value>): this;
370
- id(): BindingIdentifier;
371
- }
372
- /**
373
- * The fluent chain after `scoped()`, sharing the `transient()` surface.
374
- *
375
- * @since 0.3.16-canary.0
376
- */
377
- export interface ScopedBindingBuilder<Value> extends TransientBindingBuilder<Value> {
378
- }
379
- /**
380
- * The fluent chain a constant enters once a lifecycle hook is added.
381
- *
382
- * @since 0.3.16-canary.0
383
- */
384
- export interface SingletonLifecycleBuilder<Value> {
385
- onActivation(fn: ActivationHandler<Value>): this;
386
- onDeactivation(fn: DeactivationHandler<Value>): this;
387
- id(): BindingIdentifier;
388
- }
389
261
  export {};
@@ -108,6 +108,18 @@ export function bindingSlotToString(slot) {
108
108
  }
109
109
  return parts.join(",");
110
110
  }
111
+ /**
112
+ * The scope a binding resolves under.
113
+ *
114
+ * @remarks Every kind declares one — an alias declares `transient`, since it defers scoping to the
115
+ * binding it points at — so this is a field read, kept as a named function because it is the
116
+ * vocabulary validation and introspection speak.
117
+ *
118
+ * @since 0.3.16-canary.0
119
+ */
120
+ export function effectiveBindingScope(binding) {
121
+ return binding.scope;
122
+ }
111
123
  // ── ID generation ────────────────────────────────────────────────────────────────────────────────────────────────────
112
124
  let bindingIdCounter = 0;
113
125
  /**
@@ -119,22 +131,6 @@ export function generateBindingId() {
119
131
  bindingIdCounter += 1;
120
132
  return bindingIdCounter;
121
133
  }
122
- /**
123
- * Narrows a registered binding to its predicate for the registry to rewrite.
124
- *
125
- * @since 0.10.0
126
- */
127
- export function writablePredicate(binding) {
128
- return binding;
129
- }
130
- /**
131
- * Narrows a registered binding to its membership flag for the registry to set.
132
- *
133
- * @since 0.10.0
134
- */
135
- export function writableMembership(binding) {
136
- return binding;
137
- }
138
134
  /**
139
135
  * The stamp of a binding whose activation need has not been computed under the current versions.
140
136
  *
@@ -142,16 +138,10 @@ export function writableMembership(binding) {
142
138
  */
143
139
  export const NO_ACTIVATION_STAMP = -1;
144
140
  /**
145
- * The registration order of a binding no registry has added yet.
146
- *
147
- * @since 0.11.0
148
- */
149
- export const UNREGISTERED_ORDER = -1;
150
- /**
151
- * Drops the memoized resolution frame, for a refinement that changes what the frame reports.
141
+ * Drops the memoized resolution frame, for a scope change that alters what the frame reports.
152
142
  *
153
- * @remarks The frame derives from `scope` and `slot`, both of which a chain now writes in place on
154
- * the registered object, so every such refinement clears it.
143
+ * @remarks The frame derives from `scope` and `slot`; the slot is final once the binding registers, so
144
+ * only a scope written in place on the registered object clears it.
155
145
  *
156
146
  * @since 0.5.0-canary.9
157
147
  */
@@ -1,4 +1,4 @@
1
- import type { BindToBuilder } from "#core/binding";
1
+ import type { BindToBuilder } from "#core/binding-builders";
2
2
  import type { BindingDeclaration, DeclaredBinding } from "#core/binding-declaration";
3
3
  import type { Token } from "#core/token";
4
4
  import type { Constructor } from "#core/types";
@@ -1,7 +1,7 @@
1
1
  import type { Binding } from "#core/binding";
2
2
  import type { BindingTag } from "#core/tag";
3
3
  import type { Token } from "#core/token";
4
- import type { BindingConstraint, BindingIdentifier, Constructor } from "#core/types";
4
+ import type { BindingIdentifier, Constructor } from "#core/types";
5
5
  /**
6
6
  * @since 0.11.0
7
7
  */
@@ -11,6 +11,8 @@ export declare class BindingRegistry {
11
11
  get version(): number;
12
12
  /** Whether a constant has ever been registered here, and so whether teardown has anything to sweep. */
13
13
  get hasHeldConstantBinding(): boolean;
14
+ /** Whether an alias has ever been registered here, and so whether a candidate list can hold one. */
15
+ get hasHeldAlias(): boolean;
14
16
  /** Whether the deferred tagged-slot index has had to be built. */
15
17
  get isTaggedIndexBuilt(): boolean;
16
18
  /** Whether an id-keyed operation has had to build the id index. */
@@ -55,8 +57,6 @@ export declare class BindingRegistry {
55
57
  allBindings(): ReadonlyArray<Binding>;
56
58
  /** Remove all bindings. Returns all removed. */
57
59
  clear(): ReadonlyArray<Binding>;
58
- /** Whether a slot-based binding currently occupies `binding`'s slot, so adding it would displace. */
59
- hasSlotOccupant(binding: Binding): boolean;
60
60
  /**
61
61
  * The binding indexed under one criterion.
62
62
  *
@@ -83,28 +83,13 @@ export declare class BindingRegistry {
83
83
  hasPredicateCandidate(token: Token<unknown> | Constructor): boolean;
84
84
  /** The binding holding a token's default slot — lone or recorded — or `undefined` when none does. */
85
85
  getDefaultSlotBinding(token: Token<unknown> | Constructor): Binding | undefined;
86
- /** A token's lone default-slot binding — the first read of every synchronous resolve. */
87
- getFastDefault(token: Token<unknown> | Constructor): Binding | undefined;
88
86
  /**
89
- * Takes a live binding out of every index, lets `rewrite` change its slot or predicate, and reports
90
- * whether it was live; the caller registers it again with `add`.
87
+ * The token's default-slot alias, which forwards a request's criteria to its target, or `undefined`.
91
88
  *
92
- * @remarks The binding keeps its object and its id, so the id index needs no touch and nothing
93
- * that holds the object has to be told. `false` means the binding was unbound or displaced since
94
- * it registered, and a refinement must not resurrect it.
89
+ * @remarks A registry that never held an alias answers without probing, so a request missing every slot of a
90
+ * token pays for forwarding only where forwarding can happen.
95
91
  */
96
- reslot(binding: Binding, rewrite: () => void): boolean;
97
- /**
98
- * Marks a live binding as a collection member in place, moving it out of the lone map: a member is
99
- * never the token's lone default answer, and nothing else indexes on membership.
100
- */
101
- setMany(binding: Binding): void;
102
- /**
103
- * Adds a predicate to a live binding in place.
104
- *
105
- * @remarks Only ever narrows — `when()` composes with any existing predicate — so the argument is
106
- * never absent. Nothing indexes on the predicate, so the binding object and its id stay; a lone
107
- * binding moves to a record because the lone map holds default-slot bindings with no predicate.
108
- */
109
- setPredicate(binding: Binding, predicate: BindingConstraint): void;
92
+ defaultSlotAlias(token: Token<unknown> | Constructor): Binding | undefined;
93
+ /** A token's lone default-slot binding — the first read of every synchronous resolve. */
94
+ getFastDefault(token: Token<unknown> | Constructor): Binding | undefined;
110
95
  }