@neocompose/cli 0.50.4 → 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
  }
@@ -80933,216 +81419,6 @@ var init_evaluateNSGetter = __esm({
80933
81419
  }
80934
81420
  });
80935
81421
 
80936
- // ../src/models/members/stored-value-placement-index.ts
80937
- function buildStoredValuePlacementIndex(args) {
80938
- const membersById = /* @__PURE__ */ new Map();
80939
- for (const member of args.members) membersById.set(member.id, member);
80940
- const valuesById = /* @__PURE__ */ new Map();
80941
- const unorderedEntriesByContainerId = /* @__PURE__ */ new Map();
80942
- for (const value of args.values) {
80943
- valuesById.set(value.id, value);
80944
- if (typeof value.containerId !== "string") continue;
80945
- const entries = unorderedEntriesByContainerId.get(value.containerId);
80946
- if (entries === void 0) {
80947
- unorderedEntriesByContainerId.set(value.containerId, [value]);
80948
- } else {
80949
- entries.push(value);
80950
- }
80951
- }
80952
- for (const entries of unorderedEntriesByContainerId.values()) {
80953
- entries.sort((left, right) => left.id.localeCompare(right.id));
80954
- }
80955
- const constructorsById = new Map(
80956
- args.constructors.map((constructor2) => [constructor2.id, constructor2])
80957
- );
80958
- const resolveConstructorSettlement = createConstructorSettlementResolver({
80959
- classes: args.classes,
80960
- constructors: args.constructors,
80961
- members: args.members
80962
- });
80963
- const resolvedMemberById = /* @__PURE__ */ new Map();
80964
- const resolvedMember = (member) => {
80965
- const cached = resolvedMemberById.get(member.id);
80966
- if (cached !== void 0) return cached;
80967
- const resolved = resolveMember2(member, args.members);
80968
- resolvedMemberById.set(member.id, resolved);
80969
- return resolved;
80970
- };
80971
- const storedSchemaByClassId = /* @__PURE__ */ new Map();
80972
- const storedSchema = (classId) => {
80973
- const cached = storedSchemaByClassId.get(classId);
80974
- if (cached !== void 0) return cached;
80975
- const schema = mergeStoredInstanceSchema(
80976
- classId,
80977
- args.classes,
80978
- args.members
80979
- );
80980
- storedSchemaByClassId.set(classId, schema);
80981
- return schema;
80982
- };
80983
- const queue = [];
80984
- for (const root of projectRootMembersInDisplayOrder(args.project)) {
80985
- const member = membersById.get(root.memberId);
80986
- if (member === void 0 || typeof member.valueId !== "string") continue;
80987
- queue.push({
80988
- memberId: member.id,
80989
- parentValueId: null,
80990
- source: {
80991
- kind: "root",
80992
- label: root.root.label,
80993
- sourcePath: `root.${root.root.key}`
80994
- },
80995
- valueId: member.valueId
80996
- });
80997
- }
80998
- for (const member of args.members) {
80999
- if (!isStaticMember(member) || memberAccessOf(member) !== 0 /* Public */)
81000
- continue;
81001
- const valueId = args.resolveStaticValueId(member.id);
81002
- if (valueId === null) continue;
81003
- const placement = findSchemaPlacement(member.id, args.classes);
81004
- if (placement === null) continue;
81005
- queue.push({
81006
- memberId: member.id,
81007
- parentValueId: null,
81008
- source: {
81009
- kind: "static",
81010
- label: placement.schemaKey,
81011
- ownerClassName: placement.ownerClass.name,
81012
- sourcePath: `static:${member.id}`
81013
- },
81014
- valueId
81015
- });
81016
- }
81017
- const placementByValueId = /* @__PURE__ */ new Map();
81018
- const mutablePlacementsByClassId = /* @__PURE__ */ new Map();
81019
- const mutablePlacementsByMemberId = /* @__PURE__ */ new Map();
81020
- const mutablePlacementsByKind = /* @__PURE__ */ new Map();
81021
- for (let cursor = 0; cursor < queue.length; cursor += 1) {
81022
- const item = queue[cursor];
81023
- if (item === void 0 || placementByValueId.has(item.valueId)) continue;
81024
- const authoredValue = valuesById.get(item.valueId);
81025
- const storedMember = membersById.get(item.memberId);
81026
- if (authoredValue === void 0 || storedMember === void 0) continue;
81027
- const value = args.resolveValue === void 0 ? authoredValue : args.resolveValue(authoredValue);
81028
- if (value === null) continue;
81029
- const placement = item;
81030
- placementByValueId.set(value.id, placement);
81031
- appendPlacement(mutablePlacementsByMemberId, storedMember.id, placement);
81032
- const member = resolvedMember(storedMember);
81033
- appendPlacement(mutablePlacementsByKind, member.kind, placement);
81034
- if (isMemberClassBase(member)) {
81035
- const classId = value.classId ?? member.classId;
81036
- appendPlacement(mutablePlacementsByClassId, classId, placement);
81037
- if (!isLiteralValueContent(value) || !isStringRecord5(value.value)) {
81038
- continue;
81039
- }
81040
- const settledChildrenBySchemaKey = /* @__PURE__ */ new Map();
81041
- const constructor2 = typeof value.instanceConstructorId === "string" ? constructorsById.get(value.instanceConstructorId) : void 0;
81042
- if (constructor2 !== void 0 && constructor2.classId === classId && value.constructorArgs != null) {
81043
- for (const [index, parameter4] of constructor2.argumentTypes.entries()) {
81044
- const settled = resolveConstructorSettlement(
81045
- classId,
81046
- parameter4.name,
81047
- constructor2.id
81048
- );
81049
- if (settled === null || Object.hasOwn(value.value, settled.schemaKey)) {
81050
- continue;
81051
- }
81052
- const childValueId = value.constructorArgs[constructorActionParameterId(constructor2, index)];
81053
- if (typeof childValueId === "string" && valuesById.has(childValueId)) {
81054
- settledChildrenBySchemaKey.set(settled.schemaKey, childValueId);
81055
- }
81056
- }
81057
- }
81058
- for (const entry of storedSchema(classId)) {
81059
- const childMember = membersById.get(entry.memberId);
81060
- const childValueId = value.value[entry.schemaKey] ?? settledChildrenBySchemaKey.get(entry.schemaKey);
81061
- if (childMember === void 0 || typeof childValueId !== "string") {
81062
- continue;
81063
- }
81064
- if (memberAccessOf(childMember) !== 0 /* Public */) continue;
81065
- queue.push({
81066
- memberId: childMember.id,
81067
- parentValueId: value.id,
81068
- source: { kind: "classField", schemaKey: entry.schemaKey },
81069
- valueId: childValueId
81070
- });
81071
- }
81072
- continue;
81073
- }
81074
- if (!isMemberListBase(member) && !isMemberDictionaryBase(member)) {
81075
- continue;
81076
- }
81077
- const entryMember = membersById.get(member.entryMemberId);
81078
- if (entryMember === void 0) continue;
81079
- if (isMemberDictionaryBase(member)) {
81080
- if (!isStringRecord5(value.value)) continue;
81081
- for (const [key, childValueId] of Object.entries(value.value)) {
81082
- queue.push({
81083
- memberId: entryMember.id,
81084
- parentValueId: value.id,
81085
- source: {
81086
- kind: "collectionEntry",
81087
- containerMemberId: storedMember.id,
81088
- entry: { kind: "dict", key, valueId: childValueId }
81089
- },
81090
- valueId: childValueId
81091
- });
81092
- }
81093
- continue;
81094
- }
81095
- const entries = listKindOf(member) === 1 /* Unordered */ ? unorderedEntriesByContainerId.get(value.id) ?? [] : Array.isArray(value.value) ? value.value.flatMap((childValueId) => {
81096
- if (typeof childValueId !== "string") return [];
81097
- const childValue = valuesById.get(childValueId);
81098
- return childValue === void 0 ? [] : [childValue];
81099
- }) : [];
81100
- for (const [index, childValue] of entries.entries()) {
81101
- queue.push({
81102
- memberId: entryMember.id,
81103
- parentValueId: value.id,
81104
- source: {
81105
- kind: "collectionEntry",
81106
- containerMemberId: storedMember.id,
81107
- entry: { kind: "list", index, valueId: childValue.id }
81108
- },
81109
- valueId: childValue.id
81110
- });
81111
- }
81112
- }
81113
- return {
81114
- placementByValueId,
81115
- placementsByClassId: mutablePlacementsByClassId,
81116
- placementsByKind: mutablePlacementsByKind,
81117
- placementsByMemberId: mutablePlacementsByMemberId
81118
- };
81119
- }
81120
- function appendPlacement(index, key, placement) {
81121
- const placements = index.get(key);
81122
- if (placements === void 0) {
81123
- index.set(key, [placement]);
81124
- } else {
81125
- placements.push(placement);
81126
- }
81127
- }
81128
- function isStringRecord5(value) {
81129
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
81130
- return false;
81131
- }
81132
- return Object.values(value).every((item) => typeof item === "string");
81133
- }
81134
- var init_stored_value_placement_index = __esm({
81135
- "../src/models/members/stored-value-placement-index.ts"() {
81136
- "use strict";
81137
- init_inheritance();
81138
- init_constructor_parameter_settlement();
81139
- init_constructors2();
81140
- init_project2();
81141
- init_member_kinds();
81142
- init_members();
81143
- }
81144
- });
81145
-
81146
81422
  // ../src/runtime/initializer-materialization.ts
81147
81423
  function declarationInitializerContext(document) {
81148
81424
  const key = initializerEvaluatorCacheKey(document);
@@ -81393,6 +81669,22 @@ function buildVirtualInstanceMaterializedIndex(args) {
81393
81669
  })
81394
81670
  };
81395
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
+ }
81396
81688
  function withoutInitializerConstructionFields(init) {
81397
81689
  if (init.compiled === void 0) return init;
81398
81690
  const baseline = deepClonePlainData(init);
@@ -81484,24 +81776,20 @@ function expandStoredInstance(args) {
81484
81776
  }
81485
81777
  const instanceRoot = literalRow(args.instanceRoot);
81486
81778
  const classId = instanceRoot.classId ?? rootMember.classId;
81487
- const schemaClass2 = args.document.classes.find(
81488
- (candidate) => candidate.id === classId
81489
- );
81779
+ const schemaIndex = projectSchemaIndexFor(args.document);
81780
+ const schemaClass2 = schemaIndex.class(classId);
81490
81781
  if (schemaClass2 === void 0) {
81491
81782
  throw new Error(
81492
81783
  `Virtual expansion root "${args.instanceRoot.id}" references missing class "${classId}".`
81493
81784
  );
81494
81785
  }
81495
- const constructors = args.document.constructors ?? [];
81496
81786
  if (instanceRoot.instanceConstructorId === void 0 && typeof instanceRoot.instanceVariantId !== "string") {
81497
81787
  throw new VirtualExpansionUnsupportedError(
81498
81788
  `Virtual expansion root "${args.instanceRoot.id}" carries no construction stamp for class "${classId}"; keep this historical graph materialized.`
81499
81789
  );
81500
81790
  }
81501
81791
  const recordedConstructorId = instanceRoot.instanceConstructorId === void 0 ? schemaClass2.requiredConstructorId ?? null : instanceRoot.instanceConstructorId;
81502
- const requiredConstructor = recordedConstructorId === null ? null : constructors.find(
81503
- (candidate) => candidate.id === recordedConstructorId
81504
- ) ?? null;
81792
+ const requiredConstructor = recordedConstructorId === null ? null : schemaIndex.constructorRecord(recordedConstructorId) ?? null;
81505
81793
  if (recordedConstructorId !== null && requiredConstructor === null) {
81506
81794
  throw new Error(
81507
81795
  `Virtual expansion class "${classId}" references missing constructor "${recordedConstructorId}".`
@@ -83610,23 +83898,25 @@ function variantSwapDeclaredMember(document, rootValueId) {
83610
83898
  }
83611
83899
  function createHeadlessVirtualInstanceResolver(args) {
83612
83900
  const { document } = args;
83901
+ const membersById = args.membersById ?? new Map(document.members.map((member) => [member.id, member]));
83613
83902
  let placementByValueId = null;
83614
- const placements = () => placementByValueId ??= buildStoredValuePlacementIndex({
83903
+ const placements = () => placementByValueId ??= args.placementByValueId ?? buildStoredValuePlacementIndex({
83615
83904
  classes: document.classes,
83616
83905
  constructors: document.constructors ?? [],
83617
83906
  members: document.members,
83618
83907
  project: document.project,
83619
- resolveStaticValueId: (memberId) => document.members.find((member) => member.id === memberId)?.valueId ?? null,
83908
+ resolveStaticValueId: (memberId) => membersById.get(memberId)?.valueId ?? null,
83620
83909
  values: document.values
83621
83910
  }).placementByValueId;
83622
- 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]));
83623
83912
  let resolverDocumentCache = null;
83624
83913
  const resolverDocumentOnce = () => resolverDocumentCache ??= composeResolverDocument(
83625
83914
  document,
83626
83915
  args.resolverLookups()
83627
83916
  );
83628
- let materializedIndex = null;
83917
+ let materializedIndex = args.materializedIndex ?? null;
83629
83918
  const graphRowsByRootId = /* @__PURE__ */ new Map();
83919
+ const emptyRows = [];
83630
83920
  const graphByValueId = /* @__PURE__ */ new Map();
83631
83921
  const failedRootIds = /* @__PURE__ */ new Set();
83632
83922
  const expandedRowById = /* @__PURE__ */ new Map();
@@ -83634,14 +83924,12 @@ function createHeadlessVirtualInstanceResolver(args) {
83634
83924
  const expandRoot = (rootId, memberId) => {
83635
83925
  const cached = graphRowsByRootId.get(rootId);
83636
83926
  if (cached !== void 0) return cached;
83637
- if (failedRootIds.has(rootId)) return /* @__PURE__ */ new Map();
83927
+ if (failedRootIds.has(rootId)) return emptyRows;
83638
83928
  const instanceRoot = rawById.get(rootId);
83639
- const declaredMember = document.members.find(
83640
- (member2) => member2.id === memberId
83641
- );
83929
+ const declaredMember = membersById.get(memberId);
83642
83930
  if (instanceRoot === void 0 || declaredMember === void 0) {
83643
83931
  failedRootIds.add(rootId);
83644
- return /* @__PURE__ */ new Map();
83932
+ return emptyRows;
83645
83933
  }
83646
83934
  const member = storedClassResolutionMember(
83647
83935
  declaredMember,
@@ -83650,7 +83938,7 @@ function createHeadlessVirtualInstanceResolver(args) {
83650
83938
  );
83651
83939
  if (member === null || !isLiteralValueContent(instanceRoot)) {
83652
83940
  failedRootIds.add(rootId);
83653
- return /* @__PURE__ */ new Map();
83941
+ return emptyRows;
83654
83942
  }
83655
83943
  try {
83656
83944
  const resolverDocument = resolverDocumentOnce();
@@ -83675,7 +83963,8 @@ function createHeadlessVirtualInstanceResolver(args) {
83675
83963
  materializedIndex,
83676
83964
  readRecorder: args.readRecorder
83677
83965
  });
83678
- graphRowsByRootId.set(rootId, graph.rowsById);
83966
+ const rows = [...graph.rowsById.values()];
83967
+ graphRowsByRootId.set(rootId, rows);
83679
83968
  for (const [id2, row] of graph.rowsById) {
83680
83969
  expandedRowById.set(id2, row);
83681
83970
  graphByValueId.set(id2, graph);
@@ -83687,10 +83976,10 @@ function createHeadlessVirtualInstanceResolver(args) {
83687
83976
  graphByValueId.set(id2, graph);
83688
83977
  }
83689
83978
  graphByValueId.set(rootId, graph);
83690
- return graph.rowsById;
83979
+ return rows;
83691
83980
  } catch {
83692
83981
  failedRootIds.add(rootId);
83693
- return /* @__PURE__ */ new Map();
83982
+ return emptyRows;
83694
83983
  }
83695
83984
  };
83696
83985
  const virtualInstanceRowsForValue = (receiverValueId) => {
@@ -83701,11 +83990,11 @@ function createHeadlessVirtualInstanceResolver(args) {
83701
83990
  args.readRecorder?.recordValueRead(placement.valueId);
83702
83991
  const raw = rawById.get(placement.valueId);
83703
83992
  if (raw !== void 0 && isLiteralValueContent(raw) && isStoredClassResolutionRoot(raw)) {
83704
- return [...expandRoot(placement.valueId, placement.memberId).values()];
83993
+ return expandRoot(placement.valueId, placement.memberId);
83705
83994
  }
83706
83995
  placement = placement.parentValueId === null ? null : placements().get(placement.parentValueId) ?? null;
83707
83996
  }
83708
- return [];
83997
+ return emptyRows;
83709
83998
  };
83710
83999
  return {
83711
84000
  virtualInstanceRowsForValue,
@@ -83725,6 +84014,7 @@ var init_virtual_instance_graph = __esm({
83725
84014
  "use strict";
83726
84015
  init_deep_clone_plain_data();
83727
84016
  init_inheritance();
84017
+ init_project_schema_index();
83728
84018
  init_constructor_parameter_settlement();
83729
84019
  init_generics();
83730
84020
  init_classes();
@@ -83914,6 +84204,175 @@ function indexedInitializerEvaluatorLookups(document, key, revision) {
83914
84204
  });
83915
84205
  return lookups;
83916
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
+ }
83917
84376
  function buildInitializerRootValueWithLookups(document, lookups, tracking) {
83918
84377
  const rootValue = {};
83919
84378
  for (const { root, memberId } of projectRootMembersInDisplayOrder(
@@ -84087,6 +84546,7 @@ var init_evaluateInitializer = __esm({
84087
84546
  init_instance_provenance();
84088
84547
  init_members();
84089
84548
  init_project2();
84549
+ init_stored_value_placement_index();
84090
84550
  init_evaluateNSGetter();
84091
84551
  init_virtual_instance_graph();
84092
84552
  evaluatorLookupsByDocument = /* @__PURE__ */ new WeakMap();
@@ -86239,7 +86699,13 @@ function collectNeoScriptRecompileImpact(args) {
86239
86699
  const dependentsById = /* @__PURE__ */ new Map();
86240
86700
  for (const record4 of [
86241
86701
  ...collectSchemaDependencyRecords(args.postDocument),
86242
- ...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
+ )
86243
86709
  ]) {
86244
86710
  for (const dependencyId of collectCompilerReferenceIds(record4.value)) {
86245
86711
  const dependents = dependentsById.get(dependencyId) ?? [];
@@ -86670,8 +87136,11 @@ function collectSchemaDependencyRecords(document) {
86670
87136
  }))
86671
87137
  ];
86672
87138
  }
86673
- function collectStructuralDependencyRecords(document) {
87139
+ function collectStructuralDependencyRecords(document, currentDocument, changedClassIds) {
86674
87140
  const records2 = [];
87141
+ const existingClassIds = new Set(
87142
+ currentDocument.classes.map((schemaClass2) => schemaClass2.id)
87143
+ );
86675
87144
  const resolver = new EffectiveStorageResolver({
86676
87145
  members: document.members,
86677
87146
  classes: document.classes,
@@ -86683,13 +87152,19 @@ function collectStructuralDependencyRecords(document) {
86683
87152
  }
86684
87153
  }
86685
87154
  for (const schemaClass2 of document.classes) {
86686
- for (const entry of mergeSchemas(
87155
+ const memberIds = existingClassIds.has(schemaClass2.id) ? mergeSchemas(
86687
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)
86688
87166
  )) {
86689
- records2.push({
86690
- id: entry.memberId,
86691
- value: { classId: schemaClass2.id }
86692
- });
87167
+ records2.push({ id: entry.memberId, value: { classId: schemaClass2.id } });
86693
87168
  }
86694
87169
  }
86695
87170
  return records2;
@@ -94929,17 +95404,271 @@ var init_push_change_intent = __esm({
94929
95404
  }
94930
95405
  });
94931
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
+
94932
95657
  // ../src/models/classes/world-layer-link-target.ts
94933
95658
  function validateWorldLayerLinkClassTargets(args) {
95659
+ const relationResolver = createEffectiveClassRelationResolver(args);
95660
+ const worldKindsByClassId = indexWorldSystemClassKinds(
95661
+ args.classes,
95662
+ relationResolver.classesById
95663
+ );
94934
95664
  for (const schemaClass2 of args.classes) {
94935
95665
  if (args.classIds !== void 0 && !args.classIds.has(schemaClass2.id)) {
94936
95666
  continue;
94937
95667
  }
94938
95668
  const directWorldKind = schemaClass2.system?.worldKind;
94939
95669
  const isSystemLinkBase = directWorldKind === NeoWorldSystemClassKind.TileLayerLink || directWorldKind === NeoWorldSystemClassKind.ObjectLayerLink;
94940
- const descriptor = worldLayerLinkTargetDescriptorForClass(
94941
- schemaClass2.id,
94942
- args.classes
95670
+ const descriptor = worldLayerLinkTargetDescriptor(
95671
+ worldKindsByClassId.get(schemaClass2.id) ?? null
94943
95672
  );
94944
95673
  if (descriptor === null) continue;
94945
95674
  if (isSystemLinkBase) {
@@ -94948,10 +95677,9 @@ function validateWorldLayerLinkClassTargets(args) {
94948
95677
  `System layer-link base class "${schemaClass2.id}" must remain abstract.`
94949
95678
  );
94950
95679
  }
94951
- if (worldLayerLinkTargetRelations(
94952
- schemaClass2.id,
94953
- descriptor,
94954
- args.relations
95680
+ if (relationResolver.directClassRelations(
95681
+ descriptor.relationKind,
95682
+ schemaClass2.id
94955
95683
  ).length > 0) {
94956
95684
  throw new Error(
94957
95685
  `System layer-link base class "${schemaClass2.id}" cannot declare a layer target relation.`
@@ -94964,7 +95692,9 @@ function validateWorldLayerLinkClassTargets(args) {
94964
95692
  classes: args.classes,
94965
95693
  linkLabel: `Concrete layer-link class "${schemaClass2.id}"`,
94966
95694
  relations: args.relations,
94967
- sourceClassId: schemaClass2.id
95695
+ sourceClassId: schemaClass2.id,
95696
+ relationResolver,
95697
+ worldKindsByClassId
94968
95698
  });
94969
95699
  }
94970
95700
  }
@@ -94988,11 +95718,6 @@ function worldLayerLinkTargetDescriptor(worldKind) {
94988
95718
  }
94989
95719
  return null;
94990
95720
  }
94991
- function worldLayerLinkTargetRelations(classId, descriptor, relations) {
94992
- return relations.filter(
94993
- (relation) => relation.relationKind === descriptor.relationKind && relation.sourceRecordKind === ProjectRecordKind.Class && relation.sourceRecordId === classId && relation.targetRecordKind === ProjectRecordKind.Class
94994
- );
94995
- }
94996
95721
  function resolveWorldLayerLinkTarget(args) {
94997
95722
  const label = args.linkLabel ?? `Layer-link class "${args.sourceClassId}"`;
94998
95723
  const relationResolver = args.relationResolver ?? createEffectiveClassRelationResolver({
@@ -95078,6 +95803,34 @@ var init_world_layer_link_target = __esm({
95078
95803
  });
95079
95804
 
95080
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
+ }
95081
95834
  function worldPlacementVariantBindings(args) {
95082
95835
  const foldersById = new Map(
95083
95836
  args.variantFolders.map((folder) => [folder.id, folder])
@@ -95086,12 +95839,15 @@ function worldPlacementVariantBindings(args) {
95086
95839
  args.members.map((member) => [member.id, member])
95087
95840
  );
95088
95841
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95842
+ const containedRows = indexContainedRows(args.values);
95843
+ const expandedGraphs = /* @__PURE__ */ new WeakMap();
95089
95844
  let cachedLookups = null;
95090
95845
  const expansionLookups = () => {
95091
95846
  return cachedLookups ??= initializerEvaluatorLookups(
95092
95847
  args.expansionDocument
95093
95848
  );
95094
95849
  };
95850
+ const lookupEntriesByMember = /* @__PURE__ */ new Map();
95095
95851
  return args.variants.map((variant2) => {
95096
95852
  const folder = variant2.folderId === null ? null : foldersById.get(variant2.folderId) ?? null;
95097
95853
  const binding = folder?.binding ?? null;
@@ -95104,17 +95860,24 @@ function worldPlacementVariantBindings(args) {
95104
95860
  lookupRowValueIds: []
95105
95861
  };
95106
95862
  }
95107
- return {
95108
- id: variant2.id,
95109
- classId: variant2.classId,
95110
- 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({
95111
95871
  collection,
95112
95872
  collectionValueId: binding.collectionValueId,
95113
95873
  lookups: expansionLookups(),
95114
- values: args.values,
95874
+ containedRows,
95875
+ expandedGraphs,
95115
95876
  valuesById
95116
- })
95117
- };
95877
+ });
95878
+ entriesByValue.set(binding.collectionValueId, lookupRowValueIds);
95879
+ }
95880
+ return { id: variant2.id, classId: variant2.classId, lookupRowValueIds };
95118
95881
  });
95119
95882
  }
95120
95883
  function lookupCollectionEntryIds(args) {
@@ -95125,24 +95888,47 @@ function lookupCollectionEntryIds(args) {
95125
95888
  if (graphRows.length === 0) {
95126
95889
  const fallbackRow = storedRow ?? args.lookups.valueById(args.collectionValueId);
95127
95890
  if (fallbackRow === null || fallbackRow === void 0) return [];
95128
- 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);
95129
95904
  }
95130
- const effectiveRows = [...args.values];
95131
- const graphRowsById = new Map(graphRows.map((row) => [row.id, row]));
95132
- for (const row of graphRows) {
95133
- if (args.valuesById.has(row.id)) continue;
95134
- 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);
95135
95910
  }
95136
- const collectionRow = graphRowsById.get(args.collectionValueId) ?? storedRow;
95911
+ const collectionRow = graph.byId.get(args.collectionValueId) ?? storedRow;
95137
95912
  if (collectionRow === void 0) return [];
95138
95913
  return listEntryIdsForValue(args.collection, collectionRow, effectiveRows);
95139
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
+ }
95140
95925
  function validateWorldContentSidecars(args) {
95926
+ const context = worldValidationContext(args);
95141
95927
  assertWorldLayerLinkValueBodiesCanonical({
95142
95928
  classes: args.classes,
95143
- values: args.values
95929
+ values: args.values,
95930
+ worldKindsByClassId: context.worldKindsByClassId
95144
95931
  });
95145
- const variants = args.variants;
95146
95932
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95147
95933
  const classesById = new Map(
95148
95934
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
@@ -95153,7 +95939,7 @@ function validateWorldContentSidecars(args) {
95153
95939
  const validatedPlacementIds = /* @__PURE__ */ new Set();
95154
95940
  const reachablePlacementIds = /* @__PURE__ */ new Set();
95155
95941
  for (const gridValue of args.values) {
95156
- if (worldKindForValue(gridValue, args.classes) !== NeoWorldSystemClassKind.TileGrid) {
95942
+ if (worldKindForValue(gridValue, context.worldKindsByClassId) !== NeoWorldSystemClassKind.TileGrid) {
95157
95943
  continue;
95158
95944
  }
95159
95945
  const gridClassId = requiredValueClassId(gridValue, "tile-grid");
@@ -95166,27 +95952,23 @@ function validateWorldContentSidecars(args) {
95166
95952
  );
95167
95953
  if (childrenList === null) continue;
95168
95954
  const registeredTileLayers = effectiveTargetIds({
95169
- classes: args.classes,
95955
+ context,
95170
95956
  relationKind: InternalRecordRelationKind.WorldGridTileLayer,
95171
- relations: args.relations,
95172
95957
  sourceClassId: gridClassId
95173
95958
  });
95174
95959
  const registeredObjectLayers = effectiveTargetIds({
95175
- classes: args.classes,
95960
+ context,
95176
95961
  relationKind: InternalRecordRelationKind.WorldGridObjectLayer,
95177
- relations: args.relations,
95178
95962
  sourceClassId: gridClassId
95179
95963
  });
95180
95964
  const importedTiles = effectiveTargetIds({
95181
- classes: args.classes,
95965
+ context,
95182
95966
  relationKind: InternalRecordRelationKind.WorldGridTileImport,
95183
- relations: args.relations,
95184
95967
  sourceClassId: gridClassId
95185
95968
  });
95186
95969
  const importedObjects = effectiveTargetIds({
95187
- classes: args.classes,
95970
+ context,
95188
95971
  relationKind: InternalRecordRelationKind.WorldGridObjectImport,
95189
- relations: args.relations,
95190
95972
  sourceClassId: gridClassId
95191
95973
  });
95192
95974
  const overrideOwnerByLayerKey = /* @__PURE__ */ new Map();
@@ -95197,7 +95979,10 @@ function validateWorldContentSidecars(args) {
95197
95979
  `Grid value "${gridValue.id}" Children references missing value "${linkId}".`
95198
95980
  );
95199
95981
  }
95200
- const linkKind = worldKindForValue(linkValue, args.classes);
95982
+ const linkKind = worldKindForValue(
95983
+ linkValue,
95984
+ context.worldKindsByClassId
95985
+ );
95201
95986
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95202
95987
  continue;
95203
95988
  }
@@ -95215,12 +96000,12 @@ function validateWorldContentSidecars(args) {
95215
96000
  reachablePlacementIds.add(placementId);
95216
96001
  }
95217
96002
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95218
- const layerClassId = resolveWorldLayerLinkTarget({
96003
+ const layerClassId = cachedWorldLayerTarget(context, {
95219
96004
  classes: args.classes,
95220
96005
  linkLabel: `Layer link value "${linkValue.id}"`,
95221
96006
  relations: args.relations,
95222
96007
  sourceClassId: linkClassId
95223
- }).targetClassId;
96008
+ });
95224
96009
  const existingOwner = ownedLinkIds.get(linkValue.id);
95225
96010
  if (existingOwner !== void 0 && existingOwner !== gridValue.id) {
95226
96011
  throw new Error(
@@ -95232,7 +96017,7 @@ function validateWorldContentSidecars(args) {
95232
96017
  const expectedLayerKind = isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer;
95233
96018
  assertConcreteWorldClass({
95234
96019
  classId: layerClassId,
95235
- classes: args.classes,
96020
+ worldKindsByClassId: context.worldKindsByClassId,
95236
96021
  classesById,
95237
96022
  expectedKind: expectedLayerKind,
95238
96023
  label: `Layer link value "${linkValue.id}" target`
@@ -95272,15 +96057,13 @@ function validateWorldContentSidecars(args) {
95272
96057
  );
95273
96058
  }
95274
96059
  validateWorldPlacementSidecars({
95275
- classes: args.classes,
96060
+ context,
95276
96061
  classesById,
95277
96062
  importedClassIds: isTile ? importedTiles : importedObjects,
95278
96063
  isTile,
95279
96064
  layerClassId,
95280
- variants,
95281
96065
  linkValueId: linkValue.id,
95282
96066
  placement,
95283
- relations: args.relations,
95284
96067
  valuesById
95285
96068
  });
95286
96069
  validatedPlacementIds.add(placement.id);
@@ -95289,7 +96072,7 @@ function validateWorldContentSidecars(args) {
95289
96072
  }
95290
96073
  for (const linkValue of args.values) {
95291
96074
  if (gridOwnedLinkIds.has(linkValue.id)) continue;
95292
- const linkKind = worldKindForValue(linkValue, args.classes);
96075
+ const linkKind = worldKindForValue(linkValue, context.worldKindsByClassId);
95293
96076
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95294
96077
  continue;
95295
96078
  }
@@ -95297,15 +96080,15 @@ function validateWorldContentSidecars(args) {
95297
96080
  if (linkRecord === null) continue;
95298
96081
  const isTile = linkKind === NeoWorldSystemClassKind.TileLayerLink;
95299
96082
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95300
- const layerClassId = resolveWorldLayerLinkTarget({
96083
+ const layerClassId = cachedWorldLayerTarget(context, {
95301
96084
  classes: args.classes,
95302
96085
  linkLabel: `Object-composition layer link value "${linkValue.id}"`,
95303
96086
  relations: args.relations,
95304
96087
  sourceClassId: linkClassId
95305
- }).targetClassId;
96088
+ });
95306
96089
  assertConcreteWorldClass({
95307
96090
  classId: layerClassId,
95308
- classes: args.classes,
96091
+ worldKindsByClassId: context.worldKindsByClassId,
95309
96092
  classesById,
95310
96093
  expectedKind: isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer,
95311
96094
  label: `Object-composition layer link value "${linkValue.id}" target`
@@ -95336,15 +96119,13 @@ function validateWorldContentSidecars(args) {
95336
96119
  );
95337
96120
  }
95338
96121
  validateWorldPlacementSidecars({
95339
- classes: args.classes,
96122
+ context,
95340
96123
  classesById,
95341
96124
  importedClassIds: null,
95342
96125
  isTile,
95343
96126
  layerClassId,
95344
- variants,
95345
96127
  linkValueId: linkValue.id,
95346
96128
  placement,
95347
- relations: args.relations,
95348
96129
  valuesById
95349
96130
  });
95350
96131
  reachablePlacementIds.add(placement.id);
@@ -95365,8 +96146,10 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95365
96146
  const classesById = new Map(
95366
96147
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95367
96148
  );
96149
+ const worldKinds = args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById);
96150
+ const storedKeysByClassId = /* @__PURE__ */ new Map();
95368
96151
  for (const value of args.values) {
95369
- const worldKind = worldKindForValue(value, args.classes);
96152
+ const worldKind = worldKindForValue(value, worldKinds);
95370
96153
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95371
96154
  continue;
95372
96155
  }
@@ -95376,6 +96159,7 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95376
96159
  assertWorldLayerLinkBodyCanonical({
95377
96160
  body,
95378
96161
  classesById,
96162
+ storedKeysByClassId,
95379
96163
  classId,
95380
96164
  worldKind,
95381
96165
  label: `Layer link value "${value.id}"`
@@ -95383,18 +96167,23 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95383
96167
  }
95384
96168
  }
95385
96169
  function assertWorldLayerLinkBodyCanonical(args) {
95386
- const storedKeys = /* @__PURE__ */ new Set([
95387
- "layerOverrideValueId",
95388
- args.worldKind === NeoWorldSystemClassKind.TileLayerLink ? "Tiles" : "Objects"
95389
- ]);
95390
- const visited = /* @__PURE__ */ new Set();
95391
- let classId = args.classId;
95392
- while (classId !== null && !visited.has(classId)) {
95393
- visited.add(classId);
95394
- const schemaClass2 = args.classesById.get(classId);
95395
- if (schemaClass2 === void 0) break;
95396
- for (const key of Object.keys(schemaClass2.schema)) storedKeys.add(key);
95397
- 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);
95398
96187
  }
95399
96188
  for (const key of Object.keys(args.body)) {
95400
96189
  if (storedKeys.has(key)) continue;
@@ -95418,7 +96207,7 @@ function validateWorldPlacementSidecars(args) {
95418
96207
  }
95419
96208
  assertConcreteWorldClass({
95420
96209
  classId: assetClassId,
95421
- classes: args.classes,
96210
+ worldKindsByClassId: args.context.worldKindsByClassId,
95422
96211
  classesById: args.classesById,
95423
96212
  expectedKind: args.isTile ? NeoWorldSystemClassKind.Tile : NeoWorldSystemClassKind.Object,
95424
96213
  label: `Placement value "${args.placement.id}" assetClassId`
@@ -95429,9 +96218,8 @@ function validateWorldPlacementSidecars(args) {
95429
96218
  );
95430
96219
  }
95431
96220
  const compatibleLayerIds = effectiveTargetIds({
95432
- classes: args.classes,
96221
+ context: args.context,
95433
96222
  relationKind: args.isTile ? InternalRecordRelationKind.WorldTileCompatibleLayer : InternalRecordRelationKind.WorldObjectCompatibleLayer,
95434
- relations: args.relations,
95435
96223
  sourceClassId: assetClassId
95436
96224
  });
95437
96225
  if (!compatibleLayerIds.has(args.layerClassId)) {
@@ -95452,7 +96240,7 @@ function validateWorldPlacementSidecars(args) {
95452
96240
  placementId: args.placement.id,
95453
96241
  variantId: optionalNonEmptyString(record4.variantId),
95454
96242
  rowValueId: optionalNonEmptyString(record4.rowValueId),
95455
- variants: args.variants
96243
+ context: args.context
95456
96244
  });
95457
96245
  }
95458
96246
  function validatePlacementVariantBinding(args) {
@@ -95464,9 +96252,7 @@ function validatePlacementVariantBinding(args) {
95464
96252
  }
95465
96253
  return;
95466
96254
  }
95467
- const variant2 = args.variants.find(
95468
- (candidate) => candidate.id === args.variantId
95469
- );
96255
+ const variant2 = args.context.variantsById.get(args.variantId);
95470
96256
  if (variant2 === void 0) {
95471
96257
  throw new Error(
95472
96258
  `Placement value "${args.placementId}" references variant "${args.variantId}", which does not resolve to a live variant record.`
@@ -95486,7 +96272,12 @@ function validatePlacementVariantBinding(args) {
95486
96272
  }
95487
96273
  return;
95488
96274
  }
95489
- 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)) {
95490
96281
  throw new Error(
95491
96282
  `Placement value "${args.placementId}" must bind a live row from lookup variant "${args.variantId}".`
95492
96283
  );
@@ -95523,7 +96314,7 @@ function assertConcreteWorldClass(args) {
95523
96314
  `${args.label} references missing class "${args.classId}".`
95524
96315
  );
95525
96316
  }
95526
- const actualKind = resolveWorldSystemClassKind(args.classId, args.classes);
96317
+ const actualKind = args.worldKindsByClassId.get(args.classId) ?? null;
95527
96318
  if (actualKind !== args.expectedKind) {
95528
96319
  throw new Error(
95529
96320
  `${args.label} must reference world class kind "${args.expectedKind}", received "${String(actualKind)}".`
@@ -95534,14 +96325,18 @@ function assertConcreteWorldClass(args) {
95534
96325
  }
95535
96326
  }
95536
96327
  function effectiveTargetIds(args) {
95537
- return new Set(
95538
- resolveEffectiveClassRelations(args).map(
95539
- (relation) => relation.targetRecordId
95540
- )
95541
- );
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;
95542
96337
  }
95543
- function worldKindForValue(value, classes) {
95544
- 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;
95545
96340
  }
95546
96341
  function requiredValueClassId(value, label) {
95547
96342
  if (typeof value.classId === "string" && value.classId.length > 0) {
@@ -95589,13 +96384,11 @@ function optionalNonEmptyString(value) {
95589
96384
  return typeof value === "string" && value.length > 0 ? value : null;
95590
96385
  }
95591
96386
  function consumeWorldPlacementSidecarKeys(args) {
95592
- 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;
95593
96388
  if (worldKind === null) return /* @__PURE__ */ new Set();
95594
96389
  const assetKind = WORLD_PLACEMENT_ASSET_KIND.get(worldKind);
95595
96390
  if (assetKind === void 0) return /* @__PURE__ */ new Set();
95596
- const classesById = new Map(
95597
- args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95598
- );
96391
+ const classesById = args.classesById ?? new Map(args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2]));
95599
96392
  const present = /* @__PURE__ */ new Set();
95600
96393
  for (const key of WORLD_PLACEMENT_SIDECAR_KEYS) {
95601
96394
  if (!Object.hasOwn(args.body, key)) continue;
@@ -95610,7 +96403,7 @@ function consumeWorldPlacementSidecarKeys(args) {
95610
96403
  if (assetClassId !== null) {
95611
96404
  assertConcreteWorldClass({
95612
96405
  classId: assetClassId,
95613
- classes: args.classes,
96406
+ worldKindsByClassId: args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById),
95614
96407
  classesById,
95615
96408
  expectedKind: assetKind,
95616
96409
  label: `${args.label} assetClassId`
@@ -101090,129 +101883,6 @@ var init_general_function_call_ir_source_recompile = __esm({
101090
101883
  }
101091
101884
  });
101092
101885
 
101093
- // ../src/database/project-record-semantics.ts
101094
- function projectRecordSemanticData(value) {
101095
- if (!isPlainRecord(value)) return value;
101096
- const semantic = {};
101097
- for (const [key, child] of Object.entries(value)) {
101098
- if (SERVER_MANAGED_PROJECT_RECORD_FIELDS.has(key)) continue;
101099
- semantic[key] = child;
101100
- }
101101
- return semantic;
101102
- }
101103
- function projectRecordDataIsSemanticallyEqual(left, right) {
101104
- return canonicalJsonStringify2(projectRecordSemanticData(left)) === canonicalJsonStringify2(projectRecordSemanticData(right));
101105
- }
101106
- function canonicalJsonStringify2(value) {
101107
- return JSON.stringify(toCanonicalJsonValue2(value));
101108
- }
101109
- function toCanonicalJsonValue2(value) {
101110
- if (value === null) return null;
101111
- if (value === void 0) return void 0;
101112
- if (value instanceof Date) return value.toISOString();
101113
- if (typeof value === "string" || typeof value === "boolean") return value;
101114
- if (typeof value === "number") {
101115
- if (!Number.isFinite(value)) {
101116
- throw new Error("Cannot canonicalize a non-finite number.");
101117
- }
101118
- return value;
101119
- }
101120
- if (typeof value === "bigint") {
101121
- throw new Error("Cannot canonicalize bigint values.");
101122
- }
101123
- if (typeof value === "symbol") {
101124
- throw new Error("Cannot canonicalize symbol values.");
101125
- }
101126
- if (typeof value === "function") {
101127
- throw new Error("Cannot canonicalize function values.");
101128
- }
101129
- if (Array.isArray(value)) {
101130
- return value.map((item) => toCanonicalJsonValue2(item) ?? null);
101131
- }
101132
- if (!isPlainRecord(value)) {
101133
- throw new Error("Cannot canonicalize a non-plain object.");
101134
- }
101135
- const canonical = {};
101136
- const entries = Object.entries(value).sort(
101137
- ([left], [right]) => left.localeCompare(right)
101138
- );
101139
- for (const [key, child] of entries) {
101140
- const canonicalChild = toCanonicalJsonValue2(child);
101141
- if (canonicalChild === void 0) continue;
101142
- canonical[key] = canonicalChild;
101143
- }
101144
- return canonical;
101145
- }
101146
- function isPlainRecord(value) {
101147
- if (value === null || typeof value !== "object") return false;
101148
- const prototype = Object.getPrototypeOf(value);
101149
- return prototype === Object.prototype || prototype === null;
101150
- }
101151
- var SERVER_MANAGED_PROJECT_RECORD_FIELDS;
101152
- var init_project_record_semantics = __esm({
101153
- "../src/database/project-record-semantics.ts"() {
101154
- "use strict";
101155
- SERVER_MANAGED_PROJECT_RECORD_FIELDS = /* @__PURE__ */ new Set([
101156
- "_id",
101157
- "projectId",
101158
- "createdAt",
101159
- "updatedAt"
101160
- ]);
101161
- }
101162
- });
101163
-
101164
- // ../src/database/project-version-relation-sweep-trigger.ts
101165
- function stagedChangesAffectClassRelations(current, changes) {
101166
- const classesById = new Map(
101167
- (current.classes ?? []).map((schemaClass2) => [schemaClass2.id, schemaClass2])
101168
- );
101169
- const valuesById = new Map(
101170
- (current.values ?? []).map((value) => [value.id, value])
101171
- );
101172
- for (const change of changes) {
101173
- if (change.recordKind === "internal-record-relation") return true;
101174
- if (change.recordKind === "class") {
101175
- if (change.operation !== "update") return true;
101176
- if (change.deleted === true) return true;
101177
- const before2 = classesById.get(change.recordId);
101178
- if (before2 === void 0) return true;
101179
- const after = change.nextData;
101180
- if (!isPlainRecord2(after)) return true;
101181
- if (before2.extendsClassId !== after.extendsClassId) return true;
101182
- continue;
101183
- }
101184
- if (change.recordKind !== "value") continue;
101185
- const before = valuesById.get(change.recordId);
101186
- if (valueCreateCannotAffectClassRelations(change, before)) continue;
101187
- if (relationEndpointClassId(before) !== relationEndpointClassId(change.nextData)) {
101188
- return true;
101189
- }
101190
- }
101191
- return false;
101192
- }
101193
- function valueCreateCannotAffectClassRelations(change, before) {
101194
- if (change.operation !== "create") return false;
101195
- if (change.deleted === true) return false;
101196
- return before === void 0;
101197
- }
101198
- function relationEndpointClassId(record4) {
101199
- if (!isPlainRecord2(record4)) return void 0;
101200
- if (typeof record4.classId === "string") return record4.classId;
101201
- return void 0;
101202
- }
101203
- function isPlainRecord2(value) {
101204
- if (value === null || typeof value !== "object") return false;
101205
- return !Array.isArray(value);
101206
- }
101207
- var init_project_version_relation_sweep_trigger = __esm({
101208
- "../src/database/project-version-relation-sweep-trigger.ts"() {
101209
- "use strict";
101210
- init_internal_record_relations();
101211
- init_project_version_types();
101212
- init_project_record_semantics();
101213
- }
101214
- });
101215
-
101216
101886
  // ../src/database/lookup-target-class-contract.ts
101217
101887
  function lookupTargetClassContractViolation(args) {
101218
101888
  const actualClassId = typeof args.targetClassId === "string" ? args.targetClassId : null;
@@ -101804,6 +102474,7 @@ var StaticBindingGraphValidator;
101804
102474
  var init_project_version_static_value_writes = __esm({
101805
102475
  "../src/database/project-version-static-value-writes.ts"() {
101806
102476
  "use strict";
102477
+ init_classes();
101807
102478
  init_members();
101808
102479
  init_inheritance();
101809
102480
  init_generics();
@@ -101847,6 +102518,10 @@ var init_project_version_static_value_writes = __esm({
101847
102518
  enums: document.enums,
101848
102519
  constructors: document.constructors
101849
102520
  });
102521
+ this.worldKindsByClassId = indexWorldSystemClassKinds(
102522
+ this.schemaIndex.classes,
102523
+ this.schemaIndex.classesById
102524
+ );
101850
102525
  this.virtualValueIds = new Set(virtualValueIds);
101851
102526
  this.mergedView = merged ?? null;
101852
102527
  }
@@ -101859,6 +102534,7 @@ var init_project_version_static_value_writes = __esm({
101859
102534
  localizedTextIds = /* @__PURE__ */ new Set();
101860
102535
  dialogueIds = /* @__PURE__ */ new Set();
101861
102536
  schemaIndex;
102537
+ worldKindsByClassId;
101862
102538
  virtualValueIds;
101863
102539
  declarationMaterializedIndex = null;
101864
102540
  stack = /* @__PURE__ */ new Set();
@@ -102069,6 +102745,8 @@ var init_project_version_static_value_writes = __esm({
102069
102745
  sidecarKeys: ({ body, classId, path }) => consumeWorldPlacementSidecarKeys({
102070
102746
  body,
102071
102747
  classes: this.schemaIndex.classes,
102748
+ classesById: this.schemaIndex.classesById,
102749
+ worldKindsByClassId: this.worldKindsByClassId,
102072
102750
  classId,
102073
102751
  label: path
102074
102752
  }),
@@ -102580,6 +103258,13 @@ function collectOwnedValueDeletionIds(args) {
102580
103258
  function createOwnedValueDeletionCollector(input, knownPlacements) {
102581
103259
  const scope = withVariantPlacementRoots(input);
102582
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
+ );
102583
103268
  const stored = new Map(document.values.map((row) => [row.id, row]));
102584
103269
  const members = new Map(
102585
103270
  document.members.map((member) => [member.id, member])
@@ -102828,16 +103513,15 @@ function createOwnedValueDeletionCollector(input, knownPlacements) {
102828
103513
  const sidecars = consumeWorldPlacementSidecarKeys({
102829
103514
  body: record4,
102830
103515
  classes: document.classes,
103516
+ classesById,
103517
+ worldKindsByClassId,
102831
103518
  classId,
102832
103519
  label: `Value "${body.id}"`
102833
103520
  });
102834
103521
  for (const key of ["assetValueId", "layerOverrideValueId"]) {
102835
103522
  if (key === "assetValueId" && !sidecars.has(key)) continue;
102836
103523
  if (key === "layerOverrideValueId") {
102837
- const worldKind = resolveWorldSystemClassKind(
102838
- classId,
102839
- document.classes
102840
- );
103524
+ const worldKind = worldKindsByClassId.get(classId);
102841
103525
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink)
102842
103526
  continue;
102843
103527
  }
@@ -104722,6 +105406,7 @@ function drainConstructedGraphValidations(args) {
104722
105406
  }
104723
105407
  }
104724
105408
  function indexAuthoredSeedDocument(document) {
105409
+ const classesById = indexRecordsById(document.classes);
104725
105410
  const declaringClassIdsByMemberId = /* @__PURE__ */ new Map();
104726
105411
  for (const schemaClass2 of document.classes) {
104727
105412
  const declared = /* @__PURE__ */ new Set();
@@ -104738,6 +105423,11 @@ function indexAuthoredSeedDocument(document) {
104738
105423
  }
104739
105424
  }
104740
105425
  return {
105426
+ classesById,
105427
+ worldKindsByClassId: indexWorldSystemClassKinds(
105428
+ document.classes,
105429
+ classesById
105430
+ ),
104741
105431
  valuesById: indexRecordsById(document.values),
104742
105432
  membersById: indexRecordsById(document.members),
104743
105433
  localizedTextIds: new Set(
@@ -105839,6 +106529,8 @@ function materializeAuthoredClassFields(args) {
105839
106529
  const sidecarKeys = consumeWorldPlacementSidecarKeys({
105840
106530
  body: args.row.value,
105841
106531
  classes: args.document.classes,
106532
+ classesById: args.documentIndex.classesById,
106533
+ worldKindsByClassId: args.documentIndex.worldKindsByClassId,
105842
106534
  classId: effectiveClassId,
105843
106535
  label: `Placement value "${args.row.id}"`
105844
106536
  });
@@ -107092,6 +107784,7 @@ var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_
107092
107784
  var init_project_version_schema_commit = __esm({
107093
107785
  "../src/database/project-version-schema-commit.ts"() {
107094
107786
  "use strict";
107787
+ init_classes();
107095
107788
  init_members();
107096
107789
  init_neo_script_derived_bodies();
107097
107790
  init_localized_instance_override_writes();
@@ -107263,7 +107956,7 @@ function systemProtectedWriteInheritedRecordId(write) {
107263
107956
  if (write.baseData !== void 0) return null;
107264
107957
  if (write.deleted) return null;
107265
107958
  if (!isSystemBearingRecordKind(write.recordKind)) return null;
107266
- if (!isPlainRecord3(write.nextData)) return null;
107959
+ if (!isPlainRecord4(write.nextData)) return null;
107267
107960
  if (readSystemMetadata(write.nextData) === null) return null;
107268
107961
  const extendsMemberId = write.nextData.extendsMemberId;
107269
107962
  if (typeof extendsMemberId !== "string") return null;
@@ -107283,7 +107976,7 @@ function assertSystemProtectedRecordWriteValid(write) {
107283
107976
  assertSystemMetadataUnchanged(write, base);
107284
107977
  }
107285
107978
  function readBaseRecord(write) {
107286
- if (!isPlainRecord3(write.baseData)) return null;
107979
+ if (!isPlainRecord4(write.baseData)) return null;
107287
107980
  return {
107288
107981
  recordKind: write.recordKind,
107289
107982
  data: write.baseData,
@@ -107296,7 +107989,7 @@ function collectSystemBearingBaseRecords(document) {
107296
107989
  const stored = document[collection];
107297
107990
  if (!Array.isArray(stored)) continue;
107298
107991
  for (const record4 of stored) {
107299
- if (!isPlainRecord3(record4)) continue;
107992
+ if (!isPlainRecord4(record4)) continue;
107300
107993
  const id2 = record4.id;
107301
107994
  if (typeof id2 !== "string") continue;
107302
107995
  records2.set(baseKey(recordKind, id2), {
@@ -107310,7 +108003,7 @@ function collectSystemBearingBaseRecords(document) {
107310
108003
  }
107311
108004
  function assertCreateDeclaresNoSystemMetadata(write) {
107312
108005
  if (!isSystemBearingRecordKind(write.recordKind)) return;
107313
- if (!isPlainRecord3(write.nextData)) return;
108006
+ if (!isPlainRecord4(write.nextData)) return;
107314
108007
  const system = readSystemMetadata(write.nextData);
107315
108008
  if (system === null) return;
107316
108009
  if (inheritsLegacyEmittedSystemMetadata(write, system)) return;
@@ -107336,7 +108029,7 @@ function assertProtectedRecordNotEdited(change, base) {
107336
108029
  )) {
107337
108030
  return;
107338
108031
  }
107339
- if (!isPlainRecord3(change.nextData)) return;
108032
+ if (!isPlainRecord4(change.nextData)) return;
107340
108033
  if (authoredFieldsEqual(change.recordKind, base.data, change.nextData)) {
107341
108034
  return;
107342
108035
  }
@@ -107345,7 +108038,7 @@ function assertProtectedRecordNotEdited(change, base) {
107345
108038
  );
107346
108039
  }
107347
108040
  function assertSystemMetadataUnchanged(change, base) {
107348
- if (!isPlainRecord3(change.nextData)) return;
108041
+ if (!isPlainRecord4(change.nextData)) return;
107349
108042
  const next = readSystemMetadata(change.nextData);
107350
108043
  if (systemMetadataEqual(base.system, next)) return;
107351
108044
  throw new Error(
@@ -107396,10 +108089,10 @@ function repointedChildValueIds(document, change) {
107396
108089
  );
107397
108090
  if (baseValue === void 0) return [];
107398
108091
  const before = baseValue.value;
107399
- if (!isPlainRecord3(before)) return [];
107400
- if (!isPlainRecord3(change.nextData)) return [];
108092
+ if (!isPlainRecord4(before)) return [];
108093
+ if (!isPlainRecord4(change.nextData)) return [];
107401
108094
  const after = change.nextData.value;
107402
- if (!isPlainRecord3(after)) return [];
108095
+ if (!isPlainRecord4(after)) return [];
107403
108096
  return Object.entries(before).flatMap(([schemaKey, childValueId]) => {
107404
108097
  if (typeof childValueId !== "string") return [];
107405
108098
  if (after[schemaKey] === childValueId) return [];
@@ -107434,7 +108127,7 @@ function isSystemBearingRecordKind(recordKind) {
107434
108127
  );
107435
108128
  }
107436
108129
  function readSystemMetadata(record4) {
107437
- if (!isPlainRecord3(record4)) return null;
108130
+ if (!isPlainRecord4(record4)) return null;
107438
108131
  const system = record4.system;
107439
108132
  if (!isSystemMetadata(system)) return null;
107440
108133
  return system;
@@ -107453,11 +108146,11 @@ function systemReason(system) {
107453
108146
  return SYSTEM_PROTECTION_RULES[system.kind].serverReason;
107454
108147
  }
107455
108148
  function describeChangedRecord(recordKind, recordId, record4) {
107456
- const name = isPlainRecord3(record4) ? record4.name : void 0;
108149
+ const name = isPlainRecord4(record4) ? record4.name : void 0;
107457
108150
  if (typeof name !== "string") return `Record ${recordKind} "${recordId}"`;
107458
108151
  return `Record ${recordKind} "${name}" (${recordId})`;
107459
108152
  }
107460
- function isPlainRecord3(value) {
108153
+ function isPlainRecord4(value) {
107461
108154
  return typeof value === "object" && value !== null && !Array.isArray(value);
107462
108155
  }
107463
108156
  function baseKey(recordKind, recordId) {
@@ -107588,7 +108281,7 @@ function readWorldReferenceList(args) {
107588
108281
  args.keyCandidates
107589
108282
  );
107590
108283
  if (schemaKey === null) return [];
107591
- if (!isPlainRecord4(args.ownerValue.value)) return [];
108284
+ if (!isPlainRecord5(args.ownerValue.value)) return [];
107592
108285
  const listValueId = args.ownerValue.value[schemaKey];
107593
108286
  if (typeof listValueId !== "string") return [];
107594
108287
  const listValue2 = args.graph.valuesById.get(listValueId);
@@ -107654,18 +108347,18 @@ function worldReferenceClassInherits(graph, classId, ancestorClassId) {
107654
108347
  return false;
107655
108348
  }
107656
108349
  function toWorldReferenceClassRecord(value) {
107657
- if (!isPlainRecord4(value)) return null;
108350
+ if (!isPlainRecord5(value)) return null;
107658
108351
  const id2 = stringField2(value, "id");
107659
108352
  if (id2 === null) return null;
107660
108353
  return {
107661
108354
  id: id2,
107662
108355
  extendsClassId: nullableStringField(value, "extendsClassId"),
107663
108356
  schema: isStringRecord8(value.schema) ? value.schema : void 0,
107664
- system: isPlainRecord4(value.system) ? value.system : null
108357
+ system: isPlainRecord5(value.system) ? value.system : null
107665
108358
  };
107666
108359
  }
107667
108360
  function toWorldReferenceValueRecord(value) {
107668
- if (!isPlainRecord4(value)) return null;
108361
+ if (!isPlainRecord5(value)) return null;
107669
108362
  const id2 = stringField2(value, "id");
107670
108363
  if (id2 === null) return null;
107671
108364
  return {
@@ -107679,10 +108372,10 @@ function worldReferenceValueClassId(value) {
107679
108372
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
107680
108373
  }
107681
108374
  function isStringRecord8(value) {
107682
- if (!isPlainRecord4(value)) return false;
108375
+ if (!isPlainRecord5(value)) return false;
107683
108376
  return Object.values(value).every((entry) => typeof entry === "string");
107684
108377
  }
107685
- function isPlainRecord4(value) {
108378
+ function isPlainRecord5(value) {
107686
108379
  return typeof value === "object" && value !== null && !Array.isArray(value);
107687
108380
  }
107688
108381
  function stringField2(value, key) {
@@ -107888,6 +108581,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107888
108581
  const valuesById = new Map(
107889
108582
  document.values.map((value) => [value.id, value])
107890
108583
  );
108584
+ const materializationBatch = createInitializerMaterializationBatch(document);
107891
108585
  let members = document.members;
107892
108586
  const deferred = /* @__PURE__ */ new Set();
107893
108587
  if (defaultInitializerMemberIds.size > 0) {
@@ -107903,7 +108597,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107903
108597
  return deferredMember;
107904
108598
  }
107905
108599
  const materialized = materializeInitializerValue2({
107906
- document: { ...document, values: [...valuesById.values()] },
108600
+ document: materializationBatch.document(),
107907
108601
  member,
107908
108602
  row: {
107909
108603
  id: `animation-validation-default:${member.id}`,
@@ -107913,6 +108607,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107913
108607
  updatedAt: 0
107914
108608
  }
107915
108609
  });
108610
+ materializationBatch.upsert(materialized.createdValues);
107916
108611
  for (const created of materialized.createdValues) {
107917
108612
  valuesById.set(created.id, created);
107918
108613
  }
@@ -107937,10 +108632,14 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107937
108632
  continue;
107938
108633
  }
107939
108634
  const materialized = materializeInitializerValue2({
107940
- document: { ...document, values: [...valuesById.values()] },
108635
+ document: materializationBatch.document(),
107941
108636
  member,
107942
108637
  row
107943
108638
  });
108639
+ materializationBatch.upsert([
108640
+ materialized.root,
108641
+ ...materialized.createdValues
108642
+ ]);
107944
108643
  valuesById.set(materialized.root.id, materialized.root);
107945
108644
  for (const created of materialized.createdValues) {
107946
108645
  valuesById.set(created.id, created);
@@ -108089,54 +108788,6 @@ function assertStagedWorldContentLayerBindingsValid(current, projected, changes)
108089
108788
  })
108090
108789
  });
108091
108790
  }
108092
- function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
108093
- const classesById = new Map(
108094
- current.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
108095
- );
108096
- const valuesById = new Map(current.values.map((value) => [value.id, value]));
108097
- const valueChanges = [];
108098
- for (const change of changes) {
108099
- if (change.recordKind === "internal-record-relation") return true;
108100
- if (change.recordKind === "value") {
108101
- valueChanges.push(change);
108102
- continue;
108103
- }
108104
- if (change.recordKind !== "class") continue;
108105
- if (change.operation !== "update") return true;
108106
- if (change.deleted === true) return true;
108107
- const before = classesById.get(change.recordId);
108108
- if (before === void 0) return true;
108109
- const after = change.nextData;
108110
- if (!isPlainRecord2(after)) return true;
108111
- if (before.extendsClassId !== after.extendsClassId) return true;
108112
- if (isAbstractClass(before) !== isAbstractClass(after)) return true;
108113
- if (!worldClassSystemBlockIsEqual(before.system, after.system)) return true;
108114
- }
108115
- if (valueChanges.length === 0) return false;
108116
- const graph = createWorldReferenceGraph({
108117
- classes: current.classes,
108118
- values: []
108119
- });
108120
- for (const change of valueChanges) {
108121
- const before = valuesById.get(change.recordId);
108122
- if (hasWorldLayerOverrideMetadata(before) || hasWorldLayerOverrideMetadata(change.nextData)) {
108123
- return true;
108124
- }
108125
- const classIds = [
108126
- relationEndpointClassId(before),
108127
- relationEndpointClassId(change.nextData)
108128
- ].filter((classId) => classId !== void 0);
108129
- for (const classId of classIds) {
108130
- const worldKind = resolveWorldKindFromClassMap(
108131
- classId,
108132
- graph.classesById
108133
- );
108134
- if (worldKind === NeoWorldSystemClassKind.TileLayerLink) return true;
108135
- if (worldKind === NeoWorldSystemClassKind.ObjectLayerLink) return true;
108136
- }
108137
- }
108138
- return false;
108139
- }
108140
108791
  function stagedAffectedWorldLayerLinkClassIds(args) {
108141
108792
  const baseRelationsById = new Map(
108142
108793
  (args.current.internalRecordRelations ?? []).map((relation) => [
@@ -108174,16 +108825,20 @@ function stagedAffectedWorldLayerLinkClassIds(args) {
108174
108825
  if (!changedClassIds.has(relation.targetRecordId)) continue;
108175
108826
  roots.add(relation.sourceRecordId);
108176
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
+ }
108177
108835
  const affected = new Set(roots);
108178
- let added = true;
108179
- while (added) {
108180
- added = false;
108181
- for (const schemaClass2 of args.classes) {
108182
- if (schemaClass2.extendsClassId === void 0) continue;
108183
- if (!affected.has(schemaClass2.extendsClassId)) continue;
108184
- if (affected.has(schemaClass2.id)) continue;
108185
- affected.add(schemaClass2.id);
108186
- 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);
108187
108842
  }
108188
108843
  }
108189
108844
  return affected;
@@ -108194,18 +108849,6 @@ function isStagedWorldLayerLinkTargetRelationKind(relationKind) {
108194
108849
  }
108195
108850
  return relationKind === InternalRecordRelationKind.WorldObjectLayerLinkTarget;
108196
108851
  }
108197
- function worldClassSystemBlockIsEqual(before, after) {
108198
- return projectRecordDataIsSemanticallyEqual(
108199
- { system: before },
108200
- { system: after }
108201
- );
108202
- }
108203
- function hasWorldLayerOverrideMetadata(record4) {
108204
- if (!isPlainRecord2(record4)) return false;
108205
- const value = record4.value;
108206
- if (!isPlainRecord2(value)) return false;
108207
- return typeof value.layerOverrideValueId === "string";
108208
- }
108209
108852
  function assertStagedProjectInterfaceValid(projected, changes) {
108210
108853
  const relevant = changes.filter(
108211
108854
  (change) => INTERFACE_VALIDATED_RECORD_KINDS.has(change.recordKind)
@@ -108501,10 +109144,11 @@ function assertStagedTileGridReferencesValid(current, projected, changes) {
108501
109144
  classes: current.classes,
108502
109145
  values: []
108503
109146
  });
109147
+ const currentValuesById = new Map(
109148
+ current.values.map((value) => [value.id, value])
109149
+ );
108504
109150
  if (deletedClassIds.size === 0 && [...deletedValueIds].every((valueId) => {
108505
- const value = current.values.find(
108506
- (candidate) => candidate.id === valueId
108507
- );
109151
+ const value = currentValuesById.get(valueId);
108508
109152
  if (value?.classId == null) return true;
108509
109153
  return resolveWorldKindFromClassMap(
108510
109154
  value.classId,
@@ -108552,10 +109196,27 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108552
109196
  const valuesById = new Map(
108553
109197
  projected.values.map((value) => [value.id, value])
108554
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();
108555
109216
  const graded = [];
108556
109217
  for (const member of variantMembers) {
108557
109218
  const declaration = substituteMemberForListenerGrading(member, projected);
108558
- const label = describeVariantMember(member, projected.classes);
109219
+ const label = labelsByMemberId.get(member.id);
108559
109220
  assertVariantMemberTargetValid({ declaration, label, classesById });
108560
109221
  const authored = authoredVariantValue(member);
108561
109222
  if (authored !== void 0) {
@@ -108579,12 +109240,12 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108579
109240
  if (row.value === null || row.value === void 0) continue;
108580
109241
  const ownerId = getMemberId(owner);
108581
109242
  if (ownerId === null) continue;
108582
- const member = projected.members.find((item) => item.id === ownerId);
109243
+ const member = membersById.get(ownerId);
108583
109244
  if (member === void 0) continue;
108584
109245
  graded.push({
108585
109246
  value: row.value,
108586
109247
  declaration: owner,
108587
- label: `${describeVariantMember(member, projected.classes)} row "${rowId}"`
109248
+ label: `${labelsByMemberId.get(member.id)} row "${rowId}"`
108588
109249
  });
108589
109250
  }
108590
109251
  }
@@ -108598,7 +109259,9 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108598
109259
  foldersById,
108599
109260
  membersById,
108600
109261
  valuesById,
108601
- values: projected.values
109262
+ values: projected.values,
109263
+ admittedClassesByTarget,
109264
+ lookupRowsByCollection
108602
109265
  });
108603
109266
  }
108604
109267
  }
@@ -108661,10 +109324,14 @@ function assertVariantReferenceValid(args) {
108661
109324
  );
108662
109325
  }
108663
109326
  if (target.type === 7 /* Class */ && value.classId !== target.classId) {
108664
- const admitted = descendantClassIds(
108665
- target.classId,
108666
- Array.from(classesById.values())
108667
- );
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
+ }
108668
109335
  if (!admitted.has(value.classId)) {
108669
109336
  const targetName = classesById.get(target.classId)?.name ?? target.classId;
108670
109337
  throw new Error(
@@ -108731,9 +109398,20 @@ function assertVariantReferenceValid(args) {
108731
109398
  }
108732
109399
  const collection = membersById.get(binding.collectionMemberId);
108733
109400
  const collectionValue = valuesById.get(binding.collectionValueId);
108734
- if (!isMemberListBase(collection) || collectionValue === void 0 || !valuesById.has(value.rowValueId) || !listEntryIdsForValue(collection, collectionValue, args.values).includes(
108735
- value.rowValueId
108736
- )) {
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()) {
108737
109415
  throw new Error(
108738
109416
  `${owner} binds row "${value.rowValueId}", which is not in lookup variant folder "${folder?.path ?? ""}".`
108739
109417
  );
@@ -108778,24 +109456,18 @@ function candidateVariantRowIds(projected, variantMembers) {
108778
109456
  }
108779
109457
  if (schemaKeys.size === 0) continue;
108780
109458
  if (!isPlainRecord2(row.value)) continue;
108781
- for (const schemaKey of schemaKeys) {
108782
- const childId = row.value[schemaKey];
108783
- 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);
108784
109462
  }
108785
109463
  }
108786
109464
  return candidates;
108787
109465
  }
108788
- function describeVariantMember(member, classes) {
108789
- const owner = classes.find(
108790
- (schemaClass2) => Object.values(schemaClass2.schema).includes(member.id)
108791
- );
108792
- if (owner === void 0) return `Variant member "${member.name}"`;
108793
- return `Variant member "${owner.name}.${member.name}"`;
108794
- }
108795
109466
  var KNOWN_TRANSACTION_OPERATIONS, INTERFACE_VALIDATED_RECORD_KINDS, ACTION_LISTENER_TRIGGER_RECORD_KINDS, ACTION_LISTENER_TARGET_KINDS, VARIANT_MEMBER_TRIGGER_RECORD_KINDS;
108796
109467
  var init_project_version_whole_graph_validation = __esm({
108797
109468
  "../src/database/project-version-whole-graph-validation.ts"() {
108798
109469
  "use strict";
109470
+ init_project_world_placement_bindings();
108799
109471
  init_project_version_types();
108800
109472
  init_internal_record_relations();
108801
109473
  init_world_content_sidecar_validation();
@@ -108814,12 +109486,11 @@ var init_project_version_whole_graph_validation = __esm({
108814
109486
  init_neoscript();
108815
109487
  init_constructor_argument_ownership();
108816
109488
  init_materialize_values();
109489
+ init_evaluateInitializer();
108817
109490
  init_world_system_classes();
108818
109491
  init_project_world_reference_graph();
108819
- init_project_record_semantics();
108820
109492
  init_project_version_relation_sweep_trigger();
108821
109493
  init_members();
108822
- init_classes();
108823
109494
  KNOWN_TRANSACTION_OPERATIONS = new Set(
108824
109495
  Object.values(ProjectVersionTransactionOperation)
108825
109496
  );
@@ -109156,6 +109827,12 @@ function computeWorkspaceStatus(workspace, options) {
109156
109827
  sourceSpan: source.span
109157
109828
  };
109158
109829
  });
109830
+ const recordsByKey = new Map(
109831
+ records2.map((record4) => [
109832
+ recordStateKey(record4.recordKind, record4.recordId),
109833
+ record4
109834
+ ])
109835
+ );
109159
109836
  if (projectAnalysisV4 === null) {
109160
109837
  throw new Error(
109161
109838
  "Format-4 project analysis was not produced before static value lowering."
@@ -109208,9 +109885,7 @@ function computeWorkspaceStatus(workspace, options) {
109208
109885
  if (document !== void 0 && isObjectRecord2(document.data)) {
109209
109886
  document.data.collectionValueId = resolvedId;
109210
109887
  }
109211
- const record4 = records2.find(
109212
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109213
- );
109888
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109214
109889
  if (record4 !== void 0 && typeof record4.fileFields.collectionValueId === "string") {
109215
109890
  record4.fileFields.collectionValueId = resolvedId;
109216
109891
  }
@@ -109245,8 +109920,8 @@ function computeWorkspaceStatus(workspace, options) {
109245
109920
  if (document !== void 0 && isObjectRecord2(document.data.binding)) {
109246
109921
  document.data.binding.collectionValueId = resolvedId;
109247
109922
  }
109248
- const record4 = records2.find(
109249
- (candidate) => candidate.recordKind === "variant-folder" && candidate.recordId === folderId
109923
+ const record4 = recordsByKey.get(
109924
+ recordStateKey("variant-folder", folderId)
109250
109925
  );
109251
109926
  if (record4 !== void 0 && isObjectRecord2(record4.fileFields.binding)) {
109252
109927
  record4.fileFields.binding.collectionValueId = resolvedId;
@@ -109295,9 +109970,7 @@ function computeWorkspaceStatus(workspace, options) {
109295
109970
  );
109296
109971
  }
109297
109972
  }
109298
- const record4 = records2.find(
109299
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109300
- );
109973
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109301
109974
  const authored = record4?.fileFields.defaultValue;
109302
109975
  if (isObjectRecord2(authored) && "value" in authored) {
109303
109976
  authored.value = substituteMemberDefaultKeyReferenceV4(
@@ -109413,14 +110086,15 @@ function computeWorkspaceStatus(workspace, options) {
109413
110086
  }
109414
110087
  }
109415
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
+ }
109416
110093
  for (const [key, recordState] of Object.entries(workspace.state.records)) {
109417
110094
  const recordFile = recordState.file ?? (orphanedStaticMemberKeys.has(key) ? STATIC_MEMBER_OWNERSHIP_RECOVERY_SOURCE : void 0);
109418
110095
  if (recordFile === void 0) continue;
109419
110096
  if (reconstructed3.has(key)) continue;
109420
- const fileStillBroken = parseErrors.some(
109421
- (error) => error.file === recordFile && isBlockingSchemaSourceError(error)
109422
- ) || conflictedFiles.includes(recordFile);
109423
- if (fileStillBroken) continue;
110097
+ if (brokenFiles.has(recordFile)) continue;
109424
110098
  if (recordState.conflictServerHash === null) continue;
109425
110099
  if (recordState.recordKind === "localized-text" && isLocalizedText(recordState.data) && recordState.data.memberSource !== void 0)
109426
110100
  continue;
@@ -109802,6 +110476,15 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109802
110476
  interfaces: replayDocument.interfaces,
109803
110477
  constructors: replayDocument.constructors ?? []
109804
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
+ );
109805
110488
  let documentBodiesCompiled = false;
109806
110489
  const fallbackValues = new Map(
109807
110490
  (fallbackDocument?.values ?? []).map((row) => [row.id, row])
@@ -109827,9 +110510,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109827
110510
  valuesById
109828
110511
  );
109829
110512
  const initializerOwnerClass = ownerContext.ownerClass;
109830
- const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : (replayDocument.constructors ?? []).find(
109831
- (constructor2) => constructor2.id === initializerOwnerClass.requiredConstructorId
109832
- );
110513
+ const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : constructorsById.get(initializerOwnerClass.requiredConstructorId);
109833
110514
  const requiredArgumentNames = new Set(
109834
110515
  requiredConstructor?.argumentTypes.map((argument2) => argument2.name) ?? []
109835
110516
  );
@@ -109842,6 +110523,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109842
110523
  replay = replayStoredConstructionV4({
109843
110524
  records: pulled,
109844
110525
  document: replayDocument,
110526
+ replayContext,
109845
110527
  valueId: row.id,
109846
110528
  code,
109847
110529
  member: owner,
@@ -110005,13 +110687,16 @@ function expandProspectiveAnimationInstances(document) {
110005
110687
  (row) => isLiteralValueContent(row) && isVirtualInstanceRootShape(row) && typeof row.classId === "string" && classBelongsToAnimationFamily(document.classesById, row.classId)
110006
110688
  );
110007
110689
  if (animationRoots.length === 0) return [...document.values];
110008
- const lookups = cliEvaluatorLookups({
110009
- project: document.project,
110010
- classes: document.classes,
110011
- constructors: document.constructors,
110012
- members: document.members,
110013
- values: document.values
110014
- });
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
+ );
110015
110700
  const byId = new Map(document.values.map((row) => [row.id, row]));
110016
110701
  for (const root of animationRoots) {
110017
110702
  for (const row of lookups.virtualInstanceRowsForValue(root.id)) {
@@ -111775,41 +112460,22 @@ function worldKindByClassId(document) {
111775
112460
  for (const classId of classes.keys()) resolve5(classId, /* @__PURE__ */ new Set());
111776
112461
  return result;
111777
112462
  }
111778
- function valueWorldKind(kinds, value) {
111779
- if (value === null || typeof value !== "object") return void 0;
111780
- const classId = Reflect.get(value, "classId");
111781
- return typeof classId === "string" ? kinds.get(classId) : void 0;
111782
- }
111783
- function hasWorldLayerOverride(value) {
111784
- if (value === null || typeof value !== "object") return false;
111785
- const body = Reflect.get(value, "value");
111786
- return body !== null && typeof body === "object" && typeof Reflect.get(body, "layerOverrideValueId") === "string";
111787
- }
111788
112463
  function commitPreparationWorldScopeKinds(args) {
111789
112464
  const allKinds = new Set(
111790
- args.postDocument.classes.flatMap(
112465
+ [...args.currentDocument.classes, ...args.postDocument.classes].flatMap(
111791
112466
  (schemaClass2) => typeof schemaClass2.system?.worldKind === "string" ? [schemaClass2.system.worldKind] : []
111792
112467
  )
111793
112468
  );
111794
- if (args.changes.some(
111795
- (change) => change.recordKind === "class" || change.recordKind === "internal-record-relation"
111796
- )) {
111797
- return allKinds;
111798
- }
111799
- const kindsByClass = worldKindByClassId(args.postDocument);
111800
- const current = projectDocumentRecordsByKey(args.currentDocument);
111801
- const requiresWholeWorld = args.changes.some((change) => {
111802
- if (change.recordKind !== "value") return false;
111803
- const prior = current.get(commitPreparationRecordKey(change));
111804
- return [prior, change.nextData].some((candidate) => {
111805
- const worldKind = valueWorldKind(kindsByClass, candidate);
111806
- return hasWorldLayerOverride(candidate) || worldKind === NeoWorldSystemClassKind.TileLayerLink || worldKind === NeoWorldSystemClassKind.ObjectLayerLink;
111807
- });
111808
- });
111809
- return requiresWholeWorld ? allKinds : /* @__PURE__ */ new Set();
112469
+ return stagedChangesRequireWorldLayerBindingValidation(
112470
+ args.currentDocument,
112471
+ args.changes
112472
+ ) ? allKinds : /* @__PURE__ */ new Set();
111810
112473
  }
111811
112474
  function commitPreparationMemberDefaultValueScope(args) {
111812
112475
  let evaluatesSource = false;
112476
+ const currentMembersById = new Map(
112477
+ args.currentDocument.members.map((member) => [member.id, member])
112478
+ );
111813
112479
  const constructorsWithSource = new Set(
111814
112480
  (args.postDocument.constructors ?? []).filter(containsAuthoredNeoScriptSource).map((constructor2) => constructor2.classId)
111815
112481
  );
@@ -111883,9 +112549,7 @@ function commitPreparationMemberDefaultValueScope(args) {
111883
112549
  for (const change of args.changes) {
111884
112550
  if (change.recordKind === "member") {
111885
112551
  visitMember(change.recordId);
111886
- const currentMember = args.currentDocument.members.find(
111887
- (member) => member.id === change.recordId
111888
- );
112552
+ const currentMember = currentMembersById.get(change.recordId);
111889
112553
  if (currentMember !== void 0) {
111890
112554
  rememberDefaultIds(currentMember.defaultValue, true);
111891
112555
  }
@@ -111939,9 +112603,7 @@ function planCommitPreparationInitialScope(args) {
111939
112603
  }
111940
112604
  if (change.recordKind === "member") {
111941
112605
  rememberExact("value", derivedMemberValueId(change.recordId), true);
111942
- const current = args.document.members.find(
111943
- (member) => member.id === change.recordId
111944
- );
112606
+ const current = previousMembers.get(change.recordId);
111945
112607
  for (const candidate of [current, change.nextData]) {
111946
112608
  if (candidate === null || typeof candidate !== "object") continue;
111947
112609
  const valueId = Reflect.get(candidate, "valueId");
@@ -111953,13 +112615,17 @@ function planCommitPreparationInitialScope(args) {
111953
112615
  rememberExact("value", valueId, true);
111954
112616
  }
111955
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
+ );
111956
112624
  const primary = postDocument.localizationConfig?.mainLocale;
111957
112625
  const primaryEdits = args.changes.flatMap((change) => {
111958
112626
  if (change.recordKind !== "localized-text" || change.operation !== "update" || !isLocalizedText(change.nextData) || primary === void 0)
111959
112627
  return [];
111960
- const old = args.document.localizedTexts?.find(
111961
- (text) => text.id === change.recordId
111962
- );
112628
+ const old = currentTextsById.get(change.recordId);
111963
112629
  return old !== void 0 && memberSourcePrimaryChanged(
111964
112630
  old,
111965
112631
  primary,
@@ -111980,9 +112646,7 @@ function planCommitPreparationInitialScope(args) {
111980
112646
  const target = localizedTextReferenceTarget(link);
111981
112647
  rememberExact(target.recordKind, target.recordId, true);
111982
112648
  if (link.kind === "member-value") {
111983
- const row = postDocument.values.find(
111984
- (value) => value.id === link.valueId
111985
- );
112649
+ const row = postValuesById.get(link.valueId);
111986
112650
  if (row !== void 0)
111987
112651
  linkedValueChanges.push({
111988
112652
  ...target,
@@ -112664,9 +113328,14 @@ function readCommitPreparationScopeInMemory(args) {
112664
113328
  key
112665
113329
  );
112666
113330
  }
113331
+ const childKeysSeenByParent = /* @__PURE__ */ new Map();
112667
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);
112668
113337
  const children = childKeysByParentKey.get(parentKey) ?? [];
112669
- if (!children.includes(childKey)) children.push(childKey);
113338
+ children.push(childKey);
112670
113339
  childKeysByParentKey.set(parentKey, children);
112671
113340
  };
112672
113341
  for (const record4 of records2) {
@@ -112920,6 +113589,7 @@ var COMMIT_PREPARATION_SCOPE_RANGE_ROW_LIMIT, COMMIT_PREPARATION_SCOPE_POSTING_R
112920
113589
  var init_project_commit_preparation_scoped_loader = __esm({
112921
113590
  "../src/database/project-commit-preparation-scoped-loader.ts"() {
112922
113591
  "use strict";
113592
+ init_project_world_placement_bindings();
112923
113593
  init_project_localization_rules();
112924
113594
  init_variant_value_graph();
112925
113595
  init_packed_value_write_fold();
@@ -113534,7 +114204,8 @@ function isPulledInitializerCompilationDocumentV4(document) {
113534
114204
  function createPulledConstructionReplayContext(args) {
113535
114205
  return {
113536
114206
  document: args.document,
113537
- constructorsValidated: false
114207
+ constructorsValidated: false,
114208
+ valuesById: new Map(args.document.values.map((value) => [value.id, value]))
113538
114209
  };
113539
114210
  }
113540
114211
  function pulledInitializerCompilerStateV4(document, compilationProject) {
@@ -113637,7 +114308,7 @@ function replayStoredConstructionV4(args) {
113637
114308
  }
113638
114309
  compilePulledProjectDocumentForEvaluationV4(document, compilationProject);
113639
114310
  }
113640
- 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);
113641
114312
  if (root === void 0) {
113642
114313
  throw new Error(
113643
114314
  `Cannot replay stored construction for missing value "${args.valueId}".`
@@ -128406,6 +129077,55 @@ var init_script = __esm({
128406
129077
  }
128407
129078
  });
128408
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
+
128409
129129
  // ../src/database/project-source-identity.ts
128410
129130
  import { createHash as createHash8 } from "node:crypto";
128411
129131
  function hashProjectSourceFiles(inputFiles) {
@@ -129470,20 +130190,10 @@ function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInit
129470
130190
  if (localInitializerMaterialization !== void 0) {
129471
130191
  collect(localInitializerMaterialization);
129472
130192
  }
129473
- const replacements = [...assigned].sort(
129474
- ([left], [right]) => right.length - left.length
129475
- );
130193
+ const rewriteString = createIdentityRewriter(assigned);
129476
130194
  const rewrite = (value) => {
129477
130195
  if (typeof value === "string") {
129478
- const exact = assigned.get(value);
129479
- if (exact !== void 0) return exact;
129480
- let result = value;
129481
- for (const [pendingId2, assignedId] of replacements) {
129482
- if (result.includes(pendingId2)) {
129483
- result = result.replaceAll(pendingId2, assignedId);
129484
- }
129485
- }
129486
- return result;
130196
+ return rewriteString(value);
129487
130197
  }
129488
130198
  if (Array.isArray(value)) return value.map((item) => rewrite(item));
129489
130199
  if (isObjectRecord2(value)) {
@@ -131296,9 +132006,7 @@ function projectTransactionResultReplacements(candidateAssignments, resultAssign
131296
132006
  }
131297
132007
  return {
131298
132008
  exact: replacements,
131299
- embedded: [...replacements].sort(
131300
- ([left], [right]) => right.length - left.length
131301
- )
132009
+ rewrite: createIdentityRewriter(replacements)
131302
132010
  };
131303
132011
  }
131304
132012
  function rewriteReconstructedRecords(records2, replacements) {
@@ -131328,13 +132036,7 @@ function rewriteReconstructedRecords(records2, replacements) {
131328
132036
  return rewritten;
131329
132037
  }
131330
132038
  function rewriteAssignedString(value, replacements) {
131331
- const exact = replacements.exact.get(value);
131332
- if (exact !== void 0) return exact;
131333
- let result = value;
131334
- for (const [source, target] of replacements.embedded) {
131335
- if (result.includes(source)) result = result.replaceAll(source, target);
131336
- }
131337
- return result;
132039
+ return replacements.rewrite(value);
131338
132040
  }
131339
132041
  function rewriteAssignedValue(value, replacements) {
131340
132042
  if (typeof value === "string") {
@@ -131474,7 +132176,7 @@ function applyPushResult(workspace, result, pendingIdAssignments = /* @__PURE__
131474
132176
  );
131475
132177
  const replacements = {
131476
132178
  exact: pendingIdAssignments,
131477
- embedded: pendingIdAssignments.entries().toArray().sort(([left], [right]) => right.length - left.length)
132179
+ rewrite: createIdentityRewriter(pendingIdAssignments)
131478
132180
  };
131479
132181
  const localRecords = rewriteReconstructedRecords(
131480
132182
  localStatus.reconstructed,
@@ -132154,52 +132856,49 @@ function prepareNSPropertySetterChanges(workspace, status) {
132154
132856
  }
132155
132857
  members.set(change.recordId, change.nextData);
132156
132858
  }
132859
+ const inheritedSetters = /* @__PURE__ */ new Map();
132157
132860
  const removedDeclarations = status.changes.filter(
132158
- (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)
132159
132862
  ).map((change) => change.recordId);
132160
- for (const declarationId of removedDeclarations) {
132161
- for (const [memberId, member] of members) {
132162
- if (memberId === declarationId) continue;
132163
- if (!memberDescendsFrom(member, declarationId, members)) {
132164
- continue;
132165
- }
132166
- if (typeof member.setterCode !== "string" && member.setter === void 0) {
132167
- continue;
132168
- }
132169
- const next = { ...member };
132170
- delete next.setterCode;
132171
- delete next.setter;
132172
- members.set(memberId, next);
132173
- const key = recordStateKey("member", memberId);
132174
- const reconstructed3 = status.reconstructed.get(key);
132175
- if (reconstructed3 !== void 0) reconstructed3.fullData = next;
132176
- const existingChange = changesById.get(memberId);
132177
- if (existingChange !== void 0) {
132178
- existingChange.nextData = next;
132179
- continue;
132180
- }
132181
- const base = workspace.state.records[key];
132182
- if (base === void 0 || reconstructed3 === void 0) {
132183
- throw new Error(
132184
- `Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
132185
- );
132186
- }
132187
- const cascadeChange = recordUpsertChange({
132188
- base,
132189
- recordKind: "member",
132190
- recordId: memberId,
132191
- file: reconstructed3.file,
132192
- nextData: next
132193
- });
132194
- status.changes.push(cascadeChange);
132195
- 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;
132196
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);
132197
132895
  }
132896
+ inheritedSetters.clear();
132198
132897
  for (const member of members.values()) {
132199
132898
  if (member.kind !== 10) continue;
132200
132899
  if (typeof member.extendsMemberId !== "string") continue;
132201
132900
  if (typeof member.setterCode !== "string") continue;
132202
- if (ancestorDeclaresSetter(member, members)) continue;
132901
+ if (ancestorDeclaresSetter(member, members, inheritedSetters)) continue;
132203
132902
  throw new Error(
132204
132903
  `Override NeoScript property "${String(member.name ?? member.id)}" cannot add a setter because its base chain does not declare one.`
132205
132904
  );
@@ -132241,14 +132940,10 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132241
132940
  members.set(next.id, next);
132242
132941
  }
132243
132942
  }
132244
- for (const [memberId, member] of members) {
132943
+ for (const memberId of memberDescendantIds(members, affectedRoots)) {
132944
+ const member = members.get(memberId);
132245
132945
  if (member.kind !== 23 || typeof member.code !== "string") continue;
132246
132946
  if (changesById.has(memberId)) continue;
132247
- if (![...affectedRoots].some(
132248
- (rootId) => memberDescendsFrom(member, rootId, members)
132249
- )) {
132250
- continue;
132251
- }
132252
132947
  const key = recordStateKey("member", memberId);
132253
132948
  const base = workspace.state.records[key];
132254
132949
  const reconstructed3 = status.reconstructed.get(key);
@@ -132268,10 +132963,16 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132268
132963
  changesById.set(memberId, cascadeChange);
132269
132964
  }
132270
132965
  }
132271
- function ancestorDeclaresSetter(member, members) {
132966
+ function ancestorDeclaresSetter(member, members, cache) {
132272
132967
  let parentId = typeof member.extendsMemberId === "string" ? member.extendsMemberId : null;
132273
132968
  const visited = /* @__PURE__ */ new Set();
132969
+ let hasSetter = false;
132274
132970
  while (parentId !== null) {
132971
+ const cached = cache.get(parentId);
132972
+ if (cached !== void 0) {
132973
+ hasSetter = cached;
132974
+ break;
132975
+ }
132275
132976
  if (visited.has(parentId)) {
132276
132977
  throw new Error(
132277
132978
  `Cannot resolve NeoScript property setter inheritance: circular member chain at "${parentId}".`
@@ -132284,23 +132985,35 @@ function ancestorDeclaresSetter(member, members) {
132284
132985
  `Cannot resolve NeoScript property setter inheritance: missing parent member "${parentId}".`
132285
132986
  );
132286
132987
  }
132287
- if (typeof parent.setterCode === "string") return true;
132988
+ if (typeof parent.setterCode === "string") {
132989
+ hasSetter = true;
132990
+ break;
132991
+ }
132288
132992
  parentId = typeof parent.extendsMemberId === "string" ? parent.extendsMemberId : null;
132289
132993
  }
132290
- return false;
132994
+ for (const id2 of visited) cache.set(id2, hasSetter);
132995
+ return hasSetter;
132291
132996
  }
132292
- function memberDescendsFrom(member, ancestorId, members) {
132293
- let parentId = typeof member.extendsMemberId === "string" ? member.extendsMemberId : null;
132294
- const visited = /* @__PURE__ */ new Set();
132295
- while (parentId !== null) {
132296
- if (parentId === ancestorId) return true;
132297
- if (visited.has(parentId)) return false;
132298
- visited.add(parentId);
132299
- const parent = members.get(parentId);
132300
- if (parent === void 0) return false;
132301
- 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);
132302
133006
  }
132303
- 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;
132304
133017
  }
132305
133018
  function resolveNSPropertyReturnTypeInfo2(member, members) {
132306
133019
  let current = member;
@@ -132386,6 +133099,7 @@ var compileNSVoidBody2, compileNSFunction2, compileNSGetter2, compileNSSetter2,
132386
133099
  var init_push = __esm({
132387
133100
  "src/commands/push.ts"() {
132388
133101
  "use strict";
133102
+ init_identity_rewriter();
132389
133103
  init_source_layout();
132390
133104
  init_src();
132391
133105
  init_src2();
@@ -132479,7 +133193,7 @@ var init_registry2 = __esm({
132479
133193
  "schema-contract/registry.mjs"() {
132480
133194
  "use strict";
132481
133195
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
132482
- cliVersion: "0.50.4",
133196
+ cliVersion: "0.50.5",
132483
133197
  projectFileUploadBatchSize: 32,
132484
133198
  documentRecords: {
132485
133199
  member: {
@@ -139695,7 +140409,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
139695
140409
  async function main() {
139696
140410
  const args = parseArgs(process.argv.slice(2));
139697
140411
  if (args.command === "--version") {
139698
- console.log("0.50.4");
140412
+ console.log("0.50.5");
139699
140413
  return;
139700
140414
  }
139701
140415
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {