@neocompose/cli 0.50.3 → 0.50.5

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/dist/neo.mjs CHANGED
@@ -46293,6 +46293,41 @@ function resolveWorldSystemClassKind(classId, classes, draft) {
46293
46293
  }
46294
46294
  return null;
46295
46295
  }
46296
+ function indexWorldSystemClassKinds(classes, classesById = indexById2(classes)) {
46297
+ const kinds = /* @__PURE__ */ new Map();
46298
+ for (const schemaClass2 of classes) {
46299
+ if (schemaClass2.system?.worldKind != null) {
46300
+ kinds.set(schemaClass2.id, schemaClass2.system.worldKind);
46301
+ } else if (schemaClass2.extendsClassId === void 0) {
46302
+ kinds.set(schemaClass2.id, null);
46303
+ }
46304
+ }
46305
+ const resolving = /* @__PURE__ */ new Set();
46306
+ for (const schemaClass2 of classes) {
46307
+ if (kinds.has(schemaClass2.id)) continue;
46308
+ const path = [];
46309
+ let current = schemaClass2;
46310
+ let resolved = null;
46311
+ while (current !== void 0) {
46312
+ if (kinds.has(current.id)) {
46313
+ resolved = kinds.get(current.id) ?? null;
46314
+ break;
46315
+ }
46316
+ if (resolving.has(current.id)) {
46317
+ resolved = null;
46318
+ break;
46319
+ }
46320
+ resolving.add(current.id);
46321
+ path.push(current);
46322
+ current = current.extendsClassId === void 0 ? void 0 : classesById.get(current.extendsClassId);
46323
+ }
46324
+ for (const candidate of path) {
46325
+ resolving.delete(candidate.id);
46326
+ kinds.set(candidate.id, resolved);
46327
+ }
46328
+ }
46329
+ return kinds;
46330
+ }
46296
46331
  function dedupeSchemaKeyOrder(order) {
46297
46332
  const seen = /* @__PURE__ */ new Set();
46298
46333
  const result = [];
@@ -70308,7 +70343,7 @@ var init_constructor_argument_ownership = __esm({
70308
70343
  membersById;
70309
70344
  constructorsById;
70310
70345
  contextualRootMembersByValueId;
70311
- parameterTypesByValueId = /* @__PURE__ */ new Map();
70346
+ parameterTypesByRow = /* @__PURE__ */ new WeakMap();
70312
70347
  settleConstructorParameter;
70313
70348
  aggregateTypeByTargetValueId = /* @__PURE__ */ new Map();
70314
70349
  typedNormalizer;
@@ -70355,10 +70390,10 @@ var init_constructor_argument_ownership = __esm({
70355
70390
  return this.ownershipFacts().independentlyOwnedValueIds;
70356
70391
  }
70357
70392
  constructorParameterTypes(root) {
70358
- const cached = this.parameterTypesByValueId.get(root.id);
70393
+ const cached = this.parameterTypesByRow.get(root);
70359
70394
  if (cached !== void 0) return cached;
70360
70395
  const result = this.resolveConstructorParameterTypes(root);
70361
- this.parameterTypesByValueId.set(root.id, result);
70396
+ this.parameterTypesByRow.set(root, result);
70362
70397
  return result;
70363
70398
  }
70364
70399
  resolveConstructorParameterTypes(root) {
@@ -70806,6 +70841,10 @@ function validateInternalRecordRelations(args) {
70806
70841
  const classesById = new Map(
70807
70842
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
70808
70843
  );
70844
+ const worldKindsByClassId = indexWorldSystemClassKinds(
70845
+ args.classes,
70846
+ classesById
70847
+ );
70809
70848
  const relationIds = /* @__PURE__ */ new Set();
70810
70849
  const edgeKeys = /* @__PURE__ */ new Set();
70811
70850
  const orderedKeys2 = /* @__PURE__ */ new Set();
@@ -70870,7 +70909,7 @@ function validateInternalRecordRelations(args) {
70870
70909
  endpoint: "source",
70871
70910
  recordEndpoint: source,
70872
70911
  classesById,
70873
- classes: args.classes
70912
+ worldKindsByClassId
70874
70913
  });
70875
70914
  validateWorldEndpoint({
70876
70915
  relation,
@@ -70878,7 +70917,7 @@ function validateInternalRecordRelations(args) {
70878
70917
  endpoint: "target",
70879
70918
  recordEndpoint: target,
70880
70919
  classesById,
70881
- classes: args.classes
70920
+ worldKindsByClassId
70882
70921
  });
70883
70922
  const edgeKey = [
70884
70923
  relation.relationKind,
@@ -70937,13 +70976,6 @@ function validateInternalRecordRelations(args) {
70937
70976
  contracts: [...contracts.values()]
70938
70977
  });
70939
70978
  }
70940
- function resolveEffectiveClassRelations(args) {
70941
- return createEffectiveClassRelationResolver({
70942
- classes: args.classes,
70943
- relations: args.relations,
70944
- contracts: args.contracts
70945
- }).resolve(args.relationKind, args.sourceClassId);
70946
- }
70947
70979
  function createEffectiveClassRelationResolver(args) {
70948
70980
  const contracts = args.contracts ?? INTERNAL_RECORD_RELATION_KIND_CONTRACTS;
70949
70981
  const contractsByKind = /* @__PURE__ */ new Map();
@@ -71189,10 +71221,7 @@ function validateWorldEndpoint(args) {
71189
71221
  `Internal record relation "${args.relation.id}" ${args.endpoint} ${classLabel} "${classId}" does not exist.`
71190
71222
  );
71191
71223
  }
71192
- const actualWorldKind = resolveWorldSystemClassKind(
71193
- schemaClass2.id,
71194
- args.classes
71195
- );
71224
+ const actualWorldKind = args.worldKindsByClassId.get(schemaClass2.id) ?? null;
71196
71225
  if (actualWorldKind !== requiredWorldKind) {
71197
71226
  throw new Error(
71198
71227
  `Internal record relation "${args.relation.id}" ${args.endpoint} ${classLabel} "${schemaClass2.id}" must extend world class kind "${requiredWorldKind}".`
@@ -71243,6 +71272,8 @@ function validateRelationCycles(relations, contracts) {
71243
71272
  for (const endpoint2 of outgoing.keys()) visit(endpoint2);
71244
71273
  }
71245
71274
  function validateDefaultLayerCompatibility(args) {
71275
+ const resolver = createEffectiveClassRelationResolver(args);
71276
+ const compatibleBySource = /* @__PURE__ */ new Map();
71246
71277
  const pairs = [
71247
71278
  {
71248
71279
  defaultKind: InternalRecordRelationKind.WorldTileDefaultLayer,
@@ -71256,16 +71287,15 @@ function validateDefaultLayerCompatibility(args) {
71256
71287
  for (const pair of pairs) {
71257
71288
  for (const relation of args.relations) {
71258
71289
  if (relation.relationKind !== pair.defaultKind) continue;
71259
- const compatible = resolveEffectiveClassRelations({
71260
- relationKind: pair.compatibleKind,
71261
- sourceClassId: relation.sourceRecordId,
71262
- relations: args.relations,
71263
- classes: args.classes,
71264
- contracts: args.contracts
71265
- });
71266
- if (compatible.some(
71267
- (effective) => effective.targetRecordId === relation.targetRecordId
71268
- )) {
71290
+ const key = `${pair.compatibleKind}:${relation.sourceRecordId}`;
71291
+ let compatible = compatibleBySource.get(key);
71292
+ if (compatible === void 0) {
71293
+ compatible = new Set(
71294
+ resolver.resolve(pair.compatibleKind, relation.sourceRecordId).map((entry) => entry.targetRecordId)
71295
+ );
71296
+ compatibleBySource.set(key, compatible);
71297
+ }
71298
+ if (compatible.has(relation.targetRecordId)) {
71269
71299
  continue;
71270
71300
  }
71271
71301
  throw new Error(
@@ -71460,6 +71490,386 @@ var init_project2 = __esm({
71460
71490
  }
71461
71491
  });
71462
71492
 
71493
+ // ../src/models/members/stored-value-placement-index.ts
71494
+ function buildStoredValuePlacementIndex(args) {
71495
+ return createStoredValuePlacementTraversal(args)();
71496
+ }
71497
+ function createStoredValuePlacementTraversal(args, trackReferences = false) {
71498
+ const membersById = /* @__PURE__ */ new Map();
71499
+ for (const member of args.members) membersById.set(member.id, member);
71500
+ const valuesById = args.indexedRows?.valuesById ?? new Map(args.values.map((row) => [row.id, row]));
71501
+ const unorderedEntriesByContainerId = /* @__PURE__ */ new Map();
71502
+ for (const value of args.indexedRows === void 0 ? args.values : []) {
71503
+ if (typeof value.containerId !== "string") continue;
71504
+ const entries = unorderedEntriesByContainerId.get(value.containerId);
71505
+ if (entries === void 0) {
71506
+ unorderedEntriesByContainerId.set(value.containerId, [value]);
71507
+ } else {
71508
+ entries.push(value);
71509
+ }
71510
+ }
71511
+ for (const entries of unorderedEntriesByContainerId.values()) {
71512
+ entries.sort((left, right) => left.id.localeCompare(right.id));
71513
+ }
71514
+ const constructorsById = new Map(
71515
+ args.constructors.map((constructor2) => [constructor2.id, constructor2])
71516
+ );
71517
+ const resolveConstructorSettlement = createConstructorSettlementResolver({
71518
+ classes: args.classes,
71519
+ constructors: args.constructors,
71520
+ members: args.members
71521
+ });
71522
+ const resolvedMemberById = /* @__PURE__ */ new Map();
71523
+ const resolvedMember = (member) => {
71524
+ const cached = resolvedMemberById.get(member.id);
71525
+ if (cached !== void 0) return cached;
71526
+ const resolved = resolveMember2(member, args.members);
71527
+ resolvedMemberById.set(member.id, resolved);
71528
+ return resolved;
71529
+ };
71530
+ const storedSchemaByClassId = /* @__PURE__ */ new Map();
71531
+ const storedSchema = (classId) => {
71532
+ const cached = storedSchemaByClassId.get(classId);
71533
+ if (cached !== void 0) return cached;
71534
+ const schema = mergeStoredInstanceSchema(
71535
+ classId,
71536
+ args.classes,
71537
+ args.members
71538
+ );
71539
+ storedSchemaByClassId.set(classId, schema);
71540
+ return schema;
71541
+ };
71542
+ return (roots) => {
71543
+ const queue = [...roots ?? []];
71544
+ if (roots === void 0) {
71545
+ for (const root of projectRootMembersInDisplayOrder(args.project)) {
71546
+ const member = membersById.get(root.memberId);
71547
+ if (member === void 0 || typeof member.valueId !== "string")
71548
+ continue;
71549
+ queue.push({
71550
+ memberId: member.id,
71551
+ parentValueId: null,
71552
+ source: {
71553
+ kind: "root",
71554
+ label: root.root.label,
71555
+ sourcePath: `root.${root.root.key}`
71556
+ },
71557
+ valueId: member.valueId
71558
+ });
71559
+ }
71560
+ for (const member of args.members) {
71561
+ if (!isStaticMember(member) || memberAccessOf(member) !== 0 /* Public */)
71562
+ continue;
71563
+ const valueId = args.resolveStaticValueId(member.id);
71564
+ if (valueId === null) continue;
71565
+ const placement = findSchemaPlacement(member.id, args.classes);
71566
+ if (placement === null) continue;
71567
+ queue.push({
71568
+ memberId: member.id,
71569
+ parentValueId: null,
71570
+ source: {
71571
+ kind: "static",
71572
+ label: placement.schemaKey,
71573
+ ownerClassName: placement.ownerClass.name,
71574
+ sourcePath: `static:${member.id}`
71575
+ },
71576
+ valueId
71577
+ });
71578
+ }
71579
+ }
71580
+ const placementByValueId = /* @__PURE__ */ new Map();
71581
+ const mutablePlacementsByClassId = /* @__PURE__ */ new Map();
71582
+ const mutablePlacementsByMemberId = /* @__PURE__ */ new Map();
71583
+ const mutablePlacementsByKind = /* @__PURE__ */ new Map();
71584
+ for (let cursor = 0; cursor < queue.length; cursor += 1) {
71585
+ const item = queue[cursor];
71586
+ if (item === void 0 || placementByValueId.has(item.valueId)) continue;
71587
+ const authoredValue = valuesById.get(item.valueId);
71588
+ const storedMember = membersById.get(item.memberId);
71589
+ if (authoredValue === void 0 || storedMember === void 0) continue;
71590
+ const value = args.resolveValue === void 0 ? authoredValue : args.resolveValue(authoredValue);
71591
+ if (value === null) continue;
71592
+ const placement = item;
71593
+ placementByValueId.set(value.id, placement);
71594
+ appendPlacement(mutablePlacementsByMemberId, storedMember.id, placement);
71595
+ const member = resolvedMember(storedMember);
71596
+ appendPlacement(mutablePlacementsByKind, member.kind, placement);
71597
+ if (isMemberClassBase(member)) {
71598
+ const classId = value.classId ?? member.classId;
71599
+ appendPlacement(mutablePlacementsByClassId, classId, placement);
71600
+ if (!isLiteralValueContent(value) || !isStringRecord5(value.value)) {
71601
+ continue;
71602
+ }
71603
+ const settledChildrenBySchemaKey = /* @__PURE__ */ new Map();
71604
+ const constructor2 = typeof value.instanceConstructorId === "string" ? constructorsById.get(value.instanceConstructorId) : void 0;
71605
+ if (constructor2 !== void 0 && constructor2.classId === classId && value.constructorArgs != null) {
71606
+ for (const [
71607
+ index,
71608
+ parameter4
71609
+ ] of constructor2.argumentTypes.entries()) {
71610
+ const settled = resolveConstructorSettlement(
71611
+ classId,
71612
+ parameter4.name,
71613
+ constructor2.id
71614
+ );
71615
+ if (settled === null || Object.hasOwn(value.value, settled.schemaKey)) {
71616
+ continue;
71617
+ }
71618
+ const childValueId = value.constructorArgs[constructorActionParameterId(constructor2, index)];
71619
+ if (typeof childValueId === "string") {
71620
+ settledChildrenBySchemaKey.set(settled.schemaKey, childValueId);
71621
+ }
71622
+ }
71623
+ }
71624
+ for (const entry of storedSchema(classId)) {
71625
+ const childMember = membersById.get(entry.memberId);
71626
+ const childValueId = value.value[entry.schemaKey] ?? settledChildrenBySchemaKey.get(entry.schemaKey);
71627
+ if (childMember === void 0 || typeof childValueId !== "string") {
71628
+ continue;
71629
+ }
71630
+ if (memberAccessOf(childMember) !== 0 /* Public */) continue;
71631
+ queue.push({
71632
+ memberId: childMember.id,
71633
+ parentValueId: value.id,
71634
+ source: { kind: "classField", schemaKey: entry.schemaKey },
71635
+ valueId: childValueId
71636
+ });
71637
+ }
71638
+ continue;
71639
+ }
71640
+ if (!isMemberListBase(member) && !isMemberDictionaryBase(member)) {
71641
+ continue;
71642
+ }
71643
+ const entryMember = membersById.get(member.entryMemberId);
71644
+ if (entryMember === void 0) continue;
71645
+ if (isMemberDictionaryBase(member)) {
71646
+ if (!isStringRecord5(value.value)) continue;
71647
+ for (const [key, childValueId] of Object.entries(value.value)) {
71648
+ queue.push({
71649
+ memberId: entryMember.id,
71650
+ parentValueId: value.id,
71651
+ source: {
71652
+ kind: "collectionEntry",
71653
+ containerMemberId: storedMember.id,
71654
+ entry: { kind: "dict", key, valueId: childValueId }
71655
+ },
71656
+ valueId: childValueId
71657
+ });
71658
+ }
71659
+ continue;
71660
+ }
71661
+ const entries = listKindOf(member) === 1 /* Unordered */ ? args.indexedRows === void 0 ? unorderedEntriesByContainerId.get(value.id) ?? [] : args.indexedRows.unorderedListEntryIds(value.id).flatMap((id2) => {
71662
+ const row = valuesById.get(id2);
71663
+ return row === void 0 ? [] : [row];
71664
+ }) : Array.isArray(value.value) ? value.value.flatMap((childValueId) => {
71665
+ if (typeof childValueId !== "string") return [];
71666
+ const childValue = valuesById.get(childValueId);
71667
+ return childValue === void 0 ? [] : [childValue];
71668
+ }) : [];
71669
+ for (const [index, childValue] of entries.entries()) {
71670
+ queue.push({
71671
+ memberId: entryMember.id,
71672
+ parentValueId: value.id,
71673
+ source: {
71674
+ kind: "collectionEntry",
71675
+ containerMemberId: storedMember.id,
71676
+ entry: { kind: "list", index, valueId: childValue.id }
71677
+ },
71678
+ valueId: childValue.id
71679
+ });
71680
+ }
71681
+ }
71682
+ const referencesByParentId = /* @__PURE__ */ new Map();
71683
+ if (trackReferences) {
71684
+ for (const id2 of placementByValueId.keys())
71685
+ referencesByParentId.set(id2, /* @__PURE__ */ new Set());
71686
+ for (const item of queue) {
71687
+ if (item.parentValueId !== null)
71688
+ referencesByParentId.get(item.parentValueId)?.add(item.valueId);
71689
+ }
71690
+ }
71691
+ return {
71692
+ referencesByParentId,
71693
+ placementByValueId,
71694
+ placementsByClassId: mutablePlacementsByClassId,
71695
+ placementsByKind: mutablePlacementsByKind,
71696
+ placementsByMemberId: mutablePlacementsByMemberId
71697
+ };
71698
+ };
71699
+ }
71700
+ function createStoredValuePlacementBatch(args) {
71701
+ const traverse = createStoredValuePlacementTraversal(args, true);
71702
+ const initial = traverse();
71703
+ const placementByValueId = new Map(initial.placementByValueId);
71704
+ const childrenByParentId = /* @__PURE__ */ new Map();
71705
+ const referencingParentsById = /* @__PURE__ */ new Map();
71706
+ const referencesByParentId = /* @__PURE__ */ new Map();
71707
+ const declaredRootIds = new Set(
71708
+ args.members.flatMap(
71709
+ (member) => typeof member.valueId === "string" ? [member.valueId] : []
71710
+ )
71711
+ );
71712
+ const indexPlacement = (placement) => {
71713
+ if (placement.parentValueId === null) return;
71714
+ const children = childrenByParentId.get(placement.parentValueId) ?? /* @__PURE__ */ new Set();
71715
+ children.add(placement.valueId);
71716
+ childrenByParentId.set(placement.parentValueId, children);
71717
+ };
71718
+ for (const placement of placementByValueId.values())
71719
+ indexPlacement(placement);
71720
+ const indexReferences2 = (parentId, references) => {
71721
+ for (const id2 of referencesByParentId.get(parentId) ?? []) {
71722
+ const parents = referencingParentsById.get(id2);
71723
+ parents?.delete(parentId);
71724
+ if (parents?.size === 0) referencingParentsById.delete(id2);
71725
+ }
71726
+ referencesByParentId.set(parentId, new Set(references));
71727
+ for (const id2 of references) {
71728
+ const parents = referencingParentsById.get(id2) ?? /* @__PURE__ */ new Set();
71729
+ parents.add(parentId);
71730
+ referencingParentsById.set(id2, parents);
71731
+ }
71732
+ };
71733
+ for (const [parentId, references] of initial.referencesByParentId)
71734
+ indexReferences2(parentId, references);
71735
+ const rebuild = () => {
71736
+ const rebuilt = traverse();
71737
+ placementByValueId.clear();
71738
+ childrenByParentId.clear();
71739
+ referencesByParentId.clear();
71740
+ referencingParentsById.clear();
71741
+ for (const placement of rebuilt.placementByValueId.values()) {
71742
+ placementByValueId.set(placement.valueId, placement);
71743
+ indexPlacement(placement);
71744
+ }
71745
+ for (const [parentId, references] of rebuilt.referencesByParentId)
71746
+ indexReferences2(parentId, references);
71747
+ };
71748
+ return {
71749
+ placementByValueId,
71750
+ /** Call after the external row/membership indexes have received these replacements. */
71751
+ refresh(rows, previousRows) {
71752
+ const affected = /* @__PURE__ */ new Set();
71753
+ const consider = (id2) => {
71754
+ if (typeof id2 === "string" && placementByValueId.has(id2))
71755
+ affected.add(id2);
71756
+ };
71757
+ let needsRootRebuild = false;
71758
+ for (const row of rows) {
71759
+ consider(row.id);
71760
+ if (!placementByValueId.has(row.id)) {
71761
+ for (const parentId of referencingParentsById.get(row.id) ?? [])
71762
+ consider(parentId);
71763
+ }
71764
+ if (!placementByValueId.has(row.id) && declaredRootIds.has(row.id))
71765
+ needsRootRebuild = true;
71766
+ }
71767
+ const previousById = new Map(
71768
+ previousRows.flatMap(
71769
+ (row) => row === void 0 ? [] : [[row.id, row]]
71770
+ )
71771
+ );
71772
+ for (const row of rows) {
71773
+ const previous = previousById.get(row.id);
71774
+ if (previous?.containerId === row.containerId) continue;
71775
+ consider(previous?.containerId);
71776
+ consider(row.containerId);
71777
+ }
71778
+ if (needsRootRebuild) {
71779
+ rebuild();
71780
+ return;
71781
+ }
71782
+ const hasAffectedAncestor = /* @__PURE__ */ new Map();
71783
+ const rootSeeds = [];
71784
+ for (const id2 of affected) {
71785
+ const placement = placementByValueId.get(id2);
71786
+ let parent = placement.parentValueId;
71787
+ const path = [];
71788
+ let found = false;
71789
+ while (parent !== null) {
71790
+ if (affected.has(parent)) {
71791
+ found = true;
71792
+ break;
71793
+ }
71794
+ const cached = hasAffectedAncestor.get(parent);
71795
+ if (cached !== void 0) {
71796
+ found = cached;
71797
+ break;
71798
+ }
71799
+ path.push(parent);
71800
+ parent = placementByValueId.get(parent)?.parentValueId ?? null;
71801
+ }
71802
+ for (const ancestor of path) hasAffectedAncestor.set(ancestor, found);
71803
+ if (!found) rootSeeds.push(placement);
71804
+ }
71805
+ const removed = /* @__PURE__ */ new Set();
71806
+ const queue = rootSeeds.map((root) => root.valueId);
71807
+ for (let index = 0; index < queue.length; index += 1) {
71808
+ const id2 = queue[index];
71809
+ if (removed.has(id2)) continue;
71810
+ removed.add(id2);
71811
+ for (const child of childrenByParentId.get(id2) ?? []) queue.push(child);
71812
+ }
71813
+ for (const id2 of removed) {
71814
+ const oldParent = placementByValueId.get(id2)?.parentValueId;
71815
+ for (const parentId of referencingParentsById.get(id2) ?? []) {
71816
+ if (!removed.has(parentId) && parentId !== oldParent && placementByValueId.has(parentId)) {
71817
+ rebuild();
71818
+ return;
71819
+ }
71820
+ }
71821
+ }
71822
+ for (const id2 of removed) {
71823
+ const parent = placementByValueId.get(id2)?.parentValueId;
71824
+ if (typeof parent === "string")
71825
+ childrenByParentId.get(parent)?.delete(id2);
71826
+ childrenByParentId.delete(id2);
71827
+ placementByValueId.delete(id2);
71828
+ }
71829
+ const next = traverse(rootSeeds);
71830
+ for (const [id2, placement] of next.placementByValueId) {
71831
+ const existing = placementByValueId.get(id2);
71832
+ if (existing !== void 0 && existing.parentValueId !== placement.parentValueId) {
71833
+ rebuild();
71834
+ return;
71835
+ }
71836
+ }
71837
+ for (const id2 of removed) indexReferences2(id2, /* @__PURE__ */ new Set());
71838
+ for (const [parentId, references] of next.referencesByParentId)
71839
+ indexReferences2(parentId, references);
71840
+ for (const placement of next.placementByValueId.values()) {
71841
+ placementByValueId.set(placement.valueId, placement);
71842
+ indexPlacement(placement);
71843
+ }
71844
+ }
71845
+ };
71846
+ }
71847
+ function appendPlacement(index, key, placement) {
71848
+ const placements = index.get(key);
71849
+ if (placements === void 0) {
71850
+ index.set(key, [placement]);
71851
+ } else {
71852
+ placements.push(placement);
71853
+ }
71854
+ }
71855
+ function isStringRecord5(value) {
71856
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
71857
+ return false;
71858
+ }
71859
+ return Object.values(value).every((item) => typeof item === "string");
71860
+ }
71861
+ var init_stored_value_placement_index = __esm({
71862
+ "../src/models/members/stored-value-placement-index.ts"() {
71863
+ "use strict";
71864
+ init_inheritance();
71865
+ init_constructor_parameter_settlement();
71866
+ init_constructors2();
71867
+ init_project2();
71868
+ init_member_kinds();
71869
+ init_members();
71870
+ }
71871
+ });
71872
+
71463
71873
  // ../src/runtime/neoscript/NeoScriptScope.ts
71464
71874
  var NeoScriptScope;
71465
71875
  var init_NeoScriptScope = __esm({
@@ -71883,6 +72293,72 @@ function makeEvaluatorLookups(members, storedValues, options = {}) {
71883
72293
  build.advance(Number.POSITIVE_INFINITY);
71884
72294
  return build.lookups;
71885
72295
  }
72296
+ function createInitializerBatchLookups(document) {
72297
+ const values = [...expandPackedValueRows(document.values)];
72298
+ const positions = new Map(values.map((row, index) => [row.id, index]));
72299
+ const valuesById = new Map(values.map((row) => [row.id, row]));
72300
+ const membersById = new Map(
72301
+ document.members.map((member) => [member.id, member])
72302
+ );
72303
+ const membership = /* @__PURE__ */ new Map();
72304
+ const sortedMembership = /* @__PURE__ */ new Map();
72305
+ const indexMembership = (row, remove = false) => {
72306
+ if (typeof row.containerId !== "string") return;
72307
+ const entries = membership.get(row.containerId) ?? /* @__PURE__ */ new Set();
72308
+ if (remove) entries.delete(row.id);
72309
+ else entries.add(row.id);
72310
+ membership.set(row.containerId, entries);
72311
+ sortedMembership.delete(row.containerId);
72312
+ };
72313
+ for (const row of values) indexMembership(row);
72314
+ const build = createEvaluatorBaseIndexBuild(
72315
+ document.members,
72316
+ values,
72317
+ valuesById
72318
+ );
72319
+ build.advance(Number.POSITIVE_INFINITY);
72320
+ const constructorInitializerIndexes2 = buildConstructorInitializerIndexes(document);
72321
+ const snapshot = () => ({
72322
+ memberById: (id2) => membersById.get(id2) ?? null,
72323
+ valueById: (id2) => valuesById.get(id2) ?? null,
72324
+ hasStoredValueId: (id2) => valuesById.has(id2),
72325
+ unorderedListEntryIds: (id2) => {
72326
+ let sorted = sortedMembership.get(id2);
72327
+ if (sorted === void 0) {
72328
+ sorted = [...membership.get(id2) ?? []].sort();
72329
+ sortedMembership.set(id2, sorted);
72330
+ }
72331
+ return sorted;
72332
+ },
72333
+ rowForValueReference: (value) => build.result.rowByValueReference.get(value) ?? null,
72334
+ virtualInstanceRowsForValue: () => [],
72335
+ evaluatorIndexes: { ...build.result },
72336
+ constructorInitializerIndexes: constructorInitializerIndexes2
72337
+ });
72338
+ return {
72339
+ values,
72340
+ valuesById,
72341
+ membersById,
72342
+ snapshot,
72343
+ upsert(rows) {
72344
+ for (const row of rows) {
72345
+ const previous = valuesById.get(row.id);
72346
+ if (previous === row) continue;
72347
+ const membershipChanged = previous?.containerId !== row.containerId;
72348
+ if (membershipChanged && previous !== void 0)
72349
+ indexMembership(previous, true);
72350
+ build.replaceRow(previous, row);
72351
+ const position = positions.get(row.id);
72352
+ if (position === void 0) {
72353
+ positions.set(row.id, values.length);
72354
+ values.push(row);
72355
+ } else values[position] = row;
72356
+ valuesById.set(row.id, row);
72357
+ if (membershipChanged) indexMembership(row);
72358
+ }
72359
+ }
72360
+ };
72361
+ }
71886
72362
  function evalMemberById(vm, id2) {
71887
72363
  if (vm.databaseVM?.memberById) return vm.databaseVM.memberById(id2);
71888
72364
  return vm.members.find((a) => a.id === id2) ?? null;
@@ -71978,6 +72454,10 @@ function createEvaluatorBaseIndexBuild(members, values, valueById) {
71978
72454
  get result() {
71979
72455
  return result;
71980
72456
  },
72457
+ replaceRow(previous, row) {
72458
+ if (previous !== void 0) unindexEvaluatorRow(indexes, previous, true);
72459
+ indexEvaluatorRow(indexes, row);
72460
+ },
71981
72461
  advance(maxRows) {
71982
72462
  if (result !== null) return true;
71983
72463
  const count = Math.max(1, Math.floor(maxRows));
@@ -72247,11 +72727,17 @@ function visitEvaluatorRecordOwnershipEdges(indexes, row, visit) {
72247
72727
  }
72248
72728
  return true;
72249
72729
  }
72250
- function unindexEvaluatorRow(indexes, row) {
72730
+ function unindexEvaluatorRow(indexes, row, preserveIncomingLinks = false) {
72251
72731
  indexes.indexedRowIds.delete(row.id);
72252
72732
  indexes.ownedValueAttachmentsByValueId.delete(row.id);
72253
72733
  indexes.constructorOwnershipDirtyValueIds.delete(row.id);
72254
- indexes.parentLinksByChildId.delete(row.id);
72734
+ if (!preserveIncomingLinks) indexes.parentLinksByChildId.delete(row.id);
72735
+ else if (typeof row.containerId === "string") {
72736
+ const retained = indexes.parentLinksByChildId.get(row.id)?.filter((link) => link.parentId !== row.containerId || link.key !== "");
72737
+ if (retained === void 0 || retained.length === 0)
72738
+ indexes.parentLinksByChildId.delete(row.id);
72739
+ else indexes.parentLinksByChildId.set(row.id, retained);
72740
+ }
72255
72741
  if (typeof row.value === "object" && row.value !== null && indexes.rowByValueReference.get(row.value) === row) {
72256
72742
  indexes.rowByValueReference.delete(row.value);
72257
72743
  }
@@ -76013,12 +76499,13 @@ function resolveRuntimeSchemaMember(receiver, schemaKey, ctx) {
76013
76499
  if (!runtimeClassId) return null;
76014
76500
  const memberId = cachedMergedSchemaMemberId(runtimeClassId, schemaKey, ctx);
76015
76501
  if (memberId === null) return null;
76016
- const member = evalMemberById(ctx.vm, memberId);
76017
- if (member === null) return null;
76502
+ const rawMember = evalMemberById(ctx.vm, memberId);
76503
+ if (rawMember === null) return null;
76504
+ const member = cachedResolvedMember(rawMember, ctx);
76018
76505
  if (member.kind !== 21 /* Generic */) return member;
76019
76506
  const env = runtimeGenericEnvForValueRow(row, ctx, /* @__PURE__ */ new Set());
76020
76507
  try {
76021
- return substituteMember(member, env, ctx.vm.members);
76508
+ return substituteMember(member, env, ctx.vm.members, member);
76022
76509
  } catch (error) {
76023
76510
  throw new NSGetterRuntimeError(
76024
76511
  `Cannot resolve runtime member '${member.name}' for Class '${runtimeClassId}': ${error instanceof Error ? error.message : String(error)}`
@@ -80932,216 +81419,6 @@ var init_evaluateNSGetter = __esm({
80932
81419
  }
80933
81420
  });
80934
81421
 
80935
- // ../src/models/members/stored-value-placement-index.ts
80936
- function buildStoredValuePlacementIndex(args) {
80937
- const membersById = /* @__PURE__ */ new Map();
80938
- for (const member of args.members) membersById.set(member.id, member);
80939
- const valuesById = /* @__PURE__ */ new Map();
80940
- const unorderedEntriesByContainerId = /* @__PURE__ */ new Map();
80941
- for (const value of args.values) {
80942
- valuesById.set(value.id, value);
80943
- if (typeof value.containerId !== "string") continue;
80944
- const entries = unorderedEntriesByContainerId.get(value.containerId);
80945
- if (entries === void 0) {
80946
- unorderedEntriesByContainerId.set(value.containerId, [value]);
80947
- } else {
80948
- entries.push(value);
80949
- }
80950
- }
80951
- for (const entries of unorderedEntriesByContainerId.values()) {
80952
- entries.sort((left, right) => left.id.localeCompare(right.id));
80953
- }
80954
- const constructorsById = new Map(
80955
- args.constructors.map((constructor2) => [constructor2.id, constructor2])
80956
- );
80957
- const resolveConstructorSettlement = createConstructorSettlementResolver({
80958
- classes: args.classes,
80959
- constructors: args.constructors,
80960
- members: args.members
80961
- });
80962
- const resolvedMemberById = /* @__PURE__ */ new Map();
80963
- const resolvedMember = (member) => {
80964
- const cached = resolvedMemberById.get(member.id);
80965
- if (cached !== void 0) return cached;
80966
- const resolved = resolveMember2(member, args.members);
80967
- resolvedMemberById.set(member.id, resolved);
80968
- return resolved;
80969
- };
80970
- const storedSchemaByClassId = /* @__PURE__ */ new Map();
80971
- const storedSchema = (classId) => {
80972
- const cached = storedSchemaByClassId.get(classId);
80973
- if (cached !== void 0) return cached;
80974
- const schema = mergeStoredInstanceSchema(
80975
- classId,
80976
- args.classes,
80977
- args.members
80978
- );
80979
- storedSchemaByClassId.set(classId, schema);
80980
- return schema;
80981
- };
80982
- const queue = [];
80983
- for (const root of projectRootMembersInDisplayOrder(args.project)) {
80984
- const member = membersById.get(root.memberId);
80985
- if (member === void 0 || typeof member.valueId !== "string") continue;
80986
- queue.push({
80987
- memberId: member.id,
80988
- parentValueId: null,
80989
- source: {
80990
- kind: "root",
80991
- label: root.root.label,
80992
- sourcePath: `root.${root.root.key}`
80993
- },
80994
- valueId: member.valueId
80995
- });
80996
- }
80997
- for (const member of args.members) {
80998
- if (!isStaticMember(member) || memberAccessOf(member) !== 0 /* Public */)
80999
- continue;
81000
- const valueId = args.resolveStaticValueId(member.id);
81001
- if (valueId === null) continue;
81002
- const placement = findSchemaPlacement(member.id, args.classes);
81003
- if (placement === null) continue;
81004
- queue.push({
81005
- memberId: member.id,
81006
- parentValueId: null,
81007
- source: {
81008
- kind: "static",
81009
- label: placement.schemaKey,
81010
- ownerClassName: placement.ownerClass.name,
81011
- sourcePath: `static:${member.id}`
81012
- },
81013
- valueId
81014
- });
81015
- }
81016
- const placementByValueId = /* @__PURE__ */ new Map();
81017
- const mutablePlacementsByClassId = /* @__PURE__ */ new Map();
81018
- const mutablePlacementsByMemberId = /* @__PURE__ */ new Map();
81019
- const mutablePlacementsByKind = /* @__PURE__ */ new Map();
81020
- for (let cursor = 0; cursor < queue.length; cursor += 1) {
81021
- const item = queue[cursor];
81022
- if (item === void 0 || placementByValueId.has(item.valueId)) continue;
81023
- const authoredValue = valuesById.get(item.valueId);
81024
- const storedMember = membersById.get(item.memberId);
81025
- if (authoredValue === void 0 || storedMember === void 0) continue;
81026
- const value = args.resolveValue === void 0 ? authoredValue : args.resolveValue(authoredValue);
81027
- if (value === null) continue;
81028
- const placement = item;
81029
- placementByValueId.set(value.id, placement);
81030
- appendPlacement(mutablePlacementsByMemberId, storedMember.id, placement);
81031
- const member = resolvedMember(storedMember);
81032
- appendPlacement(mutablePlacementsByKind, member.kind, placement);
81033
- if (isMemberClassBase(member)) {
81034
- const classId = value.classId ?? member.classId;
81035
- appendPlacement(mutablePlacementsByClassId, classId, placement);
81036
- if (!isLiteralValueContent(value) || !isStringRecord5(value.value)) {
81037
- continue;
81038
- }
81039
- const settledChildrenBySchemaKey = /* @__PURE__ */ new Map();
81040
- const constructor2 = typeof value.instanceConstructorId === "string" ? constructorsById.get(value.instanceConstructorId) : void 0;
81041
- if (constructor2 !== void 0 && constructor2.classId === classId && value.constructorArgs != null) {
81042
- for (const [index, parameter4] of constructor2.argumentTypes.entries()) {
81043
- const settled = resolveConstructorSettlement(
81044
- classId,
81045
- parameter4.name,
81046
- constructor2.id
81047
- );
81048
- if (settled === null || Object.hasOwn(value.value, settled.schemaKey)) {
81049
- continue;
81050
- }
81051
- const childValueId = value.constructorArgs[constructorActionParameterId(constructor2, index)];
81052
- if (typeof childValueId === "string" && valuesById.has(childValueId)) {
81053
- settledChildrenBySchemaKey.set(settled.schemaKey, childValueId);
81054
- }
81055
- }
81056
- }
81057
- for (const entry of storedSchema(classId)) {
81058
- const childMember = membersById.get(entry.memberId);
81059
- const childValueId = value.value[entry.schemaKey] ?? settledChildrenBySchemaKey.get(entry.schemaKey);
81060
- if (childMember === void 0 || typeof childValueId !== "string") {
81061
- continue;
81062
- }
81063
- if (memberAccessOf(childMember) !== 0 /* Public */) continue;
81064
- queue.push({
81065
- memberId: childMember.id,
81066
- parentValueId: value.id,
81067
- source: { kind: "classField", schemaKey: entry.schemaKey },
81068
- valueId: childValueId
81069
- });
81070
- }
81071
- continue;
81072
- }
81073
- if (!isMemberListBase(member) && !isMemberDictionaryBase(member)) {
81074
- continue;
81075
- }
81076
- const entryMember = membersById.get(member.entryMemberId);
81077
- if (entryMember === void 0) continue;
81078
- if (isMemberDictionaryBase(member)) {
81079
- if (!isStringRecord5(value.value)) continue;
81080
- for (const [key, childValueId] of Object.entries(value.value)) {
81081
- queue.push({
81082
- memberId: entryMember.id,
81083
- parentValueId: value.id,
81084
- source: {
81085
- kind: "collectionEntry",
81086
- containerMemberId: storedMember.id,
81087
- entry: { kind: "dict", key, valueId: childValueId }
81088
- },
81089
- valueId: childValueId
81090
- });
81091
- }
81092
- continue;
81093
- }
81094
- const entries = listKindOf(member) === 1 /* Unordered */ ? unorderedEntriesByContainerId.get(value.id) ?? [] : Array.isArray(value.value) ? value.value.flatMap((childValueId) => {
81095
- if (typeof childValueId !== "string") return [];
81096
- const childValue = valuesById.get(childValueId);
81097
- return childValue === void 0 ? [] : [childValue];
81098
- }) : [];
81099
- for (const [index, childValue] of entries.entries()) {
81100
- queue.push({
81101
- memberId: entryMember.id,
81102
- parentValueId: value.id,
81103
- source: {
81104
- kind: "collectionEntry",
81105
- containerMemberId: storedMember.id,
81106
- entry: { kind: "list", index, valueId: childValue.id }
81107
- },
81108
- valueId: childValue.id
81109
- });
81110
- }
81111
- }
81112
- return {
81113
- placementByValueId,
81114
- placementsByClassId: mutablePlacementsByClassId,
81115
- placementsByKind: mutablePlacementsByKind,
81116
- placementsByMemberId: mutablePlacementsByMemberId
81117
- };
81118
- }
81119
- function appendPlacement(index, key, placement) {
81120
- const placements = index.get(key);
81121
- if (placements === void 0) {
81122
- index.set(key, [placement]);
81123
- } else {
81124
- placements.push(placement);
81125
- }
81126
- }
81127
- function isStringRecord5(value) {
81128
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
81129
- return false;
81130
- }
81131
- return Object.values(value).every((item) => typeof item === "string");
81132
- }
81133
- var init_stored_value_placement_index = __esm({
81134
- "../src/models/members/stored-value-placement-index.ts"() {
81135
- "use strict";
81136
- init_inheritance();
81137
- init_constructor_parameter_settlement();
81138
- init_constructors2();
81139
- init_project2();
81140
- init_member_kinds();
81141
- init_members();
81142
- }
81143
- });
81144
-
81145
81422
  // ../src/runtime/initializer-materialization.ts
81146
81423
  function declarationInitializerContext(document) {
81147
81424
  const key = initializerEvaluatorCacheKey(document);
@@ -81392,6 +81669,22 @@ function buildVirtualInstanceMaterializedIndex(args) {
81392
81669
  })
81393
81670
  };
81394
81671
  }
81672
+ function createBatchVirtualInstanceMaterializedIndex(args) {
81673
+ return {
81674
+ rows: args.rows,
81675
+ rowsById: args.rowsById,
81676
+ graph: new MaterializedValueGraphContext({ ...args.document, values: [] }),
81677
+ unorderedEntryIdsByContainerId: { get: args.unorderedListEntryIds },
81678
+ constructorsById: new Map(
81679
+ (args.document.constructors ?? []).map((row) => [row.id, row])
81680
+ ),
81681
+ resolveConstructorSettlement: createConstructorSettlementResolver({
81682
+ classes: args.document.classes,
81683
+ constructors: args.document.constructors ?? [],
81684
+ members: args.document.members
81685
+ })
81686
+ };
81687
+ }
81395
81688
  function withoutInitializerConstructionFields(init) {
81396
81689
  if (init.compiled === void 0) return init;
81397
81690
  const baseline = deepClonePlainData(init);
@@ -81483,24 +81776,20 @@ function expandStoredInstance(args) {
81483
81776
  }
81484
81777
  const instanceRoot = literalRow(args.instanceRoot);
81485
81778
  const classId = instanceRoot.classId ?? rootMember.classId;
81486
- const schemaClass2 = args.document.classes.find(
81487
- (candidate) => candidate.id === classId
81488
- );
81779
+ const schemaIndex = projectSchemaIndexFor(args.document);
81780
+ const schemaClass2 = schemaIndex.class(classId);
81489
81781
  if (schemaClass2 === void 0) {
81490
81782
  throw new Error(
81491
81783
  `Virtual expansion root "${args.instanceRoot.id}" references missing class "${classId}".`
81492
81784
  );
81493
81785
  }
81494
- const constructors = args.document.constructors ?? [];
81495
81786
  if (instanceRoot.instanceConstructorId === void 0 && typeof instanceRoot.instanceVariantId !== "string") {
81496
81787
  throw new VirtualExpansionUnsupportedError(
81497
81788
  `Virtual expansion root "${args.instanceRoot.id}" carries no construction stamp for class "${classId}"; keep this historical graph materialized.`
81498
81789
  );
81499
81790
  }
81500
81791
  const recordedConstructorId = instanceRoot.instanceConstructorId === void 0 ? schemaClass2.requiredConstructorId ?? null : instanceRoot.instanceConstructorId;
81501
- const requiredConstructor = recordedConstructorId === null ? null : constructors.find(
81502
- (candidate) => candidate.id === recordedConstructorId
81503
- ) ?? null;
81792
+ const requiredConstructor = recordedConstructorId === null ? null : schemaIndex.constructorRecord(recordedConstructorId) ?? null;
81504
81793
  if (recordedConstructorId !== null && requiredConstructor === null) {
81505
81794
  throw new Error(
81506
81795
  `Virtual expansion class "${classId}" references missing constructor "${recordedConstructorId}".`
@@ -83609,23 +83898,25 @@ function variantSwapDeclaredMember(document, rootValueId) {
83609
83898
  }
83610
83899
  function createHeadlessVirtualInstanceResolver(args) {
83611
83900
  const { document } = args;
83901
+ const membersById = args.membersById ?? new Map(document.members.map((member) => [member.id, member]));
83612
83902
  let placementByValueId = null;
83613
- const placements = () => placementByValueId ??= buildStoredValuePlacementIndex({
83903
+ const placements = () => placementByValueId ??= args.placementByValueId ?? buildStoredValuePlacementIndex({
83614
83904
  classes: document.classes,
83615
83905
  constructors: document.constructors ?? [],
83616
83906
  members: document.members,
83617
83907
  project: document.project,
83618
- resolveStaticValueId: (memberId) => document.members.find((member) => member.id === memberId)?.valueId ?? null,
83908
+ resolveStaticValueId: (memberId) => membersById.get(memberId)?.valueId ?? null,
83619
83909
  values: document.values
83620
83910
  }).placementByValueId;
83621
- const rawById = new Map(document.values.map((row) => [row.id, row]));
83911
+ const rawById = args.valuesById ?? new Map(document.values.map((row) => [row.id, row]));
83622
83912
  let resolverDocumentCache = null;
83623
83913
  const resolverDocumentOnce = () => resolverDocumentCache ??= composeResolverDocument(
83624
83914
  document,
83625
83915
  args.resolverLookups()
83626
83916
  );
83627
- let materializedIndex = null;
83917
+ let materializedIndex = args.materializedIndex ?? null;
83628
83918
  const graphRowsByRootId = /* @__PURE__ */ new Map();
83919
+ const emptyRows = [];
83629
83920
  const graphByValueId = /* @__PURE__ */ new Map();
83630
83921
  const failedRootIds = /* @__PURE__ */ new Set();
83631
83922
  const expandedRowById = /* @__PURE__ */ new Map();
@@ -83633,14 +83924,12 @@ function createHeadlessVirtualInstanceResolver(args) {
83633
83924
  const expandRoot = (rootId, memberId) => {
83634
83925
  const cached = graphRowsByRootId.get(rootId);
83635
83926
  if (cached !== void 0) return cached;
83636
- if (failedRootIds.has(rootId)) return /* @__PURE__ */ new Map();
83927
+ if (failedRootIds.has(rootId)) return emptyRows;
83637
83928
  const instanceRoot = rawById.get(rootId);
83638
- const declaredMember = document.members.find(
83639
- (member2) => member2.id === memberId
83640
- );
83929
+ const declaredMember = membersById.get(memberId);
83641
83930
  if (instanceRoot === void 0 || declaredMember === void 0) {
83642
83931
  failedRootIds.add(rootId);
83643
- return /* @__PURE__ */ new Map();
83932
+ return emptyRows;
83644
83933
  }
83645
83934
  const member = storedClassResolutionMember(
83646
83935
  declaredMember,
@@ -83649,7 +83938,7 @@ function createHeadlessVirtualInstanceResolver(args) {
83649
83938
  );
83650
83939
  if (member === null || !isLiteralValueContent(instanceRoot)) {
83651
83940
  failedRootIds.add(rootId);
83652
- return /* @__PURE__ */ new Map();
83941
+ return emptyRows;
83653
83942
  }
83654
83943
  try {
83655
83944
  const resolverDocument = resolverDocumentOnce();
@@ -83674,7 +83963,8 @@ function createHeadlessVirtualInstanceResolver(args) {
83674
83963
  materializedIndex,
83675
83964
  readRecorder: args.readRecorder
83676
83965
  });
83677
- graphRowsByRootId.set(rootId, graph.rowsById);
83966
+ const rows = [...graph.rowsById.values()];
83967
+ graphRowsByRootId.set(rootId, rows);
83678
83968
  for (const [id2, row] of graph.rowsById) {
83679
83969
  expandedRowById.set(id2, row);
83680
83970
  graphByValueId.set(id2, graph);
@@ -83686,10 +83976,10 @@ function createHeadlessVirtualInstanceResolver(args) {
83686
83976
  graphByValueId.set(id2, graph);
83687
83977
  }
83688
83978
  graphByValueId.set(rootId, graph);
83689
- return graph.rowsById;
83979
+ return rows;
83690
83980
  } catch {
83691
83981
  failedRootIds.add(rootId);
83692
- return /* @__PURE__ */ new Map();
83982
+ return emptyRows;
83693
83983
  }
83694
83984
  };
83695
83985
  const virtualInstanceRowsForValue = (receiverValueId) => {
@@ -83700,11 +83990,11 @@ function createHeadlessVirtualInstanceResolver(args) {
83700
83990
  args.readRecorder?.recordValueRead(placement.valueId);
83701
83991
  const raw = rawById.get(placement.valueId);
83702
83992
  if (raw !== void 0 && isLiteralValueContent(raw) && isStoredClassResolutionRoot(raw)) {
83703
- return [...expandRoot(placement.valueId, placement.memberId).values()];
83993
+ return expandRoot(placement.valueId, placement.memberId);
83704
83994
  }
83705
83995
  placement = placement.parentValueId === null ? null : placements().get(placement.parentValueId) ?? null;
83706
83996
  }
83707
- return [];
83997
+ return emptyRows;
83708
83998
  };
83709
83999
  return {
83710
84000
  virtualInstanceRowsForValue,
@@ -83724,6 +84014,7 @@ var init_virtual_instance_graph = __esm({
83724
84014
  "use strict";
83725
84015
  init_deep_clone_plain_data();
83726
84016
  init_inheritance();
84017
+ init_project_schema_index();
83727
84018
  init_constructor_parameter_settlement();
83728
84019
  init_generics();
83729
84020
  init_classes();
@@ -83913,6 +84204,175 @@ function indexedInitializerEvaluatorLookups(document, key, revision) {
83913
84204
  });
83914
84205
  return lookups;
83915
84206
  }
84207
+ function createInitializerMaterializationBatch(authoredDocument) {
84208
+ const indexed = createInitializerBatchLookups(authoredDocument);
84209
+ const unorderedListEntryIds2 = indexed.snapshot().unorderedListEntryIds;
84210
+ let materializedIndex;
84211
+ let placementBatch;
84212
+ const cachedById = /* @__PURE__ */ new Map();
84213
+ const dependents = /* @__PURE__ */ new Map();
84214
+ const globalReads = /* @__PURE__ */ new Set();
84215
+ const expandedById = /* @__PURE__ */ new Map();
84216
+ const expandedByReference = /* @__PURE__ */ new WeakMap();
84217
+ const activeReads = [];
84218
+ const recordRead = (id2) => {
84219
+ for (const entry of activeReads) entry.reads.add(id2);
84220
+ };
84221
+ const recorder = {
84222
+ recordValueRead: recordRead,
84223
+ recordContainerMembershipRead: recordRead,
84224
+ recordGlobalRead: () => {
84225
+ for (const entry of activeReads) entry.global = true;
84226
+ },
84227
+ // Schema, variants and localization do not change during this batch.
84228
+ recordLocalizedTextRead: () => {
84229
+ },
84230
+ recordVariantRead: () => {
84231
+ },
84232
+ recordStaticMemberRead: () => {
84233
+ },
84234
+ // Resolver placement walks record every ancestor id. Upserts below also
84235
+ // invalidate old/new ownership targets, including newly attached rows.
84236
+ recordValuePlacementRead: () => {
84237
+ }
84238
+ };
84239
+ const invalidate = (entry) => {
84240
+ for (const id2 of entry.aliases)
84241
+ if (cachedById.get(id2) === entry) cachedById.delete(id2);
84242
+ for (const id2 of entry.reads) {
84243
+ const bucket = dependents.get(id2);
84244
+ bucket?.delete(entry);
84245
+ if (bucket?.size === 0) dependents.delete(id2);
84246
+ }
84247
+ for (const row of entry.rows) {
84248
+ if (expandedById.get(row.id) === row) expandedById.delete(row.id);
84249
+ if (typeof row.value === "object" && row.value !== null && expandedByReference.get(row.value) === row)
84250
+ expandedByReference.delete(row.value);
84251
+ }
84252
+ globalReads.delete(entry);
84253
+ };
84254
+ return {
84255
+ upsert(rows) {
84256
+ const previousRows = [];
84257
+ const touched = /* @__PURE__ */ new Set();
84258
+ const visited = /* @__PURE__ */ new WeakSet();
84259
+ const references = (value) => {
84260
+ if (typeof value === "string") touched.add(value);
84261
+ else if (typeof value === "object" && value !== null && !visited.has(value)) {
84262
+ visited.add(value);
84263
+ for (const child of Object.values(value)) references(child);
84264
+ }
84265
+ };
84266
+ for (const row of rows) {
84267
+ touched.add(row.id);
84268
+ const previous = indexed.valuesById.get(row.id);
84269
+ if (previous !== void 0) previousRows.push(previous);
84270
+ for (const candidate of [previous, row]) {
84271
+ if (candidate === void 0) continue;
84272
+ if (typeof candidate.containerId === "string")
84273
+ touched.add(candidate.containerId);
84274
+ references(candidate.value);
84275
+ if ("constructorArgs" in candidate)
84276
+ references(candidate.constructorArgs);
84277
+ }
84278
+ }
84279
+ const invalidated = new Set(globalReads);
84280
+ for (const id2 of touched)
84281
+ for (const entry of dependents.get(id2) ?? []) invalidated.add(entry);
84282
+ for (const entry of invalidated) {
84283
+ for (const alias of entry.aliases) {
84284
+ for (const dependent of dependents.get(alias) ?? [])
84285
+ invalidated.add(dependent);
84286
+ }
84287
+ }
84288
+ for (const entry of invalidated) invalidate(entry);
84289
+ indexed.upsert(rows);
84290
+ placementBatch?.refresh(rows, previousRows);
84291
+ },
84292
+ document() {
84293
+ const document = {
84294
+ ...authoredDocument,
84295
+ values: indexed.values,
84296
+ valueById: (id2) => {
84297
+ recordRead(id2);
84298
+ return indexed.valuesById.get(id2) ?? null;
84299
+ }
84300
+ };
84301
+ const base = indexed.snapshot();
84302
+ let resolver;
84303
+ const virtual = () => resolver ??= createHeadlessVirtualInstanceResolver({
84304
+ evaluateInitializer: evaluateMemberInitializer,
84305
+ document,
84306
+ membersById: indexed.membersById,
84307
+ valuesById: indexed.valuesById,
84308
+ placementByValueId: (placementBatch ??= createStoredValuePlacementBatch({
84309
+ ...authoredDocument,
84310
+ values: indexed.values,
84311
+ constructors: authoredDocument.constructors ?? [],
84312
+ resolveStaticValueId: (id2) => indexed.membersById.get(id2)?.valueId ?? null,
84313
+ indexedRows: {
84314
+ valuesById: indexed.valuesById,
84315
+ unorderedListEntryIds: unorderedListEntryIds2
84316
+ }
84317
+ })).placementByValueId,
84318
+ materializedIndex: materializedIndex ??= createBatchVirtualInstanceMaterializedIndex({
84319
+ document: authoredDocument,
84320
+ rows: indexed.values,
84321
+ rowsById: indexed.valuesById,
84322
+ unorderedListEntryIds: unorderedListEntryIds2
84323
+ }),
84324
+ readRecorder: recorder,
84325
+ resolverLookups: () => lookups
84326
+ });
84327
+ const lookups = {
84328
+ ...base,
84329
+ valueById: (id2) => base.valueById(id2) ?? expandedById.get(id2) ?? virtual().valueById(id2),
84330
+ rowForValueReference: (value) => base.rowForValueReference(value) ?? expandedByReference.get(value) ?? virtual().rowForValueReference(value),
84331
+ virtualInstanceRowsForValue: (id2) => {
84332
+ const cached = cachedById.get(id2);
84333
+ if (cached !== void 0) {
84334
+ for (const read of cached.reads) recordRead(read);
84335
+ if (cached.global) recorder.recordGlobalRead("cached-virtual-read");
84336
+ return cached.rows;
84337
+ }
84338
+ const entry = {
84339
+ rows: [],
84340
+ reads: /* @__PURE__ */ new Set([id2]),
84341
+ aliases: /* @__PURE__ */ new Set([id2]),
84342
+ global: false
84343
+ };
84344
+ activeReads.push(entry);
84345
+ try {
84346
+ entry.rows = virtual().virtualInstanceRowsForValue(id2);
84347
+ } finally {
84348
+ activeReads.pop();
84349
+ }
84350
+ for (const row of entry.rows) {
84351
+ entry.aliases.add(row.id);
84352
+ expandedById.set(row.id, row);
84353
+ if (typeof row.value === "object" && row.value !== null)
84354
+ expandedByReference.set(row.value, row);
84355
+ }
84356
+ for (const alias of entry.aliases) cachedById.set(alias, entry);
84357
+ for (const read of entry.reads) {
84358
+ const bucket = dependents.get(read) ?? /* @__PURE__ */ new Set();
84359
+ bucket.add(entry);
84360
+ dependents.set(read, bucket);
84361
+ }
84362
+ if (entry.global) globalReads.add(entry);
84363
+ return entry.rows;
84364
+ },
84365
+ resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
84366
+ evaluateInitializer: evaluateMemberInitializer,
84367
+ document,
84368
+ resolverLookups: lookups,
84369
+ ...args
84370
+ })
84371
+ };
84372
+ return { ...document, databaseVM: lookups };
84373
+ }
84374
+ };
84375
+ }
83916
84376
  function buildInitializerRootValueWithLookups(document, lookups, tracking) {
83917
84377
  const rootValue = {};
83918
84378
  for (const { root, memberId } of projectRootMembersInDisplayOrder(
@@ -84086,6 +84546,7 @@ var init_evaluateInitializer = __esm({
84086
84546
  init_instance_provenance();
84087
84547
  init_members();
84088
84548
  init_project2();
84549
+ init_stored_value_placement_index();
84089
84550
  init_evaluateNSGetter();
84090
84551
  init_virtual_instance_graph();
84091
84552
  evaluatorLookupsByDocument = /* @__PURE__ */ new WeakMap();
@@ -86238,7 +86699,13 @@ function collectNeoScriptRecompileImpact(args) {
86238
86699
  const dependentsById = /* @__PURE__ */ new Map();
86239
86700
  for (const record4 of [
86240
86701
  ...collectSchemaDependencyRecords(args.postDocument),
86241
- ...collectStructuralDependencyRecords(args.postDocument)
86702
+ ...collectStructuralDependencyRecords(
86703
+ args.postDocument,
86704
+ args.currentDocument,
86705
+ new Set(
86706
+ args.changes.filter((change) => change.recordKind === "class").map((change) => change.recordId)
86707
+ )
86708
+ )
86242
86709
  ]) {
86243
86710
  for (const dependencyId of collectCompilerReferenceIds(record4.value)) {
86244
86711
  const dependents = dependentsById.get(dependencyId) ?? [];
@@ -86669,8 +87136,11 @@ function collectSchemaDependencyRecords(document) {
86669
87136
  }))
86670
87137
  ];
86671
87138
  }
86672
- function collectStructuralDependencyRecords(document) {
87139
+ function collectStructuralDependencyRecords(document, currentDocument, changedClassIds) {
86673
87140
  const records2 = [];
87141
+ const existingClassIds = new Set(
87142
+ currentDocument.classes.map((schemaClass2) => schemaClass2.id)
87143
+ );
86674
87144
  const resolver = new EffectiveStorageResolver({
86675
87145
  members: document.members,
86676
87146
  classes: document.classes,
@@ -86682,13 +87152,19 @@ function collectStructuralDependencyRecords(document) {
86682
87152
  }
86683
87153
  }
86684
87154
  for (const schemaClass2 of document.classes) {
86685
- for (const entry of mergeSchemas(
87155
+ const memberIds = existingClassIds.has(schemaClass2.id) ? mergeSchemas(
86686
87156
  resolveInheritanceChain(schemaClass2.id, document.classes)
87157
+ ).map((entry) => entry.memberId) : Object.values(schemaClass2.schema);
87158
+ for (const memberId of memberIds) {
87159
+ records2.push({ id: memberId, value: { classId: schemaClass2.id } });
87160
+ }
87161
+ }
87162
+ for (const schemaClass2 of currentDocument.classes) {
87163
+ if (!changedClassIds.has(schemaClass2.id)) continue;
87164
+ for (const entry of mergeSchemas(
87165
+ resolveInheritanceChain(schemaClass2.id, currentDocument.classes)
86687
87166
  )) {
86688
- records2.push({
86689
- id: entry.memberId,
86690
- value: { classId: schemaClass2.id }
86691
- });
87167
+ records2.push({ id: entry.memberId, value: { classId: schemaClass2.id } });
86692
87168
  }
86693
87169
  }
86694
87170
  return records2;
@@ -94928,17 +95404,271 @@ var init_push_change_intent = __esm({
94928
95404
  }
94929
95405
  });
94930
95406
 
95407
+ // ../src/database/project-record-semantics.ts
95408
+ function projectRecordSemanticData(value) {
95409
+ if (!isPlainRecord(value)) return value;
95410
+ const semantic = {};
95411
+ for (const [key, child] of Object.entries(value)) {
95412
+ if (SERVER_MANAGED_PROJECT_RECORD_FIELDS.has(key)) continue;
95413
+ semantic[key] = child;
95414
+ }
95415
+ return semantic;
95416
+ }
95417
+ function projectRecordDataIsSemanticallyEqual(left, right) {
95418
+ return canonicalJsonStringify2(projectRecordSemanticData(left)) === canonicalJsonStringify2(projectRecordSemanticData(right));
95419
+ }
95420
+ function canonicalJsonStringify2(value) {
95421
+ return JSON.stringify(toCanonicalJsonValue2(value));
95422
+ }
95423
+ function toCanonicalJsonValue2(value) {
95424
+ if (value === null) return null;
95425
+ if (value === void 0) return void 0;
95426
+ if (value instanceof Date) return value.toISOString();
95427
+ if (typeof value === "string" || typeof value === "boolean") return value;
95428
+ if (typeof value === "number") {
95429
+ if (!Number.isFinite(value)) {
95430
+ throw new Error("Cannot canonicalize a non-finite number.");
95431
+ }
95432
+ return value;
95433
+ }
95434
+ if (typeof value === "bigint") {
95435
+ throw new Error("Cannot canonicalize bigint values.");
95436
+ }
95437
+ if (typeof value === "symbol") {
95438
+ throw new Error("Cannot canonicalize symbol values.");
95439
+ }
95440
+ if (typeof value === "function") {
95441
+ throw new Error("Cannot canonicalize function values.");
95442
+ }
95443
+ if (Array.isArray(value)) {
95444
+ return value.map((item) => toCanonicalJsonValue2(item) ?? null);
95445
+ }
95446
+ if (!isPlainRecord(value)) {
95447
+ throw new Error("Cannot canonicalize a non-plain object.");
95448
+ }
95449
+ const canonical = {};
95450
+ const entries = Object.entries(value).sort(
95451
+ ([left], [right]) => left.localeCompare(right)
95452
+ );
95453
+ for (const [key, child] of entries) {
95454
+ const canonicalChild = toCanonicalJsonValue2(child);
95455
+ if (canonicalChild === void 0) continue;
95456
+ canonical[key] = canonicalChild;
95457
+ }
95458
+ return canonical;
95459
+ }
95460
+ function isPlainRecord(value) {
95461
+ if (value === null || typeof value !== "object") return false;
95462
+ const prototype = Object.getPrototypeOf(value);
95463
+ return prototype === Object.prototype || prototype === null;
95464
+ }
95465
+ var SERVER_MANAGED_PROJECT_RECORD_FIELDS;
95466
+ var init_project_record_semantics = __esm({
95467
+ "../src/database/project-record-semantics.ts"() {
95468
+ "use strict";
95469
+ SERVER_MANAGED_PROJECT_RECORD_FIELDS = /* @__PURE__ */ new Set([
95470
+ "_id",
95471
+ "projectId",
95472
+ "createdAt",
95473
+ "updatedAt"
95474
+ ]);
95475
+ }
95476
+ });
95477
+
95478
+ // ../src/database/project-version-relation-sweep-trigger.ts
95479
+ function stagedChangesAffectClassRelations(current, changes) {
95480
+ const classesById = new Map(
95481
+ (current.classes ?? []).map((schemaClass2) => [schemaClass2.id, schemaClass2])
95482
+ );
95483
+ const valuesById = new Map(
95484
+ (current.values ?? []).map((value) => [value.id, value])
95485
+ );
95486
+ for (const change of changes) {
95487
+ if (change.recordKind === "internal-record-relation") return true;
95488
+ if (change.recordKind === "class") {
95489
+ if (change.operation !== "update") return true;
95490
+ if (change.deleted === true) return true;
95491
+ const before2 = classesById.get(change.recordId);
95492
+ if (before2 === void 0) return true;
95493
+ const after = change.nextData;
95494
+ if (!isPlainRecord2(after)) return true;
95495
+ if (before2.extendsClassId !== after.extendsClassId) return true;
95496
+ continue;
95497
+ }
95498
+ if (change.recordKind !== "value") continue;
95499
+ const before = valuesById.get(change.recordId);
95500
+ if (valueCreateCannotAffectClassRelations(change, before)) continue;
95501
+ if (relationEndpointClassId(before) !== relationEndpointClassId(change.nextData)) {
95502
+ return true;
95503
+ }
95504
+ }
95505
+ return false;
95506
+ }
95507
+ function valueCreateCannotAffectClassRelations(change, before) {
95508
+ if (change.operation !== "create") return false;
95509
+ if (change.deleted === true) return false;
95510
+ return before === void 0;
95511
+ }
95512
+ function relationEndpointClassId(record4) {
95513
+ if (!isPlainRecord2(record4)) return void 0;
95514
+ if (typeof record4.classId === "string") return record4.classId;
95515
+ return void 0;
95516
+ }
95517
+ function isPlainRecord2(value) {
95518
+ if (value === null || typeof value !== "object") return false;
95519
+ return !Array.isArray(value);
95520
+ }
95521
+ var init_project_version_relation_sweep_trigger = __esm({
95522
+ "../src/database/project-version-relation-sweep-trigger.ts"() {
95523
+ "use strict";
95524
+ init_internal_record_relations();
95525
+ init_project_version_types();
95526
+ init_project_record_semantics();
95527
+ }
95528
+ });
95529
+
95530
+ // ../src/database/project-world-placement-bindings.ts
95531
+ function hasWorldPlacementSidecar(value) {
95532
+ if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return false;
95533
+ const body = value.value;
95534
+ if (typeof body.assetClassId === "string") return true;
95535
+ if (typeof body.assetValueId === "string") return true;
95536
+ if (isVariantRefValue(body)) return false;
95537
+ return typeof body.variantId === "string";
95538
+ }
95539
+ function worldPlacementBindingChanged(before, after) {
95540
+ return !projectRecordDataIsSemanticallyEqual(
95541
+ worldPlacementBindingSlice(before),
95542
+ worldPlacementBindingSlice(after)
95543
+ );
95544
+ }
95545
+ function worldPlacementBindingSlice(value) {
95546
+ if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return null;
95547
+ return {
95548
+ containerId: value.containerId ?? null,
95549
+ assetClassId: value.value.assetClassId ?? null,
95550
+ assetValueId: value.value.assetValueId ?? null,
95551
+ rowValueId: value.value.rowValueId ?? null,
95552
+ variantId: value.value.variantId ?? null
95553
+ };
95554
+ }
95555
+ function ownedSparseValueBindingChanged(before, after) {
95556
+ return !projectRecordDataIsSemanticallyEqual(
95557
+ ownedSparseValueBindingSlice(before),
95558
+ ownedSparseValueBindingSlice(after)
95559
+ );
95560
+ }
95561
+ function ownedSparseValueBindingSlice(value) {
95562
+ if (!isPlainRecord3(value)) return null;
95563
+ return {
95564
+ classId: value.classId ?? null,
95565
+ containerId: value.containerId ?? null
95566
+ };
95567
+ }
95568
+ function isPlainRecord3(value) {
95569
+ return typeof value === "object" && value !== null && !Array.isArray(value);
95570
+ }
95571
+ function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
95572
+ const classesById = new Map(
95573
+ current.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95574
+ );
95575
+ const valuesById = new Map(current.values.map((value) => [value.id, value]));
95576
+ const valueChanges = [];
95577
+ for (const change of changes) {
95578
+ if (change.recordKind === "internal-record-relation") return true;
95579
+ if (change.recordKind === "value") {
95580
+ valueChanges.push(change);
95581
+ continue;
95582
+ }
95583
+ if (change.recordKind !== "class") continue;
95584
+ if (change.operation === "create" && change.deleted !== true && !classesById.has(change.recordId) && isPlainRecord3(change.nextData) && change.nextData.extendsClassId == null && change.nextData.system == null)
95585
+ continue;
95586
+ if (change.operation !== "update") return true;
95587
+ if (change.deleted === true) return true;
95588
+ const before = classesById.get(change.recordId);
95589
+ if (before === void 0) return true;
95590
+ const after = change.nextData;
95591
+ if (!isPlainRecord3(after)) return true;
95592
+ if (before.extendsClassId !== after.extendsClassId) return true;
95593
+ if (isAbstractClass(before) !== isAbstractClass(after)) return true;
95594
+ if (!worldClassSystemBlockIsEqual(before.system, after.system)) return true;
95595
+ }
95596
+ if (valueChanges.length === 0) return false;
95597
+ const worldKinds = indexWorldSystemClassKinds(current.classes, classesById);
95598
+ const changedValuesById = new Map(
95599
+ valueChanges.map((change) => [change.recordId, change.nextData])
95600
+ );
95601
+ for (const change of valueChanges) {
95602
+ const before = valuesById.get(change.recordId);
95603
+ if (hasWorldLayerOverrideMetadata(before) || hasWorldLayerOverrideMetadata(change.nextData) || (hasWorldPlacementSidecar(before) || hasWorldPlacementSidecar(change.nextData)) && worldPlacementBindingChanged(
95604
+ before,
95605
+ change.deleted === true || change.operation === "delete" ? null : change.nextData
95606
+ )) {
95607
+ return true;
95608
+ }
95609
+ for (const row of ownedSparseValueBindingChanged(
95610
+ before,
95611
+ change.deleted === true || change.operation === "delete" ? null : change.nextData
95612
+ ) ? [before, change.nextData] : []) {
95613
+ if (!isPlainRecord3(row) || typeof row.containerId !== "string") continue;
95614
+ for (const owner of [
95615
+ valuesById.get(row.containerId),
95616
+ changedValuesById.get(row.containerId)
95617
+ ]) {
95618
+ if (isPlainRecord3(owner) && isPlainRecord3(owner.value) && owner.value.assetValueId === change.recordId)
95619
+ return true;
95620
+ }
95621
+ }
95622
+ const classIds = [
95623
+ relationEndpointClassId(before),
95624
+ relationEndpointClassId(change.nextData)
95625
+ ].filter((classId) => classId !== void 0);
95626
+ for (const classId of classIds) {
95627
+ const worldKind = worldKinds.get(classId);
95628
+ if (worldKind === NeoWorldSystemClassKind.TileLayerLink) return true;
95629
+ if (worldKind === NeoWorldSystemClassKind.ObjectLayerLink) return true;
95630
+ }
95631
+ }
95632
+ return false;
95633
+ }
95634
+ function worldClassSystemBlockIsEqual(before, after) {
95635
+ return projectRecordDataIsSemanticallyEqual(
95636
+ { system: before },
95637
+ { system: after }
95638
+ );
95639
+ }
95640
+ function hasWorldLayerOverrideMetadata(record4) {
95641
+ if (!isPlainRecord3(record4)) return false;
95642
+ const value = record4.value;
95643
+ if (!isPlainRecord3(value)) return false;
95644
+ return typeof value.layerOverrideValueId === "string";
95645
+ }
95646
+ var init_project_world_placement_bindings = __esm({
95647
+ "../src/database/project-world-placement-bindings.ts"() {
95648
+ "use strict";
95649
+ init_classes();
95650
+ init_core();
95651
+ init_project_version_relation_sweep_trigger();
95652
+ init_members();
95653
+ init_project_record_semantics();
95654
+ }
95655
+ });
95656
+
94931
95657
  // ../src/models/classes/world-layer-link-target.ts
94932
95658
  function validateWorldLayerLinkClassTargets(args) {
95659
+ const relationResolver = createEffectiveClassRelationResolver(args);
95660
+ const worldKindsByClassId = indexWorldSystemClassKinds(
95661
+ args.classes,
95662
+ relationResolver.classesById
95663
+ );
94933
95664
  for (const schemaClass2 of args.classes) {
94934
95665
  if (args.classIds !== void 0 && !args.classIds.has(schemaClass2.id)) {
94935
95666
  continue;
94936
95667
  }
94937
95668
  const directWorldKind = schemaClass2.system?.worldKind;
94938
95669
  const isSystemLinkBase = directWorldKind === NeoWorldSystemClassKind.TileLayerLink || directWorldKind === NeoWorldSystemClassKind.ObjectLayerLink;
94939
- const descriptor = worldLayerLinkTargetDescriptorForClass(
94940
- schemaClass2.id,
94941
- args.classes
95670
+ const descriptor = worldLayerLinkTargetDescriptor(
95671
+ worldKindsByClassId.get(schemaClass2.id) ?? null
94942
95672
  );
94943
95673
  if (descriptor === null) continue;
94944
95674
  if (isSystemLinkBase) {
@@ -94947,10 +95677,9 @@ function validateWorldLayerLinkClassTargets(args) {
94947
95677
  `System layer-link base class "${schemaClass2.id}" must remain abstract.`
94948
95678
  );
94949
95679
  }
94950
- if (worldLayerLinkTargetRelations(
94951
- schemaClass2.id,
94952
- descriptor,
94953
- args.relations
95680
+ if (relationResolver.directClassRelations(
95681
+ descriptor.relationKind,
95682
+ schemaClass2.id
94954
95683
  ).length > 0) {
94955
95684
  throw new Error(
94956
95685
  `System layer-link base class "${schemaClass2.id}" cannot declare a layer target relation.`
@@ -94963,7 +95692,9 @@ function validateWorldLayerLinkClassTargets(args) {
94963
95692
  classes: args.classes,
94964
95693
  linkLabel: `Concrete layer-link class "${schemaClass2.id}"`,
94965
95694
  relations: args.relations,
94966
- sourceClassId: schemaClass2.id
95695
+ sourceClassId: schemaClass2.id,
95696
+ relationResolver,
95697
+ worldKindsByClassId
94967
95698
  });
94968
95699
  }
94969
95700
  }
@@ -94987,11 +95718,6 @@ function worldLayerLinkTargetDescriptor(worldKind) {
94987
95718
  }
94988
95719
  return null;
94989
95720
  }
94990
- function worldLayerLinkTargetRelations(classId, descriptor, relations) {
94991
- return relations.filter(
94992
- (relation) => relation.relationKind === descriptor.relationKind && relation.sourceRecordKind === ProjectRecordKind.Class && relation.sourceRecordId === classId && relation.targetRecordKind === ProjectRecordKind.Class
94993
- );
94994
- }
94995
95721
  function resolveWorldLayerLinkTarget(args) {
94996
95722
  const label = args.linkLabel ?? `Layer-link class "${args.sourceClassId}"`;
94997
95723
  const relationResolver = args.relationResolver ?? createEffectiveClassRelationResolver({
@@ -95077,6 +95803,34 @@ var init_world_layer_link_target = __esm({
95077
95803
  });
95078
95804
 
95079
95805
  // ../src/models/project/world-content-sidecar-validation.ts
95806
+ function cachedWorldLayerTarget(context, args) {
95807
+ let target = context.linkTargetsByClassId.get(args.sourceClassId);
95808
+ if (target === void 0) {
95809
+ target = resolveWorldLayerLinkTarget({
95810
+ ...args,
95811
+ relationResolver: context.relationResolver,
95812
+ worldKindsByClassId: context.worldKindsByClassId
95813
+ }).targetClassId;
95814
+ context.linkTargetsByClassId.set(args.sourceClassId, target);
95815
+ }
95816
+ return target;
95817
+ }
95818
+ function worldValidationContext(args) {
95819
+ const relationResolver = createEffectiveClassRelationResolver(args);
95820
+ return {
95821
+ relationResolver,
95822
+ worldKindsByClassId: indexWorldSystemClassKinds(
95823
+ args.classes,
95824
+ relationResolver.classesById
95825
+ ),
95826
+ targetIds: /* @__PURE__ */ new Map(),
95827
+ linkTargetsByClassId: /* @__PURE__ */ new Map(),
95828
+ variantsById: new Map(
95829
+ args.variants.map((variant2) => [variant2.id, variant2])
95830
+ ),
95831
+ lookupRowSets: /* @__PURE__ */ new WeakMap()
95832
+ };
95833
+ }
95080
95834
  function worldPlacementVariantBindings(args) {
95081
95835
  const foldersById = new Map(
95082
95836
  args.variantFolders.map((folder) => [folder.id, folder])
@@ -95085,12 +95839,15 @@ function worldPlacementVariantBindings(args) {
95085
95839
  args.members.map((member) => [member.id, member])
95086
95840
  );
95087
95841
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95842
+ const containedRows = indexContainedRows(args.values);
95843
+ const expandedGraphs = /* @__PURE__ */ new WeakMap();
95088
95844
  let cachedLookups = null;
95089
95845
  const expansionLookups = () => {
95090
95846
  return cachedLookups ??= initializerEvaluatorLookups(
95091
95847
  args.expansionDocument
95092
95848
  );
95093
95849
  };
95850
+ const lookupEntriesByMember = /* @__PURE__ */ new Map();
95094
95851
  return args.variants.map((variant2) => {
95095
95852
  const folder = variant2.folderId === null ? null : foldersById.get(variant2.folderId) ?? null;
95096
95853
  const binding = folder?.binding ?? null;
@@ -95103,17 +95860,24 @@ function worldPlacementVariantBindings(args) {
95103
95860
  lookupRowValueIds: []
95104
95861
  };
95105
95862
  }
95106
- return {
95107
- id: variant2.id,
95108
- classId: variant2.classId,
95109
- lookupRowValueIds: lookupCollectionEntryIds({
95863
+ let entriesByValue = lookupEntriesByMember.get(binding.collectionMemberId);
95864
+ if (entriesByValue === void 0) {
95865
+ entriesByValue = /* @__PURE__ */ new Map();
95866
+ lookupEntriesByMember.set(binding.collectionMemberId, entriesByValue);
95867
+ }
95868
+ let lookupRowValueIds = entriesByValue.get(binding.collectionValueId);
95869
+ if (lookupRowValueIds === void 0) {
95870
+ lookupRowValueIds = lookupCollectionEntryIds({
95110
95871
  collection,
95111
95872
  collectionValueId: binding.collectionValueId,
95112
95873
  lookups: expansionLookups(),
95113
- values: args.values,
95874
+ containedRows,
95875
+ expandedGraphs,
95114
95876
  valuesById
95115
- })
95116
- };
95877
+ });
95878
+ entriesByValue.set(binding.collectionValueId, lookupRowValueIds);
95879
+ }
95880
+ return { id: variant2.id, classId: variant2.classId, lookupRowValueIds };
95117
95881
  });
95118
95882
  }
95119
95883
  function lookupCollectionEntryIds(args) {
@@ -95124,24 +95888,47 @@ function lookupCollectionEntryIds(args) {
95124
95888
  if (graphRows.length === 0) {
95125
95889
  const fallbackRow = storedRow ?? args.lookups.valueById(args.collectionValueId);
95126
95890
  if (fallbackRow === null || fallbackRow === void 0) return [];
95127
- return listEntryIdsForValue(args.collection, fallbackRow, args.values);
95891
+ return listEntryIdsForValue(
95892
+ args.collection,
95893
+ fallbackRow,
95894
+ args.containedRows.get(args.collectionValueId) ?? []
95895
+ );
95896
+ }
95897
+ let graph = args.expandedGraphs.get(graphRows);
95898
+ if (graph === void 0) {
95899
+ graph = {
95900
+ byId: new Map(graphRows.map((row) => [row.id, row])),
95901
+ containedRows: indexContainedRows(graphRows)
95902
+ };
95903
+ args.expandedGraphs.set(graphRows, graph);
95128
95904
  }
95129
- const effectiveRows = [...args.values];
95130
- const graphRowsById = new Map(graphRows.map((row) => [row.id, row]));
95131
- for (const row of graphRows) {
95132
- if (args.valuesById.has(row.id)) continue;
95133
- effectiveRows.push(row);
95905
+ const effectiveRows = [
95906
+ ...args.containedRows.get(args.collectionValueId) ?? []
95907
+ ];
95908
+ for (const row of graph.containedRows.get(args.collectionValueId) ?? []) {
95909
+ if (!args.valuesById.has(row.id)) effectiveRows.push(row);
95134
95910
  }
95135
- const collectionRow = graphRowsById.get(args.collectionValueId) ?? storedRow;
95911
+ const collectionRow = graph.byId.get(args.collectionValueId) ?? storedRow;
95136
95912
  if (collectionRow === void 0) return [];
95137
95913
  return listEntryIdsForValue(args.collection, collectionRow, effectiveRows);
95138
95914
  }
95915
+ function indexContainedRows(values) {
95916
+ const byContainer = /* @__PURE__ */ new Map();
95917
+ for (const row of values) {
95918
+ if (typeof row.containerId !== "string") continue;
95919
+ const rows = byContainer.get(row.containerId) ?? [];
95920
+ rows.push(row);
95921
+ byContainer.set(row.containerId, rows);
95922
+ }
95923
+ return byContainer;
95924
+ }
95139
95925
  function validateWorldContentSidecars(args) {
95926
+ const context = worldValidationContext(args);
95140
95927
  assertWorldLayerLinkValueBodiesCanonical({
95141
95928
  classes: args.classes,
95142
- values: args.values
95929
+ values: args.values,
95930
+ worldKindsByClassId: context.worldKindsByClassId
95143
95931
  });
95144
- const variants = args.variants;
95145
95932
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95146
95933
  const classesById = new Map(
95147
95934
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
@@ -95152,7 +95939,7 @@ function validateWorldContentSidecars(args) {
95152
95939
  const validatedPlacementIds = /* @__PURE__ */ new Set();
95153
95940
  const reachablePlacementIds = /* @__PURE__ */ new Set();
95154
95941
  for (const gridValue of args.values) {
95155
- if (worldKindForValue(gridValue, args.classes) !== NeoWorldSystemClassKind.TileGrid) {
95942
+ if (worldKindForValue(gridValue, context.worldKindsByClassId) !== NeoWorldSystemClassKind.TileGrid) {
95156
95943
  continue;
95157
95944
  }
95158
95945
  const gridClassId = requiredValueClassId(gridValue, "tile-grid");
@@ -95165,27 +95952,23 @@ function validateWorldContentSidecars(args) {
95165
95952
  );
95166
95953
  if (childrenList === null) continue;
95167
95954
  const registeredTileLayers = effectiveTargetIds({
95168
- classes: args.classes,
95955
+ context,
95169
95956
  relationKind: InternalRecordRelationKind.WorldGridTileLayer,
95170
- relations: args.relations,
95171
95957
  sourceClassId: gridClassId
95172
95958
  });
95173
95959
  const registeredObjectLayers = effectiveTargetIds({
95174
- classes: args.classes,
95960
+ context,
95175
95961
  relationKind: InternalRecordRelationKind.WorldGridObjectLayer,
95176
- relations: args.relations,
95177
95962
  sourceClassId: gridClassId
95178
95963
  });
95179
95964
  const importedTiles = effectiveTargetIds({
95180
- classes: args.classes,
95965
+ context,
95181
95966
  relationKind: InternalRecordRelationKind.WorldGridTileImport,
95182
- relations: args.relations,
95183
95967
  sourceClassId: gridClassId
95184
95968
  });
95185
95969
  const importedObjects = effectiveTargetIds({
95186
- classes: args.classes,
95970
+ context,
95187
95971
  relationKind: InternalRecordRelationKind.WorldGridObjectImport,
95188
- relations: args.relations,
95189
95972
  sourceClassId: gridClassId
95190
95973
  });
95191
95974
  const overrideOwnerByLayerKey = /* @__PURE__ */ new Map();
@@ -95196,7 +95979,10 @@ function validateWorldContentSidecars(args) {
95196
95979
  `Grid value "${gridValue.id}" Children references missing value "${linkId}".`
95197
95980
  );
95198
95981
  }
95199
- const linkKind = worldKindForValue(linkValue, args.classes);
95982
+ const linkKind = worldKindForValue(
95983
+ linkValue,
95984
+ context.worldKindsByClassId
95985
+ );
95200
95986
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95201
95987
  continue;
95202
95988
  }
@@ -95214,12 +96000,12 @@ function validateWorldContentSidecars(args) {
95214
96000
  reachablePlacementIds.add(placementId);
95215
96001
  }
95216
96002
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95217
- const layerClassId = resolveWorldLayerLinkTarget({
96003
+ const layerClassId = cachedWorldLayerTarget(context, {
95218
96004
  classes: args.classes,
95219
96005
  linkLabel: `Layer link value "${linkValue.id}"`,
95220
96006
  relations: args.relations,
95221
96007
  sourceClassId: linkClassId
95222
- }).targetClassId;
96008
+ });
95223
96009
  const existingOwner = ownedLinkIds.get(linkValue.id);
95224
96010
  if (existingOwner !== void 0 && existingOwner !== gridValue.id) {
95225
96011
  throw new Error(
@@ -95231,7 +96017,7 @@ function validateWorldContentSidecars(args) {
95231
96017
  const expectedLayerKind = isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer;
95232
96018
  assertConcreteWorldClass({
95233
96019
  classId: layerClassId,
95234
- classes: args.classes,
96020
+ worldKindsByClassId: context.worldKindsByClassId,
95235
96021
  classesById,
95236
96022
  expectedKind: expectedLayerKind,
95237
96023
  label: `Layer link value "${linkValue.id}" target`
@@ -95271,15 +96057,13 @@ function validateWorldContentSidecars(args) {
95271
96057
  );
95272
96058
  }
95273
96059
  validateWorldPlacementSidecars({
95274
- classes: args.classes,
96060
+ context,
95275
96061
  classesById,
95276
96062
  importedClassIds: isTile ? importedTiles : importedObjects,
95277
96063
  isTile,
95278
96064
  layerClassId,
95279
- variants,
95280
96065
  linkValueId: linkValue.id,
95281
96066
  placement,
95282
- relations: args.relations,
95283
96067
  valuesById
95284
96068
  });
95285
96069
  validatedPlacementIds.add(placement.id);
@@ -95288,7 +96072,7 @@ function validateWorldContentSidecars(args) {
95288
96072
  }
95289
96073
  for (const linkValue of args.values) {
95290
96074
  if (gridOwnedLinkIds.has(linkValue.id)) continue;
95291
- const linkKind = worldKindForValue(linkValue, args.classes);
96075
+ const linkKind = worldKindForValue(linkValue, context.worldKindsByClassId);
95292
96076
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95293
96077
  continue;
95294
96078
  }
@@ -95296,15 +96080,15 @@ function validateWorldContentSidecars(args) {
95296
96080
  if (linkRecord === null) continue;
95297
96081
  const isTile = linkKind === NeoWorldSystemClassKind.TileLayerLink;
95298
96082
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95299
- const layerClassId = resolveWorldLayerLinkTarget({
96083
+ const layerClassId = cachedWorldLayerTarget(context, {
95300
96084
  classes: args.classes,
95301
96085
  linkLabel: `Object-composition layer link value "${linkValue.id}"`,
95302
96086
  relations: args.relations,
95303
96087
  sourceClassId: linkClassId
95304
- }).targetClassId;
96088
+ });
95305
96089
  assertConcreteWorldClass({
95306
96090
  classId: layerClassId,
95307
- classes: args.classes,
96091
+ worldKindsByClassId: context.worldKindsByClassId,
95308
96092
  classesById,
95309
96093
  expectedKind: isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer,
95310
96094
  label: `Object-composition layer link value "${linkValue.id}" target`
@@ -95335,15 +96119,13 @@ function validateWorldContentSidecars(args) {
95335
96119
  );
95336
96120
  }
95337
96121
  validateWorldPlacementSidecars({
95338
- classes: args.classes,
96122
+ context,
95339
96123
  classesById,
95340
96124
  importedClassIds: null,
95341
96125
  isTile,
95342
96126
  layerClassId,
95343
- variants,
95344
96127
  linkValueId: linkValue.id,
95345
96128
  placement,
95346
- relations: args.relations,
95347
96129
  valuesById
95348
96130
  });
95349
96131
  reachablePlacementIds.add(placement.id);
@@ -95364,8 +96146,10 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95364
96146
  const classesById = new Map(
95365
96147
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95366
96148
  );
96149
+ const worldKinds = args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById);
96150
+ const storedKeysByClassId = /* @__PURE__ */ new Map();
95367
96151
  for (const value of args.values) {
95368
- const worldKind = worldKindForValue(value, args.classes);
96152
+ const worldKind = worldKindForValue(value, worldKinds);
95369
96153
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95370
96154
  continue;
95371
96155
  }
@@ -95375,6 +96159,7 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95375
96159
  assertWorldLayerLinkBodyCanonical({
95376
96160
  body,
95377
96161
  classesById,
96162
+ storedKeysByClassId,
95378
96163
  classId,
95379
96164
  worldKind,
95380
96165
  label: `Layer link value "${value.id}"`
@@ -95382,18 +96167,23 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95382
96167
  }
95383
96168
  }
95384
96169
  function assertWorldLayerLinkBodyCanonical(args) {
95385
- const storedKeys = /* @__PURE__ */ new Set([
95386
- "layerOverrideValueId",
95387
- args.worldKind === NeoWorldSystemClassKind.TileLayerLink ? "Tiles" : "Objects"
95388
- ]);
95389
- const visited = /* @__PURE__ */ new Set();
95390
- let classId = args.classId;
95391
- while (classId !== null && !visited.has(classId)) {
95392
- visited.add(classId);
95393
- const schemaClass2 = args.classesById.get(classId);
95394
- if (schemaClass2 === void 0) break;
95395
- for (const key of Object.keys(schemaClass2.schema)) storedKeys.add(key);
95396
- classId = schemaClass2.extendsClassId ?? null;
96170
+ let storedKeys = args.storedKeysByClassId.get(args.classId);
96171
+ if (storedKeys === void 0) {
96172
+ const keys = /* @__PURE__ */ new Set([
96173
+ "layerOverrideValueId",
96174
+ args.worldKind === NeoWorldSystemClassKind.TileLayerLink ? "Tiles" : "Objects"
96175
+ ]);
96176
+ const visited = /* @__PURE__ */ new Set();
96177
+ let classId = args.classId;
96178
+ while (classId !== null && !visited.has(classId)) {
96179
+ visited.add(classId);
96180
+ const schemaClass2 = args.classesById.get(classId);
96181
+ if (schemaClass2 === void 0) break;
96182
+ for (const key of Object.keys(schemaClass2.schema)) keys.add(key);
96183
+ classId = schemaClass2.extendsClassId ?? null;
96184
+ }
96185
+ storedKeys = keys;
96186
+ args.storedKeysByClassId.set(args.classId, storedKeys);
95397
96187
  }
95398
96188
  for (const key of Object.keys(args.body)) {
95399
96189
  if (storedKeys.has(key)) continue;
@@ -95417,7 +96207,7 @@ function validateWorldPlacementSidecars(args) {
95417
96207
  }
95418
96208
  assertConcreteWorldClass({
95419
96209
  classId: assetClassId,
95420
- classes: args.classes,
96210
+ worldKindsByClassId: args.context.worldKindsByClassId,
95421
96211
  classesById: args.classesById,
95422
96212
  expectedKind: args.isTile ? NeoWorldSystemClassKind.Tile : NeoWorldSystemClassKind.Object,
95423
96213
  label: `Placement value "${args.placement.id}" assetClassId`
@@ -95428,9 +96218,8 @@ function validateWorldPlacementSidecars(args) {
95428
96218
  );
95429
96219
  }
95430
96220
  const compatibleLayerIds = effectiveTargetIds({
95431
- classes: args.classes,
96221
+ context: args.context,
95432
96222
  relationKind: args.isTile ? InternalRecordRelationKind.WorldTileCompatibleLayer : InternalRecordRelationKind.WorldObjectCompatibleLayer,
95433
- relations: args.relations,
95434
96223
  sourceClassId: assetClassId
95435
96224
  });
95436
96225
  if (!compatibleLayerIds.has(args.layerClassId)) {
@@ -95451,7 +96240,7 @@ function validateWorldPlacementSidecars(args) {
95451
96240
  placementId: args.placement.id,
95452
96241
  variantId: optionalNonEmptyString(record4.variantId),
95453
96242
  rowValueId: optionalNonEmptyString(record4.rowValueId),
95454
- variants: args.variants
96243
+ context: args.context
95455
96244
  });
95456
96245
  }
95457
96246
  function validatePlacementVariantBinding(args) {
@@ -95463,9 +96252,7 @@ function validatePlacementVariantBinding(args) {
95463
96252
  }
95464
96253
  return;
95465
96254
  }
95466
- const variant2 = args.variants.find(
95467
- (candidate) => candidate.id === args.variantId
95468
- );
96255
+ const variant2 = args.context.variantsById.get(args.variantId);
95469
96256
  if (variant2 === void 0) {
95470
96257
  throw new Error(
95471
96258
  `Placement value "${args.placementId}" references variant "${args.variantId}", which does not resolve to a live variant record.`
@@ -95485,7 +96272,12 @@ function validatePlacementVariantBinding(args) {
95485
96272
  }
95486
96273
  return;
95487
96274
  }
95488
- if (args.rowValueId === null || !lookupRows.includes(args.rowValueId)) {
96275
+ let rowIds = args.context.lookupRowSets.get(lookupRows);
96276
+ if (rowIds === void 0) {
96277
+ rowIds = new Set(lookupRows);
96278
+ args.context.lookupRowSets.set(lookupRows, rowIds);
96279
+ }
96280
+ if (args.rowValueId === null || !rowIds.has(args.rowValueId)) {
95489
96281
  throw new Error(
95490
96282
  `Placement value "${args.placementId}" must bind a live row from lookup variant "${args.variantId}".`
95491
96283
  );
@@ -95522,7 +96314,7 @@ function assertConcreteWorldClass(args) {
95522
96314
  `${args.label} references missing class "${args.classId}".`
95523
96315
  );
95524
96316
  }
95525
- const actualKind = resolveWorldSystemClassKind(args.classId, args.classes);
96317
+ const actualKind = args.worldKindsByClassId.get(args.classId) ?? null;
95526
96318
  if (actualKind !== args.expectedKind) {
95527
96319
  throw new Error(
95528
96320
  `${args.label} must reference world class kind "${args.expectedKind}", received "${String(actualKind)}".`
@@ -95533,14 +96325,18 @@ function assertConcreteWorldClass(args) {
95533
96325
  }
95534
96326
  }
95535
96327
  function effectiveTargetIds(args) {
95536
- return new Set(
95537
- resolveEffectiveClassRelations(args).map(
95538
- (relation) => relation.targetRecordId
95539
- )
95540
- );
96328
+ const key = `${args.relationKind}:${args.sourceClassId}`;
96329
+ let targets = args.context.targetIds.get(key);
96330
+ if (targets === void 0) {
96331
+ targets = new Set(
96332
+ args.context.relationResolver.resolve(args.relationKind, args.sourceClassId).map((relation) => relation.targetRecordId)
96333
+ );
96334
+ args.context.targetIds.set(key, targets);
96335
+ }
96336
+ return targets;
95541
96337
  }
95542
- function worldKindForValue(value, classes) {
95543
- return typeof value.classId === "string" ? resolveWorldSystemClassKind(value.classId, classes) : null;
96338
+ function worldKindForValue(value, worldKindsByClassId) {
96339
+ return typeof value.classId === "string" ? worldKindsByClassId.get(value.classId) ?? null : null;
95544
96340
  }
95545
96341
  function requiredValueClassId(value, label) {
95546
96342
  if (typeof value.classId === "string" && value.classId.length > 0) {
@@ -95588,13 +96384,11 @@ function optionalNonEmptyString(value) {
95588
96384
  return typeof value === "string" && value.length > 0 ? value : null;
95589
96385
  }
95590
96386
  function consumeWorldPlacementSidecarKeys(args) {
95591
- const worldKind = resolveWorldSystemClassKind(args.classId, args.classes);
96387
+ const worldKind = args.worldKindsByClassId === void 0 ? resolveWorldSystemClassKind(args.classId, args.classes) : args.worldKindsByClassId.get(args.classId) ?? null;
95592
96388
  if (worldKind === null) return /* @__PURE__ */ new Set();
95593
96389
  const assetKind = WORLD_PLACEMENT_ASSET_KIND.get(worldKind);
95594
96390
  if (assetKind === void 0) return /* @__PURE__ */ new Set();
95595
- const classesById = new Map(
95596
- args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95597
- );
96391
+ const classesById = args.classesById ?? new Map(args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2]));
95598
96392
  const present = /* @__PURE__ */ new Set();
95599
96393
  for (const key of WORLD_PLACEMENT_SIDECAR_KEYS) {
95600
96394
  if (!Object.hasOwn(args.body, key)) continue;
@@ -95609,7 +96403,7 @@ function consumeWorldPlacementSidecarKeys(args) {
95609
96403
  if (assetClassId !== null) {
95610
96404
  assertConcreteWorldClass({
95611
96405
  classId: assetClassId,
95612
- classes: args.classes,
96406
+ worldKindsByClassId: args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById),
95613
96407
  classesById,
95614
96408
  expectedKind: assetKind,
95615
96409
  label: `${args.label} assetClassId`
@@ -101089,129 +101883,6 @@ var init_general_function_call_ir_source_recompile = __esm({
101089
101883
  }
101090
101884
  });
101091
101885
 
101092
- // ../src/database/project-record-semantics.ts
101093
- function projectRecordSemanticData(value) {
101094
- if (!isPlainRecord(value)) return value;
101095
- const semantic = {};
101096
- for (const [key, child] of Object.entries(value)) {
101097
- if (SERVER_MANAGED_PROJECT_RECORD_FIELDS.has(key)) continue;
101098
- semantic[key] = child;
101099
- }
101100
- return semantic;
101101
- }
101102
- function projectRecordDataIsSemanticallyEqual(left, right) {
101103
- return canonicalJsonStringify2(projectRecordSemanticData(left)) === canonicalJsonStringify2(projectRecordSemanticData(right));
101104
- }
101105
- function canonicalJsonStringify2(value) {
101106
- return JSON.stringify(toCanonicalJsonValue2(value));
101107
- }
101108
- function toCanonicalJsonValue2(value) {
101109
- if (value === null) return null;
101110
- if (value === void 0) return void 0;
101111
- if (value instanceof Date) return value.toISOString();
101112
- if (typeof value === "string" || typeof value === "boolean") return value;
101113
- if (typeof value === "number") {
101114
- if (!Number.isFinite(value)) {
101115
- throw new Error("Cannot canonicalize a non-finite number.");
101116
- }
101117
- return value;
101118
- }
101119
- if (typeof value === "bigint") {
101120
- throw new Error("Cannot canonicalize bigint values.");
101121
- }
101122
- if (typeof value === "symbol") {
101123
- throw new Error("Cannot canonicalize symbol values.");
101124
- }
101125
- if (typeof value === "function") {
101126
- throw new Error("Cannot canonicalize function values.");
101127
- }
101128
- if (Array.isArray(value)) {
101129
- return value.map((item) => toCanonicalJsonValue2(item) ?? null);
101130
- }
101131
- if (!isPlainRecord(value)) {
101132
- throw new Error("Cannot canonicalize a non-plain object.");
101133
- }
101134
- const canonical = {};
101135
- const entries = Object.entries(value).sort(
101136
- ([left], [right]) => left.localeCompare(right)
101137
- );
101138
- for (const [key, child] of entries) {
101139
- const canonicalChild = toCanonicalJsonValue2(child);
101140
- if (canonicalChild === void 0) continue;
101141
- canonical[key] = canonicalChild;
101142
- }
101143
- return canonical;
101144
- }
101145
- function isPlainRecord(value) {
101146
- if (value === null || typeof value !== "object") return false;
101147
- const prototype = Object.getPrototypeOf(value);
101148
- return prototype === Object.prototype || prototype === null;
101149
- }
101150
- var SERVER_MANAGED_PROJECT_RECORD_FIELDS;
101151
- var init_project_record_semantics = __esm({
101152
- "../src/database/project-record-semantics.ts"() {
101153
- "use strict";
101154
- SERVER_MANAGED_PROJECT_RECORD_FIELDS = /* @__PURE__ */ new Set([
101155
- "_id",
101156
- "projectId",
101157
- "createdAt",
101158
- "updatedAt"
101159
- ]);
101160
- }
101161
- });
101162
-
101163
- // ../src/database/project-version-relation-sweep-trigger.ts
101164
- function stagedChangesAffectClassRelations(current, changes) {
101165
- const classesById = new Map(
101166
- (current.classes ?? []).map((schemaClass2) => [schemaClass2.id, schemaClass2])
101167
- );
101168
- const valuesById = new Map(
101169
- (current.values ?? []).map((value) => [value.id, value])
101170
- );
101171
- for (const change of changes) {
101172
- if (change.recordKind === "internal-record-relation") return true;
101173
- if (change.recordKind === "class") {
101174
- if (change.operation !== "update") return true;
101175
- if (change.deleted === true) return true;
101176
- const before2 = classesById.get(change.recordId);
101177
- if (before2 === void 0) return true;
101178
- const after = change.nextData;
101179
- if (!isPlainRecord2(after)) return true;
101180
- if (before2.extendsClassId !== after.extendsClassId) return true;
101181
- continue;
101182
- }
101183
- if (change.recordKind !== "value") continue;
101184
- const before = valuesById.get(change.recordId);
101185
- if (valueCreateCannotAffectClassRelations(change, before)) continue;
101186
- if (relationEndpointClassId(before) !== relationEndpointClassId(change.nextData)) {
101187
- return true;
101188
- }
101189
- }
101190
- return false;
101191
- }
101192
- function valueCreateCannotAffectClassRelations(change, before) {
101193
- if (change.operation !== "create") return false;
101194
- if (change.deleted === true) return false;
101195
- return before === void 0;
101196
- }
101197
- function relationEndpointClassId(record4) {
101198
- if (!isPlainRecord2(record4)) return void 0;
101199
- if (typeof record4.classId === "string") return record4.classId;
101200
- return void 0;
101201
- }
101202
- function isPlainRecord2(value) {
101203
- if (value === null || typeof value !== "object") return false;
101204
- return !Array.isArray(value);
101205
- }
101206
- var init_project_version_relation_sweep_trigger = __esm({
101207
- "../src/database/project-version-relation-sweep-trigger.ts"() {
101208
- "use strict";
101209
- init_internal_record_relations();
101210
- init_project_version_types();
101211
- init_project_record_semantics();
101212
- }
101213
- });
101214
-
101215
101886
  // ../src/database/lookup-target-class-contract.ts
101216
101887
  function lookupTargetClassContractViolation(args) {
101217
101888
  const actualClassId = typeof args.targetClassId === "string" ? args.targetClassId : null;
@@ -101803,6 +102474,7 @@ var StaticBindingGraphValidator;
101803
102474
  var init_project_version_static_value_writes = __esm({
101804
102475
  "../src/database/project-version-static-value-writes.ts"() {
101805
102476
  "use strict";
102477
+ init_classes();
101806
102478
  init_members();
101807
102479
  init_inheritance();
101808
102480
  init_generics();
@@ -101846,6 +102518,10 @@ var init_project_version_static_value_writes = __esm({
101846
102518
  enums: document.enums,
101847
102519
  constructors: document.constructors
101848
102520
  });
102521
+ this.worldKindsByClassId = indexWorldSystemClassKinds(
102522
+ this.schemaIndex.classes,
102523
+ this.schemaIndex.classesById
102524
+ );
101849
102525
  this.virtualValueIds = new Set(virtualValueIds);
101850
102526
  this.mergedView = merged ?? null;
101851
102527
  }
@@ -101858,6 +102534,7 @@ var init_project_version_static_value_writes = __esm({
101858
102534
  localizedTextIds = /* @__PURE__ */ new Set();
101859
102535
  dialogueIds = /* @__PURE__ */ new Set();
101860
102536
  schemaIndex;
102537
+ worldKindsByClassId;
101861
102538
  virtualValueIds;
101862
102539
  declarationMaterializedIndex = null;
101863
102540
  stack = /* @__PURE__ */ new Set();
@@ -102068,6 +102745,8 @@ var init_project_version_static_value_writes = __esm({
102068
102745
  sidecarKeys: ({ body, classId, path }) => consumeWorldPlacementSidecarKeys({
102069
102746
  body,
102070
102747
  classes: this.schemaIndex.classes,
102748
+ classesById: this.schemaIndex.classesById,
102749
+ worldKindsByClassId: this.worldKindsByClassId,
102071
102750
  classId,
102072
102751
  label: path
102073
102752
  }),
@@ -102579,6 +103258,13 @@ function collectOwnedValueDeletionIds(args) {
102579
103258
  function createOwnedValueDeletionCollector(input, knownPlacements) {
102580
103259
  const scope = withVariantPlacementRoots(input);
102581
103260
  const document = scope.document;
103261
+ const classesById = new Map(
103262
+ document.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
103263
+ );
103264
+ const worldKindsByClassId = indexWorldSystemClassKinds(
103265
+ document.classes,
103266
+ classesById
103267
+ );
102582
103268
  const stored = new Map(document.values.map((row) => [row.id, row]));
102583
103269
  const members = new Map(
102584
103270
  document.members.map((member) => [member.id, member])
@@ -102827,16 +103513,15 @@ function createOwnedValueDeletionCollector(input, knownPlacements) {
102827
103513
  const sidecars = consumeWorldPlacementSidecarKeys({
102828
103514
  body: record4,
102829
103515
  classes: document.classes,
103516
+ classesById,
103517
+ worldKindsByClassId,
102830
103518
  classId,
102831
103519
  label: `Value "${body.id}"`
102832
103520
  });
102833
103521
  for (const key of ["assetValueId", "layerOverrideValueId"]) {
102834
103522
  if (key === "assetValueId" && !sidecars.has(key)) continue;
102835
103523
  if (key === "layerOverrideValueId") {
102836
- const worldKind = resolveWorldSystemClassKind(
102837
- classId,
102838
- document.classes
102839
- );
103524
+ const worldKind = worldKindsByClassId.get(classId);
102840
103525
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink)
102841
103526
  continue;
102842
103527
  }
@@ -104721,6 +105406,7 @@ function drainConstructedGraphValidations(args) {
104721
105406
  }
104722
105407
  }
104723
105408
  function indexAuthoredSeedDocument(document) {
105409
+ const classesById = indexRecordsById(document.classes);
104724
105410
  const declaringClassIdsByMemberId = /* @__PURE__ */ new Map();
104725
105411
  for (const schemaClass2 of document.classes) {
104726
105412
  const declared = /* @__PURE__ */ new Set();
@@ -104737,6 +105423,11 @@ function indexAuthoredSeedDocument(document) {
104737
105423
  }
104738
105424
  }
104739
105425
  return {
105426
+ classesById,
105427
+ worldKindsByClassId: indexWorldSystemClassKinds(
105428
+ document.classes,
105429
+ classesById
105430
+ ),
104740
105431
  valuesById: indexRecordsById(document.values),
104741
105432
  membersById: indexRecordsById(document.members),
104742
105433
  localizedTextIds: new Set(
@@ -105838,6 +106529,8 @@ function materializeAuthoredClassFields(args) {
105838
106529
  const sidecarKeys = consumeWorldPlacementSidecarKeys({
105839
106530
  body: args.row.value,
105840
106531
  classes: args.document.classes,
106532
+ classesById: args.documentIndex.classesById,
106533
+ worldKindsByClassId: args.documentIndex.worldKindsByClassId,
105841
106534
  classId: effectiveClassId,
105842
106535
  label: `Placement value "${args.row.id}"`
105843
106536
  });
@@ -107091,6 +107784,7 @@ var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_
107091
107784
  var init_project_version_schema_commit = __esm({
107092
107785
  "../src/database/project-version-schema-commit.ts"() {
107093
107786
  "use strict";
107787
+ init_classes();
107094
107788
  init_members();
107095
107789
  init_neo_script_derived_bodies();
107096
107790
  init_localized_instance_override_writes();
@@ -107262,7 +107956,7 @@ function systemProtectedWriteInheritedRecordId(write) {
107262
107956
  if (write.baseData !== void 0) return null;
107263
107957
  if (write.deleted) return null;
107264
107958
  if (!isSystemBearingRecordKind(write.recordKind)) return null;
107265
- if (!isPlainRecord3(write.nextData)) return null;
107959
+ if (!isPlainRecord4(write.nextData)) return null;
107266
107960
  if (readSystemMetadata(write.nextData) === null) return null;
107267
107961
  const extendsMemberId = write.nextData.extendsMemberId;
107268
107962
  if (typeof extendsMemberId !== "string") return null;
@@ -107282,7 +107976,7 @@ function assertSystemProtectedRecordWriteValid(write) {
107282
107976
  assertSystemMetadataUnchanged(write, base);
107283
107977
  }
107284
107978
  function readBaseRecord(write) {
107285
- if (!isPlainRecord3(write.baseData)) return null;
107979
+ if (!isPlainRecord4(write.baseData)) return null;
107286
107980
  return {
107287
107981
  recordKind: write.recordKind,
107288
107982
  data: write.baseData,
@@ -107295,7 +107989,7 @@ function collectSystemBearingBaseRecords(document) {
107295
107989
  const stored = document[collection];
107296
107990
  if (!Array.isArray(stored)) continue;
107297
107991
  for (const record4 of stored) {
107298
- if (!isPlainRecord3(record4)) continue;
107992
+ if (!isPlainRecord4(record4)) continue;
107299
107993
  const id2 = record4.id;
107300
107994
  if (typeof id2 !== "string") continue;
107301
107995
  records2.set(baseKey(recordKind, id2), {
@@ -107309,7 +108003,7 @@ function collectSystemBearingBaseRecords(document) {
107309
108003
  }
107310
108004
  function assertCreateDeclaresNoSystemMetadata(write) {
107311
108005
  if (!isSystemBearingRecordKind(write.recordKind)) return;
107312
- if (!isPlainRecord3(write.nextData)) return;
108006
+ if (!isPlainRecord4(write.nextData)) return;
107313
108007
  const system = readSystemMetadata(write.nextData);
107314
108008
  if (system === null) return;
107315
108009
  if (inheritsLegacyEmittedSystemMetadata(write, system)) return;
@@ -107335,7 +108029,7 @@ function assertProtectedRecordNotEdited(change, base) {
107335
108029
  )) {
107336
108030
  return;
107337
108031
  }
107338
- if (!isPlainRecord3(change.nextData)) return;
108032
+ if (!isPlainRecord4(change.nextData)) return;
107339
108033
  if (authoredFieldsEqual(change.recordKind, base.data, change.nextData)) {
107340
108034
  return;
107341
108035
  }
@@ -107344,7 +108038,7 @@ function assertProtectedRecordNotEdited(change, base) {
107344
108038
  );
107345
108039
  }
107346
108040
  function assertSystemMetadataUnchanged(change, base) {
107347
- if (!isPlainRecord3(change.nextData)) return;
108041
+ if (!isPlainRecord4(change.nextData)) return;
107348
108042
  const next = readSystemMetadata(change.nextData);
107349
108043
  if (systemMetadataEqual(base.system, next)) return;
107350
108044
  throw new Error(
@@ -107395,10 +108089,10 @@ function repointedChildValueIds(document, change) {
107395
108089
  );
107396
108090
  if (baseValue === void 0) return [];
107397
108091
  const before = baseValue.value;
107398
- if (!isPlainRecord3(before)) return [];
107399
- if (!isPlainRecord3(change.nextData)) return [];
108092
+ if (!isPlainRecord4(before)) return [];
108093
+ if (!isPlainRecord4(change.nextData)) return [];
107400
108094
  const after = change.nextData.value;
107401
- if (!isPlainRecord3(after)) return [];
108095
+ if (!isPlainRecord4(after)) return [];
107402
108096
  return Object.entries(before).flatMap(([schemaKey, childValueId]) => {
107403
108097
  if (typeof childValueId !== "string") return [];
107404
108098
  if (after[schemaKey] === childValueId) return [];
@@ -107433,7 +108127,7 @@ function isSystemBearingRecordKind(recordKind) {
107433
108127
  );
107434
108128
  }
107435
108129
  function readSystemMetadata(record4) {
107436
- if (!isPlainRecord3(record4)) return null;
108130
+ if (!isPlainRecord4(record4)) return null;
107437
108131
  const system = record4.system;
107438
108132
  if (!isSystemMetadata(system)) return null;
107439
108133
  return system;
@@ -107452,11 +108146,11 @@ function systemReason(system) {
107452
108146
  return SYSTEM_PROTECTION_RULES[system.kind].serverReason;
107453
108147
  }
107454
108148
  function describeChangedRecord(recordKind, recordId, record4) {
107455
- const name = isPlainRecord3(record4) ? record4.name : void 0;
108149
+ const name = isPlainRecord4(record4) ? record4.name : void 0;
107456
108150
  if (typeof name !== "string") return `Record ${recordKind} "${recordId}"`;
107457
108151
  return `Record ${recordKind} "${name}" (${recordId})`;
107458
108152
  }
107459
- function isPlainRecord3(value) {
108153
+ function isPlainRecord4(value) {
107460
108154
  return typeof value === "object" && value !== null && !Array.isArray(value);
107461
108155
  }
107462
108156
  function baseKey(recordKind, recordId) {
@@ -107587,7 +108281,7 @@ function readWorldReferenceList(args) {
107587
108281
  args.keyCandidates
107588
108282
  );
107589
108283
  if (schemaKey === null) return [];
107590
- if (!isPlainRecord4(args.ownerValue.value)) return [];
108284
+ if (!isPlainRecord5(args.ownerValue.value)) return [];
107591
108285
  const listValueId = args.ownerValue.value[schemaKey];
107592
108286
  if (typeof listValueId !== "string") return [];
107593
108287
  const listValue2 = args.graph.valuesById.get(listValueId);
@@ -107653,18 +108347,18 @@ function worldReferenceClassInherits(graph, classId, ancestorClassId) {
107653
108347
  return false;
107654
108348
  }
107655
108349
  function toWorldReferenceClassRecord(value) {
107656
- if (!isPlainRecord4(value)) return null;
108350
+ if (!isPlainRecord5(value)) return null;
107657
108351
  const id2 = stringField2(value, "id");
107658
108352
  if (id2 === null) return null;
107659
108353
  return {
107660
108354
  id: id2,
107661
108355
  extendsClassId: nullableStringField(value, "extendsClassId"),
107662
108356
  schema: isStringRecord8(value.schema) ? value.schema : void 0,
107663
- system: isPlainRecord4(value.system) ? value.system : null
108357
+ system: isPlainRecord5(value.system) ? value.system : null
107664
108358
  };
107665
108359
  }
107666
108360
  function toWorldReferenceValueRecord(value) {
107667
- if (!isPlainRecord4(value)) return null;
108361
+ if (!isPlainRecord5(value)) return null;
107668
108362
  const id2 = stringField2(value, "id");
107669
108363
  if (id2 === null) return null;
107670
108364
  return {
@@ -107678,10 +108372,10 @@ function worldReferenceValueClassId(value) {
107678
108372
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
107679
108373
  }
107680
108374
  function isStringRecord8(value) {
107681
- if (!isPlainRecord4(value)) return false;
108375
+ if (!isPlainRecord5(value)) return false;
107682
108376
  return Object.values(value).every((entry) => typeof entry === "string");
107683
108377
  }
107684
- function isPlainRecord4(value) {
108378
+ function isPlainRecord5(value) {
107685
108379
  return typeof value === "object" && value !== null && !Array.isArray(value);
107686
108380
  }
107687
108381
  function stringField2(value, key) {
@@ -107887,6 +108581,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107887
108581
  const valuesById = new Map(
107888
108582
  document.values.map((value) => [value.id, value])
107889
108583
  );
108584
+ const materializationBatch = createInitializerMaterializationBatch(document);
107890
108585
  let members = document.members;
107891
108586
  const deferred = /* @__PURE__ */ new Set();
107892
108587
  if (defaultInitializerMemberIds.size > 0) {
@@ -107902,7 +108597,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107902
108597
  return deferredMember;
107903
108598
  }
107904
108599
  const materialized = materializeInitializerValue2({
107905
- document: { ...document, values: [...valuesById.values()] },
108600
+ document: materializationBatch.document(),
107906
108601
  member,
107907
108602
  row: {
107908
108603
  id: `animation-validation-default:${member.id}`,
@@ -107912,6 +108607,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107912
108607
  updatedAt: 0
107913
108608
  }
107914
108609
  });
108610
+ materializationBatch.upsert(materialized.createdValues);
107915
108611
  for (const created of materialized.createdValues) {
107916
108612
  valuesById.set(created.id, created);
107917
108613
  }
@@ -107936,10 +108632,14 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107936
108632
  continue;
107937
108633
  }
107938
108634
  const materialized = materializeInitializerValue2({
107939
- document: { ...document, values: [...valuesById.values()] },
108635
+ document: materializationBatch.document(),
107940
108636
  member,
107941
108637
  row
107942
108638
  });
108639
+ materializationBatch.upsert([
108640
+ materialized.root,
108641
+ ...materialized.createdValues
108642
+ ]);
107943
108643
  valuesById.set(materialized.root.id, materialized.root);
107944
108644
  for (const created of materialized.createdValues) {
107945
108645
  valuesById.set(created.id, created);
@@ -108088,54 +108788,6 @@ function assertStagedWorldContentLayerBindingsValid(current, projected, changes)
108088
108788
  })
108089
108789
  });
108090
108790
  }
108091
- function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
108092
- const classesById = new Map(
108093
- current.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
108094
- );
108095
- const valuesById = new Map(current.values.map((value) => [value.id, value]));
108096
- const valueChanges = [];
108097
- for (const change of changes) {
108098
- if (change.recordKind === "internal-record-relation") return true;
108099
- if (change.recordKind === "value") {
108100
- valueChanges.push(change);
108101
- continue;
108102
- }
108103
- if (change.recordKind !== "class") continue;
108104
- if (change.operation !== "update") return true;
108105
- if (change.deleted === true) return true;
108106
- const before = classesById.get(change.recordId);
108107
- if (before === void 0) return true;
108108
- const after = change.nextData;
108109
- if (!isPlainRecord2(after)) return true;
108110
- if (before.extendsClassId !== after.extendsClassId) return true;
108111
- if (isAbstractClass(before) !== isAbstractClass(after)) return true;
108112
- if (!worldClassSystemBlockIsEqual(before.system, after.system)) return true;
108113
- }
108114
- if (valueChanges.length === 0) return false;
108115
- const graph = createWorldReferenceGraph({
108116
- classes: current.classes,
108117
- values: []
108118
- });
108119
- for (const change of valueChanges) {
108120
- const before = valuesById.get(change.recordId);
108121
- if (hasWorldLayerOverrideMetadata(before) || hasWorldLayerOverrideMetadata(change.nextData)) {
108122
- return true;
108123
- }
108124
- const classIds = [
108125
- relationEndpointClassId(before),
108126
- relationEndpointClassId(change.nextData)
108127
- ].filter((classId) => classId !== void 0);
108128
- for (const classId of classIds) {
108129
- const worldKind = resolveWorldKindFromClassMap(
108130
- classId,
108131
- graph.classesById
108132
- );
108133
- if (worldKind === NeoWorldSystemClassKind.TileLayerLink) return true;
108134
- if (worldKind === NeoWorldSystemClassKind.ObjectLayerLink) return true;
108135
- }
108136
- }
108137
- return false;
108138
- }
108139
108791
  function stagedAffectedWorldLayerLinkClassIds(args) {
108140
108792
  const baseRelationsById = new Map(
108141
108793
  (args.current.internalRecordRelations ?? []).map((relation) => [
@@ -108173,16 +108825,20 @@ function stagedAffectedWorldLayerLinkClassIds(args) {
108173
108825
  if (!changedClassIds.has(relation.targetRecordId)) continue;
108174
108826
  roots.add(relation.sourceRecordId);
108175
108827
  }
108828
+ const childrenByClassId = /* @__PURE__ */ new Map();
108829
+ for (const schemaClass2 of args.classes) {
108830
+ if (schemaClass2.extendsClassId === void 0) continue;
108831
+ const children = childrenByClassId.get(schemaClass2.extendsClassId) ?? [];
108832
+ children.push(schemaClass2.id);
108833
+ childrenByClassId.set(schemaClass2.extendsClassId, children);
108834
+ }
108176
108835
  const affected = new Set(roots);
108177
- let added = true;
108178
- while (added) {
108179
- added = false;
108180
- for (const schemaClass2 of args.classes) {
108181
- if (schemaClass2.extendsClassId === void 0) continue;
108182
- if (!affected.has(schemaClass2.extendsClassId)) continue;
108183
- if (affected.has(schemaClass2.id)) continue;
108184
- affected.add(schemaClass2.id);
108185
- added = true;
108836
+ const pending = [...roots];
108837
+ for (let index = 0; index < pending.length; index += 1) {
108838
+ for (const childId of childrenByClassId.get(pending[index]) ?? []) {
108839
+ if (affected.has(childId)) continue;
108840
+ affected.add(childId);
108841
+ pending.push(childId);
108186
108842
  }
108187
108843
  }
108188
108844
  return affected;
@@ -108193,18 +108849,6 @@ function isStagedWorldLayerLinkTargetRelationKind(relationKind) {
108193
108849
  }
108194
108850
  return relationKind === InternalRecordRelationKind.WorldObjectLayerLinkTarget;
108195
108851
  }
108196
- function worldClassSystemBlockIsEqual(before, after) {
108197
- return projectRecordDataIsSemanticallyEqual(
108198
- { system: before },
108199
- { system: after }
108200
- );
108201
- }
108202
- function hasWorldLayerOverrideMetadata(record4) {
108203
- if (!isPlainRecord2(record4)) return false;
108204
- const value = record4.value;
108205
- if (!isPlainRecord2(value)) return false;
108206
- return typeof value.layerOverrideValueId === "string";
108207
- }
108208
108852
  function assertStagedProjectInterfaceValid(projected, changes) {
108209
108853
  const relevant = changes.filter(
108210
108854
  (change) => INTERFACE_VALIDATED_RECORD_KINDS.has(change.recordKind)
@@ -108500,10 +109144,11 @@ function assertStagedTileGridReferencesValid(current, projected, changes) {
108500
109144
  classes: current.classes,
108501
109145
  values: []
108502
109146
  });
109147
+ const currentValuesById = new Map(
109148
+ current.values.map((value) => [value.id, value])
109149
+ );
108503
109150
  if (deletedClassIds.size === 0 && [...deletedValueIds].every((valueId) => {
108504
- const value = current.values.find(
108505
- (candidate) => candidate.id === valueId
108506
- );
109151
+ const value = currentValuesById.get(valueId);
108507
109152
  if (value?.classId == null) return true;
108508
109153
  return resolveWorldKindFromClassMap(
108509
109154
  value.classId,
@@ -108551,10 +109196,27 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108551
109196
  const valuesById = new Map(
108552
109197
  projected.values.map((value) => [value.id, value])
108553
109198
  );
109199
+ const labelsByMemberId = /* @__PURE__ */ new Map();
109200
+ const memberClasses = /* @__PURE__ */ new Map();
109201
+ for (const schemaClass2 of projected.classes) {
109202
+ for (const memberId of Object.values(schemaClass2.schema)) {
109203
+ if (!memberClasses.has(memberId))
109204
+ memberClasses.set(memberId, schemaClass2);
109205
+ }
109206
+ }
109207
+ for (const member of variantMembers) {
109208
+ const owner = memberClasses.get(member.id);
109209
+ labelsByMemberId.set(
109210
+ member.id,
109211
+ owner === void 0 ? `Variant member "${member.name}"` : `Variant member "${owner.name}.${member.name}"`
109212
+ );
109213
+ }
109214
+ const admittedClassesByTarget = /* @__PURE__ */ new Map();
109215
+ const lookupRowsByCollection = /* @__PURE__ */ new Map();
108554
109216
  const graded = [];
108555
109217
  for (const member of variantMembers) {
108556
109218
  const declaration = substituteMemberForListenerGrading(member, projected);
108557
- const label = describeVariantMember(member, projected.classes);
109219
+ const label = labelsByMemberId.get(member.id);
108558
109220
  assertVariantMemberTargetValid({ declaration, label, classesById });
108559
109221
  const authored = authoredVariantValue(member);
108560
109222
  if (authored !== void 0) {
@@ -108578,12 +109240,12 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108578
109240
  if (row.value === null || row.value === void 0) continue;
108579
109241
  const ownerId = getMemberId(owner);
108580
109242
  if (ownerId === null) continue;
108581
- const member = projected.members.find((item) => item.id === ownerId);
109243
+ const member = membersById.get(ownerId);
108582
109244
  if (member === void 0) continue;
108583
109245
  graded.push({
108584
109246
  value: row.value,
108585
109247
  declaration: owner,
108586
- label: `${describeVariantMember(member, projected.classes)} row "${rowId}"`
109248
+ label: `${labelsByMemberId.get(member.id)} row "${rowId}"`
108587
109249
  });
108588
109250
  }
108589
109251
  }
@@ -108597,7 +109259,9 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108597
109259
  foldersById,
108598
109260
  membersById,
108599
109261
  valuesById,
108600
- values: projected.values
109262
+ values: projected.values,
109263
+ admittedClassesByTarget,
109264
+ lookupRowsByCollection
108601
109265
  });
108602
109266
  }
108603
109267
  }
@@ -108660,10 +109324,14 @@ function assertVariantReferenceValid(args) {
108660
109324
  );
108661
109325
  }
108662
109326
  if (target.type === 7 /* Class */ && value.classId !== target.classId) {
108663
- const admitted = descendantClassIds(
108664
- target.classId,
108665
- Array.from(classesById.values())
108666
- );
109327
+ let admitted = args.admittedClassesByTarget.get(target.classId);
109328
+ if (admitted === void 0) {
109329
+ admitted = descendantClassIds(
109330
+ target.classId,
109331
+ Array.from(classesById.values())
109332
+ );
109333
+ args.admittedClassesByTarget.set(target.classId, admitted);
109334
+ }
108667
109335
  if (!admitted.has(value.classId)) {
108668
109336
  const targetName = classesById.get(target.classId)?.name ?? target.classId;
108669
109337
  throw new Error(
@@ -108730,9 +109398,20 @@ function assertVariantReferenceValid(args) {
108730
109398
  }
108731
109399
  const collection = membersById.get(binding.collectionMemberId);
108732
109400
  const collectionValue = valuesById.get(binding.collectionValueId);
108733
- if (!isMemberListBase(collection) || collectionValue === void 0 || !valuesById.has(value.rowValueId) || !listEntryIdsForValue(collection, collectionValue, args.values).includes(
108734
- value.rowValueId
108735
- )) {
109401
+ const rowIsInCollection = () => {
109402
+ if (!isMemberListBase(collection) || collectionValue === void 0)
109403
+ return false;
109404
+ const key = `${binding.collectionMemberId}:${binding.collectionValueId}`;
109405
+ let ids = args.lookupRowsByCollection.get(key);
109406
+ if (ids === void 0) {
109407
+ ids = new Set(
109408
+ listEntryIdsForValue(collection, collectionValue, args.values)
109409
+ );
109410
+ args.lookupRowsByCollection.set(key, ids);
109411
+ }
109412
+ return ids.has(value.rowValueId);
109413
+ };
109414
+ if (!isMemberListBase(collection) || collectionValue === void 0 || !valuesById.has(value.rowValueId) || !rowIsInCollection()) {
108736
109415
  throw new Error(
108737
109416
  `${owner} binds row "${value.rowValueId}", which is not in lookup variant folder "${folder?.path ?? ""}".`
108738
109417
  );
@@ -108777,24 +109456,18 @@ function candidateVariantRowIds(projected, variantMembers) {
108777
109456
  }
108778
109457
  if (schemaKeys.size === 0) continue;
108779
109458
  if (!isPlainRecord2(row.value)) continue;
108780
- for (const schemaKey of schemaKeys) {
108781
- const childId = row.value[schemaKey];
108782
- if (typeof childId === "string") candidates.add(childId);
109459
+ for (const [schemaKey, childId] of Object.entries(row.value)) {
109460
+ if (schemaKeys.has(schemaKey) && typeof childId === "string")
109461
+ candidates.add(childId);
108783
109462
  }
108784
109463
  }
108785
109464
  return candidates;
108786
109465
  }
108787
- function describeVariantMember(member, classes) {
108788
- const owner = classes.find(
108789
- (schemaClass2) => Object.values(schemaClass2.schema).includes(member.id)
108790
- );
108791
- if (owner === void 0) return `Variant member "${member.name}"`;
108792
- return `Variant member "${owner.name}.${member.name}"`;
108793
- }
108794
109466
  var KNOWN_TRANSACTION_OPERATIONS, INTERFACE_VALIDATED_RECORD_KINDS, ACTION_LISTENER_TRIGGER_RECORD_KINDS, ACTION_LISTENER_TARGET_KINDS, VARIANT_MEMBER_TRIGGER_RECORD_KINDS;
108795
109467
  var init_project_version_whole_graph_validation = __esm({
108796
109468
  "../src/database/project-version-whole-graph-validation.ts"() {
108797
109469
  "use strict";
109470
+ init_project_world_placement_bindings();
108798
109471
  init_project_version_types();
108799
109472
  init_internal_record_relations();
108800
109473
  init_world_content_sidecar_validation();
@@ -108813,12 +109486,11 @@ var init_project_version_whole_graph_validation = __esm({
108813
109486
  init_neoscript();
108814
109487
  init_constructor_argument_ownership();
108815
109488
  init_materialize_values();
109489
+ init_evaluateInitializer();
108816
109490
  init_world_system_classes();
108817
109491
  init_project_world_reference_graph();
108818
- init_project_record_semantics();
108819
109492
  init_project_version_relation_sweep_trigger();
108820
109493
  init_members();
108821
- init_classes();
108822
109494
  KNOWN_TRANSACTION_OPERATIONS = new Set(
108823
109495
  Object.values(ProjectVersionTransactionOperation)
108824
109496
  );
@@ -109155,6 +109827,12 @@ function computeWorkspaceStatus(workspace, options) {
109155
109827
  sourceSpan: source.span
109156
109828
  };
109157
109829
  });
109830
+ const recordsByKey = new Map(
109831
+ records2.map((record4) => [
109832
+ recordStateKey(record4.recordKind, record4.recordId),
109833
+ record4
109834
+ ])
109835
+ );
109158
109836
  if (projectAnalysisV4 === null) {
109159
109837
  throw new Error(
109160
109838
  "Format-4 project analysis was not produced before static value lowering."
@@ -109207,9 +109885,7 @@ function computeWorkspaceStatus(workspace, options) {
109207
109885
  if (document !== void 0 && isObjectRecord2(document.data)) {
109208
109886
  document.data.collectionValueId = resolvedId;
109209
109887
  }
109210
- const record4 = records2.find(
109211
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109212
- );
109888
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109213
109889
  if (record4 !== void 0 && typeof record4.fileFields.collectionValueId === "string") {
109214
109890
  record4.fileFields.collectionValueId = resolvedId;
109215
109891
  }
@@ -109244,8 +109920,8 @@ function computeWorkspaceStatus(workspace, options) {
109244
109920
  if (document !== void 0 && isObjectRecord2(document.data.binding)) {
109245
109921
  document.data.binding.collectionValueId = resolvedId;
109246
109922
  }
109247
- const record4 = records2.find(
109248
- (candidate) => candidate.recordKind === "variant-folder" && candidate.recordId === folderId
109923
+ const record4 = recordsByKey.get(
109924
+ recordStateKey("variant-folder", folderId)
109249
109925
  );
109250
109926
  if (record4 !== void 0 && isObjectRecord2(record4.fileFields.binding)) {
109251
109927
  record4.fileFields.binding.collectionValueId = resolvedId;
@@ -109294,9 +109970,7 @@ function computeWorkspaceStatus(workspace, options) {
109294
109970
  );
109295
109971
  }
109296
109972
  }
109297
- const record4 = records2.find(
109298
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109299
- );
109973
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109300
109974
  const authored = record4?.fileFields.defaultValue;
109301
109975
  if (isObjectRecord2(authored) && "value" in authored) {
109302
109976
  authored.value = substituteMemberDefaultKeyReferenceV4(
@@ -109412,14 +110086,15 @@ function computeWorkspaceStatus(workspace, options) {
109412
110086
  }
109413
110087
  }
109414
110088
  const deletedValueIds = /* @__PURE__ */ new Set();
110089
+ const brokenFiles = new Set(conflictedFiles);
110090
+ for (const error of parseErrors) {
110091
+ if (isBlockingSchemaSourceError(error)) brokenFiles.add(error.file);
110092
+ }
109415
110093
  for (const [key, recordState] of Object.entries(workspace.state.records)) {
109416
110094
  const recordFile = recordState.file ?? (orphanedStaticMemberKeys.has(key) ? STATIC_MEMBER_OWNERSHIP_RECOVERY_SOURCE : void 0);
109417
110095
  if (recordFile === void 0) continue;
109418
110096
  if (reconstructed3.has(key)) continue;
109419
- const fileStillBroken = parseErrors.some(
109420
- (error) => error.file === recordFile && isBlockingSchemaSourceError(error)
109421
- ) || conflictedFiles.includes(recordFile);
109422
- if (fileStillBroken) continue;
110097
+ if (brokenFiles.has(recordFile)) continue;
109423
110098
  if (recordState.conflictServerHash === null) continue;
109424
110099
  if (recordState.recordKind === "localized-text" && isLocalizedText(recordState.data) && recordState.data.memberSource !== void 0)
109425
110100
  continue;
@@ -109801,6 +110476,15 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109801
110476
  interfaces: replayDocument.interfaces,
109802
110477
  constructors: replayDocument.constructors ?? []
109803
110478
  });
110479
+ const replayContext = createPulledConstructionReplayContext({
110480
+ document: replayDocument
110481
+ });
110482
+ const constructorsById = new Map(
110483
+ (replayDocument.constructors ?? []).map((constructor2) => [
110484
+ constructor2.id,
110485
+ constructor2
110486
+ ])
110487
+ );
109804
110488
  let documentBodiesCompiled = false;
109805
110489
  const fallbackValues = new Map(
109806
110490
  (fallbackDocument?.values ?? []).map((row) => [row.id, row])
@@ -109826,9 +110510,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109826
110510
  valuesById
109827
110511
  );
109828
110512
  const initializerOwnerClass = ownerContext.ownerClass;
109829
- const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : (replayDocument.constructors ?? []).find(
109830
- (constructor2) => constructor2.id === initializerOwnerClass.requiredConstructorId
109831
- );
110513
+ const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : constructorsById.get(initializerOwnerClass.requiredConstructorId);
109832
110514
  const requiredArgumentNames = new Set(
109833
110515
  requiredConstructor?.argumentTypes.map((argument2) => argument2.name) ?? []
109834
110516
  );
@@ -109841,6 +110523,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109841
110523
  replay = replayStoredConstructionV4({
109842
110524
  records: pulled,
109843
110525
  document: replayDocument,
110526
+ replayContext,
109844
110527
  valueId: row.id,
109845
110528
  code,
109846
110529
  member: owner,
@@ -110004,13 +110687,16 @@ function expandProspectiveAnimationInstances(document) {
110004
110687
  (row) => isLiteralValueContent(row) && isVirtualInstanceRootShape(row) && typeof row.classId === "string" && classBelongsToAnimationFamily(document.classesById, row.classId)
110005
110688
  );
110006
110689
  if (animationRoots.length === 0) return [...document.values];
110007
- const lookups = cliEvaluatorLookups({
110008
- project: document.project,
110009
- classes: document.classes,
110010
- constructors: document.constructors,
110011
- members: document.members,
110012
- values: document.values
110013
- });
110690
+ const lookups = cliEvaluatorLookups(
110691
+ {
110692
+ project: document.project,
110693
+ classes: document.classes,
110694
+ constructors: document.constructors,
110695
+ members: document.members,
110696
+ values: document.values
110697
+ },
110698
+ { includeValueGraphIndexes: true }
110699
+ );
110014
110700
  const byId = new Map(document.values.map((row) => [row.id, row]));
110015
110701
  for (const root of animationRoots) {
110016
110702
  for (const row of lookups.virtualInstanceRowsForValue(root.id)) {
@@ -111774,41 +112460,22 @@ function worldKindByClassId(document) {
111774
112460
  for (const classId of classes.keys()) resolve5(classId, /* @__PURE__ */ new Set());
111775
112461
  return result;
111776
112462
  }
111777
- function valueWorldKind(kinds, value) {
111778
- if (value === null || typeof value !== "object") return void 0;
111779
- const classId = Reflect.get(value, "classId");
111780
- return typeof classId === "string" ? kinds.get(classId) : void 0;
111781
- }
111782
- function hasWorldLayerOverride(value) {
111783
- if (value === null || typeof value !== "object") return false;
111784
- const body = Reflect.get(value, "value");
111785
- return body !== null && typeof body === "object" && typeof Reflect.get(body, "layerOverrideValueId") === "string";
111786
- }
111787
112463
  function commitPreparationWorldScopeKinds(args) {
111788
112464
  const allKinds = new Set(
111789
- args.postDocument.classes.flatMap(
112465
+ [...args.currentDocument.classes, ...args.postDocument.classes].flatMap(
111790
112466
  (schemaClass2) => typeof schemaClass2.system?.worldKind === "string" ? [schemaClass2.system.worldKind] : []
111791
112467
  )
111792
112468
  );
111793
- if (args.changes.some(
111794
- (change) => change.recordKind === "class" || change.recordKind === "internal-record-relation"
111795
- )) {
111796
- return allKinds;
111797
- }
111798
- const kindsByClass = worldKindByClassId(args.postDocument);
111799
- const current = projectDocumentRecordsByKey(args.currentDocument);
111800
- const requiresWholeWorld = args.changes.some((change) => {
111801
- if (change.recordKind !== "value") return false;
111802
- const prior = current.get(commitPreparationRecordKey(change));
111803
- return [prior, change.nextData].some((candidate) => {
111804
- const worldKind = valueWorldKind(kindsByClass, candidate);
111805
- return hasWorldLayerOverride(candidate) || worldKind === NeoWorldSystemClassKind.TileLayerLink || worldKind === NeoWorldSystemClassKind.ObjectLayerLink;
111806
- });
111807
- });
111808
- return requiresWholeWorld ? allKinds : /* @__PURE__ */ new Set();
112469
+ return stagedChangesRequireWorldLayerBindingValidation(
112470
+ args.currentDocument,
112471
+ args.changes
112472
+ ) ? allKinds : /* @__PURE__ */ new Set();
111809
112473
  }
111810
112474
  function commitPreparationMemberDefaultValueScope(args) {
111811
112475
  let evaluatesSource = false;
112476
+ const currentMembersById = new Map(
112477
+ args.currentDocument.members.map((member) => [member.id, member])
112478
+ );
111812
112479
  const constructorsWithSource = new Set(
111813
112480
  (args.postDocument.constructors ?? []).filter(containsAuthoredNeoScriptSource).map((constructor2) => constructor2.classId)
111814
112481
  );
@@ -111882,9 +112549,7 @@ function commitPreparationMemberDefaultValueScope(args) {
111882
112549
  for (const change of args.changes) {
111883
112550
  if (change.recordKind === "member") {
111884
112551
  visitMember(change.recordId);
111885
- const currentMember = args.currentDocument.members.find(
111886
- (member) => member.id === change.recordId
111887
- );
112552
+ const currentMember = currentMembersById.get(change.recordId);
111888
112553
  if (currentMember !== void 0) {
111889
112554
  rememberDefaultIds(currentMember.defaultValue, true);
111890
112555
  }
@@ -111938,9 +112603,7 @@ function planCommitPreparationInitialScope(args) {
111938
112603
  }
111939
112604
  if (change.recordKind === "member") {
111940
112605
  rememberExact("value", derivedMemberValueId(change.recordId), true);
111941
- const current = args.document.members.find(
111942
- (member) => member.id === change.recordId
111943
- );
112606
+ const current = previousMembers.get(change.recordId);
111944
112607
  for (const candidate of [current, change.nextData]) {
111945
112608
  if (candidate === null || typeof candidate !== "object") continue;
111946
112609
  const valueId = Reflect.get(candidate, "valueId");
@@ -111952,13 +112615,17 @@ function planCommitPreparationInitialScope(args) {
111952
112615
  rememberExact("value", valueId, true);
111953
112616
  }
111954
112617
  }
112618
+ const currentTextsById = new Map(
112619
+ (args.document.localizedTexts ?? []).map((text) => [text.id, text])
112620
+ );
112621
+ const postValuesById = new Map(
112622
+ postDocument.values.map((row) => [row.id, row])
112623
+ );
111955
112624
  const primary = postDocument.localizationConfig?.mainLocale;
111956
112625
  const primaryEdits = args.changes.flatMap((change) => {
111957
112626
  if (change.recordKind !== "localized-text" || change.operation !== "update" || !isLocalizedText(change.nextData) || primary === void 0)
111958
112627
  return [];
111959
- const old = args.document.localizedTexts?.find(
111960
- (text) => text.id === change.recordId
111961
- );
112628
+ const old = currentTextsById.get(change.recordId);
111962
112629
  return old !== void 0 && memberSourcePrimaryChanged(
111963
112630
  old,
111964
112631
  primary,
@@ -111979,9 +112646,7 @@ function planCommitPreparationInitialScope(args) {
111979
112646
  const target = localizedTextReferenceTarget(link);
111980
112647
  rememberExact(target.recordKind, target.recordId, true);
111981
112648
  if (link.kind === "member-value") {
111982
- const row = postDocument.values.find(
111983
- (value) => value.id === link.valueId
111984
- );
112649
+ const row = postValuesById.get(link.valueId);
111985
112650
  if (row !== void 0)
111986
112651
  linkedValueChanges.push({
111987
112652
  ...target,
@@ -112663,9 +113328,14 @@ function readCommitPreparationScopeInMemory(args) {
112663
113328
  key
112664
113329
  );
112665
113330
  }
113331
+ const childKeysSeenByParent = /* @__PURE__ */ new Map();
112666
113332
  const rememberChild = (parentKey, childKey) => {
113333
+ const seen = childKeysSeenByParent.get(parentKey) ?? /* @__PURE__ */ new Set();
113334
+ if (seen.has(childKey)) return;
113335
+ seen.add(childKey);
113336
+ childKeysSeenByParent.set(parentKey, seen);
112667
113337
  const children = childKeysByParentKey.get(parentKey) ?? [];
112668
- if (!children.includes(childKey)) children.push(childKey);
113338
+ children.push(childKey);
112669
113339
  childKeysByParentKey.set(parentKey, children);
112670
113340
  };
112671
113341
  for (const record4 of records2) {
@@ -112919,6 +113589,7 @@ var COMMIT_PREPARATION_SCOPE_RANGE_ROW_LIMIT, COMMIT_PREPARATION_SCOPE_POSTING_R
112919
113589
  var init_project_commit_preparation_scoped_loader = __esm({
112920
113590
  "../src/database/project-commit-preparation-scoped-loader.ts"() {
112921
113591
  "use strict";
113592
+ init_project_world_placement_bindings();
112922
113593
  init_project_localization_rules();
112923
113594
  init_variant_value_graph();
112924
113595
  init_packed_value_write_fold();
@@ -113533,7 +114204,8 @@ function isPulledInitializerCompilationDocumentV4(document) {
113533
114204
  function createPulledConstructionReplayContext(args) {
113534
114205
  return {
113535
114206
  document: args.document,
113536
- constructorsValidated: false
114207
+ constructorsValidated: false,
114208
+ valuesById: new Map(args.document.values.map((value) => [value.id, value]))
113537
114209
  };
113538
114210
  }
113539
114211
  function pulledInitializerCompilerStateV4(document, compilationProject) {
@@ -113636,7 +114308,7 @@ function replayStoredConstructionV4(args) {
113636
114308
  }
113637
114309
  compilePulledProjectDocumentForEvaluationV4(document, compilationProject);
113638
114310
  }
113639
- const root = document.values.find((value) => value.id === args.valueId);
114311
+ const root = args.replayContext === void 0 ? document.values.find((value) => value.id === args.valueId) : args.replayContext.valuesById.get(args.valueId);
113640
114312
  if (root === void 0) {
113641
114313
  throw new Error(
113642
114314
  `Cannot replay stored construction for missing value "${args.valueId}".`
@@ -128405,6 +129077,55 @@ var init_script = __esm({
128405
129077
  }
128406
129078
  });
128407
129079
 
129080
+ // src/project-source/identity-rewriter.ts
129081
+ function createIdentityRewriter(assignments) {
129082
+ if (assignments.size === 0) return (value) => value;
129083
+ const root = { children: /* @__PURE__ */ new Map() };
129084
+ for (const [source, replacement] of assignments) {
129085
+ let prefix = root;
129086
+ for (let index = 0; index < source.length; index += 1) {
129087
+ const character = source[index];
129088
+ let child = prefix.children.get(character);
129089
+ if (child === void 0) {
129090
+ child = { children: /* @__PURE__ */ new Map() };
129091
+ prefix.children.set(character, child);
129092
+ }
129093
+ prefix = child;
129094
+ }
129095
+ prefix.replacement = replacement;
129096
+ }
129097
+ return (value) => {
129098
+ const exact = assignments.get(value);
129099
+ if (exact !== void 0) return exact;
129100
+ const parts = [];
129101
+ let copiedThrough = 0;
129102
+ for (let start = 0; start < value.length; start += 1) {
129103
+ let prefix = root.children.get(value[start]);
129104
+ let replacement;
129105
+ let end = start;
129106
+ for (let index = start; prefix !== void 0; index += 1) {
129107
+ if (prefix.replacement !== void 0) {
129108
+ replacement = prefix.replacement;
129109
+ end = index + 1;
129110
+ }
129111
+ prefix = prefix.children.get(value[index + 1]);
129112
+ }
129113
+ if (replacement === void 0) continue;
129114
+ parts.push(value.slice(copiedThrough, start), replacement);
129115
+ copiedThrough = end;
129116
+ start = end - 1;
129117
+ }
129118
+ if (copiedThrough === 0) return value;
129119
+ parts.push(value.slice(copiedThrough));
129120
+ return parts.join("");
129121
+ };
129122
+ }
129123
+ var init_identity_rewriter = __esm({
129124
+ "src/project-source/identity-rewriter.ts"() {
129125
+ "use strict";
129126
+ }
129127
+ });
129128
+
128408
129129
  // ../src/database/project-source-identity.ts
128409
129130
  import { createHash as createHash8 } from "node:crypto";
128410
129131
  function hashProjectSourceFiles(inputFiles) {
@@ -129469,20 +130190,10 @@ function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInit
129469
130190
  if (localInitializerMaterialization !== void 0) {
129470
130191
  collect(localInitializerMaterialization);
129471
130192
  }
129472
- const replacements = [...assigned].sort(
129473
- ([left], [right]) => right.length - left.length
129474
- );
130193
+ const rewriteString = createIdentityRewriter(assigned);
129475
130194
  const rewrite = (value) => {
129476
130195
  if (typeof value === "string") {
129477
- const exact = assigned.get(value);
129478
- if (exact !== void 0) return exact;
129479
- let result = value;
129480
- for (const [pendingId2, assignedId] of replacements) {
129481
- if (result.includes(pendingId2)) {
129482
- result = result.replaceAll(pendingId2, assignedId);
129483
- }
129484
- }
129485
- return result;
130196
+ return rewriteString(value);
129486
130197
  }
129487
130198
  if (Array.isArray(value)) return value.map((item) => rewrite(item));
129488
130199
  if (isObjectRecord2(value)) {
@@ -131295,9 +132006,7 @@ function projectTransactionResultReplacements(candidateAssignments, resultAssign
131295
132006
  }
131296
132007
  return {
131297
132008
  exact: replacements,
131298
- embedded: [...replacements].sort(
131299
- ([left], [right]) => right.length - left.length
131300
- )
132009
+ rewrite: createIdentityRewriter(replacements)
131301
132010
  };
131302
132011
  }
131303
132012
  function rewriteReconstructedRecords(records2, replacements) {
@@ -131327,13 +132036,7 @@ function rewriteReconstructedRecords(records2, replacements) {
131327
132036
  return rewritten;
131328
132037
  }
131329
132038
  function rewriteAssignedString(value, replacements) {
131330
- const exact = replacements.exact.get(value);
131331
- if (exact !== void 0) return exact;
131332
- let result = value;
131333
- for (const [source, target] of replacements.embedded) {
131334
- if (result.includes(source)) result = result.replaceAll(source, target);
131335
- }
131336
- return result;
132039
+ return replacements.rewrite(value);
131337
132040
  }
131338
132041
  function rewriteAssignedValue(value, replacements) {
131339
132042
  if (typeof value === "string") {
@@ -131473,7 +132176,7 @@ function applyPushResult(workspace, result, pendingIdAssignments = /* @__PURE__
131473
132176
  );
131474
132177
  const replacements = {
131475
132178
  exact: pendingIdAssignments,
131476
- embedded: pendingIdAssignments.entries().toArray().sort(([left], [right]) => right.length - left.length)
132179
+ rewrite: createIdentityRewriter(pendingIdAssignments)
131477
132180
  };
131478
132181
  const localRecords = rewriteReconstructedRecords(
131479
132182
  localStatus.reconstructed,
@@ -132153,52 +132856,49 @@ function prepareNSPropertySetterChanges(workspace, status) {
132153
132856
  }
132154
132857
  members.set(change.recordId, change.nextData);
132155
132858
  }
132859
+ const inheritedSetters = /* @__PURE__ */ new Map();
132156
132860
  const removedDeclarations = status.changes.filter(
132157
- (change) => change.recordKind === "member" && change.nextData?.kind === 10 && isObjectRecord2(change.baseData) && typeof change.baseData.setterCode === "string" && typeof change.nextData.setterCode !== "string" && !ancestorDeclaresSetter(change.nextData, members)
132861
+ (change) => change.recordKind === "member" && change.nextData?.kind === 10 && isObjectRecord2(change.baseData) && typeof change.baseData.setterCode === "string" && typeof change.nextData.setterCode !== "string" && !ancestorDeclaresSetter(change.nextData, members, inheritedSetters)
132158
132862
  ).map((change) => change.recordId);
132159
- for (const declarationId of removedDeclarations) {
132160
- for (const [memberId, member] of members) {
132161
- if (memberId === declarationId) continue;
132162
- if (!memberDescendsFrom(member, declarationId, members)) {
132163
- continue;
132164
- }
132165
- if (typeof member.setterCode !== "string" && member.setter === void 0) {
132166
- continue;
132167
- }
132168
- const next = { ...member };
132169
- delete next.setterCode;
132170
- delete next.setter;
132171
- members.set(memberId, next);
132172
- const key = recordStateKey("member", memberId);
132173
- const reconstructed3 = status.reconstructed.get(key);
132174
- if (reconstructed3 !== void 0) reconstructed3.fullData = next;
132175
- const existingChange = changesById.get(memberId);
132176
- if (existingChange !== void 0) {
132177
- existingChange.nextData = next;
132178
- continue;
132179
- }
132180
- const base = workspace.state.records[key];
132181
- if (base === void 0 || reconstructed3 === void 0) {
132182
- throw new Error(
132183
- `Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
132184
- );
132185
- }
132186
- const cascadeChange = recordUpsertChange({
132187
- base,
132188
- recordKind: "member",
132189
- recordId: memberId,
132190
- file: reconstructed3.file,
132191
- nextData: next
132192
- });
132193
- status.changes.push(cascadeChange);
132194
- changesById.set(memberId, cascadeChange);
132863
+ for (const memberId of memberDescendantIds(members, removedDeclarations)) {
132864
+ const member = members.get(memberId);
132865
+ if (typeof member.setterCode !== "string" && member.setter === void 0) {
132866
+ continue;
132195
132867
  }
132868
+ const next = { ...member };
132869
+ delete next.setterCode;
132870
+ delete next.setter;
132871
+ members.set(memberId, next);
132872
+ const key = recordStateKey("member", memberId);
132873
+ const reconstructed3 = status.reconstructed.get(key);
132874
+ if (reconstructed3 !== void 0) reconstructed3.fullData = next;
132875
+ const existingChange = changesById.get(memberId);
132876
+ if (existingChange !== void 0) {
132877
+ existingChange.nextData = next;
132878
+ continue;
132879
+ }
132880
+ const base = workspace.state.records[key];
132881
+ if (base === void 0 || reconstructed3 === void 0) {
132882
+ throw new Error(
132883
+ `Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
132884
+ );
132885
+ }
132886
+ const cascadeChange = recordUpsertChange({
132887
+ base,
132888
+ recordKind: "member",
132889
+ recordId: memberId,
132890
+ file: reconstructed3.file,
132891
+ nextData: next
132892
+ });
132893
+ status.changes.push(cascadeChange);
132894
+ changesById.set(memberId, cascadeChange);
132196
132895
  }
132896
+ inheritedSetters.clear();
132197
132897
  for (const member of members.values()) {
132198
132898
  if (member.kind !== 10) continue;
132199
132899
  if (typeof member.extendsMemberId !== "string") continue;
132200
132900
  if (typeof member.setterCode !== "string") continue;
132201
- if (ancestorDeclaresSetter(member, members)) continue;
132901
+ if (ancestorDeclaresSetter(member, members, inheritedSetters)) continue;
132202
132902
  throw new Error(
132203
132903
  `Override NeoScript property "${String(member.name ?? member.id)}" cannot add a setter because its base chain does not declare one.`
132204
132904
  );
@@ -132240,14 +132940,10 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132240
132940
  members.set(next.id, next);
132241
132941
  }
132242
132942
  }
132243
- for (const [memberId, member] of members) {
132943
+ for (const memberId of memberDescendantIds(members, affectedRoots)) {
132944
+ const member = members.get(memberId);
132244
132945
  if (member.kind !== 23 || typeof member.code !== "string") continue;
132245
132946
  if (changesById.has(memberId)) continue;
132246
- if (![...affectedRoots].some(
132247
- (rootId) => memberDescendsFrom(member, rootId, members)
132248
- )) {
132249
- continue;
132250
- }
132251
132947
  const key = recordStateKey("member", memberId);
132252
132948
  const base = workspace.state.records[key];
132253
132949
  const reconstructed3 = status.reconstructed.get(key);
@@ -132267,10 +132963,16 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132267
132963
  changesById.set(memberId, cascadeChange);
132268
132964
  }
132269
132965
  }
132270
- function ancestorDeclaresSetter(member, members) {
132966
+ function ancestorDeclaresSetter(member, members, cache) {
132271
132967
  let parentId = typeof member.extendsMemberId === "string" ? member.extendsMemberId : null;
132272
132968
  const visited = /* @__PURE__ */ new Set();
132969
+ let hasSetter = false;
132273
132970
  while (parentId !== null) {
132971
+ const cached = cache.get(parentId);
132972
+ if (cached !== void 0) {
132973
+ hasSetter = cached;
132974
+ break;
132975
+ }
132274
132976
  if (visited.has(parentId)) {
132275
132977
  throw new Error(
132276
132978
  `Cannot resolve NeoScript property setter inheritance: circular member chain at "${parentId}".`
@@ -132283,23 +132985,35 @@ function ancestorDeclaresSetter(member, members) {
132283
132985
  `Cannot resolve NeoScript property setter inheritance: missing parent member "${parentId}".`
132284
132986
  );
132285
132987
  }
132286
- if (typeof parent.setterCode === "string") return true;
132988
+ if (typeof parent.setterCode === "string") {
132989
+ hasSetter = true;
132990
+ break;
132991
+ }
132287
132992
  parentId = typeof parent.extendsMemberId === "string" ? parent.extendsMemberId : null;
132288
132993
  }
132289
- return false;
132994
+ for (const id2 of visited) cache.set(id2, hasSetter);
132995
+ return hasSetter;
132290
132996
  }
132291
- function memberDescendsFrom(member, ancestorId, members) {
132292
- let parentId = typeof member.extendsMemberId === "string" ? member.extendsMemberId : null;
132293
- const visited = /* @__PURE__ */ new Set();
132294
- while (parentId !== null) {
132295
- if (parentId === ancestorId) return true;
132296
- if (visited.has(parentId)) return false;
132297
- visited.add(parentId);
132298
- const parent = members.get(parentId);
132299
- if (parent === void 0) return false;
132300
- parentId = typeof parent.extendsMemberId === "string" ? parent.extendsMemberId : null;
132997
+ function memberDescendantIds(members, rootIds) {
132998
+ const roots = [...rootIds];
132999
+ if (roots.length === 0) return /* @__PURE__ */ new Set();
133000
+ const children = /* @__PURE__ */ new Map();
133001
+ for (const [id2, member] of members) {
133002
+ if (typeof member.extendsMemberId !== "string") continue;
133003
+ const siblings = children.get(member.extendsMemberId);
133004
+ if (siblings === void 0) children.set(member.extendsMemberId, [id2]);
133005
+ else siblings.push(id2);
132301
133006
  }
132302
- return false;
133007
+ const descendants = /* @__PURE__ */ new Set();
133008
+ const pending = [...roots];
133009
+ for (let index = 0; index < pending.length; index += 1) {
133010
+ for (const childId of children.get(pending[index]) ?? []) {
133011
+ if (descendants.has(childId)) continue;
133012
+ descendants.add(childId);
133013
+ pending.push(childId);
133014
+ }
133015
+ }
133016
+ return descendants;
132303
133017
  }
132304
133018
  function resolveNSPropertyReturnTypeInfo2(member, members) {
132305
133019
  let current = member;
@@ -132385,6 +133099,7 @@ var compileNSVoidBody2, compileNSFunction2, compileNSGetter2, compileNSSetter2,
132385
133099
  var init_push = __esm({
132386
133100
  "src/commands/push.ts"() {
132387
133101
  "use strict";
133102
+ init_identity_rewriter();
132388
133103
  init_source_layout();
132389
133104
  init_src();
132390
133105
  init_src2();
@@ -132478,7 +133193,7 @@ var init_registry2 = __esm({
132478
133193
  "schema-contract/registry.mjs"() {
132479
133194
  "use strict";
132480
133195
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
132481
- cliVersion: "0.50.3",
133196
+ cliVersion: "0.50.5",
132482
133197
  projectFileUploadBatchSize: 32,
132483
133198
  documentRecords: {
132484
133199
  member: {
@@ -139694,7 +140409,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
139694
140409
  async function main() {
139695
140410
  const args = parseArgs(process.argv.slice(2));
139696
140411
  if (args.command === "--version") {
139697
- console.log("0.50.3");
140412
+ console.log("0.50.5");
139698
140413
  return;
139699
140414
  }
139700
140415
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {