@neocompose/cli 0.50.4 → 0.50.6

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,281 @@ 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 createdWorldPlacementIds(changes) {
95532
+ if (changes.length === 0) return null;
95533
+ const ids = /* @__PURE__ */ new Set();
95534
+ for (const change of changes) {
95535
+ if (change.recordKind !== "value" || change.operation !== "create" || change.deleted === true || !hasWorldPlacementSidecar(change.nextData))
95536
+ return null;
95537
+ ids.add(change.recordId);
95538
+ }
95539
+ return ids;
95540
+ }
95541
+ function hasWorldPlacementSidecar(value) {
95542
+ if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return false;
95543
+ const body = value.value;
95544
+ if (typeof body.assetClassId === "string") return true;
95545
+ if (typeof body.assetValueId === "string") return true;
95546
+ if (isVariantRefValue(body)) return false;
95547
+ return typeof body.variantId === "string";
95548
+ }
95549
+ function worldPlacementBindingChanged(before, after) {
95550
+ return !projectRecordDataIsSemanticallyEqual(
95551
+ worldPlacementBindingSlice(before),
95552
+ worldPlacementBindingSlice(after)
95553
+ );
95554
+ }
95555
+ function worldPlacementBindingSlice(value) {
95556
+ if (!isPlainRecord3(value) || !isPlainRecord3(value.value)) return null;
95557
+ return {
95558
+ containerId: value.containerId ?? null,
95559
+ assetClassId: value.value.assetClassId ?? null,
95560
+ assetValueId: value.value.assetValueId ?? null,
95561
+ rowValueId: value.value.rowValueId ?? null,
95562
+ variantId: value.value.variantId ?? null
95563
+ };
95564
+ }
95565
+ function ownedSparseValueBindingChanged(before, after) {
95566
+ return !projectRecordDataIsSemanticallyEqual(
95567
+ ownedSparseValueBindingSlice(before),
95568
+ ownedSparseValueBindingSlice(after)
95569
+ );
95570
+ }
95571
+ function ownedSparseValueBindingSlice(value) {
95572
+ if (!isPlainRecord3(value)) return null;
95573
+ return {
95574
+ classId: value.classId ?? null,
95575
+ containerId: value.containerId ?? null
95576
+ };
95577
+ }
95578
+ function isPlainRecord3(value) {
95579
+ return typeof value === "object" && value !== null && !Array.isArray(value);
95580
+ }
95581
+ function stagedChangesRequireWorldLayerBindingValidation(current, changes) {
95582
+ const classesById = new Map(
95583
+ current.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95584
+ );
95585
+ const valuesById = new Map(current.values.map((value) => [value.id, value]));
95586
+ const valueChanges = [];
95587
+ for (const change of changes) {
95588
+ if (change.recordKind === "internal-record-relation") return true;
95589
+ if (change.recordKind === "value") {
95590
+ valueChanges.push(change);
95591
+ continue;
95592
+ }
95593
+ if (change.recordKind !== "class") continue;
95594
+ if (change.operation === "create" && change.deleted !== true && !classesById.has(change.recordId) && isPlainRecord3(change.nextData) && change.nextData.extendsClassId == null && change.nextData.system == null)
95595
+ continue;
95596
+ if (change.operation !== "update") return true;
95597
+ if (change.deleted === true) return true;
95598
+ const before = classesById.get(change.recordId);
95599
+ if (before === void 0) return true;
95600
+ const after = change.nextData;
95601
+ if (!isPlainRecord3(after)) return true;
95602
+ if (before.extendsClassId !== after.extendsClassId) return true;
95603
+ if (isAbstractClass(before) !== isAbstractClass(after)) return true;
95604
+ if (!worldClassSystemBlockIsEqual(before.system, after.system)) return true;
95605
+ }
95606
+ if (valueChanges.length === 0) return false;
95607
+ const worldKinds = indexWorldSystemClassKinds(current.classes, classesById);
95608
+ const changedValuesById = new Map(
95609
+ valueChanges.map((change) => [change.recordId, change.nextData])
95610
+ );
95611
+ for (const change of valueChanges) {
95612
+ const before = valuesById.get(change.recordId);
95613
+ if (hasWorldLayerOverrideMetadata(before) || hasWorldLayerOverrideMetadata(change.nextData) || (hasWorldPlacementSidecar(before) || hasWorldPlacementSidecar(change.nextData)) && worldPlacementBindingChanged(
95614
+ before,
95615
+ change.deleted === true || change.operation === "delete" ? null : change.nextData
95616
+ )) {
95617
+ return true;
95618
+ }
95619
+ for (const row of ownedSparseValueBindingChanged(
95620
+ before,
95621
+ change.deleted === true || change.operation === "delete" ? null : change.nextData
95622
+ ) ? [before, change.nextData] : []) {
95623
+ if (!isPlainRecord3(row) || typeof row.containerId !== "string") continue;
95624
+ for (const owner of [
95625
+ valuesById.get(row.containerId),
95626
+ changedValuesById.get(row.containerId)
95627
+ ]) {
95628
+ if (isPlainRecord3(owner) && isPlainRecord3(owner.value) && owner.value.assetValueId === change.recordId)
95629
+ return true;
95630
+ }
95631
+ }
95632
+ const classIds = [
95633
+ relationEndpointClassId(before),
95634
+ relationEndpointClassId(change.nextData)
95635
+ ].filter((classId) => classId !== void 0);
95636
+ for (const classId of classIds) {
95637
+ const worldKind = worldKinds.get(classId);
95638
+ if (worldKind === NeoWorldSystemClassKind.TileLayerLink) return true;
95639
+ if (worldKind === NeoWorldSystemClassKind.ObjectLayerLink) return true;
95640
+ }
95641
+ }
95642
+ return false;
95643
+ }
95644
+ function worldClassSystemBlockIsEqual(before, after) {
95645
+ return projectRecordDataIsSemanticallyEqual(
95646
+ { system: before },
95647
+ { system: after }
95648
+ );
95649
+ }
95650
+ function hasWorldLayerOverrideMetadata(record4) {
95651
+ if (!isPlainRecord3(record4)) return false;
95652
+ const value = record4.value;
95653
+ if (!isPlainRecord3(value)) return false;
95654
+ return typeof value.layerOverrideValueId === "string";
95655
+ }
95656
+ var init_project_world_placement_bindings = __esm({
95657
+ "../src/database/project-world-placement-bindings.ts"() {
95658
+ "use strict";
95659
+ init_classes();
95660
+ init_core();
95661
+ init_project_version_relation_sweep_trigger();
95662
+ init_members();
95663
+ init_project_record_semantics();
95664
+ }
95665
+ });
95666
+
94932
95667
  // ../src/models/classes/world-layer-link-target.ts
94933
95668
  function validateWorldLayerLinkClassTargets(args) {
95669
+ const relationResolver = createEffectiveClassRelationResolver(args);
95670
+ const worldKindsByClassId = indexWorldSystemClassKinds(
95671
+ args.classes,
95672
+ relationResolver.classesById
95673
+ );
94934
95674
  for (const schemaClass2 of args.classes) {
94935
95675
  if (args.classIds !== void 0 && !args.classIds.has(schemaClass2.id)) {
94936
95676
  continue;
94937
95677
  }
94938
95678
  const directWorldKind = schemaClass2.system?.worldKind;
94939
95679
  const isSystemLinkBase = directWorldKind === NeoWorldSystemClassKind.TileLayerLink || directWorldKind === NeoWorldSystemClassKind.ObjectLayerLink;
94940
- const descriptor = worldLayerLinkTargetDescriptorForClass(
94941
- schemaClass2.id,
94942
- args.classes
95680
+ const descriptor = worldLayerLinkTargetDescriptor(
95681
+ worldKindsByClassId.get(schemaClass2.id) ?? null
94943
95682
  );
94944
95683
  if (descriptor === null) continue;
94945
95684
  if (isSystemLinkBase) {
@@ -94948,10 +95687,9 @@ function validateWorldLayerLinkClassTargets(args) {
94948
95687
  `System layer-link base class "${schemaClass2.id}" must remain abstract.`
94949
95688
  );
94950
95689
  }
94951
- if (worldLayerLinkTargetRelations(
94952
- schemaClass2.id,
94953
- descriptor,
94954
- args.relations
95690
+ if (relationResolver.directClassRelations(
95691
+ descriptor.relationKind,
95692
+ schemaClass2.id
94955
95693
  ).length > 0) {
94956
95694
  throw new Error(
94957
95695
  `System layer-link base class "${schemaClass2.id}" cannot declare a layer target relation.`
@@ -94964,7 +95702,9 @@ function validateWorldLayerLinkClassTargets(args) {
94964
95702
  classes: args.classes,
94965
95703
  linkLabel: `Concrete layer-link class "${schemaClass2.id}"`,
94966
95704
  relations: args.relations,
94967
- sourceClassId: schemaClass2.id
95705
+ sourceClassId: schemaClass2.id,
95706
+ relationResolver,
95707
+ worldKindsByClassId
94968
95708
  });
94969
95709
  }
94970
95710
  }
@@ -94988,11 +95728,6 @@ function worldLayerLinkTargetDescriptor(worldKind) {
94988
95728
  }
94989
95729
  return null;
94990
95730
  }
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
95731
  function resolveWorldLayerLinkTarget(args) {
94997
95732
  const label = args.linkLabel ?? `Layer-link class "${args.sourceClassId}"`;
94998
95733
  const relationResolver = args.relationResolver ?? createEffectiveClassRelationResolver({
@@ -95078,6 +95813,34 @@ var init_world_layer_link_target = __esm({
95078
95813
  });
95079
95814
 
95080
95815
  // ../src/models/project/world-content-sidecar-validation.ts
95816
+ function cachedWorldLayerTarget(context, args) {
95817
+ let target = context.linkTargetsByClassId.get(args.sourceClassId);
95818
+ if (target === void 0) {
95819
+ target = resolveWorldLayerLinkTarget({
95820
+ ...args,
95821
+ relationResolver: context.relationResolver,
95822
+ worldKindsByClassId: context.worldKindsByClassId
95823
+ }).targetClassId;
95824
+ context.linkTargetsByClassId.set(args.sourceClassId, target);
95825
+ }
95826
+ return target;
95827
+ }
95828
+ function worldValidationContext(args) {
95829
+ const relationResolver = createEffectiveClassRelationResolver(args);
95830
+ return {
95831
+ relationResolver,
95832
+ worldKindsByClassId: indexWorldSystemClassKinds(
95833
+ args.classes,
95834
+ relationResolver.classesById
95835
+ ),
95836
+ targetIds: /* @__PURE__ */ new Map(),
95837
+ linkTargetsByClassId: /* @__PURE__ */ new Map(),
95838
+ variantsById: new Map(
95839
+ args.variants.map((variant2) => [variant2.id, variant2])
95840
+ ),
95841
+ lookupRowSets: /* @__PURE__ */ new WeakMap()
95842
+ };
95843
+ }
95081
95844
  function worldPlacementVariantBindings(args) {
95082
95845
  const foldersById = new Map(
95083
95846
  args.variantFolders.map((folder) => [folder.id, folder])
@@ -95086,12 +95849,15 @@ function worldPlacementVariantBindings(args) {
95086
95849
  args.members.map((member) => [member.id, member])
95087
95850
  );
95088
95851
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95852
+ const containedRows = indexContainedRows(args.values);
95853
+ const expandedGraphs = /* @__PURE__ */ new WeakMap();
95089
95854
  let cachedLookups = null;
95090
95855
  const expansionLookups = () => {
95091
95856
  return cachedLookups ??= initializerEvaluatorLookups(
95092
95857
  args.expansionDocument
95093
95858
  );
95094
95859
  };
95860
+ const lookupEntriesByMember = /* @__PURE__ */ new Map();
95095
95861
  return args.variants.map((variant2) => {
95096
95862
  const folder = variant2.folderId === null ? null : foldersById.get(variant2.folderId) ?? null;
95097
95863
  const binding = folder?.binding ?? null;
@@ -95104,17 +95870,24 @@ function worldPlacementVariantBindings(args) {
95104
95870
  lookupRowValueIds: []
95105
95871
  };
95106
95872
  }
95107
- return {
95108
- id: variant2.id,
95109
- classId: variant2.classId,
95110
- lookupRowValueIds: lookupCollectionEntryIds({
95873
+ let entriesByValue = lookupEntriesByMember.get(binding.collectionMemberId);
95874
+ if (entriesByValue === void 0) {
95875
+ entriesByValue = /* @__PURE__ */ new Map();
95876
+ lookupEntriesByMember.set(binding.collectionMemberId, entriesByValue);
95877
+ }
95878
+ let lookupRowValueIds = entriesByValue.get(binding.collectionValueId);
95879
+ if (lookupRowValueIds === void 0) {
95880
+ lookupRowValueIds = lookupCollectionEntryIds({
95111
95881
  collection,
95112
95882
  collectionValueId: binding.collectionValueId,
95113
95883
  lookups: expansionLookups(),
95114
- values: args.values,
95884
+ containedRows,
95885
+ expandedGraphs,
95115
95886
  valuesById
95116
- })
95117
- };
95887
+ });
95888
+ entriesByValue.set(binding.collectionValueId, lookupRowValueIds);
95889
+ }
95890
+ return { id: variant2.id, classId: variant2.classId, lookupRowValueIds };
95118
95891
  });
95119
95892
  }
95120
95893
  function lookupCollectionEntryIds(args) {
@@ -95125,24 +95898,47 @@ function lookupCollectionEntryIds(args) {
95125
95898
  if (graphRows.length === 0) {
95126
95899
  const fallbackRow = storedRow ?? args.lookups.valueById(args.collectionValueId);
95127
95900
  if (fallbackRow === null || fallbackRow === void 0) return [];
95128
- return listEntryIdsForValue(args.collection, fallbackRow, args.values);
95901
+ return listEntryIdsForValue(
95902
+ args.collection,
95903
+ fallbackRow,
95904
+ args.containedRows.get(args.collectionValueId) ?? []
95905
+ );
95129
95906
  }
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);
95907
+ let graph = args.expandedGraphs.get(graphRows);
95908
+ if (graph === void 0) {
95909
+ graph = {
95910
+ byId: new Map(graphRows.map((row) => [row.id, row])),
95911
+ containedRows: indexContainedRows(graphRows)
95912
+ };
95913
+ args.expandedGraphs.set(graphRows, graph);
95135
95914
  }
95136
- const collectionRow = graphRowsById.get(args.collectionValueId) ?? storedRow;
95915
+ const effectiveRows = [
95916
+ ...args.containedRows.get(args.collectionValueId) ?? []
95917
+ ];
95918
+ for (const row of graph.containedRows.get(args.collectionValueId) ?? []) {
95919
+ if (!args.valuesById.has(row.id)) effectiveRows.push(row);
95920
+ }
95921
+ const collectionRow = graph.byId.get(args.collectionValueId) ?? storedRow;
95137
95922
  if (collectionRow === void 0) return [];
95138
95923
  return listEntryIdsForValue(args.collection, collectionRow, effectiveRows);
95139
95924
  }
95925
+ function indexContainedRows(values) {
95926
+ const byContainer = /* @__PURE__ */ new Map();
95927
+ for (const row of values) {
95928
+ if (typeof row.containerId !== "string") continue;
95929
+ const rows = byContainer.get(row.containerId) ?? [];
95930
+ rows.push(row);
95931
+ byContainer.set(row.containerId, rows);
95932
+ }
95933
+ return byContainer;
95934
+ }
95140
95935
  function validateWorldContentSidecars(args) {
95936
+ const context = worldValidationContext(args);
95141
95937
  assertWorldLayerLinkValueBodiesCanonical({
95142
95938
  classes: args.classes,
95143
- values: args.values
95939
+ values: args.values,
95940
+ worldKindsByClassId: context.worldKindsByClassId
95144
95941
  });
95145
- const variants = args.variants;
95146
95942
  const valuesById = new Map(args.values.map((value) => [value.id, value]));
95147
95943
  const classesById = new Map(
95148
95944
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
@@ -95153,7 +95949,7 @@ function validateWorldContentSidecars(args) {
95153
95949
  const validatedPlacementIds = /* @__PURE__ */ new Set();
95154
95950
  const reachablePlacementIds = /* @__PURE__ */ new Set();
95155
95951
  for (const gridValue of args.values) {
95156
- if (worldKindForValue(gridValue, args.classes) !== NeoWorldSystemClassKind.TileGrid) {
95952
+ if (worldKindForValue(gridValue, context.worldKindsByClassId) !== NeoWorldSystemClassKind.TileGrid) {
95157
95953
  continue;
95158
95954
  }
95159
95955
  const gridClassId = requiredValueClassId(gridValue, "tile-grid");
@@ -95166,27 +95962,23 @@ function validateWorldContentSidecars(args) {
95166
95962
  );
95167
95963
  if (childrenList === null) continue;
95168
95964
  const registeredTileLayers = effectiveTargetIds({
95169
- classes: args.classes,
95965
+ context,
95170
95966
  relationKind: InternalRecordRelationKind.WorldGridTileLayer,
95171
- relations: args.relations,
95172
95967
  sourceClassId: gridClassId
95173
95968
  });
95174
95969
  const registeredObjectLayers = effectiveTargetIds({
95175
- classes: args.classes,
95970
+ context,
95176
95971
  relationKind: InternalRecordRelationKind.WorldGridObjectLayer,
95177
- relations: args.relations,
95178
95972
  sourceClassId: gridClassId
95179
95973
  });
95180
95974
  const importedTiles = effectiveTargetIds({
95181
- classes: args.classes,
95975
+ context,
95182
95976
  relationKind: InternalRecordRelationKind.WorldGridTileImport,
95183
- relations: args.relations,
95184
95977
  sourceClassId: gridClassId
95185
95978
  });
95186
95979
  const importedObjects = effectiveTargetIds({
95187
- classes: args.classes,
95980
+ context,
95188
95981
  relationKind: InternalRecordRelationKind.WorldGridObjectImport,
95189
- relations: args.relations,
95190
95982
  sourceClassId: gridClassId
95191
95983
  });
95192
95984
  const overrideOwnerByLayerKey = /* @__PURE__ */ new Map();
@@ -95197,7 +95989,10 @@ function validateWorldContentSidecars(args) {
95197
95989
  `Grid value "${gridValue.id}" Children references missing value "${linkId}".`
95198
95990
  );
95199
95991
  }
95200
- const linkKind = worldKindForValue(linkValue, args.classes);
95992
+ const linkKind = worldKindForValue(
95993
+ linkValue,
95994
+ context.worldKindsByClassId
95995
+ );
95201
95996
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95202
95997
  continue;
95203
95998
  }
@@ -95215,12 +96010,12 @@ function validateWorldContentSidecars(args) {
95215
96010
  reachablePlacementIds.add(placementId);
95216
96011
  }
95217
96012
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95218
- const layerClassId = resolveWorldLayerLinkTarget({
96013
+ const layerClassId = cachedWorldLayerTarget(context, {
95219
96014
  classes: args.classes,
95220
96015
  linkLabel: `Layer link value "${linkValue.id}"`,
95221
96016
  relations: args.relations,
95222
96017
  sourceClassId: linkClassId
95223
- }).targetClassId;
96018
+ });
95224
96019
  const existingOwner = ownedLinkIds.get(linkValue.id);
95225
96020
  if (existingOwner !== void 0 && existingOwner !== gridValue.id) {
95226
96021
  throw new Error(
@@ -95232,7 +96027,7 @@ function validateWorldContentSidecars(args) {
95232
96027
  const expectedLayerKind = isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer;
95233
96028
  assertConcreteWorldClass({
95234
96029
  classId: layerClassId,
95235
- classes: args.classes,
96030
+ worldKindsByClassId: context.worldKindsByClassId,
95236
96031
  classesById,
95237
96032
  expectedKind: expectedLayerKind,
95238
96033
  label: `Layer link value "${linkValue.id}" target`
@@ -95265,6 +96060,8 @@ function validateWorldContentSidecars(args) {
95265
96060
  valuesById
95266
96061
  });
95267
96062
  for (const placementId of placementIds) {
96063
+ if (args.placementIds !== void 0 && !args.placementIds.has(placementId))
96064
+ continue;
95268
96065
  const placement = valuesById.get(placementId);
95269
96066
  if (placement === void 0) {
95270
96067
  throw new Error(
@@ -95272,15 +96069,13 @@ function validateWorldContentSidecars(args) {
95272
96069
  );
95273
96070
  }
95274
96071
  validateWorldPlacementSidecars({
95275
- classes: args.classes,
96072
+ context,
95276
96073
  classesById,
95277
96074
  importedClassIds: isTile ? importedTiles : importedObjects,
95278
96075
  isTile,
95279
96076
  layerClassId,
95280
- variants,
95281
96077
  linkValueId: linkValue.id,
95282
96078
  placement,
95283
- relations: args.relations,
95284
96079
  valuesById
95285
96080
  });
95286
96081
  validatedPlacementIds.add(placement.id);
@@ -95289,7 +96084,7 @@ function validateWorldContentSidecars(args) {
95289
96084
  }
95290
96085
  for (const linkValue of args.values) {
95291
96086
  if (gridOwnedLinkIds.has(linkValue.id)) continue;
95292
- const linkKind = worldKindForValue(linkValue, args.classes);
96087
+ const linkKind = worldKindForValue(linkValue, context.worldKindsByClassId);
95293
96088
  if (linkKind !== NeoWorldSystemClassKind.TileLayerLink && linkKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95294
96089
  continue;
95295
96090
  }
@@ -95297,15 +96092,15 @@ function validateWorldContentSidecars(args) {
95297
96092
  if (linkRecord === null) continue;
95298
96093
  const isTile = linkKind === NeoWorldSystemClassKind.TileLayerLink;
95299
96094
  const linkClassId = requiredValueClassId(linkValue, "layer-link");
95300
- const layerClassId = resolveWorldLayerLinkTarget({
96095
+ const layerClassId = cachedWorldLayerTarget(context, {
95301
96096
  classes: args.classes,
95302
96097
  linkLabel: `Object-composition layer link value "${linkValue.id}"`,
95303
96098
  relations: args.relations,
95304
96099
  sourceClassId: linkClassId
95305
- }).targetClassId;
96100
+ });
95306
96101
  assertConcreteWorldClass({
95307
96102
  classId: layerClassId,
95308
- classes: args.classes,
96103
+ worldKindsByClassId: context.worldKindsByClassId,
95309
96104
  classesById,
95310
96105
  expectedKind: isTile ? NeoWorldSystemClassKind.TileLayer : NeoWorldSystemClassKind.ObjectLayer,
95311
96106
  label: `Object-composition layer link value "${linkValue.id}" target`
@@ -95329,6 +96124,8 @@ function validateWorldContentSidecars(args) {
95329
96124
  placementList,
95330
96125
  containedIds
95331
96126
  )) {
96127
+ if (args.placementIds !== void 0 && !args.placementIds.has(placementId))
96128
+ continue;
95332
96129
  const placement = valuesById.get(placementId);
95333
96130
  if (placement === void 0) {
95334
96131
  throw new Error(
@@ -95336,15 +96133,13 @@ function validateWorldContentSidecars(args) {
95336
96133
  );
95337
96134
  }
95338
96135
  validateWorldPlacementSidecars({
95339
- classes: args.classes,
96136
+ context,
95340
96137
  classesById,
95341
96138
  importedClassIds: null,
95342
96139
  isTile,
95343
96140
  layerClassId,
95344
- variants,
95345
96141
  linkValueId: linkValue.id,
95346
96142
  placement,
95347
- relations: args.relations,
95348
96143
  valuesById
95349
96144
  });
95350
96145
  reachablePlacementIds.add(placement.id);
@@ -95352,6 +96147,8 @@ function validateWorldContentSidecars(args) {
95352
96147
  }
95353
96148
  }
95354
96149
  for (const value of args.values) {
96150
+ if (args.placementIds !== void 0 && !args.placementIds.has(value.id))
96151
+ continue;
95355
96152
  const record4 = valueObjectRecord(value);
95356
96153
  if (record4 === null) continue;
95357
96154
  if (optionalNonEmptyString(record4.assetClassId) !== null && !validatedPlacementIds.has(value.id) && !reachablePlacementIds.has(value.id)) {
@@ -95365,8 +96162,10 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95365
96162
  const classesById = new Map(
95366
96163
  args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95367
96164
  );
96165
+ const worldKinds = args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById);
96166
+ const storedKeysByClassId = /* @__PURE__ */ new Map();
95368
96167
  for (const value of args.values) {
95369
- const worldKind = worldKindForValue(value, args.classes);
96168
+ const worldKind = worldKindForValue(value, worldKinds);
95370
96169
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink) {
95371
96170
  continue;
95372
96171
  }
@@ -95376,6 +96175,7 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95376
96175
  assertWorldLayerLinkBodyCanonical({
95377
96176
  body,
95378
96177
  classesById,
96178
+ storedKeysByClassId,
95379
96179
  classId,
95380
96180
  worldKind,
95381
96181
  label: `Layer link value "${value.id}"`
@@ -95383,18 +96183,23 @@ function assertWorldLayerLinkValueBodiesCanonical(args) {
95383
96183
  }
95384
96184
  }
95385
96185
  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;
96186
+ let storedKeys = args.storedKeysByClassId.get(args.classId);
96187
+ if (storedKeys === void 0) {
96188
+ const keys = /* @__PURE__ */ new Set([
96189
+ "layerOverrideValueId",
96190
+ args.worldKind === NeoWorldSystemClassKind.TileLayerLink ? "Tiles" : "Objects"
96191
+ ]);
96192
+ const visited = /* @__PURE__ */ new Set();
96193
+ let classId = args.classId;
96194
+ while (classId !== null && !visited.has(classId)) {
96195
+ visited.add(classId);
96196
+ const schemaClass2 = args.classesById.get(classId);
96197
+ if (schemaClass2 === void 0) break;
96198
+ for (const key of Object.keys(schemaClass2.schema)) keys.add(key);
96199
+ classId = schemaClass2.extendsClassId ?? null;
96200
+ }
96201
+ storedKeys = keys;
96202
+ args.storedKeysByClassId.set(args.classId, storedKeys);
95398
96203
  }
95399
96204
  for (const key of Object.keys(args.body)) {
95400
96205
  if (storedKeys.has(key)) continue;
@@ -95418,7 +96223,7 @@ function validateWorldPlacementSidecars(args) {
95418
96223
  }
95419
96224
  assertConcreteWorldClass({
95420
96225
  classId: assetClassId,
95421
- classes: args.classes,
96226
+ worldKindsByClassId: args.context.worldKindsByClassId,
95422
96227
  classesById: args.classesById,
95423
96228
  expectedKind: args.isTile ? NeoWorldSystemClassKind.Tile : NeoWorldSystemClassKind.Object,
95424
96229
  label: `Placement value "${args.placement.id}" assetClassId`
@@ -95429,9 +96234,8 @@ function validateWorldPlacementSidecars(args) {
95429
96234
  );
95430
96235
  }
95431
96236
  const compatibleLayerIds = effectiveTargetIds({
95432
- classes: args.classes,
96237
+ context: args.context,
95433
96238
  relationKind: args.isTile ? InternalRecordRelationKind.WorldTileCompatibleLayer : InternalRecordRelationKind.WorldObjectCompatibleLayer,
95434
- relations: args.relations,
95435
96239
  sourceClassId: assetClassId
95436
96240
  });
95437
96241
  if (!compatibleLayerIds.has(args.layerClassId)) {
@@ -95452,7 +96256,7 @@ function validateWorldPlacementSidecars(args) {
95452
96256
  placementId: args.placement.id,
95453
96257
  variantId: optionalNonEmptyString(record4.variantId),
95454
96258
  rowValueId: optionalNonEmptyString(record4.rowValueId),
95455
- variants: args.variants
96259
+ context: args.context
95456
96260
  });
95457
96261
  }
95458
96262
  function validatePlacementVariantBinding(args) {
@@ -95464,9 +96268,7 @@ function validatePlacementVariantBinding(args) {
95464
96268
  }
95465
96269
  return;
95466
96270
  }
95467
- const variant2 = args.variants.find(
95468
- (candidate) => candidate.id === args.variantId
95469
- );
96271
+ const variant2 = args.context.variantsById.get(args.variantId);
95470
96272
  if (variant2 === void 0) {
95471
96273
  throw new Error(
95472
96274
  `Placement value "${args.placementId}" references variant "${args.variantId}", which does not resolve to a live variant record.`
@@ -95486,7 +96288,12 @@ function validatePlacementVariantBinding(args) {
95486
96288
  }
95487
96289
  return;
95488
96290
  }
95489
- if (args.rowValueId === null || !lookupRows.includes(args.rowValueId)) {
96291
+ let rowIds = args.context.lookupRowSets.get(lookupRows);
96292
+ if (rowIds === void 0) {
96293
+ rowIds = new Set(lookupRows);
96294
+ args.context.lookupRowSets.set(lookupRows, rowIds);
96295
+ }
96296
+ if (args.rowValueId === null || !rowIds.has(args.rowValueId)) {
95490
96297
  throw new Error(
95491
96298
  `Placement value "${args.placementId}" must bind a live row from lookup variant "${args.variantId}".`
95492
96299
  );
@@ -95523,7 +96330,7 @@ function assertConcreteWorldClass(args) {
95523
96330
  `${args.label} references missing class "${args.classId}".`
95524
96331
  );
95525
96332
  }
95526
- const actualKind = resolveWorldSystemClassKind(args.classId, args.classes);
96333
+ const actualKind = args.worldKindsByClassId.get(args.classId) ?? null;
95527
96334
  if (actualKind !== args.expectedKind) {
95528
96335
  throw new Error(
95529
96336
  `${args.label} must reference world class kind "${args.expectedKind}", received "${String(actualKind)}".`
@@ -95534,14 +96341,18 @@ function assertConcreteWorldClass(args) {
95534
96341
  }
95535
96342
  }
95536
96343
  function effectiveTargetIds(args) {
95537
- return new Set(
95538
- resolveEffectiveClassRelations(args).map(
95539
- (relation) => relation.targetRecordId
95540
- )
95541
- );
96344
+ const key = `${args.relationKind}:${args.sourceClassId}`;
96345
+ let targets = args.context.targetIds.get(key);
96346
+ if (targets === void 0) {
96347
+ targets = new Set(
96348
+ args.context.relationResolver.resolve(args.relationKind, args.sourceClassId).map((relation) => relation.targetRecordId)
96349
+ );
96350
+ args.context.targetIds.set(key, targets);
96351
+ }
96352
+ return targets;
95542
96353
  }
95543
- function worldKindForValue(value, classes) {
95544
- return typeof value.classId === "string" ? resolveWorldSystemClassKind(value.classId, classes) : null;
96354
+ function worldKindForValue(value, worldKindsByClassId) {
96355
+ return typeof value.classId === "string" ? worldKindsByClassId.get(value.classId) ?? null : null;
95545
96356
  }
95546
96357
  function requiredValueClassId(value, label) {
95547
96358
  if (typeof value.classId === "string" && value.classId.length > 0) {
@@ -95589,13 +96400,11 @@ function optionalNonEmptyString(value) {
95589
96400
  return typeof value === "string" && value.length > 0 ? value : null;
95590
96401
  }
95591
96402
  function consumeWorldPlacementSidecarKeys(args) {
95592
- const worldKind = resolveWorldSystemClassKind(args.classId, args.classes);
96403
+ const worldKind = args.worldKindsByClassId === void 0 ? resolveWorldSystemClassKind(args.classId, args.classes) : args.worldKindsByClassId.get(args.classId) ?? null;
95593
96404
  if (worldKind === null) return /* @__PURE__ */ new Set();
95594
96405
  const assetKind = WORLD_PLACEMENT_ASSET_KIND.get(worldKind);
95595
96406
  if (assetKind === void 0) return /* @__PURE__ */ new Set();
95596
- const classesById = new Map(
95597
- args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
95598
- );
96407
+ const classesById = args.classesById ?? new Map(args.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2]));
95599
96408
  const present = /* @__PURE__ */ new Set();
95600
96409
  for (const key of WORLD_PLACEMENT_SIDECAR_KEYS) {
95601
96410
  if (!Object.hasOwn(args.body, key)) continue;
@@ -95610,7 +96419,7 @@ function consumeWorldPlacementSidecarKeys(args) {
95610
96419
  if (assetClassId !== null) {
95611
96420
  assertConcreteWorldClass({
95612
96421
  classId: assetClassId,
95613
- classes: args.classes,
96422
+ worldKindsByClassId: args.worldKindsByClassId ?? indexWorldSystemClassKinds(args.classes, classesById),
95614
96423
  classesById,
95615
96424
  expectedKind: assetKind,
95616
96425
  label: `${args.label} assetClassId`
@@ -101090,129 +101899,6 @@ var init_general_function_call_ir_source_recompile = __esm({
101090
101899
  }
101091
101900
  });
101092
101901
 
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
101902
  // ../src/database/lookup-target-class-contract.ts
101217
101903
  function lookupTargetClassContractViolation(args) {
101218
101904
  const actualClassId = typeof args.targetClassId === "string" ? args.targetClassId : null;
@@ -101804,6 +102490,7 @@ var StaticBindingGraphValidator;
101804
102490
  var init_project_version_static_value_writes = __esm({
101805
102491
  "../src/database/project-version-static-value-writes.ts"() {
101806
102492
  "use strict";
102493
+ init_classes();
101807
102494
  init_members();
101808
102495
  init_inheritance();
101809
102496
  init_generics();
@@ -101847,6 +102534,10 @@ var init_project_version_static_value_writes = __esm({
101847
102534
  enums: document.enums,
101848
102535
  constructors: document.constructors
101849
102536
  });
102537
+ this.worldKindsByClassId = indexWorldSystemClassKinds(
102538
+ this.schemaIndex.classes,
102539
+ this.schemaIndex.classesById
102540
+ );
101850
102541
  this.virtualValueIds = new Set(virtualValueIds);
101851
102542
  this.mergedView = merged ?? null;
101852
102543
  }
@@ -101859,6 +102550,7 @@ var init_project_version_static_value_writes = __esm({
101859
102550
  localizedTextIds = /* @__PURE__ */ new Set();
101860
102551
  dialogueIds = /* @__PURE__ */ new Set();
101861
102552
  schemaIndex;
102553
+ worldKindsByClassId;
101862
102554
  virtualValueIds;
101863
102555
  declarationMaterializedIndex = null;
101864
102556
  stack = /* @__PURE__ */ new Set();
@@ -102069,6 +102761,8 @@ var init_project_version_static_value_writes = __esm({
102069
102761
  sidecarKeys: ({ body, classId, path }) => consumeWorldPlacementSidecarKeys({
102070
102762
  body,
102071
102763
  classes: this.schemaIndex.classes,
102764
+ classesById: this.schemaIndex.classesById,
102765
+ worldKindsByClassId: this.worldKindsByClassId,
102072
102766
  classId,
102073
102767
  label: path
102074
102768
  }),
@@ -102580,6 +103274,13 @@ function collectOwnedValueDeletionIds(args) {
102580
103274
  function createOwnedValueDeletionCollector(input, knownPlacements) {
102581
103275
  const scope = withVariantPlacementRoots(input);
102582
103276
  const document = scope.document;
103277
+ const classesById = new Map(
103278
+ document.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
103279
+ );
103280
+ const worldKindsByClassId = indexWorldSystemClassKinds(
103281
+ document.classes,
103282
+ classesById
103283
+ );
102583
103284
  const stored = new Map(document.values.map((row) => [row.id, row]));
102584
103285
  const members = new Map(
102585
103286
  document.members.map((member) => [member.id, member])
@@ -102828,16 +103529,15 @@ function createOwnedValueDeletionCollector(input, knownPlacements) {
102828
103529
  const sidecars = consumeWorldPlacementSidecarKeys({
102829
103530
  body: record4,
102830
103531
  classes: document.classes,
103532
+ classesById,
103533
+ worldKindsByClassId,
102831
103534
  classId,
102832
103535
  label: `Value "${body.id}"`
102833
103536
  });
102834
103537
  for (const key of ["assetValueId", "layerOverrideValueId"]) {
102835
103538
  if (key === "assetValueId" && !sidecars.has(key)) continue;
102836
103539
  if (key === "layerOverrideValueId") {
102837
- const worldKind = resolveWorldSystemClassKind(
102838
- classId,
102839
- document.classes
102840
- );
103540
+ const worldKind = worldKindsByClassId.get(classId);
102841
103541
  if (worldKind !== NeoWorldSystemClassKind.TileLayerLink && worldKind !== NeoWorldSystemClassKind.ObjectLayerLink)
102842
103542
  continue;
102843
103543
  }
@@ -103293,7 +103993,7 @@ function* prepareServerOwnedSchemaCommitPasses(args) {
103293
103993
  (change) => change.recordKind === "value"
103294
103994
  );
103295
103995
  const hasAdditionalContractImpact = (args.additionalImpactedIds?.size ?? 0) > 0 || (args.additionalChangedValueIds?.size ?? 0) > 0;
103296
- if (!hasSchemaChange && !hasMigrationChange && !hasDialogueSourceChange && !hasValueChange && !hasAdditionalContractImpact) {
103996
+ if (!hasSchemaChange && !hasMigrationChange && !hasDialogueSourceChange && !hasValueChange && !hasAdditionalContractImpact && (args.authoredValueSeeds?.length ?? 0) === 0) {
103297
103997
  return authoredChanges;
103298
103998
  }
103299
103999
  args.passLifecycle?.("start", "neo-script-recompile-targets");
@@ -104722,6 +105422,7 @@ function drainConstructedGraphValidations(args) {
104722
105422
  }
104723
105423
  }
104724
105424
  function indexAuthoredSeedDocument(document) {
105425
+ const classesById = indexRecordsById(document.classes);
104725
105426
  const declaringClassIdsByMemberId = /* @__PURE__ */ new Map();
104726
105427
  for (const schemaClass2 of document.classes) {
104727
105428
  const declared = /* @__PURE__ */ new Set();
@@ -104738,6 +105439,11 @@ function indexAuthoredSeedDocument(document) {
104738
105439
  }
104739
105440
  }
104740
105441
  return {
105442
+ classesById,
105443
+ worldKindsByClassId: indexWorldSystemClassKinds(
105444
+ document.classes,
105445
+ classesById
105446
+ ),
104741
105447
  valuesById: indexRecordsById(document.values),
104742
105448
  membersById: indexRecordsById(document.members),
104743
105449
  localizedTextIds: new Set(
@@ -105839,6 +106545,8 @@ function materializeAuthoredClassFields(args) {
105839
106545
  const sidecarKeys = consumeWorldPlacementSidecarKeys({
105840
106546
  body: args.row.value,
105841
106547
  classes: args.document.classes,
106548
+ classesById: args.documentIndex.classesById,
106549
+ worldKindsByClassId: args.documentIndex.worldKindsByClassId,
105842
106550
  classId: effectiveClassId,
105843
106551
  label: `Placement value "${args.row.id}"`
105844
106552
  });
@@ -107092,6 +107800,7 @@ var SERVER_COMPILATION_PROJECT_CACHE_LIMIT, serverCompilationProjectCache, READ_
107092
107800
  var init_project_version_schema_commit = __esm({
107093
107801
  "../src/database/project-version-schema-commit.ts"() {
107094
107802
  "use strict";
107803
+ init_classes();
107095
107804
  init_members();
107096
107805
  init_neo_script_derived_bodies();
107097
107806
  init_localized_instance_override_writes();
@@ -107263,7 +107972,7 @@ function systemProtectedWriteInheritedRecordId(write) {
107263
107972
  if (write.baseData !== void 0) return null;
107264
107973
  if (write.deleted) return null;
107265
107974
  if (!isSystemBearingRecordKind(write.recordKind)) return null;
107266
- if (!isPlainRecord3(write.nextData)) return null;
107975
+ if (!isPlainRecord4(write.nextData)) return null;
107267
107976
  if (readSystemMetadata(write.nextData) === null) return null;
107268
107977
  const extendsMemberId = write.nextData.extendsMemberId;
107269
107978
  if (typeof extendsMemberId !== "string") return null;
@@ -107283,7 +107992,7 @@ function assertSystemProtectedRecordWriteValid(write) {
107283
107992
  assertSystemMetadataUnchanged(write, base);
107284
107993
  }
107285
107994
  function readBaseRecord(write) {
107286
- if (!isPlainRecord3(write.baseData)) return null;
107995
+ if (!isPlainRecord4(write.baseData)) return null;
107287
107996
  return {
107288
107997
  recordKind: write.recordKind,
107289
107998
  data: write.baseData,
@@ -107296,7 +108005,7 @@ function collectSystemBearingBaseRecords(document) {
107296
108005
  const stored = document[collection];
107297
108006
  if (!Array.isArray(stored)) continue;
107298
108007
  for (const record4 of stored) {
107299
- if (!isPlainRecord3(record4)) continue;
108008
+ if (!isPlainRecord4(record4)) continue;
107300
108009
  const id2 = record4.id;
107301
108010
  if (typeof id2 !== "string") continue;
107302
108011
  records2.set(baseKey(recordKind, id2), {
@@ -107310,7 +108019,7 @@ function collectSystemBearingBaseRecords(document) {
107310
108019
  }
107311
108020
  function assertCreateDeclaresNoSystemMetadata(write) {
107312
108021
  if (!isSystemBearingRecordKind(write.recordKind)) return;
107313
- if (!isPlainRecord3(write.nextData)) return;
108022
+ if (!isPlainRecord4(write.nextData)) return;
107314
108023
  const system = readSystemMetadata(write.nextData);
107315
108024
  if (system === null) return;
107316
108025
  if (inheritsLegacyEmittedSystemMetadata(write, system)) return;
@@ -107336,7 +108045,7 @@ function assertProtectedRecordNotEdited(change, base) {
107336
108045
  )) {
107337
108046
  return;
107338
108047
  }
107339
- if (!isPlainRecord3(change.nextData)) return;
108048
+ if (!isPlainRecord4(change.nextData)) return;
107340
108049
  if (authoredFieldsEqual(change.recordKind, base.data, change.nextData)) {
107341
108050
  return;
107342
108051
  }
@@ -107345,7 +108054,7 @@ function assertProtectedRecordNotEdited(change, base) {
107345
108054
  );
107346
108055
  }
107347
108056
  function assertSystemMetadataUnchanged(change, base) {
107348
- if (!isPlainRecord3(change.nextData)) return;
108057
+ if (!isPlainRecord4(change.nextData)) return;
107349
108058
  const next = readSystemMetadata(change.nextData);
107350
108059
  if (systemMetadataEqual(base.system, next)) return;
107351
108060
  throw new Error(
@@ -107396,10 +108105,10 @@ function repointedChildValueIds(document, change) {
107396
108105
  );
107397
108106
  if (baseValue === void 0) return [];
107398
108107
  const before = baseValue.value;
107399
- if (!isPlainRecord3(before)) return [];
107400
- if (!isPlainRecord3(change.nextData)) return [];
108108
+ if (!isPlainRecord4(before)) return [];
108109
+ if (!isPlainRecord4(change.nextData)) return [];
107401
108110
  const after = change.nextData.value;
107402
- if (!isPlainRecord3(after)) return [];
108111
+ if (!isPlainRecord4(after)) return [];
107403
108112
  return Object.entries(before).flatMap(([schemaKey, childValueId]) => {
107404
108113
  if (typeof childValueId !== "string") return [];
107405
108114
  if (after[schemaKey] === childValueId) return [];
@@ -107434,7 +108143,7 @@ function isSystemBearingRecordKind(recordKind) {
107434
108143
  );
107435
108144
  }
107436
108145
  function readSystemMetadata(record4) {
107437
- if (!isPlainRecord3(record4)) return null;
108146
+ if (!isPlainRecord4(record4)) return null;
107438
108147
  const system = record4.system;
107439
108148
  if (!isSystemMetadata(system)) return null;
107440
108149
  return system;
@@ -107453,11 +108162,11 @@ function systemReason(system) {
107453
108162
  return SYSTEM_PROTECTION_RULES[system.kind].serverReason;
107454
108163
  }
107455
108164
  function describeChangedRecord(recordKind, recordId, record4) {
107456
- const name = isPlainRecord3(record4) ? record4.name : void 0;
108165
+ const name = isPlainRecord4(record4) ? record4.name : void 0;
107457
108166
  if (typeof name !== "string") return `Record ${recordKind} "${recordId}"`;
107458
108167
  return `Record ${recordKind} "${name}" (${recordId})`;
107459
108168
  }
107460
- function isPlainRecord3(value) {
108169
+ function isPlainRecord4(value) {
107461
108170
  return typeof value === "object" && value !== null && !Array.isArray(value);
107462
108171
  }
107463
108172
  function baseKey(recordKind, recordId) {
@@ -107588,7 +108297,7 @@ function readWorldReferenceList(args) {
107588
108297
  args.keyCandidates
107589
108298
  );
107590
108299
  if (schemaKey === null) return [];
107591
- if (!isPlainRecord4(args.ownerValue.value)) return [];
108300
+ if (!isPlainRecord5(args.ownerValue.value)) return [];
107592
108301
  const listValueId = args.ownerValue.value[schemaKey];
107593
108302
  if (typeof listValueId !== "string") return [];
107594
108303
  const listValue2 = args.graph.valuesById.get(listValueId);
@@ -107654,18 +108363,18 @@ function worldReferenceClassInherits(graph, classId, ancestorClassId) {
107654
108363
  return false;
107655
108364
  }
107656
108365
  function toWorldReferenceClassRecord(value) {
107657
- if (!isPlainRecord4(value)) return null;
108366
+ if (!isPlainRecord5(value)) return null;
107658
108367
  const id2 = stringField2(value, "id");
107659
108368
  if (id2 === null) return null;
107660
108369
  return {
107661
108370
  id: id2,
107662
108371
  extendsClassId: nullableStringField(value, "extendsClassId"),
107663
108372
  schema: isStringRecord8(value.schema) ? value.schema : void 0,
107664
- system: isPlainRecord4(value.system) ? value.system : null
108373
+ system: isPlainRecord5(value.system) ? value.system : null
107665
108374
  };
107666
108375
  }
107667
108376
  function toWorldReferenceValueRecord(value) {
107668
- if (!isPlainRecord4(value)) return null;
108377
+ if (!isPlainRecord5(value)) return null;
107669
108378
  const id2 = stringField2(value, "id");
107670
108379
  if (id2 === null) return null;
107671
108380
  return {
@@ -107679,10 +108388,10 @@ function worldReferenceValueClassId(value) {
107679
108388
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
107680
108389
  }
107681
108390
  function isStringRecord8(value) {
107682
- if (!isPlainRecord4(value)) return false;
108391
+ if (!isPlainRecord5(value)) return false;
107683
108392
  return Object.values(value).every((entry) => typeof entry === "string");
107684
108393
  }
107685
- function isPlainRecord4(value) {
108394
+ function isPlainRecord5(value) {
107686
108395
  return typeof value === "object" && value !== null && !Array.isArray(value);
107687
108396
  }
107688
108397
  function stringField2(value, key) {
@@ -107888,6 +108597,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107888
108597
  const valuesById = new Map(
107889
108598
  document.values.map((value) => [value.id, value])
107890
108599
  );
108600
+ const materializationBatch = createInitializerMaterializationBatch(document);
107891
108601
  let members = document.members;
107892
108602
  const deferred = /* @__PURE__ */ new Set();
107893
108603
  if (defaultInitializerMemberIds.size > 0) {
@@ -107903,7 +108613,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107903
108613
  return deferredMember;
107904
108614
  }
107905
108615
  const materialized = materializeInitializerValue2({
107906
- document: { ...document, values: [...valuesById.values()] },
108616
+ document: materializationBatch.document(),
107907
108617
  member,
107908
108618
  row: {
107909
108619
  id: `animation-validation-default:${member.id}`,
@@ -107913,6 +108623,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107913
108623
  updatedAt: 0
107914
108624
  }
107915
108625
  });
108626
+ materializationBatch.upsert(materialized.createdValues);
107916
108627
  for (const created of materialized.createdValues) {
107917
108628
  valuesById.set(created.id, created);
107918
108629
  }
@@ -107937,10 +108648,14 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
107937
108648
  continue;
107938
108649
  }
107939
108650
  const materialized = materializeInitializerValue2({
107940
- document: { ...document, values: [...valuesById.values()] },
108651
+ document: materializationBatch.document(),
107941
108652
  member,
107942
108653
  row
107943
108654
  });
108655
+ materializationBatch.upsert([
108656
+ materialized.root,
108657
+ ...materialized.createdValues
108658
+ ]);
107944
108659
  valuesById.set(materialized.root.id, materialized.root);
107945
108660
  for (const created of materialized.createdValues) {
107946
108661
  valuesById.set(created.id, created);
@@ -108066,6 +108781,7 @@ function assertStagedWorldContentLayerBindingsValid(current, projected, changes)
108066
108781
  classes,
108067
108782
  relations,
108068
108783
  values: projected.values,
108784
+ placementIds: createdWorldPlacementIds(changes) ?? void 0,
108069
108785
  variants: worldPlacementVariantBindings({
108070
108786
  variants: projected.variants ?? [],
108071
108787
  variantFolders: projected.variantFolders ?? [],
@@ -108089,54 +108805,6 @@ function assertStagedWorldContentLayerBindingsValid(current, projected, changes)
108089
108805
  })
108090
108806
  });
108091
108807
  }
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
108808
  function stagedAffectedWorldLayerLinkClassIds(args) {
108141
108809
  const baseRelationsById = new Map(
108142
108810
  (args.current.internalRecordRelations ?? []).map((relation) => [
@@ -108174,16 +108842,20 @@ function stagedAffectedWorldLayerLinkClassIds(args) {
108174
108842
  if (!changedClassIds.has(relation.targetRecordId)) continue;
108175
108843
  roots.add(relation.sourceRecordId);
108176
108844
  }
108845
+ const childrenByClassId = /* @__PURE__ */ new Map();
108846
+ for (const schemaClass2 of args.classes) {
108847
+ if (schemaClass2.extendsClassId === void 0) continue;
108848
+ const children = childrenByClassId.get(schemaClass2.extendsClassId) ?? [];
108849
+ children.push(schemaClass2.id);
108850
+ childrenByClassId.set(schemaClass2.extendsClassId, children);
108851
+ }
108177
108852
  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;
108853
+ const pending = [...roots];
108854
+ for (let index = 0; index < pending.length; index += 1) {
108855
+ for (const childId of childrenByClassId.get(pending[index]) ?? []) {
108856
+ if (affected.has(childId)) continue;
108857
+ affected.add(childId);
108858
+ pending.push(childId);
108187
108859
  }
108188
108860
  }
108189
108861
  return affected;
@@ -108194,18 +108866,6 @@ function isStagedWorldLayerLinkTargetRelationKind(relationKind) {
108194
108866
  }
108195
108867
  return relationKind === InternalRecordRelationKind.WorldObjectLayerLinkTarget;
108196
108868
  }
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
108869
  function assertStagedProjectInterfaceValid(projected, changes) {
108210
108870
  const relevant = changes.filter(
108211
108871
  (change) => INTERFACE_VALIDATED_RECORD_KINDS.has(change.recordKind)
@@ -108501,10 +109161,11 @@ function assertStagedTileGridReferencesValid(current, projected, changes) {
108501
109161
  classes: current.classes,
108502
109162
  values: []
108503
109163
  });
109164
+ const currentValuesById = new Map(
109165
+ current.values.map((value) => [value.id, value])
109166
+ );
108504
109167
  if (deletedClassIds.size === 0 && [...deletedValueIds].every((valueId) => {
108505
- const value = current.values.find(
108506
- (candidate) => candidate.id === valueId
108507
- );
109168
+ const value = currentValuesById.get(valueId);
108508
109169
  if (value?.classId == null) return true;
108509
109170
  return resolveWorldKindFromClassMap(
108510
109171
  value.classId,
@@ -108552,10 +109213,27 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108552
109213
  const valuesById = new Map(
108553
109214
  projected.values.map((value) => [value.id, value])
108554
109215
  );
109216
+ const labelsByMemberId = /* @__PURE__ */ new Map();
109217
+ const memberClasses = /* @__PURE__ */ new Map();
109218
+ for (const schemaClass2 of projected.classes) {
109219
+ for (const memberId of Object.values(schemaClass2.schema)) {
109220
+ if (!memberClasses.has(memberId))
109221
+ memberClasses.set(memberId, schemaClass2);
109222
+ }
109223
+ }
109224
+ for (const member of variantMembers) {
109225
+ const owner = memberClasses.get(member.id);
109226
+ labelsByMemberId.set(
109227
+ member.id,
109228
+ owner === void 0 ? `Variant member "${member.name}"` : `Variant member "${owner.name}.${member.name}"`
109229
+ );
109230
+ }
109231
+ const admittedClassesByTarget = /* @__PURE__ */ new Map();
109232
+ const lookupRowsByCollection = /* @__PURE__ */ new Map();
108555
109233
  const graded = [];
108556
109234
  for (const member of variantMembers) {
108557
109235
  const declaration = substituteMemberForListenerGrading(member, projected);
108558
- const label = describeVariantMember(member, projected.classes);
109236
+ const label = labelsByMemberId.get(member.id);
108559
109237
  assertVariantMemberTargetValid({ declaration, label, classesById });
108560
109238
  const authored = authoredVariantValue(member);
108561
109239
  if (authored !== void 0) {
@@ -108579,12 +109257,12 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108579
109257
  if (row.value === null || row.value === void 0) continue;
108580
109258
  const ownerId = getMemberId(owner);
108581
109259
  if (ownerId === null) continue;
108582
- const member = projected.members.find((item) => item.id === ownerId);
109260
+ const member = membersById.get(ownerId);
108583
109261
  if (member === void 0) continue;
108584
109262
  graded.push({
108585
109263
  value: row.value,
108586
109264
  declaration: owner,
108587
- label: `${describeVariantMember(member, projected.classes)} row "${rowId}"`
109265
+ label: `${labelsByMemberId.get(member.id)} row "${rowId}"`
108588
109266
  });
108589
109267
  }
108590
109268
  }
@@ -108598,7 +109276,9 @@ function assertStagedVariantMemberValuesValid(projected, changes) {
108598
109276
  foldersById,
108599
109277
  membersById,
108600
109278
  valuesById,
108601
- values: projected.values
109279
+ values: projected.values,
109280
+ admittedClassesByTarget,
109281
+ lookupRowsByCollection
108602
109282
  });
108603
109283
  }
108604
109284
  }
@@ -108661,10 +109341,14 @@ function assertVariantReferenceValid(args) {
108661
109341
  );
108662
109342
  }
108663
109343
  if (target.type === 7 /* Class */ && value.classId !== target.classId) {
108664
- const admitted = descendantClassIds(
108665
- target.classId,
108666
- Array.from(classesById.values())
108667
- );
109344
+ let admitted = args.admittedClassesByTarget.get(target.classId);
109345
+ if (admitted === void 0) {
109346
+ admitted = descendantClassIds(
109347
+ target.classId,
109348
+ Array.from(classesById.values())
109349
+ );
109350
+ args.admittedClassesByTarget.set(target.classId, admitted);
109351
+ }
108668
109352
  if (!admitted.has(value.classId)) {
108669
109353
  const targetName = classesById.get(target.classId)?.name ?? target.classId;
108670
109354
  throw new Error(
@@ -108731,9 +109415,20 @@ function assertVariantReferenceValid(args) {
108731
109415
  }
108732
109416
  const collection = membersById.get(binding.collectionMemberId);
108733
109417
  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
- )) {
109418
+ const rowIsInCollection = () => {
109419
+ if (!isMemberListBase(collection) || collectionValue === void 0)
109420
+ return false;
109421
+ const key = `${binding.collectionMemberId}:${binding.collectionValueId}`;
109422
+ let ids = args.lookupRowsByCollection.get(key);
109423
+ if (ids === void 0) {
109424
+ ids = new Set(
109425
+ listEntryIdsForValue(collection, collectionValue, args.values)
109426
+ );
109427
+ args.lookupRowsByCollection.set(key, ids);
109428
+ }
109429
+ return ids.has(value.rowValueId);
109430
+ };
109431
+ if (!isMemberListBase(collection) || collectionValue === void 0 || !valuesById.has(value.rowValueId) || !rowIsInCollection()) {
108737
109432
  throw new Error(
108738
109433
  `${owner} binds row "${value.rowValueId}", which is not in lookup variant folder "${folder?.path ?? ""}".`
108739
109434
  );
@@ -108778,24 +109473,18 @@ function candidateVariantRowIds(projected, variantMembers) {
108778
109473
  }
108779
109474
  if (schemaKeys.size === 0) continue;
108780
109475
  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);
109476
+ for (const [schemaKey, childId] of Object.entries(row.value)) {
109477
+ if (schemaKeys.has(schemaKey) && typeof childId === "string")
109478
+ candidates.add(childId);
108784
109479
  }
108785
109480
  }
108786
109481
  return candidates;
108787
109482
  }
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
109483
  var KNOWN_TRANSACTION_OPERATIONS, INTERFACE_VALIDATED_RECORD_KINDS, ACTION_LISTENER_TRIGGER_RECORD_KINDS, ACTION_LISTENER_TARGET_KINDS, VARIANT_MEMBER_TRIGGER_RECORD_KINDS;
108796
109484
  var init_project_version_whole_graph_validation = __esm({
108797
109485
  "../src/database/project-version-whole-graph-validation.ts"() {
108798
109486
  "use strict";
109487
+ init_project_world_placement_bindings();
108799
109488
  init_project_version_types();
108800
109489
  init_internal_record_relations();
108801
109490
  init_world_content_sidecar_validation();
@@ -108814,12 +109503,11 @@ var init_project_version_whole_graph_validation = __esm({
108814
109503
  init_neoscript();
108815
109504
  init_constructor_argument_ownership();
108816
109505
  init_materialize_values();
109506
+ init_evaluateInitializer();
108817
109507
  init_world_system_classes();
108818
109508
  init_project_world_reference_graph();
108819
- init_project_record_semantics();
108820
109509
  init_project_version_relation_sweep_trigger();
108821
109510
  init_members();
108822
- init_classes();
108823
109511
  KNOWN_TRANSACTION_OPERATIONS = new Set(
108824
109512
  Object.values(ProjectVersionTransactionOperation)
108825
109513
  );
@@ -109156,6 +109844,12 @@ function computeWorkspaceStatus(workspace, options) {
109156
109844
  sourceSpan: source.span
109157
109845
  };
109158
109846
  });
109847
+ const recordsByKey = new Map(
109848
+ records2.map((record4) => [
109849
+ recordStateKey(record4.recordKind, record4.recordId),
109850
+ record4
109851
+ ])
109852
+ );
109159
109853
  if (projectAnalysisV4 === null) {
109160
109854
  throw new Error(
109161
109855
  "Format-4 project analysis was not produced before static value lowering."
@@ -109208,9 +109902,7 @@ function computeWorkspaceStatus(workspace, options) {
109208
109902
  if (document !== void 0 && isObjectRecord2(document.data)) {
109209
109903
  document.data.collectionValueId = resolvedId;
109210
109904
  }
109211
- const record4 = records2.find(
109212
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109213
- );
109905
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109214
109906
  if (record4 !== void 0 && typeof record4.fileFields.collectionValueId === "string") {
109215
109907
  record4.fileFields.collectionValueId = resolvedId;
109216
109908
  }
@@ -109245,8 +109937,8 @@ function computeWorkspaceStatus(workspace, options) {
109245
109937
  if (document !== void 0 && isObjectRecord2(document.data.binding)) {
109246
109938
  document.data.binding.collectionValueId = resolvedId;
109247
109939
  }
109248
- const record4 = records2.find(
109249
- (candidate) => candidate.recordKind === "variant-folder" && candidate.recordId === folderId
109940
+ const record4 = recordsByKey.get(
109941
+ recordStateKey("variant-folder", folderId)
109250
109942
  );
109251
109943
  if (record4 !== void 0 && isObjectRecord2(record4.fileFields.binding)) {
109252
109944
  record4.fileFields.binding.collectionValueId = resolvedId;
@@ -109295,9 +109987,7 @@ function computeWorkspaceStatus(workspace, options) {
109295
109987
  );
109296
109988
  }
109297
109989
  }
109298
- const record4 = records2.find(
109299
- (candidate) => candidate.recordKind === "member" && candidate.recordId === memberId
109300
- );
109990
+ const record4 = recordsByKey.get(recordStateKey("member", memberId));
109301
109991
  const authored = record4?.fileFields.defaultValue;
109302
109992
  if (isObjectRecord2(authored) && "value" in authored) {
109303
109993
  authored.value = substituteMemberDefaultKeyReferenceV4(
@@ -109413,14 +110103,15 @@ function computeWorkspaceStatus(workspace, options) {
109413
110103
  }
109414
110104
  }
109415
110105
  const deletedValueIds = /* @__PURE__ */ new Set();
110106
+ const brokenFiles = new Set(conflictedFiles);
110107
+ for (const error of parseErrors) {
110108
+ if (isBlockingSchemaSourceError(error)) brokenFiles.add(error.file);
110109
+ }
109416
110110
  for (const [key, recordState] of Object.entries(workspace.state.records)) {
109417
110111
  const recordFile = recordState.file ?? (orphanedStaticMemberKeys.has(key) ? STATIC_MEMBER_OWNERSHIP_RECOVERY_SOURCE : void 0);
109418
110112
  if (recordFile === void 0) continue;
109419
110113
  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;
110114
+ if (brokenFiles.has(recordFile)) continue;
109424
110115
  if (recordState.conflictServerHash === null) continue;
109425
110116
  if (recordState.recordKind === "localized-text" && isLocalizedText(recordState.data) && recordState.data.memberSource !== void 0)
109426
110117
  continue;
@@ -109802,6 +110493,15 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109802
110493
  interfaces: replayDocument.interfaces,
109803
110494
  constructors: replayDocument.constructors ?? []
109804
110495
  });
110496
+ const replayContext = createPulledConstructionReplayContext({
110497
+ document: replayDocument
110498
+ });
110499
+ const constructorsById = new Map(
110500
+ (replayDocument.constructors ?? []).map((constructor2) => [
110501
+ constructor2.id,
110502
+ constructor2
110503
+ ])
110504
+ );
109805
110505
  let documentBodiesCompiled = false;
109806
110506
  const fallbackValues = new Map(
109807
110507
  (fallbackDocument?.values ?? []).map((row) => [row.id, row])
@@ -109827,9 +110527,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109827
110527
  valuesById
109828
110528
  );
109829
110529
  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
- );
110530
+ const requiredConstructor = initializerOwnerClass?.requiredConstructorId === void 0 || initializerOwnerClass.requiredConstructorId === null ? void 0 : constructorsById.get(initializerOwnerClass.requiredConstructorId);
109833
110531
  const requiredArgumentNames = new Set(
109834
110532
  requiredConstructor?.argumentTypes.map((argument2) => argument2.name) ?? []
109835
110533
  );
@@ -109842,6 +110540,7 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
109842
110540
  replay = replayStoredConstructionV4({
109843
110541
  records: pulled,
109844
110542
  document: replayDocument,
110543
+ replayContext,
109845
110544
  valueId: row.id,
109846
110545
  code,
109847
110546
  member: owner,
@@ -110005,13 +110704,16 @@ function expandProspectiveAnimationInstances(document) {
110005
110704
  (row) => isLiteralValueContent(row) && isVirtualInstanceRootShape(row) && typeof row.classId === "string" && classBelongsToAnimationFamily(document.classesById, row.classId)
110006
110705
  );
110007
110706
  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
- });
110707
+ const lookups = cliEvaluatorLookups(
110708
+ {
110709
+ project: document.project,
110710
+ classes: document.classes,
110711
+ constructors: document.constructors,
110712
+ members: document.members,
110713
+ values: document.values
110714
+ },
110715
+ { includeValueGraphIndexes: true }
110716
+ );
110015
110717
  const byId = new Map(document.values.map((row) => [row.id, row]));
110016
110718
  for (const root of animationRoots) {
110017
110719
  for (const row of lookups.virtualInstanceRowsForValue(root.id)) {
@@ -111775,41 +112477,24 @@ function worldKindByClassId(document) {
111775
112477
  for (const classId of classes.keys()) resolve5(classId, /* @__PURE__ */ new Set());
111776
112478
  return result;
111777
112479
  }
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
112480
  function commitPreparationWorldScopeKinds(args) {
112481
+ if (createdWorldPlacementIds(args.changes) !== null)
112482
+ return /* @__PURE__ */ new Set(["tileGrid", "tileLayerLink", "objectLayerLink"]);
111789
112483
  const allKinds = new Set(
111790
- args.postDocument.classes.flatMap(
112484
+ [...args.currentDocument.classes, ...args.postDocument.classes].flatMap(
111791
112485
  (schemaClass2) => typeof schemaClass2.system?.worldKind === "string" ? [schemaClass2.system.worldKind] : []
111792
112486
  )
111793
112487
  );
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();
112488
+ return stagedChangesRequireWorldLayerBindingValidation(
112489
+ args.currentDocument,
112490
+ args.changes
112491
+ ) ? allKinds : /* @__PURE__ */ new Set();
111810
112492
  }
111811
112493
  function commitPreparationMemberDefaultValueScope(args) {
111812
112494
  let evaluatesSource = false;
112495
+ const currentMembersById = new Map(
112496
+ args.currentDocument.members.map((member) => [member.id, member])
112497
+ );
111813
112498
  const constructorsWithSource = new Set(
111814
112499
  (args.postDocument.constructors ?? []).filter(containsAuthoredNeoScriptSource).map((constructor2) => constructor2.classId)
111815
112500
  );
@@ -111883,9 +112568,7 @@ function commitPreparationMemberDefaultValueScope(args) {
111883
112568
  for (const change of args.changes) {
111884
112569
  if (change.recordKind === "member") {
111885
112570
  visitMember(change.recordId);
111886
- const currentMember = args.currentDocument.members.find(
111887
- (member) => member.id === change.recordId
111888
- );
112571
+ const currentMember = currentMembersById.get(change.recordId);
111889
112572
  if (currentMember !== void 0) {
111890
112573
  rememberDefaultIds(currentMember.defaultValue, true);
111891
112574
  }
@@ -111939,9 +112622,7 @@ function planCommitPreparationInitialScope(args) {
111939
112622
  }
111940
112623
  if (change.recordKind === "member") {
111941
112624
  rememberExact("value", derivedMemberValueId(change.recordId), true);
111942
- const current = args.document.members.find(
111943
- (member) => member.id === change.recordId
111944
- );
112625
+ const current = previousMembers.get(change.recordId);
111945
112626
  for (const candidate of [current, change.nextData]) {
111946
112627
  if (candidate === null || typeof candidate !== "object") continue;
111947
112628
  const valueId = Reflect.get(candidate, "valueId");
@@ -111950,16 +112631,23 @@ function planCommitPreparationInitialScope(args) {
111950
112631
  }
111951
112632
  if (change.recordKind !== "localized-text") {
111952
112633
  for (const valueId of collectStoredRecordIds(change.nextData))
111953
- rememberExact("value", valueId, true);
112634
+ rememberExact("value", valueId, change.recordKind !== "value");
112635
+ if (change.recordKind === "value")
112636
+ for (const valueId of collectStoredDescendantRecordIds(change.nextData))
112637
+ rememberExact("value", valueId, true);
111954
112638
  }
111955
112639
  }
112640
+ const currentTextsById = new Map(
112641
+ (args.document.localizedTexts ?? []).map((text) => [text.id, text])
112642
+ );
112643
+ const postValuesById = new Map(
112644
+ postDocument.values.map((row) => [row.id, row])
112645
+ );
111956
112646
  const primary = postDocument.localizationConfig?.mainLocale;
111957
112647
  const primaryEdits = args.changes.flatMap((change) => {
111958
112648
  if (change.recordKind !== "localized-text" || change.operation !== "update" || !isLocalizedText(change.nextData) || primary === void 0)
111959
112649
  return [];
111960
- const old = args.document.localizedTexts?.find(
111961
- (text) => text.id === change.recordId
111962
- );
112650
+ const old = currentTextsById.get(change.recordId);
111963
112651
  return old !== void 0 && memberSourcePrimaryChanged(
111964
112652
  old,
111965
112653
  primary,
@@ -111980,9 +112668,7 @@ function planCommitPreparationInitialScope(args) {
111980
112668
  const target = localizedTextReferenceTarget(link);
111981
112669
  rememberExact(target.recordKind, target.recordId, true);
111982
112670
  if (link.kind === "member-value") {
111983
- const row = postDocument.values.find(
111984
- (value) => value.id === link.valueId
111985
- );
112671
+ const row = postValuesById.get(link.valueId);
111986
112672
  if (row !== void 0)
111987
112673
  linkedValueChanges.push({
111988
112674
  ...target,
@@ -112441,10 +113127,27 @@ function planCommitPreparationLoadedClosureScope(args) {
112441
113127
  });
112442
113128
  }
112443
113129
  }
113130
+ if (args.placementCreationScope && record4.recordKind === "value" && record4.data !== null && typeof record4.data === "object") {
113131
+ const body = Reflect.get(record4.data, "value");
113132
+ if (body !== null && typeof body === "object") {
113133
+ for (const key of [
113134
+ "Children",
113135
+ "Tiles",
113136
+ "Objects",
113137
+ "layerOverrideValueId"
113138
+ ])
113139
+ if (typeof Reflect.get(body, key) === "string")
113140
+ rememberExact("value", Reflect.get(body, key));
113141
+ }
113142
+ }
112444
113143
  if (record4.includeDescendants !== false) {
112445
113144
  for (const valueId of collectStoredRecordIds(record4.data)) {
112446
- rememberDescendant("value", valueId);
113145
+ if (record4.recordKind === "value") rememberExact("value", valueId);
113146
+ else rememberDescendant("value", valueId);
112447
113147
  }
113148
+ if (record4.recordKind === "value")
113149
+ for (const valueId of collectStoredDescendantRecordIds(record4.data))
113150
+ rememberDescendant("value", valueId);
112448
113151
  }
112449
113152
  }
112450
113153
  return {
@@ -112664,9 +113367,14 @@ function readCommitPreparationScopeInMemory(args) {
112664
113367
  key
112665
113368
  );
112666
113369
  }
113370
+ const childKeysSeenByParent = /* @__PURE__ */ new Map();
112667
113371
  const rememberChild = (parentKey, childKey) => {
113372
+ const seen = childKeysSeenByParent.get(parentKey) ?? /* @__PURE__ */ new Set();
113373
+ if (seen.has(childKey)) return;
113374
+ seen.add(childKey);
113375
+ childKeysSeenByParent.set(parentKey, seen);
112668
113376
  const children = childKeysByParentKey.get(parentKey) ?? [];
112669
- if (!children.includes(childKey)) children.push(childKey);
113377
+ children.push(childKey);
112670
113378
  childKeysByParentKey.set(parentKey, children);
112671
113379
  };
112672
113380
  for (const record4 of records2) {
@@ -112882,6 +113590,14 @@ function projectDocumentRecordsByKey(document) {
112882
113590
  add("value", document.values ?? []);
112883
113591
  return result;
112884
113592
  }
113593
+ function collectStoredDescendantRecordIds(value) {
113594
+ if (value === null || typeof value !== "object" || Array.isArray(value))
113595
+ return collectStoredRecordIds(value);
113596
+ const descendants = [];
113597
+ for (const [key, entry] of Object.entries(value))
113598
+ if (key !== "containerId") descendants.push(entry);
113599
+ return collectStoredRecordIds(descendants);
113600
+ }
112885
113601
  function collectStoredRecordIds(value) {
112886
113602
  const result = /* @__PURE__ */ new Set();
112887
113603
  const visit = (candidate) => {
@@ -112920,6 +113636,7 @@ var COMMIT_PREPARATION_SCOPE_RANGE_ROW_LIMIT, COMMIT_PREPARATION_SCOPE_POSTING_R
112920
113636
  var init_project_commit_preparation_scoped_loader = __esm({
112921
113637
  "../src/database/project-commit-preparation-scoped-loader.ts"() {
112922
113638
  "use strict";
113639
+ init_project_world_placement_bindings();
112923
113640
  init_project_localization_rules();
112924
113641
  init_variant_value_graph();
112925
113642
  init_packed_value_write_fold();
@@ -113333,7 +114050,8 @@ function closeInMemoryLoadedScope(args) {
113333
114050
  records: closureRecords,
113334
114051
  rangeLimit: COMMIT_PREPARATION_SCOPE_RANGE_ROW_LIMIT,
113335
114052
  postingLimit: COMMIT_PREPARATION_SCOPE_POSTING_ROW_LIMIT,
113336
- animationSchema
114053
+ animationSchema,
114054
+ placementCreationScope: createdWorldPlacementIds(args.prepared) !== null
113337
114055
  });
113338
114056
  const answer = readCommitPreparationScopeInMemory({
113339
114057
  request,
@@ -113495,6 +114213,7 @@ var init_server_preparation_preflight = __esm({
113495
114213
  init_trusted_commit_verification();
113496
114214
  init_project_version_schema_commit();
113497
114215
  init_project_version_whole_graph_validation();
114216
+ init_project_world_placement_bindings();
113498
114217
  init_projectRecordBuckets();
113499
114218
  init_compile_ns_property();
113500
114219
  init_valueHeadPlacementGraph();
@@ -113534,7 +114253,8 @@ function isPulledInitializerCompilationDocumentV4(document) {
113534
114253
  function createPulledConstructionReplayContext(args) {
113535
114254
  return {
113536
114255
  document: args.document,
113537
- constructorsValidated: false
114256
+ constructorsValidated: false,
114257
+ valuesById: new Map(args.document.values.map((value) => [value.id, value]))
113538
114258
  };
113539
114259
  }
113540
114260
  function pulledInitializerCompilerStateV4(document, compilationProject) {
@@ -113637,7 +114357,7 @@ function replayStoredConstructionV4(args) {
113637
114357
  }
113638
114358
  compilePulledProjectDocumentForEvaluationV4(document, compilationProject);
113639
114359
  }
113640
- const root = document.values.find((value) => value.id === args.valueId);
114360
+ const root = args.replayContext === void 0 ? document.values.find((value) => value.id === args.valueId) : args.replayContext.valuesById.get(args.valueId);
113641
114361
  if (root === void 0) {
113642
114362
  throw new Error(
113643
114363
  `Cannot replay stored construction for missing value "${args.valueId}".`
@@ -128406,6 +129126,55 @@ var init_script = __esm({
128406
129126
  }
128407
129127
  });
128408
129128
 
129129
+ // src/project-source/identity-rewriter.ts
129130
+ function createIdentityRewriter(assignments) {
129131
+ if (assignments.size === 0) return (value) => value;
129132
+ const root = { children: /* @__PURE__ */ new Map() };
129133
+ for (const [source, replacement] of assignments) {
129134
+ let prefix = root;
129135
+ for (let index = 0; index < source.length; index += 1) {
129136
+ const character = source[index];
129137
+ let child = prefix.children.get(character);
129138
+ if (child === void 0) {
129139
+ child = { children: /* @__PURE__ */ new Map() };
129140
+ prefix.children.set(character, child);
129141
+ }
129142
+ prefix = child;
129143
+ }
129144
+ prefix.replacement = replacement;
129145
+ }
129146
+ return (value) => {
129147
+ const exact = assignments.get(value);
129148
+ if (exact !== void 0) return exact;
129149
+ const parts = [];
129150
+ let copiedThrough = 0;
129151
+ for (let start = 0; start < value.length; start += 1) {
129152
+ let prefix = root.children.get(value[start]);
129153
+ let replacement;
129154
+ let end = start;
129155
+ for (let index = start; prefix !== void 0; index += 1) {
129156
+ if (prefix.replacement !== void 0) {
129157
+ replacement = prefix.replacement;
129158
+ end = index + 1;
129159
+ }
129160
+ prefix = prefix.children.get(value[index + 1]);
129161
+ }
129162
+ if (replacement === void 0) continue;
129163
+ parts.push(value.slice(copiedThrough, start), replacement);
129164
+ copiedThrough = end;
129165
+ start = end - 1;
129166
+ }
129167
+ if (copiedThrough === 0) return value;
129168
+ parts.push(value.slice(copiedThrough));
129169
+ return parts.join("");
129170
+ };
129171
+ }
129172
+ var init_identity_rewriter = __esm({
129173
+ "src/project-source/identity-rewriter.ts"() {
129174
+ "use strict";
129175
+ }
129176
+ });
129177
+
128409
129178
  // ../src/database/project-source-identity.ts
128410
129179
  import { createHash as createHash8 } from "node:crypto";
128411
129180
  function hashProjectSourceFiles(inputFiles) {
@@ -129470,20 +130239,10 @@ function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInit
129470
130239
  if (localInitializerMaterialization !== void 0) {
129471
130240
  collect(localInitializerMaterialization);
129472
130241
  }
129473
- const replacements = [...assigned].sort(
129474
- ([left], [right]) => right.length - left.length
129475
- );
130242
+ const rewriteString = createIdentityRewriter(assigned);
129476
130243
  const rewrite = (value) => {
129477
130244
  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;
130245
+ return rewriteString(value);
129487
130246
  }
129488
130247
  if (Array.isArray(value)) return value.map((item) => rewrite(item));
129489
130248
  if (isObjectRecord2(value)) {
@@ -131296,9 +132055,7 @@ function projectTransactionResultReplacements(candidateAssignments, resultAssign
131296
132055
  }
131297
132056
  return {
131298
132057
  exact: replacements,
131299
- embedded: [...replacements].sort(
131300
- ([left], [right]) => right.length - left.length
131301
- )
132058
+ rewrite: createIdentityRewriter(replacements)
131302
132059
  };
131303
132060
  }
131304
132061
  function rewriteReconstructedRecords(records2, replacements) {
@@ -131328,13 +132085,7 @@ function rewriteReconstructedRecords(records2, replacements) {
131328
132085
  return rewritten;
131329
132086
  }
131330
132087
  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;
132088
+ return replacements.rewrite(value);
131338
132089
  }
131339
132090
  function rewriteAssignedValue(value, replacements) {
131340
132091
  if (typeof value === "string") {
@@ -131474,7 +132225,7 @@ function applyPushResult(workspace, result, pendingIdAssignments = /* @__PURE__
131474
132225
  );
131475
132226
  const replacements = {
131476
132227
  exact: pendingIdAssignments,
131477
- embedded: pendingIdAssignments.entries().toArray().sort(([left], [right]) => right.length - left.length)
132228
+ rewrite: createIdentityRewriter(pendingIdAssignments)
131478
132229
  };
131479
132230
  const localRecords = rewriteReconstructedRecords(
131480
132231
  localStatus.reconstructed,
@@ -132154,52 +132905,49 @@ function prepareNSPropertySetterChanges(workspace, status) {
132154
132905
  }
132155
132906
  members.set(change.recordId, change.nextData);
132156
132907
  }
132908
+ const inheritedSetters = /* @__PURE__ */ new Map();
132157
132909
  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)
132910
+ (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
132911
  ).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);
132912
+ for (const memberId of memberDescendantIds(members, removedDeclarations)) {
132913
+ const member = members.get(memberId);
132914
+ if (typeof member.setterCode !== "string" && member.setter === void 0) {
132915
+ continue;
132196
132916
  }
132917
+ const next = { ...member };
132918
+ delete next.setterCode;
132919
+ delete next.setter;
132920
+ members.set(memberId, next);
132921
+ const key = recordStateKey("member", memberId);
132922
+ const reconstructed3 = status.reconstructed.get(key);
132923
+ if (reconstructed3 !== void 0) reconstructed3.fullData = next;
132924
+ const existingChange = changesById.get(memberId);
132925
+ if (existingChange !== void 0) {
132926
+ existingChange.nextData = next;
132927
+ continue;
132928
+ }
132929
+ const base = workspace.state.records[key];
132930
+ if (base === void 0 || reconstructed3 === void 0) {
132931
+ throw new Error(
132932
+ `Cannot cascade removal of NeoScript property setter to override "${memberId}": its working-copy state is missing.`
132933
+ );
132934
+ }
132935
+ const cascadeChange = recordUpsertChange({
132936
+ base,
132937
+ recordKind: "member",
132938
+ recordId: memberId,
132939
+ file: reconstructed3.file,
132940
+ nextData: next
132941
+ });
132942
+ status.changes.push(cascadeChange);
132943
+ changesById.set(memberId, cascadeChange);
132197
132944
  }
132945
+ inheritedSetters.clear();
132198
132946
  for (const member of members.values()) {
132199
132947
  if (member.kind !== 10) continue;
132200
132948
  if (typeof member.extendsMemberId !== "string") continue;
132201
132949
  if (typeof member.setterCode !== "string") continue;
132202
- if (ancestorDeclaresSetter(member, members)) continue;
132950
+ if (ancestorDeclaresSetter(member, members, inheritedSetters)) continue;
132203
132951
  throw new Error(
132204
132952
  `Override NeoScript property "${String(member.name ?? member.id)}" cannot add a setter because its base chain does not declare one.`
132205
132953
  );
@@ -132241,14 +132989,10 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132241
132989
  members.set(next.id, next);
132242
132990
  }
132243
132991
  }
132244
- for (const [memberId, member] of members) {
132992
+ for (const memberId of memberDescendantIds(members, affectedRoots)) {
132993
+ const member = members.get(memberId);
132245
132994
  if (member.kind !== 23 || typeof member.code !== "string") continue;
132246
132995
  if (changesById.has(memberId)) continue;
132247
- if (![...affectedRoots].some(
132248
- (rootId) => memberDescendsFrom(member, rootId, members)
132249
- )) {
132250
- continue;
132251
- }
132252
132996
  const key = recordStateKey("member", memberId);
132253
132997
  const base = workspace.state.records[key];
132254
132998
  const reconstructed3 = status.reconstructed.get(key);
@@ -132268,10 +133012,16 @@ function prepareNSFunctionBodyChanges(workspace, status) {
132268
133012
  changesById.set(memberId, cascadeChange);
132269
133013
  }
132270
133014
  }
132271
- function ancestorDeclaresSetter(member, members) {
133015
+ function ancestorDeclaresSetter(member, members, cache) {
132272
133016
  let parentId = typeof member.extendsMemberId === "string" ? member.extendsMemberId : null;
132273
133017
  const visited = /* @__PURE__ */ new Set();
133018
+ let hasSetter = false;
132274
133019
  while (parentId !== null) {
133020
+ const cached = cache.get(parentId);
133021
+ if (cached !== void 0) {
133022
+ hasSetter = cached;
133023
+ break;
133024
+ }
132275
133025
  if (visited.has(parentId)) {
132276
133026
  throw new Error(
132277
133027
  `Cannot resolve NeoScript property setter inheritance: circular member chain at "${parentId}".`
@@ -132284,23 +133034,35 @@ function ancestorDeclaresSetter(member, members) {
132284
133034
  `Cannot resolve NeoScript property setter inheritance: missing parent member "${parentId}".`
132285
133035
  );
132286
133036
  }
132287
- if (typeof parent.setterCode === "string") return true;
133037
+ if (typeof parent.setterCode === "string") {
133038
+ hasSetter = true;
133039
+ break;
133040
+ }
132288
133041
  parentId = typeof parent.extendsMemberId === "string" ? parent.extendsMemberId : null;
132289
133042
  }
132290
- return false;
133043
+ for (const id2 of visited) cache.set(id2, hasSetter);
133044
+ return hasSetter;
132291
133045
  }
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;
133046
+ function memberDescendantIds(members, rootIds) {
133047
+ const roots = [...rootIds];
133048
+ if (roots.length === 0) return /* @__PURE__ */ new Set();
133049
+ const children = /* @__PURE__ */ new Map();
133050
+ for (const [id2, member] of members) {
133051
+ if (typeof member.extendsMemberId !== "string") continue;
133052
+ const siblings = children.get(member.extendsMemberId);
133053
+ if (siblings === void 0) children.set(member.extendsMemberId, [id2]);
133054
+ else siblings.push(id2);
132302
133055
  }
132303
- return false;
133056
+ const descendants = /* @__PURE__ */ new Set();
133057
+ const pending = [...roots];
133058
+ for (let index = 0; index < pending.length; index += 1) {
133059
+ for (const childId of children.get(pending[index]) ?? []) {
133060
+ if (descendants.has(childId)) continue;
133061
+ descendants.add(childId);
133062
+ pending.push(childId);
133063
+ }
133064
+ }
133065
+ return descendants;
132304
133066
  }
132305
133067
  function resolveNSPropertyReturnTypeInfo2(member, members) {
132306
133068
  let current = member;
@@ -132386,6 +133148,7 @@ var compileNSVoidBody2, compileNSFunction2, compileNSGetter2, compileNSSetter2,
132386
133148
  var init_push = __esm({
132387
133149
  "src/commands/push.ts"() {
132388
133150
  "use strict";
133151
+ init_identity_rewriter();
132389
133152
  init_source_layout();
132390
133153
  init_src();
132391
133154
  init_src2();
@@ -132479,7 +133242,7 @@ var init_registry2 = __esm({
132479
133242
  "schema-contract/registry.mjs"() {
132480
133243
  "use strict";
132481
133244
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
132482
- cliVersion: "0.50.4",
133245
+ cliVersion: "0.50.6",
132483
133246
  projectFileUploadBatchSize: 32,
132484
133247
  documentRecords: {
132485
133248
  member: {
@@ -139695,7 +140458,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
139695
140458
  async function main() {
139696
140459
  const args = parseArgs(process.argv.slice(2));
139697
140460
  if (args.command === "--version") {
139698
- console.log("0.50.4");
140461
+ console.log("0.50.6");
139699
140462
  return;
139700
140463
  }
139701
140464
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {