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