@adaas/a-concept 0.3.7 → 0.3.9
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.
- package/benchmarks/feature-chaining.bench.ts +465 -0
- package/benchmarks/feature-optimize.bench.ts +280 -0
- package/dist/browser/index.d.mts +64 -13
- package/dist/browser/index.mjs +2 -2
- package/dist/browser/index.mjs.map +1 -1
- package/dist/node/index.cjs +329 -129
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.mts +64 -13
- package/dist/node/index.d.ts +64 -13
- package/dist/node/index.mjs +329 -129
- package/dist/node/index.mjs.map +1 -1
- package/package.json +3 -1
- package/src/lib/A-Context/A-Context.class.ts +214 -41
- package/src/lib/A-Entity/A-Entity.class.ts +3 -3
- package/src/lib/A-Feature/A-Feature.class.ts +64 -56
- package/src/lib/A-Scope/A-Scope.class.ts +143 -72
- package/tests/A-Feature.test.ts +101 -0
- package/tests/A-Meta.test.ts +46 -2
- package/tests/A-Scope.test.ts +188 -0
- package/tsconfig.json +1 -0
package/dist/node/index.mjs
CHANGED
|
@@ -1117,13 +1117,13 @@ var A_Entity = class {
|
|
|
1117
1117
|
* @param lifecycleMethod
|
|
1118
1118
|
* @param args
|
|
1119
1119
|
*/
|
|
1120
|
-
|
|
1120
|
+
call(feature, scope) {
|
|
1121
1121
|
const newFeature = new A_Feature({
|
|
1122
1122
|
name: feature,
|
|
1123
1123
|
component: this,
|
|
1124
1124
|
scope
|
|
1125
1125
|
});
|
|
1126
|
-
return
|
|
1126
|
+
return newFeature.process(scope);
|
|
1127
1127
|
}
|
|
1128
1128
|
// ====================================================================
|
|
1129
1129
|
// ================== Entity Base Methods =============================
|
|
@@ -3324,7 +3324,7 @@ var A_Feature = class _A_Feature {
|
|
|
3324
3324
|
if (!params || typeof params !== "object") {
|
|
3325
3325
|
throw new A_FeatureError(
|
|
3326
3326
|
A_FeatureError.FeatureInitializationError,
|
|
3327
|
-
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)
|
|
3327
|
+
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)?.slice(0, 100)}...`
|
|
3328
3328
|
);
|
|
3329
3329
|
}
|
|
3330
3330
|
}
|
|
@@ -3343,7 +3343,7 @@ var A_Feature = class _A_Feature {
|
|
|
3343
3343
|
default:
|
|
3344
3344
|
throw new A_FeatureError(
|
|
3345
3345
|
A_FeatureError.FeatureInitializationError,
|
|
3346
|
-
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)
|
|
3346
|
+
`Invalid A-Feature initialization parameters of type: ${typeof params} with value: ${JSON.stringify(params)?.slice(0, 100)}...`
|
|
3347
3347
|
);
|
|
3348
3348
|
}
|
|
3349
3349
|
}
|
|
@@ -3356,13 +3356,13 @@ var A_Feature = class _A_Feature {
|
|
|
3356
3356
|
if (!params.template || !Array.isArray(params.template)) {
|
|
3357
3357
|
throw new A_FeatureError(
|
|
3358
3358
|
A_FeatureError.FeatureInitializationError,
|
|
3359
|
-
`Invalid A-Feature template provided of type: ${typeof params.template} with value: ${JSON.stringify(params.template)
|
|
3359
|
+
`Invalid A-Feature template provided of type: ${typeof params.template} with value: ${JSON.stringify(params.template)?.slice(0, 100)}...`
|
|
3360
3360
|
);
|
|
3361
3361
|
}
|
|
3362
3362
|
if (!params.component && (!params.scope || !(params.scope instanceof A_Scope))) {
|
|
3363
3363
|
throw new A_FeatureError(
|
|
3364
3364
|
A_FeatureError.FeatureInitializationError,
|
|
3365
|
-
`Invalid A-Feature scope provided of type: ${typeof params.scope} with value: ${JSON.stringify(params.scope)
|
|
3365
|
+
`Invalid A-Feature scope provided of type: ${typeof params.scope} with value: ${JSON.stringify(params.scope)?.slice(0, 100)}...`
|
|
3366
3366
|
);
|
|
3367
3367
|
}
|
|
3368
3368
|
this._name = params.name;
|
|
@@ -3394,7 +3394,7 @@ var A_Feature = class _A_Feature {
|
|
|
3394
3394
|
if (!params.component || !A_TypeGuards.isAllowedForFeatureDefinition(params.component)) {
|
|
3395
3395
|
throw new A_FeatureError(
|
|
3396
3396
|
A_FeatureError.FeatureInitializationError,
|
|
3397
|
-
`Invalid A-Feature component provided of type: ${typeof params.component} with value: ${JSON.stringify(params.component)
|
|
3397
|
+
`Invalid A-Feature component provided of type: ${typeof params.component} with value: ${JSON.stringify(params.component)?.slice(0, 100)}...`
|
|
3398
3398
|
);
|
|
3399
3399
|
}
|
|
3400
3400
|
this._name = params.name;
|
|
@@ -3429,8 +3429,26 @@ var A_Feature = class _A_Feature {
|
|
|
3429
3429
|
if (this.isProcessed)
|
|
3430
3430
|
return;
|
|
3431
3431
|
this._state = "PROCESSING" /* PROCESSING */;
|
|
3432
|
-
const
|
|
3433
|
-
|
|
3432
|
+
for (const stage of this) {
|
|
3433
|
+
if (this.state === "INTERRUPTED" /* INTERRUPTED */) return;
|
|
3434
|
+
let result;
|
|
3435
|
+
try {
|
|
3436
|
+
result = stage.process(scope);
|
|
3437
|
+
} catch (error) {
|
|
3438
|
+
throw this.createStageError(error, stage);
|
|
3439
|
+
}
|
|
3440
|
+
if (A_TypeGuards.isPromiseInstance(result)) {
|
|
3441
|
+
return result.then(() => {
|
|
3442
|
+
if (this.state === "INTERRUPTED" /* INTERRUPTED */) return;
|
|
3443
|
+
return this.processRemainingStagesAsync(scope);
|
|
3444
|
+
}).catch((error) => {
|
|
3445
|
+
throw this.createStageError(error, stage);
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
}
|
|
3449
|
+
if (this.state !== "INTERRUPTED" /* INTERRUPTED */) {
|
|
3450
|
+
this.completed();
|
|
3451
|
+
}
|
|
3434
3452
|
} catch (error) {
|
|
3435
3453
|
throw this.failed(new A_FeatureError({
|
|
3436
3454
|
title: A_FeatureError.FeatureProcessingError,
|
|
@@ -3441,45 +3459,37 @@ var A_Feature = class _A_Feature {
|
|
|
3441
3459
|
}
|
|
3442
3460
|
}
|
|
3443
3461
|
/**
|
|
3444
|
-
*
|
|
3462
|
+
* Async continuation — processes remaining stages after the first async pivot.
|
|
3463
|
+
* Resumes from the current iterator position (this._index).
|
|
3445
3464
|
*/
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
if (this.state === "INTERRUPTED" /* INTERRUPTED */)
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
}
|
|
3455
|
-
const stage = stages[index];
|
|
3456
|
-
const result = stage.process(scope);
|
|
3457
|
-
if (A_TypeGuards.isPromiseInstance(result)) {
|
|
3458
|
-
return result.then(() => {
|
|
3459
|
-
if (this.state === "INTERRUPTED" /* INTERRUPTED */) {
|
|
3460
|
-
return;
|
|
3461
|
-
}
|
|
3462
|
-
return this.processStagesSequentially(stages, scope, index + 1);
|
|
3463
|
-
}).catch((error) => {
|
|
3464
|
-
throw this.failed(new A_FeatureError({
|
|
3465
|
-
title: A_FeatureError.FeatureProcessingError,
|
|
3466
|
-
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3467
|
-
stage,
|
|
3468
|
-
originalError: error
|
|
3469
|
-
}));
|
|
3470
|
-
});
|
|
3471
|
-
} else {
|
|
3472
|
-
return this.processStagesSequentially(stages, scope, index + 1);
|
|
3465
|
+
async processRemainingStagesAsync(scope) {
|
|
3466
|
+
for (const stage of this) {
|
|
3467
|
+
if (this.state === "INTERRUPTED" /* INTERRUPTED */) return;
|
|
3468
|
+
try {
|
|
3469
|
+
const result = stage.process(scope);
|
|
3470
|
+
if (A_TypeGuards.isPromiseInstance(result)) await result;
|
|
3471
|
+
} catch (error) {
|
|
3472
|
+
throw this.createStageError(error, stage);
|
|
3473
3473
|
}
|
|
3474
|
-
}
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${this.stage?.name || "N/A"}.`,
|
|
3478
|
-
stage: this.stage,
|
|
3479
|
-
originalError: error
|
|
3480
|
-
}));
|
|
3474
|
+
}
|
|
3475
|
+
if (this.state !== "INTERRUPTED" /* INTERRUPTED */) {
|
|
3476
|
+
this.completed();
|
|
3481
3477
|
}
|
|
3482
3478
|
}
|
|
3479
|
+
createStageError(error, stage) {
|
|
3480
|
+
this.failed(new A_FeatureError({
|
|
3481
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
3482
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3483
|
+
stage,
|
|
3484
|
+
originalError: error
|
|
3485
|
+
}));
|
|
3486
|
+
return new A_FeatureError({
|
|
3487
|
+
title: A_FeatureError.FeatureProcessingError,
|
|
3488
|
+
description: `An error occurred while processing the A-Feature: ${this.name}. Failed at stage: ${stage.name}.`,
|
|
3489
|
+
stage,
|
|
3490
|
+
originalError: error
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3483
3493
|
/**
|
|
3484
3494
|
* This method moves the feature to the next stage
|
|
3485
3495
|
*
|
|
@@ -3679,13 +3689,8 @@ var A_ComponentMeta = class extends A_Meta {
|
|
|
3679
3689
|
};
|
|
3680
3690
|
|
|
3681
3691
|
// src/lib/A-Scope/A-Scope.class.ts
|
|
3682
|
-
var
|
|
3692
|
+
var A_Scope = class {
|
|
3683
3693
|
constructor(param1, param2) {
|
|
3684
|
-
/**
|
|
3685
|
-
* Unique numeric ID for this scope instance. Used as a cache key discriminator
|
|
3686
|
-
* to prevent collisions between scopes with the same name or version.
|
|
3687
|
-
*/
|
|
3688
|
-
this.uid = _A_Scope._nextUid++;
|
|
3689
3694
|
/**
|
|
3690
3695
|
* Internal meta storage using A_Meta for type-safe key-value operations.
|
|
3691
3696
|
* This stores all the scope's runtime data that can be accessed and modified
|
|
@@ -3709,6 +3714,7 @@ var _A_Scope = class _A_Scope {
|
|
|
3709
3714
|
* Invalidated by incrementing _version (cache is cleared on bump).
|
|
3710
3715
|
*/
|
|
3711
3716
|
this._resolveConstructorCache = /* @__PURE__ */ new Map();
|
|
3717
|
+
this._cachedFingerprintVersion = -1;
|
|
3712
3718
|
// ===========================================================================
|
|
3713
3719
|
// --------------------ALLowed Constructors--------------------------------
|
|
3714
3720
|
// ===========================================================================
|
|
@@ -3801,6 +3807,20 @@ var _A_Scope = class _A_Scope {
|
|
|
3801
3807
|
get version() {
|
|
3802
3808
|
return this._version;
|
|
3803
3809
|
}
|
|
3810
|
+
/**
|
|
3811
|
+
* Returns a content-addressable fingerprint of the scope.
|
|
3812
|
+
* Two scopes with identical content (components, entities, fragments, errors, imports, parent)
|
|
3813
|
+
* will produce the same fingerprint. Dynamically recomputed when scope content changes.
|
|
3814
|
+
*/
|
|
3815
|
+
get fingerprint() {
|
|
3816
|
+
const aggregateVersion = this.aggregateVersion(/* @__PURE__ */ new Set());
|
|
3817
|
+
if (this._cachedFingerprint !== void 0 && this._cachedFingerprintVersion === aggregateVersion) {
|
|
3818
|
+
return this._cachedFingerprint;
|
|
3819
|
+
}
|
|
3820
|
+
this._cachedFingerprint = this.computeFingerprint(/* @__PURE__ */ new Set());
|
|
3821
|
+
this._cachedFingerprintVersion = aggregateVersion;
|
|
3822
|
+
return this._cachedFingerprint;
|
|
3823
|
+
}
|
|
3804
3824
|
// ===========================================================================
|
|
3805
3825
|
// --------------------Readonly Registered Properties--------------------------
|
|
3806
3826
|
// ===========================================================================
|
|
@@ -3859,6 +3879,45 @@ var _A_Scope = class _A_Scope {
|
|
|
3859
3879
|
bumpVersion() {
|
|
3860
3880
|
this._version++;
|
|
3861
3881
|
this._resolveConstructorCache.clear();
|
|
3882
|
+
this._cachedFingerprint = void 0;
|
|
3883
|
+
}
|
|
3884
|
+
/**
|
|
3885
|
+
* Computes the aggregate version of this scope and all reachable scopes (parent + imports).
|
|
3886
|
+
* Used to detect when any transitive dependency has changed, so the fingerprint cache can be invalidated.
|
|
3887
|
+
*/
|
|
3888
|
+
aggregateVersion(visited) {
|
|
3889
|
+
if (visited.has(this)) return 0;
|
|
3890
|
+
visited.add(this);
|
|
3891
|
+
let v = this._version;
|
|
3892
|
+
if (this._parent) v += this._parent.aggregateVersion(visited);
|
|
3893
|
+
for (const imp of this._imports) v += imp.aggregateVersion(visited);
|
|
3894
|
+
return v;
|
|
3895
|
+
}
|
|
3896
|
+
/**
|
|
3897
|
+
* Computes a deterministic content-addressable fingerprint string.
|
|
3898
|
+
* Includes components, entities, fragments, errors, parent, and imports.
|
|
3899
|
+
*/
|
|
3900
|
+
computeFingerprint(visited) {
|
|
3901
|
+
if (visited.has(this)) return "~circular~";
|
|
3902
|
+
visited.add(this);
|
|
3903
|
+
const parts = [];
|
|
3904
|
+
parts.push("P:" + (this._parent ? this._parent.computeFingerprint(visited) : "-"));
|
|
3905
|
+
const allowedComponentNames = Array.from(this._allowedComponents).map((c) => A_CommonHelper.getComponentName(c.name)).sort();
|
|
3906
|
+
parts.push("AC:" + allowedComponentNames.join(","));
|
|
3907
|
+
const allowedEntityNames = Array.from(this._allowedEntities).map((e) => A_CommonHelper.getComponentName(e.name)).sort();
|
|
3908
|
+
parts.push("AE:" + allowedEntityNames.join(","));
|
|
3909
|
+
const allowedFragmentNames = Array.from(this._allowedFragments).map((f) => A_CommonHelper.getComponentName(f.name)).sort();
|
|
3910
|
+
parts.push("AF:" + allowedFragmentNames.join(","));
|
|
3911
|
+
const allowedErrorNames = Array.from(this._allowedErrors).map((e) => A_CommonHelper.getComponentName(e.name)).sort();
|
|
3912
|
+
parts.push("AR:" + allowedErrorNames.join(","));
|
|
3913
|
+
const importFingerprints = Array.from(this._imports).map((s) => s.computeFingerprint(visited)).sort();
|
|
3914
|
+
parts.push("I:" + importFingerprints.join(","));
|
|
3915
|
+
const raw = parts.join("|");
|
|
3916
|
+
let hash = 5381;
|
|
3917
|
+
for (let i = 0; i < raw.length; i++) {
|
|
3918
|
+
hash = (hash << 5) + hash + raw.charCodeAt(i) | 0;
|
|
3919
|
+
}
|
|
3920
|
+
return (hash >>> 0).toString(16);
|
|
3862
3921
|
}
|
|
3863
3922
|
/**
|
|
3864
3923
|
* Generator to iterate through all parent scopes
|
|
@@ -3990,9 +4049,6 @@ var _A_Scope = class _A_Scope {
|
|
|
3990
4049
|
this._fragments.clear();
|
|
3991
4050
|
this._entities.clear();
|
|
3992
4051
|
this._imports.clear();
|
|
3993
|
-
if (this.issuer()) {
|
|
3994
|
-
A_Context.deallocate(this);
|
|
3995
|
-
}
|
|
3996
4052
|
this.bumpVersion();
|
|
3997
4053
|
}
|
|
3998
4054
|
/**
|
|
@@ -4141,29 +4197,26 @@ var _A_Scope = class _A_Scope {
|
|
|
4141
4197
|
}
|
|
4142
4198
|
// 3) Check if it's a Component
|
|
4143
4199
|
case A_TypeGuards.isComponentConstructor(ctor): {
|
|
4144
|
-
found = this.isAllowedComponent(ctor) || !!
|
|
4200
|
+
found = this.isAllowedComponent(ctor) || !!A_Context.findDescendantIn(ctor, this.allowedComponents);
|
|
4145
4201
|
break;
|
|
4146
4202
|
}
|
|
4147
4203
|
// 4) Check if it's an Entity
|
|
4148
4204
|
case A_TypeGuards.isEntityConstructor(ctor): {
|
|
4149
|
-
found = this.isAllowedEntity(ctor) || !!
|
|
4205
|
+
found = this.isAllowedEntity(ctor) || !!A_Context.findDescendantIn(ctor, this.allowedEntities);
|
|
4150
4206
|
break;
|
|
4151
4207
|
}
|
|
4152
4208
|
// 5) Check if it's a Fragment
|
|
4153
4209
|
case A_TypeGuards.isFragmentConstructor(ctor): {
|
|
4154
|
-
found = this.isAllowedFragment(ctor) || !!
|
|
4210
|
+
found = this.isAllowedFragment(ctor) || !!A_Context.findDescendantIn(ctor, this.allowedFragments);
|
|
4155
4211
|
break;
|
|
4156
4212
|
}
|
|
4157
4213
|
// 6) Check if it's an Error
|
|
4158
4214
|
case A_TypeGuards.isErrorConstructor(ctor): {
|
|
4159
|
-
found = this.isAllowedError(ctor) || !!
|
|
4215
|
+
found = this.isAllowedError(ctor) || !!A_Context.findDescendantIn(ctor, this.allowedErrors);
|
|
4160
4216
|
break;
|
|
4161
4217
|
}
|
|
4162
4218
|
// 7) Check scope issuer
|
|
4163
|
-
case (this.issuer() && (this.issuer().constructor === ctor ||
|
|
4164
|
-
this.issuer().constructor,
|
|
4165
|
-
ctor
|
|
4166
|
-
))): {
|
|
4219
|
+
case (this.issuer() && (this.issuer().constructor === ctor || A_Context.isIndexedInheritedFrom(this.issuer().constructor, ctor))): {
|
|
4167
4220
|
found = true;
|
|
4168
4221
|
break;
|
|
4169
4222
|
}
|
|
@@ -4235,13 +4288,13 @@ var _A_Scope = class _A_Scope {
|
|
|
4235
4288
|
resolveConstructor(name) {
|
|
4236
4289
|
switch (true) {
|
|
4237
4290
|
case A_TypeGuards.isComponentConstructor(name):
|
|
4238
|
-
return
|
|
4291
|
+
return A_Context.findDescendantIn(name, this.allowedComponents);
|
|
4239
4292
|
case A_TypeGuards.isEntityConstructor(name):
|
|
4240
|
-
return
|
|
4293
|
+
return A_Context.findDescendantIn(name, this.allowedEntities);
|
|
4241
4294
|
case A_TypeGuards.isFragmentConstructor(name):
|
|
4242
|
-
return
|
|
4295
|
+
return A_Context.findDescendantIn(name, this.allowedFragments);
|
|
4243
4296
|
case A_TypeGuards.isErrorConstructor(name):
|
|
4244
|
-
return
|
|
4297
|
+
return A_Context.findDescendantIn(name, this.allowedErrors);
|
|
4245
4298
|
}
|
|
4246
4299
|
if (!A_TypeGuards.isString(name))
|
|
4247
4300
|
throw new A_ScopeError(
|
|
@@ -4267,19 +4320,15 @@ var _A_Scope = class _A_Scope {
|
|
|
4267
4320
|
);
|
|
4268
4321
|
if (component) return component;
|
|
4269
4322
|
else {
|
|
4270
|
-
const
|
|
4271
|
-
|
|
4272
|
-
(c)
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
return true;
|
|
4277
|
-
}
|
|
4278
|
-
current = Object.getPrototypeOf(current);
|
|
4279
|
-
}
|
|
4280
|
-
return false;
|
|
4323
|
+
const pascalName = A_FormatterHelper.toPascalCase(name);
|
|
4324
|
+
const protoComponent = Array.from(this.allowedComponents).find((c) => {
|
|
4325
|
+
const ancestors = A_Context.getAncestors(c);
|
|
4326
|
+
if (!ancestors) return false;
|
|
4327
|
+
for (const ancestor of ancestors) {
|
|
4328
|
+
if (ancestor.name === name || ancestor.name === pascalName) return true;
|
|
4281
4329
|
}
|
|
4282
|
-
|
|
4330
|
+
return false;
|
|
4331
|
+
});
|
|
4283
4332
|
if (protoComponent) return protoComponent;
|
|
4284
4333
|
}
|
|
4285
4334
|
const entity = Array.from(this.allowedEntities).find(
|
|
@@ -4287,9 +4336,15 @@ var _A_Scope = class _A_Scope {
|
|
|
4287
4336
|
);
|
|
4288
4337
|
if (entity) return entity;
|
|
4289
4338
|
else {
|
|
4290
|
-
const
|
|
4291
|
-
|
|
4292
|
-
|
|
4339
|
+
const pascalName = A_FormatterHelper.toPascalCase(name);
|
|
4340
|
+
const protoEntity = Array.from(this.allowedEntities).find((e) => {
|
|
4341
|
+
const ancestors = A_Context.getAncestors(e);
|
|
4342
|
+
if (!ancestors) return false;
|
|
4343
|
+
for (const ancestor of ancestors) {
|
|
4344
|
+
if (ancestor.name === name || ancestor.name === pascalName) return true;
|
|
4345
|
+
}
|
|
4346
|
+
return false;
|
|
4347
|
+
});
|
|
4293
4348
|
if (protoEntity) return protoEntity;
|
|
4294
4349
|
}
|
|
4295
4350
|
const fragment = Array.from(this.allowedFragments).find(
|
|
@@ -4297,9 +4352,15 @@ var _A_Scope = class _A_Scope {
|
|
|
4297
4352
|
);
|
|
4298
4353
|
if (fragment) return fragment;
|
|
4299
4354
|
else {
|
|
4300
|
-
const
|
|
4301
|
-
|
|
4302
|
-
|
|
4355
|
+
const pascalName = A_FormatterHelper.toPascalCase(name);
|
|
4356
|
+
const protoFragment = Array.from(this.allowedFragments).find((f) => {
|
|
4357
|
+
const ancestors = A_Context.getAncestors(f);
|
|
4358
|
+
if (!ancestors) return false;
|
|
4359
|
+
for (const ancestor of ancestors) {
|
|
4360
|
+
if (ancestor.name === name || ancestor.name === pascalName) return true;
|
|
4361
|
+
}
|
|
4362
|
+
return false;
|
|
4363
|
+
});
|
|
4303
4364
|
if (protoFragment) return protoFragment;
|
|
4304
4365
|
}
|
|
4305
4366
|
for (const importedScope of this._imports) {
|
|
@@ -4337,7 +4398,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4337
4398
|
// 1) if a parameter is a component constructor
|
|
4338
4399
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4339
4400
|
this.allowedComponents.forEach((ctor) => {
|
|
4340
|
-
if (
|
|
4401
|
+
if (A_Context.isIndexedInheritedFrom(ctor, param1)) {
|
|
4341
4402
|
const instance = this.resolveOnce(ctor);
|
|
4342
4403
|
if (instance) results.push(instance);
|
|
4343
4404
|
}
|
|
@@ -4347,7 +4408,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4347
4408
|
// 2) if a parameter is a fragment constructor
|
|
4348
4409
|
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
4349
4410
|
this.allowedFragments.forEach((ctor) => {
|
|
4350
|
-
if (
|
|
4411
|
+
if (A_Context.isIndexedInheritedFrom(ctor, param1)) {
|
|
4351
4412
|
const instance = this.resolveOnce(ctor);
|
|
4352
4413
|
if (instance) results.push(instance);
|
|
4353
4414
|
}
|
|
@@ -4356,7 +4417,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4356
4417
|
}
|
|
4357
4418
|
case A_TypeGuards.isEntityConstructor(param1): {
|
|
4358
4419
|
this.entities.forEach((entity) => {
|
|
4359
|
-
if (
|
|
4420
|
+
if (A_Context.isIndexedInheritedFrom(entity.constructor, param1)) {
|
|
4360
4421
|
results.push(entity);
|
|
4361
4422
|
}
|
|
4362
4423
|
});
|
|
@@ -4502,7 +4563,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4502
4563
|
*/
|
|
4503
4564
|
resolveIssuer(ctor) {
|
|
4504
4565
|
const issuer = this.issuer();
|
|
4505
|
-
if (issuer && (issuer.constructor === ctor ||
|
|
4566
|
+
if (issuer && (issuer.constructor === ctor || A_Context.isIndexedInheritedFrom(issuer?.constructor, ctor))) {
|
|
4506
4567
|
return issuer;
|
|
4507
4568
|
}
|
|
4508
4569
|
return void 0;
|
|
@@ -4545,9 +4606,10 @@ var _A_Scope = class _A_Scope {
|
|
|
4545
4606
|
switch (true) {
|
|
4546
4607
|
case (fragmentInstancePresented && this._fragments.has(fragment)):
|
|
4547
4608
|
return fragmentInstancePresented;
|
|
4548
|
-
// 3) In case when there's a
|
|
4549
|
-
case
|
|
4550
|
-
const found =
|
|
4609
|
+
// 3) In case when there's a fragment that is inherited from the required fragment
|
|
4610
|
+
case !fragmentInstancePresented: {
|
|
4611
|
+
const found = A_Context.findDescendantIn(fragment, this._allowedFragments);
|
|
4612
|
+
if (!found) return void 0;
|
|
4551
4613
|
return this.resolveFragment(found);
|
|
4552
4614
|
}
|
|
4553
4615
|
default:
|
|
@@ -4587,8 +4649,9 @@ var _A_Scope = class _A_Scope {
|
|
|
4587
4649
|
return this._components.get(component);
|
|
4588
4650
|
}
|
|
4589
4651
|
// 3) In case when there's a component that is inherited from the required component
|
|
4590
|
-
case
|
|
4591
|
-
const found =
|
|
4652
|
+
case !this.allowedComponents.has(component): {
|
|
4653
|
+
const found = A_Context.findDescendantIn(component, this.allowedComponents);
|
|
4654
|
+
if (!found) return void 0;
|
|
4592
4655
|
return this.resolveComponent(found);
|
|
4593
4656
|
}
|
|
4594
4657
|
default:
|
|
@@ -4608,6 +4671,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4608
4671
|
param1.constructor,
|
|
4609
4672
|
param1
|
|
4610
4673
|
);
|
|
4674
|
+
A_Context.indexConstructor(param1.constructor);
|
|
4611
4675
|
A_Context.register(this, param1);
|
|
4612
4676
|
this.bumpVersion();
|
|
4613
4677
|
break;
|
|
@@ -4617,6 +4681,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4617
4681
|
if (!this.allowedEntities.has(param1.constructor))
|
|
4618
4682
|
this.allowedEntities.add(param1.constructor);
|
|
4619
4683
|
this._entities.set(param1.aseid.toString(), param1);
|
|
4684
|
+
A_Context.indexConstructor(param1.constructor);
|
|
4620
4685
|
A_Context.register(this, param1);
|
|
4621
4686
|
this.bumpVersion();
|
|
4622
4687
|
break;
|
|
@@ -4629,6 +4694,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4629
4694
|
param1.constructor,
|
|
4630
4695
|
param1
|
|
4631
4696
|
);
|
|
4697
|
+
A_Context.indexConstructor(param1.constructor);
|
|
4632
4698
|
A_Context.register(this, param1);
|
|
4633
4699
|
this.bumpVersion();
|
|
4634
4700
|
break;
|
|
@@ -4641,6 +4707,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4641
4707
|
param1.code,
|
|
4642
4708
|
param1
|
|
4643
4709
|
);
|
|
4710
|
+
A_Context.indexConstructor(param1.constructor);
|
|
4644
4711
|
A_Context.register(this, param1);
|
|
4645
4712
|
this.bumpVersion();
|
|
4646
4713
|
break;
|
|
@@ -4652,6 +4719,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4652
4719
|
case A_TypeGuards.isComponentConstructor(param1): {
|
|
4653
4720
|
if (!this.allowedComponents.has(param1)) {
|
|
4654
4721
|
this.allowedComponents.add(param1);
|
|
4722
|
+
A_Context.indexConstructor(param1);
|
|
4655
4723
|
this.bumpVersion();
|
|
4656
4724
|
}
|
|
4657
4725
|
break;
|
|
@@ -4660,6 +4728,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4660
4728
|
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
4661
4729
|
if (!this.allowedFragments.has(param1)) {
|
|
4662
4730
|
this.allowedFragments.add(param1);
|
|
4731
|
+
A_Context.indexConstructor(param1);
|
|
4663
4732
|
this.bumpVersion();
|
|
4664
4733
|
}
|
|
4665
4734
|
break;
|
|
@@ -4668,6 +4737,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4668
4737
|
case A_TypeGuards.isEntityConstructor(param1): {
|
|
4669
4738
|
if (!this.allowedEntities.has(param1)) {
|
|
4670
4739
|
this.allowedEntities.add(param1);
|
|
4740
|
+
A_Context.indexConstructor(param1);
|
|
4671
4741
|
this.bumpVersion();
|
|
4672
4742
|
}
|
|
4673
4743
|
break;
|
|
@@ -4676,6 +4746,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4676
4746
|
case A_TypeGuards.isErrorConstructor(param1): {
|
|
4677
4747
|
if (!this.allowedErrors.has(param1)) {
|
|
4678
4748
|
this.allowedErrors.add(param1);
|
|
4749
|
+
A_Context.indexConstructor(param1);
|
|
4679
4750
|
this.bumpVersion();
|
|
4680
4751
|
}
|
|
4681
4752
|
break;
|
|
@@ -4769,7 +4840,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4769
4840
|
case A_TypeGuards.isFragmentConstructor(param1): {
|
|
4770
4841
|
this.allowedFragments.delete(param1);
|
|
4771
4842
|
Array.from(this._fragments.entries()).forEach(([ctor, instance]) => {
|
|
4772
|
-
if (
|
|
4843
|
+
if (A_Context.isIndexedInheritedFrom(ctor, param1)) {
|
|
4773
4844
|
this._fragments.delete(ctor);
|
|
4774
4845
|
A_Context.deregister(instance);
|
|
4775
4846
|
}
|
|
@@ -4781,7 +4852,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4781
4852
|
case A_TypeGuards.isEntityConstructor(param1): {
|
|
4782
4853
|
this.allowedEntities.delete(param1);
|
|
4783
4854
|
Array.from(this._entities.entries()).forEach(([aseid, instance]) => {
|
|
4784
|
-
if (
|
|
4855
|
+
if (A_Context.isIndexedInheritedFrom(instance.constructor, param1)) {
|
|
4785
4856
|
this._entities.delete(aseid);
|
|
4786
4857
|
A_Context.deregister(instance);
|
|
4787
4858
|
}
|
|
@@ -4793,7 +4864,7 @@ var _A_Scope = class _A_Scope {
|
|
|
4793
4864
|
case A_TypeGuards.isErrorConstructor(param1): {
|
|
4794
4865
|
this.allowedErrors.delete(param1);
|
|
4795
4866
|
Array.from(this._errors.entries()).forEach(([code, instance]) => {
|
|
4796
|
-
if (
|
|
4867
|
+
if (A_Context.isIndexedInheritedFrom(instance.constructor, param1)) {
|
|
4797
4868
|
this._errors.delete(code);
|
|
4798
4869
|
A_Context.deregister(instance);
|
|
4799
4870
|
}
|
|
@@ -4919,11 +4990,6 @@ var _A_Scope = class _A_Scope {
|
|
|
4919
4990
|
console.log(chain.join(" -> "));
|
|
4920
4991
|
}
|
|
4921
4992
|
};
|
|
4922
|
-
/**
|
|
4923
|
-
* Auto-incrementing counter for generating unique scope IDs.
|
|
4924
|
-
*/
|
|
4925
|
-
_A_Scope._nextUid = 0;
|
|
4926
|
-
var A_Scope = _A_Scope;
|
|
4927
4993
|
|
|
4928
4994
|
// src/lib/A-Scope/A-Scope.error.ts
|
|
4929
4995
|
var A_ScopeError = class extends A_Error {
|
|
@@ -4998,7 +5064,20 @@ var _A_Context = class _A_Context {
|
|
|
4998
5064
|
* Key format: `${featureName}::${componentConstructorName}::${scopeVersion}::${metaVersion}`
|
|
4999
5065
|
* Automatically invalidated when scope version or meta version changes.
|
|
5000
5066
|
*/
|
|
5001
|
-
this.
|
|
5067
|
+
this._featureCache = /* @__PURE__ */ new Map();
|
|
5068
|
+
// ====================================================================================================
|
|
5069
|
+
// ================================ INHERITANCE INDEX ==================================================
|
|
5070
|
+
// ====================================================================================================
|
|
5071
|
+
/**
|
|
5072
|
+
* For each indexed constructor, stores the set of all its ancestor constructors
|
|
5073
|
+
* (walking up the prototype chain). Enables O(1) isInheritedFrom checks.
|
|
5074
|
+
*/
|
|
5075
|
+
this._ancestors = /* @__PURE__ */ new Map();
|
|
5076
|
+
/**
|
|
5077
|
+
* For each constructor, stores the set of all known descendant constructors.
|
|
5078
|
+
* Enables O(1) "find a descendant in a Set" lookups.
|
|
5079
|
+
*/
|
|
5080
|
+
this._descendants = /* @__PURE__ */ new Map();
|
|
5002
5081
|
this._globals = /* @__PURE__ */ new Map();
|
|
5003
5082
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
5004
5083
|
this._root = new A_Scope({ name });
|
|
@@ -5074,17 +5153,18 @@ var _A_Context = class _A_Context {
|
|
|
5074
5153
|
* @param component - Component to deregister from the context.
|
|
5075
5154
|
*/
|
|
5076
5155
|
static deregister(component) {
|
|
5077
|
-
const componentName = A_CommonHelper.getComponentName(component);
|
|
5078
|
-
const instance = this.getInstance();
|
|
5079
5156
|
if (!component) throw new A_ContextError(
|
|
5080
5157
|
A_ContextError.InvalidDeregisterParameterError,
|
|
5081
5158
|
`Unable to deregister component. Component cannot be null or undefined.`
|
|
5082
5159
|
);
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5160
|
+
const instance = this.getInstance();
|
|
5161
|
+
if (!instance._scopeStorage.delete(component)) {
|
|
5162
|
+
const componentName = A_CommonHelper.getComponentName(component);
|
|
5163
|
+
throw new A_ContextError(
|
|
5164
|
+
A_ContextError.ComponentNotRegisteredError,
|
|
5165
|
+
`Unable to deregister component. Component ${componentName} is not registered.`
|
|
5166
|
+
);
|
|
5167
|
+
}
|
|
5088
5168
|
}
|
|
5089
5169
|
static allocate(component, importing) {
|
|
5090
5170
|
const componentName = A_CommonHelper.getComponentName(component);
|
|
@@ -5203,6 +5283,7 @@ var _A_Context = class _A_Context {
|
|
|
5203
5283
|
inheritedMeta = new metaType();
|
|
5204
5284
|
instance._metaStorage.set(property, inheritedMeta.clone());
|
|
5205
5285
|
instance._metaVersion++;
|
|
5286
|
+
this.indexConstructor(property);
|
|
5206
5287
|
}
|
|
5207
5288
|
return instance._metaStorage.get(property);
|
|
5208
5289
|
}
|
|
@@ -5271,12 +5352,22 @@ var _A_Context = class _A_Context {
|
|
|
5271
5352
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5272
5353
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5273
5354
|
throw new A_ContextError(A_ContextError.InvalidFeatureTemplateParameterError, `Unable to get feature template. Component of type ${A_CommonHelper.getComponentName(component)} is not allowed for feature definition.`);
|
|
5355
|
+
const instance = this.getInstance();
|
|
5356
|
+
const cacheKey = `${String(name)}::${A_CommonHelper.getComponentName(component)}::s${scope.fingerprint}::m${instance._metaVersion}`;
|
|
5357
|
+
const cached = instance._featureCache.get(cacheKey);
|
|
5358
|
+
if (cached) {
|
|
5359
|
+
return cached;
|
|
5360
|
+
}
|
|
5274
5361
|
const steps = [
|
|
5275
5362
|
// 1) Get the base feature definition from the component
|
|
5276
5363
|
...this.featureDefinition(name, component),
|
|
5277
5364
|
// 2) Get all extensions for the feature from other components in the scope
|
|
5278
5365
|
...this.featureExtensions(name, component, scope)
|
|
5279
5366
|
];
|
|
5367
|
+
if (instance._featureCache.size >= _A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE) {
|
|
5368
|
+
instance._featureCache.clear();
|
|
5369
|
+
}
|
|
5370
|
+
instance._featureCache.set(cacheKey, steps);
|
|
5280
5371
|
return steps;
|
|
5281
5372
|
}
|
|
5282
5373
|
// ----------------------------------------------------------------------------------------------------------
|
|
@@ -5297,13 +5388,6 @@ var _A_Context = class _A_Context {
|
|
|
5297
5388
|
if (!name) throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Feature name cannot be null or undefined.`);
|
|
5298
5389
|
if (!A_TypeGuards.isAllowedForFeatureDefinition(component))
|
|
5299
5390
|
throw new A_ContextError(A_ContextError.InvalidFeatureExtensionParameterError, `Unable to get feature template. Component of type ${A_CommonHelper.getComponentName(component)} is not allowed for feature definition.`);
|
|
5300
|
-
const componentCtor = typeof component === "function" ? component : component.constructor;
|
|
5301
|
-
const effectiveScope = scope.parent || scope;
|
|
5302
|
-
const cacheKey = `${String(name)}::${componentCtor.name}::s${effectiveScope.uid}v${effectiveScope.version}::m${instance._metaVersion}`;
|
|
5303
|
-
const cached = instance._featureExtensionsCache.get(cacheKey);
|
|
5304
|
-
if (cached) {
|
|
5305
|
-
return cached;
|
|
5306
|
-
}
|
|
5307
5391
|
const callNames = A_CommonHelper.getClassInheritanceChain(component).filter((c) => c !== A_Component && c !== A_Container && c !== A_Entity).map((c) => `${c.name}.${name}`);
|
|
5308
5392
|
const steps = /* @__PURE__ */ new Map();
|
|
5309
5393
|
const allowedComponents = /* @__PURE__ */ new Set();
|
|
@@ -5337,7 +5421,7 @@ var _A_Context = class _A_Context {
|
|
|
5337
5421
|
const extensions = meta.extensions(callName);
|
|
5338
5422
|
for (let i = 0; i < extensions.length; i++) {
|
|
5339
5423
|
const declaration = extensions[i];
|
|
5340
|
-
const inherited = Array.from(allowedComponents).reverse().find((c) =>
|
|
5424
|
+
const inherited = Array.from(allowedComponents).reverse().find((c) => _A_Context.isIndexedInheritedFrom(cmp, c) && c !== cmp);
|
|
5341
5425
|
if (inherited) {
|
|
5342
5426
|
steps.delete(`${getNameCached(inherited)}.${declaration.handler}`);
|
|
5343
5427
|
}
|
|
@@ -5357,10 +5441,6 @@ var _A_Context = class _A_Context {
|
|
|
5357
5441
|
}
|
|
5358
5442
|
}
|
|
5359
5443
|
const result = instance.filterToMostDerived(scope, Array.from(steps.values()));
|
|
5360
|
-
if (instance._featureExtensionsCache.size >= _A_Context.FEATURE_EXTENSIONS_CACHE_MAX_SIZE) {
|
|
5361
|
-
instance._featureExtensionsCache.clear();
|
|
5362
|
-
}
|
|
5363
|
-
instance._featureExtensionsCache.set(cacheKey, result);
|
|
5364
5444
|
return result;
|
|
5365
5445
|
}
|
|
5366
5446
|
/**
|
|
@@ -5392,14 +5472,14 @@ var _A_Context = class _A_Context {
|
|
|
5392
5472
|
}
|
|
5393
5473
|
for (const [depName, ctor] of resolvedClasses) {
|
|
5394
5474
|
if (!ctor) continue;
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
const
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5475
|
+
const ancestors = _A_Context.getAncestors(ctor);
|
|
5476
|
+
if (ancestors) {
|
|
5477
|
+
for (const ancestor of ancestors) {
|
|
5478
|
+
const ancestorName = ctorToName.get(ancestor);
|
|
5479
|
+
if (ancestorName && ancestorName !== depName && presentNames.has(ancestorName)) {
|
|
5480
|
+
parentNames.add(ancestorName);
|
|
5481
|
+
}
|
|
5401
5482
|
}
|
|
5402
|
-
ancestor = Object.getPrototypeOf(ancestor);
|
|
5403
5483
|
}
|
|
5404
5484
|
}
|
|
5405
5485
|
return items.filter((item) => !parentNames.has(item.dependency.name));
|
|
@@ -5498,7 +5578,7 @@ var _A_Context = class _A_Context {
|
|
|
5498
5578
|
if (scope.has(cmp) && (A_TypeGuards.isComponentMetaInstance(meta) || A_TypeGuards.isContainerMetaInstance(meta))) {
|
|
5499
5579
|
allowedComponents.add(cmp);
|
|
5500
5580
|
meta.abstractions(abstraction).forEach((declaration) => {
|
|
5501
|
-
const inherited = Array.from(allowedComponents).reverse().find((c) =>
|
|
5581
|
+
const inherited = Array.from(allowedComponents).reverse().find((c) => _A_Context.isIndexedInheritedFrom(cmp, c) && c !== cmp);
|
|
5502
5582
|
if (inherited) {
|
|
5503
5583
|
steps.delete(`${A_CommonHelper.getComponentName(inherited)}.${declaration.handler}`);
|
|
5504
5584
|
}
|
|
@@ -5517,12 +5597,132 @@ var _A_Context = class _A_Context {
|
|
|
5517
5597
|
static reset() {
|
|
5518
5598
|
const instance = _A_Context.getInstance();
|
|
5519
5599
|
instance._registry = /* @__PURE__ */ new WeakMap();
|
|
5520
|
-
instance.
|
|
5600
|
+
instance._featureCache.clear();
|
|
5601
|
+
instance._ancestors.clear();
|
|
5602
|
+
instance._descendants.clear();
|
|
5521
5603
|
instance._metaVersion++;
|
|
5522
5604
|
const name = String(A_CONCEPT_ENV.A_CONCEPT_ROOT_SCOPE) || "root";
|
|
5523
5605
|
instance._root = new A_Scope({ name });
|
|
5524
5606
|
}
|
|
5525
5607
|
// ====================================================================================================================
|
|
5608
|
+
// ====================================== INHERITANCE INDEX ============================================================
|
|
5609
|
+
// ====================================================================================================================
|
|
5610
|
+
/**
|
|
5611
|
+
* Index a constructor's full prototype chain into the inheritance graph.
|
|
5612
|
+
* Safe to call multiple times for the same constructor — it's a no-op if already indexed.
|
|
5613
|
+
*
|
|
5614
|
+
* After indexing, `A_Context.isIndexedInheritedFrom(child, parent)` becomes O(1).
|
|
5615
|
+
*/
|
|
5616
|
+
static indexConstructor(ctor) {
|
|
5617
|
+
const instance = this.getInstance();
|
|
5618
|
+
if (instance._ancestors.has(ctor)) return;
|
|
5619
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
5620
|
+
let current = Object.getPrototypeOf(ctor);
|
|
5621
|
+
while (current && current !== Function.prototype && current !== Object) {
|
|
5622
|
+
ancestors.add(current);
|
|
5623
|
+
let desc = instance._descendants.get(current);
|
|
5624
|
+
if (!desc) {
|
|
5625
|
+
desc = /* @__PURE__ */ new Set();
|
|
5626
|
+
instance._descendants.set(current, desc);
|
|
5627
|
+
}
|
|
5628
|
+
desc.add(ctor);
|
|
5629
|
+
const existingAncestors = instance._ancestors.get(current);
|
|
5630
|
+
if (existingAncestors) {
|
|
5631
|
+
for (const a of existingAncestors) {
|
|
5632
|
+
ancestors.add(a);
|
|
5633
|
+
let desc2 = instance._descendants.get(a);
|
|
5634
|
+
if (!desc2) {
|
|
5635
|
+
desc2 = /* @__PURE__ */ new Set();
|
|
5636
|
+
instance._descendants.set(a, desc2);
|
|
5637
|
+
}
|
|
5638
|
+
desc2.add(ctor);
|
|
5639
|
+
}
|
|
5640
|
+
break;
|
|
5641
|
+
}
|
|
5642
|
+
current = Object.getPrototypeOf(current);
|
|
5643
|
+
}
|
|
5644
|
+
instance._ancestors.set(ctor, ancestors);
|
|
5645
|
+
if (!instance._descendants.has(ctor)) {
|
|
5646
|
+
instance._descendants.set(ctor, /* @__PURE__ */ new Set());
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
/**
|
|
5650
|
+
* O(1) check whether `child` inherits from `parent` using the pre-built index.
|
|
5651
|
+
* Falls back to prototype chain walking if either is not yet indexed.
|
|
5652
|
+
*
|
|
5653
|
+
* [!] Handles the same-class case: returns true if child === parent.
|
|
5654
|
+
*/
|
|
5655
|
+
static isIndexedInheritedFrom(child, parent) {
|
|
5656
|
+
if (child === parent) return true;
|
|
5657
|
+
const instance = this.getInstance();
|
|
5658
|
+
const ancestors = instance._ancestors.get(child);
|
|
5659
|
+
if (ancestors) return ancestors.has(parent);
|
|
5660
|
+
return A_CommonHelper.isInheritedFrom(child, parent);
|
|
5661
|
+
}
|
|
5662
|
+
/**
|
|
5663
|
+
* Find the first constructor in `candidates` that is a descendant of (or equal to) `parent`.
|
|
5664
|
+
* Returns undefined if none found.
|
|
5665
|
+
*
|
|
5666
|
+
* Uses the optimal strategy based on set sizes:
|
|
5667
|
+
* - If candidates is small, iterates candidates and checks ancestry (O(c))
|
|
5668
|
+
* - If descendants is small, iterates descendants and checks membership (O(d))
|
|
5669
|
+
*/
|
|
5670
|
+
static findDescendantIn(parent, candidates) {
|
|
5671
|
+
const candidateSize = candidates instanceof Set ? candidates.size : candidates.length;
|
|
5672
|
+
if (candidates instanceof Set) {
|
|
5673
|
+
if (candidates.has(parent)) return parent;
|
|
5674
|
+
} else {
|
|
5675
|
+
if (candidates.includes(parent)) return parent;
|
|
5676
|
+
}
|
|
5677
|
+
const instance = this.getInstance();
|
|
5678
|
+
const descendants = instance._descendants.get(parent);
|
|
5679
|
+
const descendantSize = descendants ? descendants.size : 0;
|
|
5680
|
+
if (descendantSize === 0) {
|
|
5681
|
+
if (candidates instanceof Set) {
|
|
5682
|
+
for (const c of candidates) {
|
|
5683
|
+
const ancestors = instance._ancestors.get(c);
|
|
5684
|
+
if (ancestors && ancestors.has(parent)) return c;
|
|
5685
|
+
}
|
|
5686
|
+
} else {
|
|
5687
|
+
for (const c of candidates) {
|
|
5688
|
+
const ancestors = instance._ancestors.get(c);
|
|
5689
|
+
if (ancestors && ancestors.has(parent)) return c;
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5692
|
+
return void 0;
|
|
5693
|
+
}
|
|
5694
|
+
if (candidateSize <= descendantSize) {
|
|
5695
|
+
if (candidates instanceof Set) {
|
|
5696
|
+
for (const c of candidates) {
|
|
5697
|
+
if (c === parent) return c;
|
|
5698
|
+
const ancestors = instance._ancestors.get(c);
|
|
5699
|
+
if (ancestors && ancestors.has(parent)) return c;
|
|
5700
|
+
}
|
|
5701
|
+
} else {
|
|
5702
|
+
for (const c of candidates) {
|
|
5703
|
+
if (c === parent) return c;
|
|
5704
|
+
const ancestors = instance._ancestors.get(c);
|
|
5705
|
+
if (ancestors && ancestors.has(parent)) return c;
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
} else {
|
|
5709
|
+
for (const desc of descendants) {
|
|
5710
|
+
if (candidates instanceof Set) {
|
|
5711
|
+
if (candidates.has(desc)) return desc;
|
|
5712
|
+
} else {
|
|
5713
|
+
if (candidates.includes(desc)) return desc;
|
|
5714
|
+
}
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5717
|
+
return void 0;
|
|
5718
|
+
}
|
|
5719
|
+
/**
|
|
5720
|
+
* Returns the set of indexed ancestors for a constructor, or undefined if not indexed.
|
|
5721
|
+
*/
|
|
5722
|
+
static getAncestors(ctor) {
|
|
5723
|
+
return this.getInstance()._ancestors.get(ctor);
|
|
5724
|
+
}
|
|
5725
|
+
// ====================================================================================================================
|
|
5526
5726
|
// ====================================== HELPERS & GUARDS ============================================================
|
|
5527
5727
|
// ====================================================================================================================
|
|
5528
5728
|
/**
|