@neocompose/cli 0.84.2 → 0.84.4

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.
@@ -3100,14 +3100,14 @@ function isNSFunctionContains(value) {
3100
3100
  if (v?.type !== "contains" /* contains */) return false;
3101
3101
  const info = v.info;
3102
3102
  if (typeof info !== "object" || info === null) return false;
3103
- return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
3103
+ return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
3104
3104
  }
3105
3105
  function isNSFunctionIndexOf(value) {
3106
3106
  const v = value;
3107
3107
  if (v?.type !== "indexOf" /* indexOf */) return false;
3108
3108
  const info = v.info;
3109
3109
  if (typeof info !== "object" || info === null) return false;
3110
- return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference);
3110
+ return isNSPointer(info.collectionPointer) && isNSPointer(info.valuePointer) && isReferenceFlag(info.reference) && (info.float === void 0 || info.float === true) && (info.decimal === void 0 || info.decimal === true);
3111
3111
  }
3112
3112
  function isNSFunctionStringOp(value) {
3113
3113
  const v = value;
@@ -3255,7 +3255,7 @@ function isNSFunctionCollectionQuery(value) {
3255
3255
  case "Reverse":
3256
3256
  return true;
3257
3257
  case "ToSet":
3258
- return info.reference === void 0 || info.reference === true;
3258
+ return (info.reference === void 0 || info.reference === true) && (info.decimalEntries === void 0 || info.decimalEntries === true);
3259
3259
  default:
3260
3260
  return false;
3261
3261
  }
@@ -17587,7 +17587,7 @@ var init_registry = __esm({
17587
17587
  "../packages/manifest/schema-contract/registry.mjs"() {
17588
17588
  "use strict";
17589
17589
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
17590
- cliVersion: "0.84.2",
17590
+ cliVersion: "0.84.4",
17591
17591
  projectFileUploadBatchSize: 32,
17592
17592
  documentRecords: {
17593
17593
  member: {
@@ -26056,13 +26056,29 @@ function memberSavedForStorage(ctx, memberId, contextSaved, declarationClassId)
26056
26056
  if (isWritableConstraint(classStorage)) return true;
26057
26057
  if (classStorage === 1 /* Immutable */) return false;
26058
26058
  }
26059
- const effective = ctx.storageResolver.effectiveStorages(memberId);
26059
+ let effective = ctx.storageResolver.effectiveStorages(memberId);
26060
+ const visited = /* @__PURE__ */ new Set([memberId]);
26061
+ let currentId = memberId;
26062
+ let baseId = member?.extendsMemberId;
26063
+ while (effective.size === 0 && baseId !== void 0 && !visited.has(baseId)) {
26064
+ if (!isResolvedAbstract(ctx, currentId) && !isResolvedAbstract(ctx, baseId))
26065
+ break;
26066
+ visited.add(baseId);
26067
+ effective = ctx.storageResolver.effectiveStorages(baseId);
26068
+ currentId = baseId;
26069
+ baseId = ctx.exportData.members[baseId]?.extendsMemberId;
26070
+ }
26060
26071
  const hasWritable = effective.has(2 /* Save */) || effective.has(3 /* Session */);
26061
26072
  const hasStatic = effective.has(1 /* Immutable */);
26062
26073
  if (hasWritable && !hasStatic) return true;
26063
26074
  if (hasStatic && !hasWritable) return false;
26064
26075
  return contextSaved;
26065
26076
  }
26077
+ function isResolvedAbstract(ctx, memberId) {
26078
+ return isAbstractMember(
26079
+ resolveMemberById(ctx, memberId, `members.${memberId}`)
26080
+ );
26081
+ }
26066
26082
  function classAllowedStorage(ctx, classId) {
26067
26083
  return ctx.storageResolver.allowedStorage(classId);
26068
26084
  }
@@ -26952,7 +26968,7 @@ function typeInfoConstructedSuffix(ctx, typeInfo, saved, genericEnv, genericBind
26952
26968
  const argType = csharpTypeInfoValueType(
26953
26969
  ctx,
26954
26970
  argInfo,
26955
- saved,
26971
+ true,
26956
26972
  genericEnv,
26957
26973
  genericBindingSaved
26958
26974
  );
@@ -42179,7 +42195,7 @@ var init_strict_resolver = __esm({
42179
42195
  scope
42180
42196
  )
42181
42197
  );
42182
- const schemaClassInfo = toWireType(targetType, this.project);
42198
+ const schemaClassInfo = this.constructorWireType(targetType, expression);
42183
42199
  if (schemaClassInfo.type !== 7 /* Class */) {
42184
42200
  throw new Error(
42185
42201
  `NeoScript constructor ${className} has non-Class return type ${this.describe(signature.returnType)}.`
@@ -42197,6 +42213,16 @@ var init_strict_resolver = __esm({
42197
42213
  writability: "session" /* Session */
42198
42214
  };
42199
42215
  }
42216
+ /** Constructor storage arguments stay distinct from their expression read types. */
42217
+ constructorWireType(target, expression) {
42218
+ const typeArguments = expression.typeArguments?.map(
42219
+ (argument2) => resolveStoredReferenceTarget(argument2, this.context, this.project)
42220
+ );
42221
+ return toWireType(
42222
+ typeArguments === void 0 ? target : { ...target, typeArguments },
42223
+ this.project
42224
+ );
42225
+ }
42200
42226
  constructorTargetType(schemaClass2, expression, expected) {
42201
42227
  const typeArguments = expression.typeArguments?.map(
42202
42228
  (argument2) => this.resolveType(argument2)
@@ -42327,7 +42353,7 @@ var init_strict_resolver = __esm({
42327
42353
  scope
42328
42354
  );
42329
42355
  const classType = targetType;
42330
- const schemaClassInfo = toWireType(classType, this.project);
42356
+ const schemaClassInfo = this.constructorWireType(classType, expression);
42331
42357
  if (schemaClassInfo.type !== 7 /* Class */) {
42332
42358
  throw new Error(
42333
42359
  `NeoScript declared constructor ${className} projected a non-Class wire type.`
@@ -43190,6 +43216,8 @@ var init_strict_resolver = __esm({
43190
43216
  {
43191
43217
  collectionPointer: receiver.pointer,
43192
43218
  valuePointer: value.pointer,
43219
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
43220
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
43193
43221
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43194
43222
  },
43195
43223
  { kind: "primitive", name: "int" }
@@ -43219,6 +43247,8 @@ var init_strict_resolver = __esm({
43219
43247
  {
43220
43248
  collectionPointer: receiver.pointer,
43221
43249
  valuePointer: value.pointer,
43250
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
43251
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
43222
43252
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43223
43253
  },
43224
43254
  { kind: "primitive", name: "bool" }
@@ -43451,6 +43481,7 @@ var init_strict_resolver = __esm({
43451
43481
  info = {
43452
43482
  ...base,
43453
43483
  op: name,
43484
+ ...isPrimitive(collection.valueType, "decimal") ? { decimalEntries: true } : {},
43454
43485
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43455
43486
  };
43456
43487
  resultType = {
@@ -52165,7 +52196,9 @@ function subscriptKeyType(receiver) {
52165
52196
  return void 0;
52166
52197
  }
52167
52198
  function validateReferenceExpression(expression, declared, scope, environment, uri, range2, diagnostics) {
52168
- const expected = declared?.name === "NeoDialogueReference" ? { ...declared, name: "NeoDialogue" } : declared;
52199
+ let expected = declared?.name === "Reference" ? declared.arguments?.[0] : declared;
52200
+ if (expected?.name === "NeoDialogueReference")
52201
+ expected = { ...expected, name: "NeoDialogue" };
52169
52202
  const typeArguments = expression.typeArguments ?? [];
52170
52203
  const names = expression.argumentNames ?? [];
52171
52204
  const idIndex = names.findIndex((name) => name === "id");
@@ -79236,16 +79269,18 @@ var init_runtime_set = __esm({
79236
79269
  "../packages/neoscript-runtime/src/neoscript/runtime-set.ts"() {
79237
79270
  "use strict";
79238
79271
  RuntimeSet = class {
79239
- constructor(source, reference2, enumEntries, slotReferences = null) {
79272
+ constructor(source, reference2, enumEntries, slotReferences = null, decimalEntries = false) {
79240
79273
  this.source = source;
79241
79274
  this.reference = reference2;
79242
79275
  this.enumEntries = enumEntries;
79243
79276
  this.slotReferences = slotReferences;
79277
+ this.decimalEntries = decimalEntries;
79244
79278
  }
79245
79279
  source;
79246
79280
  reference;
79247
79281
  enumEntries;
79248
79282
  slotReferences;
79283
+ decimalEntries;
79249
79284
  entries = /* @__PURE__ */ new Map();
79250
79285
  validations = /* @__PURE__ */ new Map();
79251
79286
  snapshot;
@@ -79255,6 +79290,9 @@ var init_runtime_set = __esm({
79255
79290
  has(key) {
79256
79291
  return this.entries.has(key);
79257
79292
  }
79293
+ *values() {
79294
+ for (const entry of this.entries.values()) yield entry.raw;
79295
+ }
79258
79296
  add(key, raw, reference2) {
79259
79297
  if (this.entries.has(key)) return;
79260
79298
  this.entries.set(key, { raw, reference: reference2 });
@@ -82723,6 +82761,7 @@ function createdSessionValuesSince(ctx, checkpoint) {
82723
82761
  return created;
82724
82762
  }
82725
82763
  function exportInitializerCollections(created, writes, ctx) {
82764
+ const inPlace = (value) => value instanceof RuntimeSet ? exportRuntimeSetValue(value, ctx) : value;
82726
82765
  const assignedValues = /* @__PURE__ */ new Set();
82727
82766
  const mutatedIds = /* @__PURE__ */ new Set();
82728
82767
  for (const write of writes) {
@@ -82730,83 +82769,134 @@ function exportInitializerCollections(created, writes, ctx) {
82730
82769
  if (destination !== void 0 && "containerValueId" in destination)
82731
82770
  mutatedIds.add(destination.containerValueId);
82732
82771
  if (write.kind === "assign" && write.valueId === void 0 && typeof write.value === "object" && write.value !== null) {
82733
- assignedValues.add(write.value);
82772
+ assignedValues.add(inPlace(write.value));
82734
82773
  }
82735
82774
  }
82736
82775
  const candidates = /* @__PURE__ */ new Set();
82776
+ const inlineFieldsByRowId = /* @__PURE__ */ new Map();
82737
82777
  for (const row of created) {
82738
- if (assignedValues.has(row.value) || row.classId === void 0 && mutatedIds.has(row.id) || Array.isArray(row.value) && row.value.length > 0 && ctx.__unorderedListProjections?.byContainerId.has(row.id)) {
82778
+ const inlineFields = inlineCollectionFields(row, ctx);
82779
+ if (inlineFields !== null) inlineFieldsByRowId.set(row.id, inlineFields);
82780
+ if (inlineFields !== null || assignedValues.has(inPlace(row.value)) || row.classId === void 0 && mutatedIds.has(row.id) || Array.isArray(row.value) && row.value.length > 0 && ctx.__unorderedListProjections?.byContainerId.has(row.id)) {
82739
82781
  candidates.add(row.id);
82740
82782
  }
82741
82783
  }
82742
82784
  if (candidates.size === 0) return created;
82743
82785
  invalidateEvaluatorIndexes(ctx, null);
82744
82786
  const extra = [];
82745
- const exported = created.map((row) => {
82746
- if (!candidates.has(row.id)) return row;
82747
- const member = memberForValueRow(row, ctx);
82748
- if (member === null) return row;
82749
- if (!isMemberWithEntries(member)) return row;
82750
- if (isMemberEntryCollectionBase(member) && listKindOf(member) === 1 /* Unordered */) {
82751
- return { ...row, value: [] };
82752
- }
82753
- if (!assignedValues.has(row.value) && !mutatedIds.has(row.id)) return row;
82754
- const values = [];
82787
+ const encode = (member, value, genericEnv, collectionOwnerId) => {
82788
+ const rows = [];
82755
82789
  const declarations = /* @__PURE__ */ new Map();
82756
- const genericEnv = runtimeGenericEnvForValueRow(row, ctx, /* @__PURE__ */ new Set());
82757
- overlayConcreteGenericEntries(
82758
- genericEnv,
82759
- envFromStamp(row.genericBindings)
82760
- );
82761
- const materialized = materializeConstructorArgumentValue({
82790
+ const root = materializeConstructorArgumentValue({
82762
82791
  member,
82763
- value: row.value,
82792
+ value,
82764
82793
  genericEnv,
82765
82794
  ctx,
82766
- createdValues: values,
82795
+ createdValues: rows,
82767
82796
  createdById: /* @__PURE__ */ new Map(),
82768
82797
  storageKeyDeclarations: declarations,
82769
- collectionEntriesAreReferences: assignedValues.has(row.value) ? false : void 0,
82770
- collectionOwnerId: row.id
82771
- });
82772
- const encoded = { ...row, value: materialized.value };
82773
- const children = values.filter((value) => value !== materialized);
82774
- declarations.delete(materialized.id);
82775
- const groupId = constructorGroupForRow(row.id, ctx);
82776
- retargetConstructorGroupDependencies(
82777
- materialized.id,
82778
- groupId ?? row.id,
82779
- ctx
82780
- );
82798
+ collectionEntriesAreReferences: assignedValues.has(value) ? false : void 0,
82799
+ collectionOwnerId
82800
+ });
82801
+ const children = rows.filter((row) => row !== root);
82802
+ return { root, children, declarations };
82803
+ };
82804
+ const adopt = (owner, rootId, rows, declarations) => {
82805
+ const groupId = constructorGroupForRow(owner.id, ctx);
82806
+ retargetConstructorGroupDependencies(rootId, groupId ?? owner.id, ctx);
82781
82807
  if (groupId !== null) {
82782
82808
  const state = ctx.__executionState;
82783
82809
  const group = state?.constructorGroups.get(groupId);
82784
- for (const child2 of children) {
82785
- retargetConstructorGroupDependencies(child2.id, groupId, ctx);
82786
- group?.add(child2.id);
82787
- state?.constructorGroupByRowId.set(child2.id, groupId);
82810
+ for (const row of rows) {
82811
+ retargetConstructorGroupDependencies(row.id, groupId, ctx);
82812
+ group?.add(row.id);
82813
+ state?.constructorGroupByRowId.set(row.id, groupId);
82788
82814
  }
82789
82815
  }
82790
- stampCreatedValuesMapKey(children, row.mapKey);
82816
+ stampCreatedValuesMapKey(rows, owner.mapKey);
82791
82817
  applyDeclaredStorageKeyOverrides({
82792
- createdValues: [encoded, ...children],
82818
+ createdValues: [owner, ...rows],
82793
82819
  declarationByValueId: declarations
82794
82820
  });
82795
- for (const child2 of children) {
82796
- if (!isLiteralValueContent(child2)) {
82821
+ for (const row of rows) {
82822
+ if (!isLiteralValueContent(row)) {
82797
82823
  throw new NSGetterRuntimeError(
82798
82824
  "Initializer collection produced an unevaluated row."
82799
82825
  );
82800
82826
  }
82801
- extra.push(child2);
82827
+ extra.push(row);
82802
82828
  }
82803
82829
  for (const [id2, declaration] of declarations) {
82804
82830
  ctx.__createdStorageKeyDeclarations?.set(id2, declaration);
82805
82831
  }
82832
+ };
82833
+ const exported = created.map((row) => {
82834
+ if (!candidates.has(row.id)) return row;
82835
+ const inlineFields = inlineFieldsByRowId.get(row.id);
82836
+ if (inlineFields !== void 0) {
82837
+ const record7 = { ...inlineFields.record };
82838
+ const encoded2 = { ...row, value: record7 };
82839
+ for (const [key, member2] of inlineFields.members) {
82840
+ const { root: root2, children: children2, declarations: declarations2 } = encode(
82841
+ member2,
82842
+ inPlace(record7[key]),
82843
+ inlineFields.genericEnv
82844
+ );
82845
+ record7[key] = root2.id;
82846
+ adopt(encoded2, root2.id, [root2, ...children2], declarations2);
82847
+ }
82848
+ return encoded2;
82849
+ }
82850
+ const member = memberForValueRow(row, ctx);
82851
+ if (member === null) return row;
82852
+ if (!isMemberWithEntries(member)) return row;
82853
+ if (isMemberEntryCollectionBase(member) && listKindOf(member) === 1 /* Unordered */) {
82854
+ return { ...row, value: [] };
82855
+ }
82856
+ const value = inPlace(row.value);
82857
+ if (!assignedValues.has(value) && !mutatedIds.has(row.id)) return row;
82858
+ const { root, children, declarations } = encode(
82859
+ member,
82860
+ value,
82861
+ rowGenericEnv(row, ctx),
82862
+ row.id
82863
+ );
82864
+ const encoded = { ...row, value: root.value };
82865
+ declarations.delete(root.id);
82866
+ adopt(encoded, root.id, children, declarations);
82806
82867
  return encoded;
82807
82868
  });
82808
82869
  return [...exported, ...extra];
82809
82870
  }
82871
+ function inlineCollectionFields(row, ctx) {
82872
+ if (typeof row.classId !== "string") return null;
82873
+ if (!isPlainRecord2(row.value)) return null;
82874
+ let fields = null;
82875
+ for (const key in row.value) {
82876
+ const value = row.value[key];
82877
+ if (typeof value !== "object" || value === null) continue;
82878
+ const rawMember = memberForCustomSchemaValue(row.classId, key, ctx);
82879
+ if (rawMember === null) continue;
82880
+ fields ??= {
82881
+ record: row.value,
82882
+ members: /* @__PURE__ */ new Map(),
82883
+ genericEnv: rowGenericEnv(row, ctx)
82884
+ };
82885
+ const member = substituteMember(
82886
+ rawMember,
82887
+ fields.genericEnv,
82888
+ ctx.vm.members,
82889
+ cachedResolvedMember(rawMember, ctx)
82890
+ );
82891
+ if (isMemberWithEntries(member)) fields.members.set(key, member);
82892
+ }
82893
+ return fields === null || fields.members.size === 0 ? null : fields;
82894
+ }
82895
+ function rowGenericEnv(row, ctx) {
82896
+ const genericEnv = runtimeGenericEnvForValueRow(row, ctx, /* @__PURE__ */ new Set());
82897
+ overlayConcreteGenericEntries(genericEnv, envFromStamp(row.genericBindings));
82898
+ return genericEnv;
82899
+ }
82810
82900
  function prepareSessionValueExport(ctx, checkpoint, writes) {
82811
82901
  const created = createdSessionValuesSince(ctx, checkpoint);
82812
82902
  if (created.length === 0) return;
@@ -82857,7 +82947,14 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
82857
82947
  for (let index = 0; index < argumentValues.length; index += 1) {
82858
82948
  const parameter4 = parameters[index];
82859
82949
  if (parameter4 === void 0) continue;
82860
- scope.setLocal(parameter4.id, argumentValues[index]);
82950
+ scope.setLocal(
82951
+ parameter4.id,
82952
+ coerceAssignmentValue(
82953
+ argumentValues[index],
82954
+ parameter4.typeInfo,
82955
+ "getter argument"
82956
+ )
82957
+ );
82861
82958
  }
82862
82959
  try {
82863
82960
  const result = evalBody(
@@ -82867,9 +82964,11 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
82867
82964
  evaluationOptions(runtimeCtx, false)
82868
82965
  );
82869
82966
  if (result.kind === "return") {
82870
- if (getter.typeInfo.type === 20 /* Decimal */ && typeof result.value === "number") {
82871
- result.value = coerceDecimalOperand(result.value, "return");
82872
- }
82967
+ result.value = coerceAssignmentValue(
82968
+ result.value,
82969
+ getter.typeInfo,
82970
+ "return"
82971
+ );
82873
82972
  if (ownsInvocationState) {
82874
82973
  flushRuntimeSets(runtimeCtx);
82875
82974
  result.value = exportRuntimeSetValue(result.value, runtimeCtx);
@@ -83704,7 +83803,11 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
83704
83803
  const parameter4 = action.parameters[index + 2];
83705
83804
  const runtimeTypeInfo = runtimeArgumentTypes[index];
83706
83805
  const value2 = asDeclaredRuntimeSet(
83707
- restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
83806
+ coerceAssignmentValue(
83807
+ restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
83808
+ runtimeTypeInfo,
83809
+ "function argument"
83810
+ ),
83708
83811
  runtimeTypeInfo,
83709
83812
  ctx
83710
83813
  );
@@ -83738,9 +83841,7 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
83738
83841
  }
83739
83842
  return null;
83740
83843
  }
83741
- if (runtimeReturnType.type === 20 /* Decimal */ && typeof value === "number") {
83742
- value = coerceDecimalOperand(value, "function return");
83743
- }
83844
+ value = coerceAssignmentValue(value, runtimeReturnType, "function return");
83744
83845
  if (!runtimeValueMatchesType(value, runtimeReturnType, ctx)) {
83745
83846
  throw new NSGetterRuntimeError(
83746
83847
  "NSFunction returned a value that does not match its compiled return type."
@@ -84079,9 +84180,11 @@ function evalInstructions(instructions, scope, ctx, options) {
84079
84180
  }
84080
84181
  case "variable" /* variable */: {
84081
84182
  let value = evalPointer(ins.variable.pointer, scope, ctx);
84082
- if (ins.variable.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
84083
- value = coerceDecimalOperand(value, "variable initialization");
84084
- }
84183
+ value = coerceAssignmentValue(
84184
+ value,
84185
+ ins.variable.typeInfo,
84186
+ "variable initialization"
84187
+ );
84085
84188
  value = asDeclaredRuntimeSet(value, ins.variable.typeInfo, ctx);
84086
84189
  scope.setLocal(ins.variable.id, value);
84087
84190
  break;
@@ -84117,9 +84220,11 @@ function evalInstructions(instructions, scope, ctx, options) {
84117
84220
  }
84118
84221
  case "assign" /* assign */: {
84119
84222
  let value = evalPointer(ins.pointer, scope, ctx);
84120
- if (ins.target.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
84121
- value = coerceDecimalOperand(value, "assignment");
84122
- }
84223
+ value = coerceAssignmentValue(
84224
+ value,
84225
+ ins.target.typeInfo,
84226
+ "assignment"
84227
+ );
84123
84228
  if (ins.target.pointer.type === "variable" /* variable */) {
84124
84229
  assertVariableBindingWritable(scope, ins.target.pointer.variableId);
84125
84230
  scope.setLocal(ins.target.pointer.variableId, value);
@@ -85893,6 +85998,21 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85893
85998
  );
85894
85999
  }
85895
86000
  const args = ins.args.map((arg) => evalPointer(arg, scope, ctx));
86001
+ const decimalEntries = "entryTypeInfo" in ins.target.typeInfo && ins.target.typeInfo.entryTypeInfo.type === 20 /* Decimal */;
86002
+ let entryArgumentIndex = null;
86003
+ const dictionary = ins.target.typeInfo.type === 5 /* Dictionary */;
86004
+ if (ins.mutation === "Add" /* Add */)
86005
+ entryArgumentIndex = dictionary ? 1 : 0;
86006
+ if (ins.mutation === "Insert" /* Insert */) entryArgumentIndex = 1;
86007
+ if (ins.mutation === "Remove" /* Remove */ && !dictionary)
86008
+ entryArgumentIndex = 0;
86009
+ if (entryArgumentIndex !== null && "entryTypeInfo" in ins.target.typeInfo) {
86010
+ args[entryArgumentIndex] = coerceAssignmentValue(
86011
+ args[entryArgumentIndex],
86012
+ ins.target.typeInfo.entryTypeInfo,
86013
+ "collection mutation entry"
86014
+ );
86015
+ }
85896
86016
  const setEntryMember = mutatesLocalVariable ? null : storedSetEntryMember(targetValue, ctx);
85897
86017
  const isLookupSet = setEntryMember === null && ins.target.typeInfo.type === 9 /* Lookup */;
85898
86018
  if (isLookupSet && Array.isArray(targetValue)) {
@@ -85900,7 +86020,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85900
86020
  targetValue,
85901
86021
  ins.reference === true,
85902
86022
  ins.target.typeInfo.type === 9 /* Lookup */ && (ins.target.typeInfo.entryTypeInfo.type === 8 /* Enum */ || ins.target.typeInfo.entryTypeInfo.type === 18 /* DialogueLookup */),
85903
- ctx
86023
+ ctx,
86024
+ decimalEntries
85904
86025
  );
85905
86026
  }
85906
86027
  const setMatch = setEntryMember !== null && Array.isArray(targetValue) && (ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) ? findStoredSetEntry(targetValue, args[0], setEntryMember, ctx) : null;
@@ -85919,7 +86040,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85919
86040
  ctx,
85920
86041
  isLookupSet,
85921
86042
  false,
85922
- ins.reference === true
86043
+ ins.reference === true,
86044
+ decimalEntries
85923
86045
  );
85924
86046
  updateCollectionReferenceProvenance(
85925
86047
  targetValue,
@@ -85997,7 +86119,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85997
86119
  ctx,
85998
86120
  isLookupSet,
85999
86121
  ins.reference !== true && ins.mutation === "Remove" /* Remove */ && isArrayCollection(targetValue) && setEntryMember === null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
86000
- ins.reference === true
86122
+ ins.reference === true,
86123
+ setEntryMember === null && decimalEntries
86001
86124
  );
86002
86125
  updateCollectionReferenceProvenance(
86003
86126
  targetValue,
@@ -86273,21 +86396,28 @@ function asDeclaredRuntimeSet(value, type, ctx) {
86273
86396
  value,
86274
86397
  entry === 7 /* Class */ || entry === 22 /* Interface */ || entry === 6 /* List */ || entry === 5 /* Dictionary */ || entry === 9 /* Lookup */,
86275
86398
  entry === 8 /* Enum */ || entry === 18 /* DialogueLookup */,
86276
- ctx
86399
+ ctx,
86400
+ entry === 20 /* Decimal */
86277
86401
  );
86278
86402
  }
86279
86403
  function runtimeSetKey(value, set, ctx) {
86280
86404
  if (set.slotReferences !== null) return slotReferenceKey(value);
86281
86405
  if (set.enumEntries && Array.isArray(value) && value.length === 1)
86282
86406
  value = value[0];
86283
- return toSetEntryKey(value, null, set.reference, ctx);
86407
+ return toSetEntryKey(value, null, set.reference, ctx, set.decimalEntries);
86284
86408
  }
86285
- function runtimeSet(array3, reference2, enumEntries, ctx) {
86409
+ function runtimeSet(array3, reference2, enumEntries, ctx, decimalEntries = false) {
86286
86410
  const sets = ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
86287
86411
  ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
86288
86412
  const existing = sets.get(array3);
86289
86413
  if (existing !== void 0) return existing;
86290
- const set = new RuntimeSet(array3, reference2, enumEntries);
86414
+ const set = new RuntimeSet(
86415
+ array3,
86416
+ reference2,
86417
+ enumEntries,
86418
+ null,
86419
+ decimalEntries
86420
+ );
86291
86421
  const references = collectionReferences(array3, ctx);
86292
86422
  for (let index = 0; index < array3.length; index++) {
86293
86423
  const raw = array3[index];
@@ -86406,7 +86536,7 @@ function removableEntryRowIds(targetValue, mutation, args, ctx) {
86406
86536
  }
86407
86537
  return rowIds;
86408
86538
  }
86409
- function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference2 = false) {
86539
+ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference2 = false, decimal2 = false) {
86410
86540
  if (targetValue instanceof RuntimeSet) {
86411
86541
  (ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(targetValue);
86412
86542
  switch (mutation) {
@@ -86458,6 +86588,7 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
86458
86588
  case "Remove" /* Remove */:
86459
86589
  if (Array.isArray(targetValue)) {
86460
86590
  const references = resolveRemovalEntries ? collectionReferences(targetValue, ctx) : recordedReferenceEntries(targetValue, ctx) ?? 1 /* Values */;
86591
+ const targetKey = decimal2 ? decimalCollectionKey(args[0]) : args[0];
86461
86592
  let index = -1;
86462
86593
  for (let candidate = 0; candidate < targetValue.length; candidate += 1) {
86463
86594
  const entry = targetValue[candidate];
@@ -86468,10 +86599,8 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
86468
86599
  }
86469
86600
  continue;
86470
86601
  }
86471
- if (jsEqual(
86472
- typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry,
86473
- args[0]
86474
- )) {
86602
+ const value = typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry;
86603
+ if (jsEqual(decimal2 ? decimalCollectionKey(value) : value, targetKey)) {
86475
86604
  index = candidate;
86476
86605
  break;
86477
86606
  }
@@ -86958,12 +87087,22 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
86958
87087
  case "function" /* function */:
86959
87088
  return evalFunction(pointer.function, scope, ctx);
86960
87089
  case "listLiteral" /* listLiteral */:
86961
- return pointer.entries.map((e) => evalPointer(e, scope, ctx));
87090
+ return pointer.entries.map(
87091
+ (entry) => coerceAssignmentValue(
87092
+ evalPointer(entry, scope, ctx),
87093
+ pointer.typeInfo.entryTypeInfo,
87094
+ "list entry"
87095
+ )
87096
+ );
86962
87097
  case "dictLiteral" /* dictLiteral */: {
86963
87098
  const out = {};
86964
87099
  for (const e of pointer.entries) {
86965
87100
  const k = evalPointer(e.key, scope, ctx);
86966
- out[String(k)] = evalPointer(e.value, scope, ctx);
87101
+ out[String(k)] = coerceAssignmentValue(
87102
+ evalPointer(e.value, scope, ctx),
87103
+ pointer.typeInfo.entryTypeInfo,
87104
+ "dictionary entry"
87105
+ );
86967
87106
  }
86968
87107
  return out;
86969
87108
  }
@@ -88625,9 +88764,9 @@ function readRecordKey(receiver, k, memberId, ctx) {
88625
88764
  if (receiver === ctx.thisValue && typeof ctx.thisValueRowId === "string") {
88626
88765
  return ctx.thisValueRowId;
88627
88766
  }
88628
- const rowId = findKnownRowIdByValueReference(receiver, ctx);
88629
- if (rowId) return rowId;
88630
- throw new NSGetterRuntimeError("Class value has no backing row id.");
88767
+ const row = trackedRowForValueReference(receiver, ctx);
88768
+ if (row !== null && classIdForValueRow(row, ctx) !== void 0)
88769
+ return row.id;
88631
88770
  }
88632
88771
  const assetMember = resolveAssetRuntimeMember(receiver, k, ctx);
88633
88772
  if (assetMember.kind === "ok") return assetMember.value;
@@ -89925,7 +90064,11 @@ function evalDecimalMathOp(info, fn, scope, ctx) {
89925
90064
  }
89926
90065
  }
89927
90066
  function evalListRepeat(info, scope, ctx) {
89928
- const value = evalPointer(info.valuePointer, scope, ctx);
90067
+ const value = coerceAssignmentValue(
90068
+ evalPointer(info.valuePointer, scope, ctx),
90069
+ info.entryTypeInfo,
90070
+ "List.Repeat entry"
90071
+ );
89929
90072
  const count = numberArg(
89930
90073
  evalPointer(info.countPointer, scope, ctx),
89931
90074
  "List.Repeat count"
@@ -90013,13 +90156,18 @@ function jsEqual(a, b) {
90013
90156
  return a instanceof NSSlotReference && b instanceof NSSlotReference && a.targetId === b.targetId;
90014
90157
  }
90015
90158
  if (a === b) return true;
90016
- if (Array.isArray(a) && Array.isArray(b)) {
90017
- if (a.length !== b.length) return false;
90018
- for (let i2 = 0; i2 < a.length; i2++) {
90019
- if (!jsEqual(a[i2], b[i2])) return false;
90159
+ if (Array.isArray(a) || a instanceof RuntimeSet) {
90160
+ if (!Array.isArray(b) && !(b instanceof RuntimeSet)) return false;
90161
+ const aSize = a instanceof RuntimeSet ? a.size : a.length;
90162
+ const bSize = b instanceof RuntimeSet ? b.size : b.length;
90163
+ if (aSize !== bSize) return false;
90164
+ const other = b.values();
90165
+ for (const entry of a.values()) {
90166
+ if (!jsEqual(entry, other.next().value)) return false;
90020
90167
  }
90021
90168
  return true;
90022
90169
  }
90170
+ if (b instanceof RuntimeSet) return false;
90023
90171
  if (typeof a === "object" && typeof b === "object" && a !== null && b !== null && !Array.isArray(a) && !Array.isArray(b)) {
90024
90172
  const aKeys = Object.keys(a);
90025
90173
  const bKeys = Object.keys(b);
@@ -90455,7 +90603,8 @@ function evalCollectionQuery(info, scope, ctx) {
90455
90603
  output,
90456
90604
  info.reference === true,
90457
90605
  info.enumEntries === true,
90458
- ctx
90606
+ ctx,
90607
+ info.decimalEntries === true
90459
90608
  ) : output;
90460
90609
  };
90461
90610
  if (info.op === "OrderBy" || info.op === "OrderByDescending") {
@@ -90507,7 +90656,8 @@ function evalCollectionQuery(info, scope, ctx) {
90507
90656
  entry,
90508
90657
  valueId,
90509
90658
  info.reference === true,
90510
- ctx
90659
+ ctx,
90660
+ info.decimalEntries === true
90511
90661
  );
90512
90662
  if (seenSetKeys.has(setKey)) return 0 /* Continue */;
90513
90663
  seenSetKeys.add(setKey);
@@ -90562,10 +90712,15 @@ function evalCollectionQuery(info, scope, ctx) {
90562
90712
  }
90563
90713
  return finish();
90564
90714
  }
90565
- function toSetEntryKey(entry, valueId, reference2, ctx) {
90715
+ function toSetEntryKey(entry, valueId, reference2, ctx, decimal2 = false) {
90566
90716
  if (reference2) return valueId ?? referenceIdOf(entry, ctx) ?? entry;
90717
+ if (decimal2) return decimalCollectionKey(entry);
90567
90718
  return typeof entry === "object" && entry !== null ? canonicalJsonStringify(entry) : entry;
90568
90719
  }
90720
+ function decimalCollectionKey(value) {
90721
+ if (value === null) return null;
90722
+ return decimalKey(coerceDecimalOperand(value, "decimal collection entry"));
90723
+ }
90569
90724
  function compareCollectionKeys(left, right, keyType) {
90570
90725
  if (left === null) return right === null ? 0 : -1;
90571
90726
  if (right === null) return 1;
@@ -90683,7 +90838,11 @@ function evalFunction(fn, scope, ctx) {
90683
90838
  }
90684
90839
  case "contains" /* contains */: {
90685
90840
  let c = evalPointer(fn.info.collectionPointer, scope, ctx);
90686
- const target = evalPointer(fn.info.valuePointer, scope, ctx);
90841
+ let target = evalPointer(fn.info.valuePointer, scope, ctx);
90842
+ if (fn.info.float === true && typeof target === "number")
90843
+ target = Math.fround(target);
90844
+ if (fn.info.decimal === true && target !== null)
90845
+ target = coerceDecimalOperand(target, "collection search");
90687
90846
  if (typeof c === "string") {
90688
90847
  if (typeof target !== "string") {
90689
90848
  throw new NSGetterRuntimeError(
@@ -90716,9 +90875,13 @@ function evalFunction(fn, scope, ctx) {
90716
90875
  return referenceIndexOf(c, target, ctx) !== null;
90717
90876
  }
90718
90877
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
90878
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
90719
90879
  let containsResolvedEntry = false;
90720
90880
  iterateCollection(c, ctx, (entry, _key, valueId) => {
90721
- if (valueId !== null && valueId === targetReferenceId || jsEqual(entry, target)) {
90881
+ if (valueId !== null && valueId === targetReferenceId || jsEqual(
90882
+ fn.info.decimal ? decimalCollectionKey(entry) : entry,
90883
+ targetKey
90884
+ )) {
90722
90885
  containsResolvedEntry = true;
90723
90886
  return 1 /* Break */;
90724
90887
  }
@@ -90731,15 +90894,21 @@ function evalFunction(fn, scope, ctx) {
90731
90894
  evalPointer(fn.info.collectionPointer, scope, ctx),
90732
90895
  "IndexOf receiver"
90733
90896
  );
90734
- const target = evalPointer(fn.info.valuePointer, scope, ctx);
90897
+ let target = evalPointer(fn.info.valuePointer, scope, ctx);
90898
+ if (fn.info.float === true && typeof target === "number")
90899
+ target = Math.fround(target);
90735
90900
  if (fn.info.reference === true) {
90736
90901
  const index = referenceIndexOf(collection, target, ctx);
90737
90902
  return index === null ? -1 : numberArg(index, "IndexOf index");
90738
90903
  }
90739
90904
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
90905
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
90740
90906
  let found = -1;
90741
90907
  iterateCollection(collection, ctx, (entry, key, valueId) => {
90742
- if (valueId !== null && valueId === targetReferenceId || jsEqual(entry, target)) {
90908
+ if (valueId !== null && valueId === targetReferenceId || jsEqual(
90909
+ fn.info.decimal ? decimalCollectionKey(entry) : entry,
90910
+ targetKey
90911
+ )) {
90743
90912
  found = numberArg(key, "IndexOf index");
90744
90913
  return 1 /* Break */;
90745
90914
  }
@@ -90947,7 +91116,19 @@ function evalFunction(fn, scope, ctx) {
90947
91116
  );
90948
91117
  iterateCollection(c, ctx, callback);
90949
91118
  }
90950
- if (found !== sentinel) return found;
91119
+ if (found !== sentinel) {
91120
+ if (typeof found === "string") {
91121
+ if (c instanceof RuntimeSet) {
91122
+ if (c.enumEntries) return [found];
91123
+ } else {
91124
+ const row = trackedRowForValueReference(c, ctx);
91125
+ const member = row === null ? null : memberForValueRow(row, ctx);
91126
+ if (member?.kind === 8 /* Enum */ || member?.kind === 18 /* DialogueLookup */)
91127
+ return [found];
91128
+ }
91129
+ }
91130
+ return found;
91131
+ }
90951
91132
  if (fn.type === "first" /* first */) {
90952
91133
  throw new NSGetterRuntimeError(
90953
91134
  innerFn ? "First() found no matching entry. Use FirstOrDefault() and handle null if no match is expected." : "First() called on an empty collection. Check that it has entries, or use FirstOrDefault() and handle null."
@@ -92160,10 +92341,19 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
92160
92341
  }
92161
92342
  return null;
92162
92343
  };
92344
+ const defaultScopeMemberId = (memberId) => walkExtendsMemberChain(
92345
+ memberId,
92346
+ ctx.vm.members,
92347
+ (declaration) => declaration.defaultValue === void 0 ? void 0 : declaration.id,
92348
+ {
92349
+ memberById: (id2) => indexes4.schemaIndex.member(id2) ?? null,
92350
+ maxHops: ctx.vm.members.length
92351
+ }
92352
+ );
92163
92353
  return (member, init, sourceValueId, genericEnv = instanceEnv) => {
92164
92354
  const memberId = Reflect.get(member, "id");
92165
92355
  const effectiveMemberId = typeof memberId === "string" ? memberId : null;
92166
- const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? effectiveMemberId;
92356
+ const scopeMemberId = indexes4.initializerScopeMemberIds.get(init) ?? (typeof sourceValueId !== "string" ? void 0 : indexes4.initializerScopeMemberIdsByValueId.get(sourceValueId)) ?? (sourceValueId === void 0 && effectiveMemberId !== null ? defaultScopeMemberId(effectiveMemberId) : void 0) ?? effectiveMemberId;
92167
92357
  const compiled = ensureInitializerCompiled({
92168
92358
  init,
92169
92359
  member,
@@ -94159,6 +94349,7 @@ function clonedConstructorProvenance(source) {
94159
94349
  }
94160
94350
  function cloneConstructorLiteralValue(value) {
94161
94351
  if (typeof value !== "object" || value === null) return value;
94352
+ if (value instanceof NSSlotReference) return value.targetId;
94162
94353
  if (Array.isArray(value)) {
94163
94354
  return value.map((entry) => cloneConstructorLiteralValue(entry));
94164
94355
  }
@@ -96204,7 +96395,7 @@ var init_constructor_argument_ownership = __esm({
96204
96395
  const typeInfo = parameterTypes.get(parameterId);
96205
96396
  return [
96206
96397
  parameterId,
96207
- typeInfo !== void 0 && isAggregateTypeInfo(typeInfo) && typeof argument2 === "string" ? rewriteId(argument2) : argument2
96398
+ typeInfo !== void 0 && (isAggregateTypeInfo(typeInfo) || typeInfo.type === 29 /* Reference */) && typeof argument2 === "string" ? rewriteId(argument2) : argument2
96208
96399
  ];
96209
96400
  }
96210
96401
  )
@@ -96240,6 +96431,41 @@ var init_constructor_argument_ownership = __esm({
96240
96431
  ids.push(edge.targetValueId);
96241
96432
  return ids;
96242
96433
  }
96434
+ /** The targets a row's Reference creation data names (P112 §1.1). */
96435
+ referenceArgumentIds(row) {
96436
+ if (!isLiteralValueContent(row)) return [];
96437
+ const args = row.constructorArgs;
96438
+ if (args === void 0 || args === null) return [];
96439
+ const ids = [];
96440
+ for (const parameterId of this.referenceParameterIds(row)) {
96441
+ const argument2 = args[parameterId];
96442
+ if (typeof argument2 === "string") ids.push(argument2);
96443
+ }
96444
+ return ids;
96445
+ }
96446
+ /** Creation data with each Reference argument's target remapped (P112 §1.1). */
96447
+ remapReferenceArguments(row, remap, contextualMember) {
96448
+ const args = row.constructorArgs;
96449
+ if (args === void 0 || args === null) return args;
96450
+ let remapped;
96451
+ for (const parameterId of this.referenceParameterIds(
96452
+ row,
96453
+ contextualMember
96454
+ )) {
96455
+ const argument2 = args[parameterId];
96456
+ if (typeof argument2 !== "string") continue;
96457
+ const target = remap(argument2);
96458
+ if (target !== argument2) (remapped ??= { ...args })[parameterId] = target;
96459
+ }
96460
+ return remapped ?? args;
96461
+ }
96462
+ *referenceParameterIds(row, contextualMember) {
96463
+ for (const [parameterId, typeInfo] of this.constructorParameterTypes(
96464
+ row,
96465
+ contextualMember
96466
+ ))
96467
+ if (typeInfo.type === 29 /* Reference */) yield parameterId;
96468
+ }
96243
96469
  slotEntries(row) {
96244
96470
  const value = row.value;
96245
96471
  switch (this.referenceSlots(row.id, void 0, value)) {
@@ -98147,7 +98373,11 @@ function resolveVirtualInstanceGraph(args) {
98147
98373
  }
98148
98374
  }
98149
98375
  }
98150
- const virtualRow = rewriteExpandedRow(indexed, expansion);
98376
+ const virtualRow = rewriteExpandedRow(
98377
+ indexed,
98378
+ expansion,
98379
+ materializedGraph
98380
+ );
98151
98381
  const location3 = {
98152
98382
  id: effectiveId2,
98153
98383
  instanceRootId: args.instanceRoot.id,
@@ -99601,6 +99831,16 @@ function sparsifyConstructedInstance(args) {
99601
99831
  protectedValueIds.add(location3.materializedRow.id);
99602
99832
  }
99603
99833
  }
99834
+ const rootId = args.constructed.root.id;
99835
+ const locationValueId = (location3) => args.virtualValueIdForSource?.(rootId, location3.sourceIdentity) ?? location3.virtualRow.id;
99836
+ if (args.bindingTargets !== void 0)
99837
+ pinReferencedSlots(
99838
+ graph,
99839
+ rootId,
99840
+ args.bindingTargets,
99841
+ locationValueId,
99842
+ protectedValueIds
99843
+ );
99604
99844
  let plan;
99605
99845
  try {
99606
99846
  plan = planCollapseVirtualInstance({
@@ -99632,10 +99872,7 @@ function sparsifyConstructedInstance(args) {
99632
99872
  if (real === null || deletedIds.has(real.id)) continue;
99633
99873
  nextIdById.set(
99634
99874
  real.id,
99635
- location3.parentSegment === null ? args.constructed.root.id : args.virtualValueIdForSource?.(
99636
- args.constructed.root.id,
99637
- location3.sourceIdentity
99638
- ) ?? location3.virtualRow.id
99875
+ location3.parentSegment === null ? rootId : locationValueId(location3)
99639
99876
  );
99640
99877
  }
99641
99878
  nextIdById.set(args.constructed.root.id, args.constructed.root.id);
@@ -99734,6 +99971,8 @@ function restoreRowsRetainedRowsName(materializedGraph, rows, updatedValueById,
99734
99971
  updated === void 0 ? row : { ...row, value: updated }
99735
99972
  ))
99736
99973
  restore(valueId);
99974
+ for (const valueId of materializedGraph.referenceArgumentIds(row))
99975
+ restore(valueId);
99737
99976
  entriesByContainerId ??= buildUnorderedListMembershipIndex(rows);
99738
99977
  for (const valueId of entriesByContainerId.get(row.id) ?? [])
99739
99978
  restore(valueId);
@@ -99856,6 +100095,24 @@ function childEnvForRow(member, row, genericEnv, document) {
99856
100095
  }
99857
100096
  return instanceEnv;
99858
100097
  }
100098
+ function pinReferencedSlots(graph, rootId, targets, locationValueId, pinned) {
100099
+ if (targets.ids.size === 0) return;
100100
+ const matched = /* @__PURE__ */ new Set();
100101
+ for (const location3 of graph.locationsByPath.values()) {
100102
+ if (location3.parentSegment === null) continue;
100103
+ const valueId = locationValueId(location3);
100104
+ if (!targets.ids.has(valueId)) continue;
100105
+ matched.add(valueId);
100106
+ if (location3.materializedRow !== null)
100107
+ pinned.add(location3.materializedRow.id);
100108
+ }
100109
+ for (const valueId of targets.pendingIdsByRootId.get(rootId) ?? []) {
100110
+ if (matched.has(valueId)) continue;
100111
+ throw new Error(
100112
+ `A binding names ${valueId}, which construction ${rootId} does not build.`
100113
+ );
100114
+ }
100115
+ }
99859
100116
  function indexExpansion(args) {
99860
100117
  const rowsByExpandedId = args.indexedRows?.rowsById ?? new Map([
99861
100118
  ...args.expandedRows.map((row) => [row.id, row]),
@@ -100122,7 +100379,7 @@ function planAtomicCollectionOverrideWrite(args) {
100122
100379
  childId = parent.id;
100123
100380
  }
100124
100381
  }
100125
- function rewriteExpandedRow(node, expansion) {
100382
+ function rewriteExpandedRow(node, expansion, graph) {
100126
100383
  const rewrite = (id2) => expansion.nodesByExpandedId.get(id2)?.virtualId ?? id2;
100127
100384
  const row = cloneRow(node.expandedRow);
100128
100385
  row.id = node.virtualId;
@@ -100144,6 +100401,12 @@ function rewriteExpandedRow(node, expansion) {
100144
100401
  if (node.member.kind === 9 /* Lookup */) {
100145
100402
  row.value = remapLookupSelection(row.value, rewrite);
100146
100403
  }
100404
+ if (isLiteralValueContent(row) && row.constructorArgs !== void 0)
100405
+ row.constructorArgs = graph.remapReferenceArguments(
100406
+ row,
100407
+ rewrite,
100408
+ node.member
100409
+ );
100147
100410
  if (typeof row.containerId === "string") {
100148
100411
  row.containerId = rewrite(row.containerId);
100149
100412
  }
@@ -100360,6 +100623,18 @@ function memberIdOf(member) {
100360
100623
  function appendVirtualValuePath(parent, segment) {
100361
100624
  return `${parent}/${JSON.stringify(segment)}`;
100362
100625
  }
100626
+ function constructedSlotValueId(rootId, steps) {
100627
+ let pathKey = ROOT_PATH;
100628
+ for (const step of steps)
100629
+ pathKey = appendVirtualValuePath(pathKey, {
100630
+ kind: "class",
100631
+ schemaKey: step.schemaKey
100632
+ });
100633
+ const memberId = steps.at(-1)?.memberId;
100634
+ if (memberId === void 0)
100635
+ throw new Error(`Construction ${rootId} names no slot.`);
100636
+ return derivedVirtualValueId(rootId, `path:${memberId}:${pathKey}`);
100637
+ }
100363
100638
  function parentPathKey(pathKey) {
100364
100639
  if (pathKey === ROOT_PATH) return null;
100365
100640
  const separator = lastPathSeparator(pathKey);
@@ -118701,21 +118976,25 @@ function projectValueHeadPlacementGraph(args) {
118701
118976
  );
118702
118977
  return { ...substituteMember(member, bindings, genericMembers, member) };
118703
118978
  };
118704
- const instanceBindings = (classId, member) => {
118979
+ const instanceBindings = (classId, member, value) => {
118705
118980
  if (classId === null || !genericClassIds.has(classId)) return emptyBindings;
118706
- if (isInterfaceTypedMember(member)) {
118707
- return resolveInstanceEnv(
118708
- classId,
118709
- slotClassArguments(member, classId, implementerIndex()),
118710
- genericClasses
118711
- );
118712
- }
118713
- const arguments_ = member.classArguments;
118981
+ const arguments_ = isInterfaceTypedMember(member) ? slotClassArguments(member, classId, implementerIndex()) : member.classArguments;
118714
118982
  if (arguments_ != null && !isGenericBindingsRecord(arguments_))
118715
118983
  throw new Error(
118716
118984
  `Class placement "${classId}" has malformed generic arguments.`
118717
118985
  );
118718
- return resolveInstanceEnv(classId, arguments_, genericClasses);
118986
+ const env = resolveInstanceEnv(classId, arguments_, genericClasses);
118987
+ const stamp = value?.genericBindings;
118988
+ if (stamp !== void 0) {
118989
+ if (!isStringRecord7(stamp))
118990
+ throw new Error(
118991
+ `Class value "${String(value?.id)}" has malformed genericBindings.`
118992
+ );
118993
+ for (const [paramId, entry] of envFromStamp(stamp))
118994
+ env.set(paramId, entry);
118995
+ closeForwardedGenericParams(env);
118996
+ }
118997
+ return env;
118719
118998
  };
118720
118999
  const unorderedByContainer = /* @__PURE__ */ new Map();
118721
119000
  for (const value of values.values()) {
@@ -118860,7 +119139,7 @@ function projectValueHeadPlacementGraph(args) {
118860
119139
  }
118861
119140
  result.set(item.valueId, projection);
118862
119141
  args.contextualMembers?.set(item.valueId, member);
118863
- const childBindings = classId === null ? item.bindings ?? emptyBindings : instanceBindings(classId, member);
119142
+ const childBindings = classId === null ? item.bindings ?? emptyBindings : instanceBindings(classId, member, value);
118864
119143
  if ((member.kind === 5 /* Dictionary */ || member.kind === 6 /* List */ || member.kind === 28 /* Set */) && childBindings.size > 0) {
118865
119144
  if (!isMemberBase(member))
118866
119145
  throw new Error(
@@ -119060,6 +119339,9 @@ function joinPath(parent, child2) {
119060
119339
  function placementsEqual(left, right) {
119061
119340
  return JSON.stringify(left) === JSON.stringify(right);
119062
119341
  }
119342
+ function isStringRecord7(value) {
119343
+ return isRecord6(value) && Object.values(value).every((entry) => typeof entry === "string");
119344
+ }
119063
119345
  function isRecord6(value) {
119064
119346
  return typeof value === "object" && value !== null && !Array.isArray(value);
119065
119347
  }
@@ -123909,6 +124191,7 @@ var init_collection_binding_materialization = __esm({
123909
124191
  "../src/database/collection-binding-materialization.ts"() {
123910
124192
  "use strict";
123911
124193
  init_members();
124194
+ init_constructor_argument_ownership();
123912
124195
  init_virtual_instance_values();
123913
124196
  init_headless_virtual_instance_lookups();
123914
124197
  init_document_initializer_compiler();
@@ -123925,6 +124208,7 @@ var init_collection_binding_materialization = __esm({
123925
124208
  pathRowsByRootId = /* @__PURE__ */ new Map();
123926
124209
  stored;
123927
124210
  lookups;
124211
+ schema;
123928
124212
  resolvePath(rootId, segments) {
123929
124213
  let id2 = rootId;
123930
124214
  const pathRows = this.pathRowsByRootId.get(rootId) ?? /* @__PURE__ */ new Set();
@@ -123982,17 +124266,20 @@ var init_collection_binding_materialization = __esm({
123982
124266
  valueId: id2,
123983
124267
  value: row.value
123984
124268
  });
124269
+ const created = [];
123985
124270
  for (const create of plan.creates) {
123986
124271
  pathRows?.add(create.id);
123987
124272
  const { valuePlacement: _placement, ...fields } = create;
123988
124273
  const previous = this.rows.get(create.id);
123989
- this.rows.set(create.id, {
124274
+ const row2 = {
123990
124275
  ...fields,
123991
124276
  value: mergeBodies(fields.value, previous?.value),
123992
124277
  projectId: this.document.project.id,
123993
124278
  createdAt: 0,
123994
124279
  updatedAt: 0
123995
- });
124280
+ };
124281
+ this.rows.set(create.id, row2);
124282
+ created.push(row2);
123996
124283
  }
123997
124284
  for (const update of plan.updates) {
123998
124285
  pathRows?.add(update.valueId);
@@ -124006,6 +124293,13 @@ var init_collection_binding_materialization = __esm({
124006
124293
  value: mergeBodies(previous.value, update.value)
124007
124294
  });
124008
124295
  }
124296
+ this.schema ??= new MaterializedValueGraphContext({
124297
+ ...this.document,
124298
+ values: []
124299
+ });
124300
+ for (const row2 of created)
124301
+ for (const targetId of this.schema.referenceArgumentIds(row2))
124302
+ if (graph.rowsById.has(targetId)) this.materialize(targetId, pathRows);
124009
124303
  return true;
124010
124304
  }
124011
124305
  };
@@ -124214,6 +124508,42 @@ var init_prepared_collection_bindings = __esm({
124214
124508
  }
124215
124509
  });
124216
124510
 
124511
+ // ../src/database/declared-binding-targets.ts
124512
+ function declaredBindingTargetIds(document) {
124513
+ const ids = /* @__PURE__ */ new Set();
124514
+ for (const member of document.members) {
124515
+ if (member.kind !== 9 /* Lookup */) continue;
124516
+ if (isMemberCollectionLookupBase(member) && typeof member.collectionValueId === "string")
124517
+ ids.add(member.collectionValueId);
124518
+ const selection2 = isLiteralValueContent(member.defaultValue) ? member.defaultValue.value : void 0;
124519
+ if (typeof selection2 === "string") ids.add(selection2);
124520
+ if (Array.isArray(selection2)) {
124521
+ for (const id2 of selection2) if (typeof id2 === "string") ids.add(id2);
124522
+ }
124523
+ }
124524
+ for (const folder of document.variantFolders ?? [])
124525
+ if (folder.binding !== void 0) ids.add(folder.binding.collectionValueId);
124526
+ for (const group of document.dialogueGroups)
124527
+ if (group.type === 1 /* Lookup */ && typeof group.collectionValueId === "string")
124528
+ ids.add(group.collectionValueId);
124529
+ const pendingIdsByRootId = /* @__PURE__ */ new Map();
124530
+ for (const id2 of ids) {
124531
+ const rootId = pendingVirtualValueIdentity(id2)?.instanceRootId;
124532
+ if (rootId === void 0) continue;
124533
+ const pending = pendingIdsByRootId.get(rootId);
124534
+ if (pending === void 0) pendingIdsByRootId.set(rootId, [id2]);
124535
+ else pending.push(id2);
124536
+ }
124537
+ return { ids, pendingIdsByRootId };
124538
+ }
124539
+ var init_declared_binding_targets = __esm({
124540
+ "../src/database/declared-binding-targets.ts"() {
124541
+ "use strict";
124542
+ init_members();
124543
+ init_member_value_id();
124544
+ }
124545
+ });
124546
+
124217
124547
  // ../src/runtime/stored-closure-captures.ts
124218
124548
  function assertStoredClosuresKeepNoCaptures(args) {
124219
124549
  for (const row of args.rows) {
@@ -124297,6 +124627,61 @@ var init_stored_closure_captures = __esm({
124297
124627
  }
124298
124628
  });
124299
124629
 
124630
+ // ../src/database/construction-replay-equality.ts
124631
+ function createConstructionReplayComparer(reader, ownedValueIds) {
124632
+ let graph;
124633
+ return (args) => {
124634
+ if (!isLiteralValueContent(args.currentRoot)) return false;
124635
+ if (!isLiteralValueContent(args.replayRoot)) return false;
124636
+ if (args.currentRoot.instanceConstructorId !== args.replayRoot.instanceConstructorId)
124637
+ return false;
124638
+ const replayArgs = args.replayRoot.constructorArgs;
124639
+ if (replayArgs === void 0 || replayArgs === null) return true;
124640
+ if (args.currentArguments === void 0 || args.currentArguments === null)
124641
+ return false;
124642
+ graph ??= new MaterializedValueGraphContext(reader.documentView);
124643
+ let owned;
124644
+ for (const edge of graph.constructorEdges(
124645
+ args.currentRoot,
124646
+ args.rootMember
124647
+ )) {
124648
+ const replayed2 = replayArgs[edge.parameterId];
124649
+ if (replayed2 === edge.targetValueId) continue;
124650
+ if (typeof replayed2 === "string" && !args.replayRows.has(replayed2))
124651
+ return false;
124652
+ owned ??= new Set(ownedValueIds(args.currentRoot, args.rootMember));
124653
+ if (!owned.has(edge.targetValueId)) return false;
124654
+ }
124655
+ const stored = { ...args.currentArguments };
124656
+ const replayed = { ...replayArgs };
124657
+ for (const [slot, value] of Object.entries(stored)) {
124658
+ if (typeof value !== "string" || replayed[slot] !== value) continue;
124659
+ delete stored[slot];
124660
+ delete replayed[slot];
124661
+ }
124662
+ return effectiveValuesEqual(
124663
+ reader.normalizeConstructorArguments(
124664
+ stored,
124665
+ args.currentRoot,
124666
+ args.rootMember
124667
+ ),
124668
+ reader.withRowOverrides(args.replayRows).normalizeConstructorArguments(
124669
+ replayed,
124670
+ args.replayRoot,
124671
+ args.rootMember
124672
+ )
124673
+ );
124674
+ };
124675
+ }
124676
+ var init_construction_replay_equality = __esm({
124677
+ "../src/database/construction-replay-equality.ts"() {
124678
+ "use strict";
124679
+ init_effective_value_comparison();
124680
+ init_constructor_argument_ownership();
124681
+ init_members();
124682
+ }
124683
+ });
124684
+
124300
124685
  // ../src/models/project/world-layer-compatibility-error.ts
124301
124686
  var WorldLayerCompatibilityError;
124302
124687
  var init_world_layer_compatibility_error = __esm({
@@ -126304,9 +126689,9 @@ function assertNumberRange(member, value, path) {
126304
126689
  }
126305
126690
  }
126306
126691
  function stringRecord3(value) {
126307
- return isStringRecord7(value) ? value : null;
126692
+ return isStringRecord8(value) ? value : null;
126308
126693
  }
126309
- function isStringRecord7(value) {
126694
+ function isStringRecord8(value) {
126310
126695
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
126311
126696
  return false;
126312
126697
  }
@@ -127942,8 +128327,7 @@ function materializePreparedInstanceInitializers(args) {
127942
128327
  compiledDocument,
127943
128328
  compiledDocument.variants ?? []
127944
128329
  );
127945
- let currentReader = null;
127946
- const requireCurrentReader = () => currentReader ??= new EffectiveValueReader(materializationScope.document);
128330
+ let compareConstruction;
127947
128331
  let ownedValueCollector;
127948
128332
  let valueHashes;
127949
128333
  const liveValueHashes = () => valueHashes ??= indexLiveContentHashesByRecordId(
@@ -127961,6 +128345,7 @@ function materializePreparedInstanceInitializers(args) {
127961
128345
  const localizedTextIds = new Set(
127962
128346
  materializationScope.document.localizedTexts.map((text) => text.id)
127963
128347
  );
128348
+ const bindingTargets = declaredBindingTargetIds(compiledDocument);
127964
128349
  const replayOnlyIndexes = [];
127965
128350
  const pendingSites = /* @__PURE__ */ new Map();
127966
128351
  for (const [valueId, site] of sites) {
@@ -128008,16 +128393,28 @@ function materializePreparedInstanceInitializers(args) {
128008
128393
  `construction-arguments-conflict: Value "${valueId}" is already materialized as class "${String(existingConstructedRoot.classId)}", and this construction builds class "${String(materialized.root.classId)}". Delete and recreate the value to change its class.`
128009
128394
  );
128010
128395
  }
128011
- if (replayedCreationDataMatches({
128012
- // The synthetic variant binding members are part of the ownership
128013
- // scope that compiled and evaluated this initializer. Stored replay
128014
- // closes its generic slot from the same ephemeral member id, so its
128015
- // expansion must read that scoped document too.
128016
- currentReader: requireCurrentReader(),
128396
+ compareConstruction ??= createConstructionReplayComparer(
128397
+ new EffectiveValueReader(materializationScope.document),
128398
+ (root, rootMember) => {
128399
+ ownedValueCollector ??= createOwnedValueDeletionCollector(
128400
+ args.document
128401
+ );
128402
+ return ownedValueCollector.collect({
128403
+ rootIds: [root.id],
128404
+ rootMembers: /* @__PURE__ */ new Map([[root.id, rootMember]])
128405
+ });
128406
+ }
128407
+ );
128408
+ const replayRows = new Map(
128409
+ materialized.createdValues.map((row) => [row.id, row])
128410
+ );
128411
+ replayRows.set(materialized.root.id, materialized.root);
128412
+ if (compareConstruction({
128017
128413
  currentRoot: existingConstructedRoot,
128414
+ currentArguments: isLiteralValueContent(existingConstructedRoot) ? existingConstructedRoot.constructorArgs : void 0,
128018
128415
  rootMember: member,
128019
128416
  replayRoot: materialized.root,
128020
- replayCreated: materialized.createdValues
128417
+ replayRows
128021
128418
  })) {
128022
128419
  replayOnlyIndexes.push(site.index);
128023
128420
  batch.upsert([existingConstructedRoot]);
@@ -128050,7 +128447,8 @@ function materializePreparedInstanceInitializers(args) {
128050
128447
  // the class default, so the evaluated construction's own field list is
128051
128448
  // what pins rows against collapse.
128052
128449
  pinnedRootSchemaKeys: materialized.pinnedRootSchemaKeys,
128053
- pinnedSchemaKeysByValueId: materialized.pinnedSchemaKeysByValueId
128450
+ pinnedSchemaKeysByValueId: materialized.pinnedSchemaKeysByValueId,
128451
+ bindingTargets
128054
128452
  });
128055
128453
  assertStoredClosuresKeepNoCaptures({
128056
128454
  sourceValueId: valueId,
@@ -128137,46 +128535,6 @@ function materializePreparedInstanceInitializers(args) {
128137
128535
  args.prepared.splice(index, 1);
128138
128536
  }
128139
128537
  }
128140
- function replayedCreationDataMatches(args) {
128141
- if (!isLiteralValueContent(args.currentRoot) || !isLiteralValueContent(args.replayRoot)) {
128142
- return false;
128143
- }
128144
- const replayArgs = args.replayRoot.constructorArgs;
128145
- if (replayArgs !== void 0 && replayArgs !== null) {
128146
- const currentArgs = args.currentRoot.constructorArgs;
128147
- if (currentArgs === void 0 || currentArgs === null || !constructorArgumentsSemanticallyEqual({
128148
- currentReader: args.currentReader,
128149
- currentRoot: args.currentRoot,
128150
- rootMember: args.rootMember,
128151
- current: currentArgs,
128152
- replayRoot: args.replayRoot,
128153
- replayCreated: args.replayCreated,
128154
- replay: replayArgs
128155
- })) {
128156
- return false;
128157
- }
128158
- }
128159
- return true;
128160
- }
128161
- function constructorArgumentsSemanticallyEqual(args) {
128162
- const current = args.currentReader;
128163
- const replayRows = /* @__PURE__ */ new Map([
128164
- [args.replayRoot.id, args.replayRoot]
128165
- ]);
128166
- for (const row of args.replayCreated) replayRows.set(row.id, row);
128167
- const replay = current.withRowOverrides(replayRows);
128168
- const currentNormalized = current.normalizeConstructorArguments(
128169
- args.current,
128170
- args.currentRoot,
128171
- args.rootMember
128172
- );
128173
- const replayNormalized = replay.normalizeConstructorArguments(
128174
- args.replay,
128175
- args.replayRoot,
128176
- args.rootMember
128177
- );
128178
- return effectiveValuesEqual(currentNormalized, replayNormalized);
128179
- }
128180
128538
  function completeLocalizedTextCreateEnvelopes(args) {
128181
128539
  const createsLocalizedText = args.changes.some(
128182
128540
  (change) => change.recordKind === "localized-text" && change.operation === "create"
@@ -131217,9 +131575,10 @@ var init_project_version_schema_commit = __esm({
131217
131575
  init_neoscript_compiler_revision();
131218
131576
  init_neoscript_source_catalog();
131219
131577
  init_prepared_collection_bindings();
131578
+ init_declared_binding_targets();
131220
131579
  init_stored_closure_captures();
131221
131580
  init_document_initializer_compiler();
131222
- init_effective_value_comparison();
131581
+ init_construction_replay_equality();
131223
131582
  init_classes();
131224
131583
  init_constructor_parameter_settlement();
131225
131584
  init_generics();
@@ -137709,7 +138068,7 @@ function toWorldReferenceClassRecord(value) {
137709
138068
  return {
137710
138069
  id: id2,
137711
138070
  extendsClassId: nullableStringField(value, "extendsClassId"),
137712
- schema: isStringRecord8(value.schema) ? value.schema : void 0,
138071
+ schema: isStringRecord9(value.schema) ? value.schema : void 0,
137713
138072
  system: isPlainRecord8(value.system) ? value.system : null
137714
138073
  };
137715
138074
  }
@@ -137727,7 +138086,7 @@ function worldReferenceValueClassId(value) {
137727
138086
  if (value === void 0) return null;
137728
138087
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
137729
138088
  }
137730
- function isStringRecord8(value) {
138089
+ function isStringRecord9(value) {
137731
138090
  if (!isPlainRecord8(value)) return false;
137732
138091
  return Object.values(value).every((entry) => typeof entry === "string");
137733
138092
  }
@@ -146847,15 +147206,27 @@ function retainConstructionArguments(context, row, schemaClass2, expression, sou
146847
147206
  const constructorArgs2 = row.constructorArgs;
146848
147207
  if (!isObjectRecord(constructorArgs2)) return;
146849
147208
  if (row.instanceConstructorId === null) return;
146850
- const constructor2 = storedValueConstructor(
146851
- context,
146852
- schemaClass2,
146853
- recordedStoredConstructorId(row, schemaClass2)
147209
+ const constructorId = recordedStoredConstructorId(row, schemaClass2);
147210
+ const stored = context.state[`constructor:${constructorId}`]?.data;
147211
+ if (!isObjectRecord(stored)) {
147212
+ throw new Error(
147213
+ `Stored construction for ${schemaClass2.name} names missing pulled constructor ${constructorId}.`
147214
+ );
147215
+ }
147216
+ if (stored.classId !== schemaClass2.id) {
147217
+ throw new Error(
147218
+ `Stored constructor ${constructorId} does not belong to ${schemaClass2.name}.`
147219
+ );
147220
+ }
147221
+ const argumentsValue = documentArgumentsToManifest(
147222
+ stored.argumentTypes,
147223
+ { recordKind: "constructor", recordId: constructorId, data: stored },
147224
+ schemaClass2.source.span
146854
147225
  );
146855
147226
  const authoredArguments = constructorArgumentExpressions(expression);
146856
147227
  const argumentEnvironment = valueGenericEnvironment(row, environment);
146857
- for (let index = 0; index < constructor2.arguments.length; index += 1) {
146858
- const argument2 = constructor2.arguments[index];
147228
+ for (let index = 0; index < argumentsValue.length; index += 1) {
147229
+ const argument2 = argumentsValue[index];
146859
147230
  if (argument2 === void 0) continue;
146860
147231
  const valueId = constructorArgs2[`__arg_${index}__`];
146861
147232
  if (typeof valueId !== "string") continue;
@@ -147641,6 +148012,7 @@ function lowerRawMemberTypeName(context, memberId) {
147641
148012
  if (member.kind === 8 /* Enum */ && typeof member.enumId === "string") {
147642
148013
  return context.enumNames.get(member.enumId) ?? null;
147643
148014
  }
148015
+ if (member.kind === 9 /* Lookup */) return "Reference";
147644
148016
  if (member.kind === 6 /* List */) return "List";
147645
148017
  if (member.kind === 28 /* Set */) return "Set";
147646
148018
  if (member.kind === 5 /* Dictionary */) return "Dictionary";
@@ -147655,6 +148027,8 @@ function lowerSchemaMemberTypeName(context, member) {
147655
148027
  return context.referenceTypes().interfaceImplementers().interface(member.interfaceId)?.name ?? null;
147656
148028
  case "enum":
147657
148029
  return context.enumNames.get(member.enumId) ?? null;
148030
+ case "lookup":
148031
+ return "Reference";
147658
148032
  case "list":
147659
148033
  return "List";
147660
148034
  case "set":
@@ -150655,10 +151029,15 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150655
151029
  throw new Error(
150656
151030
  `Stored constructor argument cannot be typed by interface type parameter ${type.genericParamId} of ${type.ownerInterfaceId}.`
150657
151031
  );
150658
- case "generic":
151032
+ case "generic": {
151033
+ const binding = storedGenericArgumentType(context, type, environment);
151034
+ const argumentType = binding.kind === "reference" ? withSchemaTypeNullability(
151035
+ referenceReadType2(context, binding.target),
151036
+ binding.nullable
151037
+ ) : binding;
150659
151038
  return storedConstructorArgumentSource(
150660
151039
  context,
150661
- storedGenericArgumentType(context, type, environment),
151040
+ argumentType,
150662
151041
  value,
150663
151042
  environment,
150664
151043
  visited,
@@ -150666,6 +151045,7 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150666
151045
  partial,
150667
151046
  constructorOwnsGraph
150668
151047
  );
151048
+ }
150669
151049
  case "interface":
150670
151050
  case "list":
150671
151051
  case "set":
@@ -150701,6 +151081,11 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150701
151081
  false
150702
151082
  );
150703
151083
  case "reference":
151084
+ if (typeof value !== "string") {
151085
+ throw new Error(
151086
+ "Stored Reference constructor argument is not a target id."
151087
+ );
151088
+ }
150704
151089
  return referenceValue(
150705
151090
  context,
150706
151091
  {
@@ -150708,7 +151093,7 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150708
151093
  name: "argument",
150709
151094
  kind: 9 /* Lookup */
150710
151095
  },
150711
- value,
151096
+ [value],
150712
151097
  false,
150713
151098
  storedTypeArgumentName(context, type.target, environment)
150714
151099
  );
@@ -150857,8 +151242,14 @@ function schemaTypeForBindingMember(context, memberId, environment, visited = /*
150857
151242
  };
150858
151243
  case "lookup": {
150859
151244
  if (member.declaredType !== null) {
150860
- const target = referenceReadType2(context, member.declaredType);
150861
- return member.collectionMemberId === null && member.multiselect ? { kind: "lookup", nullable: nullable2, entryType: target } : withSchemaTypeNullability(target, nullable2);
151245
+ if (member.collectionMemberId === null && member.multiselect) {
151246
+ return {
151247
+ kind: "lookup",
151248
+ nullable: nullable2,
151249
+ entryType: referenceReadType2(context, member.declaredType)
151250
+ };
151251
+ }
151252
+ return { kind: "reference", nullable: nullable2, target: member.declaredType };
150862
151253
  }
150863
151254
  if (member.collectionMemberId === null) {
150864
151255
  throw new Error(
@@ -151427,7 +151818,8 @@ function resolveGenericValueMember(context, member, environment) {
151427
151818
  }
151428
151819
  return {
151429
151820
  ...bindingMember,
151430
- id: member.id,
151821
+ // Lookup emission reads the binding's declared target and collection.
151822
+ id: bindingMember.kind === 9 /* Lookup */ ? bindingMemberId : member.id,
151431
151823
  name: member.name,
151432
151824
  defaultValue: member.defaultValue,
151433
151825
  ...member.payload === 1 /* Partial */ ? { payload: 1 /* Partial */ } : {}
@@ -151505,7 +151897,8 @@ function resolveGenericSchemaMember(context, member, environment) {
151505
151897
  }
151506
151898
  const resolved = {
151507
151899
  ...bindingMember,
151508
- id: member.id,
151900
+ // Deferred reference checks resolve this concrete lookup declaration.
151901
+ id: bindingMember.kind === "lookup" ? bindingMemberId : member.id,
151509
151902
  name: member.name,
151510
151903
  defaultValue: member.defaultValue
151511
151904
  };
@@ -153164,8 +153557,15 @@ function reconcileMaterializedInitializersV4(args) {
153164
153557
  );
153165
153558
  }
153166
153559
  let currentRows;
153167
- let currentReader;
153560
+ let compareConstruction;
153168
153561
  let ownedValues;
153562
+ const storedOwnedValues = () => {
153563
+ if (ownedValues !== void 0) return ownedValues;
153564
+ const storedDocument = currentState().document;
153565
+ compilePulledUncompiledConstructorsV4(storedDocument);
153566
+ assertPulledConstructorsCompiled(storedDocument);
153567
+ return ownedValues = createOwnedValueDeletionCollector(storedDocument);
153568
+ };
153169
153569
  const rebuilds = [];
153170
153570
  for (const reconciliation of constructions.values()) {
153171
153571
  if (!replayableValueIds.has(reconciliation.valueId)) continue;
@@ -153217,8 +153617,14 @@ function reconcileMaterializedInitializersV4(args) {
153217
153617
  currentState().document,
153218
153618
  replayDocument
153219
153619
  );
153220
- currentReader ??= new EffectiveValueReader(
153221
- storedRowsDocument(replayDocument, currentRows)
153620
+ compareConstruction ??= createConstructionReplayComparer(
153621
+ new EffectiveValueReader(storedRowsDocument(replayDocument, currentRows)),
153622
+ (root, member) => {
153623
+ return storedOwnedValues().collect({
153624
+ rootIds: [root.id],
153625
+ rootMembers: /* @__PURE__ */ new Map([[root.id, member]])
153626
+ });
153627
+ }
153222
153628
  );
153223
153629
  const replay = replayRows.get(reconciliation.valueId);
153224
153630
  if (replay === void 0) {
@@ -153248,13 +153654,12 @@ function reconcileMaterializedInitializersV4(args) {
153248
153654
  );
153249
153655
  continue;
153250
153656
  }
153251
- if (reconciliation.kind === "storedArguments" && storedArgumentsMatch({
153252
- reader: currentReader,
153253
- stored: reconciliation.storedConstructorArgs,
153657
+ if (reconciliation.kind === "storedArguments" && compareConstruction({
153254
153658
  currentRoot,
153255
- replay,
153659
+ currentArguments: reconciliation.storedConstructorArgs,
153660
+ replayRoot: replay,
153256
153661
  replayRows,
153257
- owner
153662
+ rootMember: owner
153258
153663
  })) {
153259
153664
  continue;
153260
153665
  }
@@ -153266,11 +153671,10 @@ function reconcileMaterializedInitializersV4(args) {
153266
153671
  `Cannot rebuild construction for value "${reconciliation.valueId}": its pulled row is missing.`
153267
153672
  );
153268
153673
  }
153269
- ownedValues ??= createOwnedValueDeletionCollector(replayDocument);
153270
153674
  rebuilds.push({
153271
153675
  valueId: reconciliation.valueId,
153272
153676
  row: rebuiltConstructionRow(stored, reconciliation.code),
153273
- ownedValueIds: ownedValues.collect({
153677
+ ownedValueIds: storedOwnedValues().collect({
153274
153678
  rootIds: [reconciliation.valueId],
153275
153679
  rootMembers: /* @__PURE__ */ new Map([[reconciliation.valueId, owner]])
153276
153680
  })
@@ -153313,22 +153717,6 @@ function sameCompiledProgram(left, right) {
153313
153717
  return literal3 && key === "value" ? isDeepStrictEqual(left[key], right[key]) : sameCompiledProgram(left[key], right[key]);
153314
153718
  });
153315
153719
  }
153316
- function storedArgumentsMatch(args) {
153317
- const replayArgs = isLiteralValueContent(args.replay) ? args.replay.constructorArgs : void 0;
153318
- if (!isObjectRecord(replayArgs)) return false;
153319
- const [storedArgs, replayedArgs] = withoutSharedArguments(
153320
- args.stored,
153321
- replayArgs
153322
- );
153323
- return effectiveValuesEqual(
153324
- args.reader.normalizeConstructorArguments(
153325
- storedArgs,
153326
- args.currentRoot,
153327
- args.owner
153328
- ),
153329
- args.reader.withRowOverrides(args.replayRows).normalizeConstructorArguments(replayedArgs, args.replay, args.owner)
153330
- );
153331
- }
153332
153720
  function rebuiltConstructionRow(data, code) {
153333
153721
  return { ...withoutMaterializedInstanceFields(data), init: { code } };
153334
153722
  }
@@ -153443,16 +153831,6 @@ function storedRowsWithRenamedKeys(before, after) {
153443
153831
  }
153444
153832
  return rows;
153445
153833
  }
153446
- function withoutSharedArguments(stored, replayed) {
153447
- const storedRest = { ...stored };
153448
- const replayedRest = { ...replayed };
153449
- for (const [slot, value] of Object.entries(stored)) {
153450
- if (typeof value !== "string" || replayed[slot] !== value) continue;
153451
- delete storedRest[slot];
153452
- delete replayedRest[slot];
153453
- }
153454
- return [storedRest, replayedRest];
153455
- }
153456
153834
  function pulledStateDocumentV4(workspace) {
153457
153835
  const state = workspace.state.records;
153458
153836
  const remembered = pulledStateDocuments.get(state);
@@ -153539,6 +153917,7 @@ function materializeInitializersLocallyV4(args) {
153539
153917
  const localizedTextIds = new Set(
153540
153918
  authoredDocument.localizedTexts?.map((text) => text.id)
153541
153919
  );
153920
+ const bindingTargets = declaredBindingTargetIds(authoredDocument);
153542
153921
  const pendingRoots = new Set(
153543
153922
  [...sourceRoots].filter((id2) => rootKinds.get(id2) !== "declaration").sort()
153544
153923
  );
@@ -153735,6 +154114,7 @@ function materializeInitializersLocallyV4(args) {
153735
154114
  // pins rows against collapse. Push preparation pins the same set.
153736
154115
  pinnedRootSchemaKeys: pinned.pinnedRootSchemaKeys,
153737
154116
  pinnedSchemaKeysByValueId: pinned.pinnedSchemaKeysByValueId,
154117
+ bindingTargets,
153738
154118
  virtualValueIdForSource: (instanceRootId, sourceIdentity3) => isPendingId(instanceRootId) || hasPendingVirtualSourceIdentity(sourceIdentity3) ? pendingVirtualValueId(instanceRootId, sourceIdentity3) : virtualValueId(instanceRootId, sourceIdentity3)
153739
154119
  });
153740
154120
  const evaluatedRows = [sparse2.root, ...sparse2.createdChildren];
@@ -153917,7 +154297,7 @@ var init_local_initializer_materialization = __esm({
153917
154297
  init_stored_closure_captures();
153918
154298
  init_initializer_dependencies();
153919
154299
  init_initializer_replay();
153920
- init_effective_value_comparison();
154300
+ init_construction_replay_equality();
153921
154301
  init_constructor_argument_ownership();
153922
154302
  init_neo_script_recompile_scope();
153923
154303
  init_compiler_adapter();
@@ -153931,6 +154311,7 @@ var init_local_initializer_materialization = __esm({
153931
154311
  init_inheritance();
153932
154312
  init_effective_value_reader();
153933
154313
  init_virtual_instance_values();
154314
+ init_declared_binding_targets();
153934
154315
  init_value_graph();
153935
154316
  init_pending_id();
153936
154317
  init_value_comparison();
@@ -156980,7 +157361,7 @@ function quote4(value) {
156980
157361
  function resolveRootPathCollectionValuesV4(args) {
156981
157362
  const resolved = /* @__PURE__ */ new Map();
156982
157363
  let rootValues;
156983
- let placements;
157364
+ let walk;
156984
157365
  for (const member of args.manifest.members) {
156985
157366
  if (member.kind !== "lookup") continue;
156986
157367
  const spelled = member.collectionValueId;
@@ -157002,16 +157383,9 @@ function resolveRootPathCollectionValuesV4(args) {
157002
157383
  };
157003
157384
  const target = walkRootValuePath(
157004
157385
  path,
157005
- args.state,
157006
- args.registry,
157007
- () => placements ??= prospectiveStoredValuePlacements(
157008
- args.state,
157009
- args.registry,
157010
- args.manifest
157011
- ),
157386
+ walk ??= valuePathWalk(args),
157012
157387
  rootValues,
157013
157388
  fail2,
157014
- args.resolveVirtualPath,
157015
157389
  args.unavailableSlots
157016
157390
  );
157017
157391
  if (target !== null) resolved.set(member.id, target);
@@ -157021,7 +157395,7 @@ function resolveRootPathCollectionValuesV4(args) {
157021
157395
  function resolveRootPathVariantFolderCollectionValuesV4(args) {
157022
157396
  const resolved = /* @__PURE__ */ new Map();
157023
157397
  let rootValues;
157024
- let placements;
157398
+ let walk;
157025
157399
  for (const folder of args.manifest.variantFolders) {
157026
157400
  const spelled = folder.binding?.collectionValueId;
157027
157401
  if (typeof spelled !== "string") continue;
@@ -157042,16 +157416,9 @@ function resolveRootPathVariantFolderCollectionValuesV4(args) {
157042
157416
  };
157043
157417
  const target = walkRootValuePath(
157044
157418
  path,
157045
- args.state,
157046
- args.registry,
157047
- () => placements ??= prospectiveStoredValuePlacements(
157048
- args.state,
157049
- args.registry,
157050
- args.manifest
157051
- ),
157419
+ walk ??= valuePathWalk(args),
157052
157420
  rootValues,
157053
157421
  fail2,
157054
- args.resolveVirtualPath,
157055
157422
  args.unavailableSlots
157056
157423
  );
157057
157424
  if (target !== null) resolved.set(folder.id, target);
@@ -157059,83 +157426,87 @@ function resolveRootPathVariantFolderCollectionValuesV4(args) {
157059
157426
  return resolved;
157060
157427
  }
157061
157428
  function createRootValuePathResolverV4(args) {
157062
- let placements;
157429
+ const walk = valuePathWalk(args);
157063
157430
  let rootValues;
157064
- let computed;
157065
- const readPlacements = () => placements ??= prospectiveStoredValuePlacements(
157066
- args.state,
157067
- args.registry,
157068
- args.manifest
157069
- );
157070
- const settle = (walk2) => {
157431
+ const settle = (resolve7) => {
157071
157432
  const failures = [];
157072
- const valueId = walk2((failure) => failures.push(failure));
157433
+ const valueId = resolve7((failure) => failures.push(failure));
157073
157434
  if (valueId !== null) {
157074
157435
  const stored = args.state[`value:${valueId}`] !== void 0 || args.registry.pendingValues.has(valueId);
157075
157436
  return {
157076
157437
  kind: "resolved",
157077
157438
  valueId,
157078
- memberId: readPlacements().placementByChildValueId.get(valueId)?.memberId ?? null,
157439
+ memberId: walk.placements().placementByChildValueId.get(valueId)?.memberId ?? null,
157079
157440
  ...stored ? {} : { virtual: true }
157080
157441
  };
157081
157442
  }
157082
157443
  const message = failures[0];
157083
157444
  return message === void 0 ? { kind: "unavailable" } : { kind: "failed", message };
157084
157445
  };
157085
- const walk = () => ({
157086
- state: args.state,
157087
- registry: args.registry,
157088
- placements: readPlacements,
157089
- resolveVirtualPath: args.resolveVirtualPath,
157090
- isComputed: computed ??= computedMemberTest(args.manifest)
157091
- });
157092
157446
  return {
157093
157447
  root: (path) => settle((fail2) => {
157094
157448
  if (rootValues === void 0) rootValues = rootSlotValueIds(args.state);
157095
157449
  return walkRootValuePath(
157096
157450
  path,
157097
- args.state,
157098
- args.registry,
157099
- readPlacements,
157451
+ walk,
157100
157452
  rootValues,
157101
157453
  fail2,
157102
- args.resolveVirtualPath,
157103
157454
  args.unavailableSlots,
157104
- "Index path",
157105
- walk().isComputed
157455
+ "Index path"
157106
157456
  );
157107
157457
  }),
157108
157458
  from: (valueId, segments, path) => settle(
157109
- (fail2) => walkValueSegments(walk(), valueId, segments, path, "Reference", fail2)
157459
+ (fail2) => walkValueSegments(walk, valueId, segments, path, "Reference", fail2)
157110
157460
  )
157111
157461
  };
157112
157462
  }
157113
- function computedMemberTest(manifest) {
157463
+ function valuePathWalk(args) {
157464
+ let placements;
157465
+ let schema;
157466
+ return {
157467
+ state: args.state,
157468
+ registry: args.registry,
157469
+ placements: () => placements ??= prospectiveStoredValuePlacements(
157470
+ args.state,
157471
+ args.registry,
157472
+ args.manifest
157473
+ ),
157474
+ schema: () => schema ??= manifestSchemaIndex(args.manifest),
157475
+ resolveVirtualPath: args.resolveVirtualPath,
157476
+ initBuiltSlots: args.initBuiltSlots ?? "derive"
157477
+ };
157478
+ }
157479
+ function manifestSchemaIndex(manifest) {
157114
157480
  const classes = new Map(
157115
157481
  manifest.classes.map((schemaClass2) => [schemaClass2.id, schemaClass2])
157116
157482
  );
157117
- const computed = new Set(
157118
- manifest.members.flatMap(
157119
- (member) => member.kind === "computed" ? [member.id] : []
157120
- )
157483
+ const members = new Map(
157484
+ manifest.members.map((member) => [member.id, member])
157121
157485
  );
157122
- return (valueId, name, walk) => {
157123
- const pending = walk.registry.pendingValues.get(valueId);
157124
- const stored = walk.state[`value:${valueId}`]?.data;
157125
- const classId = pending?.nodeType === "literal" ? pending.classId : isObjectRecord(stored) ? stored.classId : void 0;
157126
- const visited = /* @__PURE__ */ new Set();
157127
- let cursor = typeof classId === "string" ? classes.get(classId) : void 0;
157128
- while (cursor !== void 0 && !visited.has(cursor.id)) {
157129
- visited.add(cursor.id);
157130
- const memberId = cursor.schema[name];
157131
- if (memberId !== void 0) return computed.has(memberId);
157132
- cursor = cursor.extendsClassId === null || cursor.extendsClassId === void 0 ? void 0 : classes.get(cursor.extendsClassId);
157486
+ return {
157487
+ member: (memberId) => members.get(memberId),
157488
+ schemaMember: (classId, schemaKey) => {
157489
+ const visited = /* @__PURE__ */ new Set();
157490
+ let cursor = classes.get(classId);
157491
+ while (cursor !== void 0 && !visited.has(cursor.id)) {
157492
+ visited.add(cursor.id);
157493
+ const memberId = cursor.schema[schemaKey];
157494
+ if (memberId !== void 0) return members.get(memberId);
157495
+ cursor = cursor.extendsClassId === null ? void 0 : classes.get(cursor.extendsClassId);
157496
+ }
157497
+ return void 0;
157133
157498
  }
157134
- return false;
157135
157499
  };
157136
157500
  }
157501
+ function isComputedMember(walk, valueId, name) {
157502
+ const pending = walk.registry.pendingValues.get(valueId);
157503
+ const stored = walk.state[`value:${valueId}`]?.data;
157504
+ const storedClassId = isObjectRecord(stored) ? stored.classId : void 0;
157505
+ const classId = pending?.nodeType === "literal" ? pending.classId : storedClassId;
157506
+ return typeof classId === "string" && walk.schema().schemaMember(classId, name)?.kind === "computed";
157507
+ }
157137
157508
  function resolveRootPathDialogueGroupCollectionValuesV4(args) {
157138
- let placements;
157509
+ let walk;
157139
157510
  let rootValues;
157140
157511
  for (const record7 of args.records) {
157141
157512
  if (record7.recordKind !== "dialogue-group") continue;
@@ -157145,13 +157516,7 @@ function resolveRootPathDialogueGroupCollectionValuesV4(args) {
157145
157516
  if (rootValues === void 0) rootValues = rootSlotValueIds(args.state);
157146
157517
  const target = walkRootValuePath(
157147
157518
  spelled.slice(ROOT_PATH_PENDING_PREFIX.length),
157148
- args.state,
157149
- args.registry,
157150
- () => placements ??= prospectiveStoredValuePlacements(
157151
- args.state,
157152
- args.registry,
157153
- args.manifest
157154
- ),
157519
+ walk ??= valuePathWalk(args),
157155
157520
  rootValues,
157156
157521
  (message) => args.registry.loweringFailures.push({
157157
157522
  message,
@@ -157165,7 +157530,6 @@ function resolveRootPathDialogueGroupCollectionValuesV4(args) {
157165
157530
  label: String(record7.fileFields.name)
157166
157531
  }
157167
157532
  }),
157168
- args.resolveVirtualPath,
157169
157533
  args.unavailableSlots
157170
157534
  );
157171
157535
  if (target !== null) record7.fileFields.collectionValueId = target;
@@ -157184,7 +157548,7 @@ function rootSlotValueIds(state) {
157184
157548
  }
157185
157549
  return values;
157186
157550
  }
157187
- function walkRootValuePath(path, state, registry, placements, rootValues, fail2, resolveVirtualPath, unavailableSlots, subject = "collectionValue path", isComputed) {
157551
+ function walkRootValuePath(path, walk, rootValues, fail2, unavailableSlots, subject = "collectionValue path") {
157188
157552
  const segments = path.split(".");
157189
157553
  const slotName = segments[1];
157190
157554
  if (segments[0] !== "root" || slotName === void 0) {
@@ -157211,7 +157575,7 @@ function walkRootValuePath(path, state, registry, placements, rootValues, fail2,
157211
157575
  return null;
157212
157576
  }
157213
157577
  return walkValueSegments(
157214
- { state, registry, placements, resolveVirtualPath, isComputed },
157578
+ walk,
157215
157579
  slotValueId,
157216
157580
  segments.slice(2),
157217
157581
  path,
@@ -157221,7 +157585,7 @@ function walkRootValuePath(path, state, registry, placements, rootValues, fail2,
157221
157585
  }
157222
157586
  function walkValueSegments(walk, startId, segments, path, subject, fail2) {
157223
157587
  let cursor = startId;
157224
- for (const segment of segments) {
157588
+ for (const [index, segment] of segments.entries()) {
157225
157589
  const pending = walk.registry.pendingValues.get(cursor);
157226
157590
  const body = (pending?.nodeType === "literal" ? pending.value : void 0) ?? (isObjectRecord(walk.state[`value:${cursor}`]?.data) ? (walk.state[`value:${cursor}`]?.data).value : void 0);
157227
157591
  if (Array.isArray(body)) {
@@ -157232,12 +157596,21 @@ function walkValueSegments(walk, startId, segments, path, subject, fail2) {
157232
157596
  }
157233
157597
  if (!isObjectRecord(body)) {
157234
157598
  const initializer = pending !== void 0 ? pending.nodeType === "initializer" : isInitValueContent(walk.state[`value:${cursor}`]?.data);
157235
- if (initializer) {
157599
+ if (initializer && walk.initBuiltSlots === "refuse") {
157236
157600
  fail2(
157237
- `${subject} ${path} stops before segment ${segment}: an init block constructs the row it reaches, so a path cannot name its members yet.`
157601
+ `${subject} ${path} stops before segment ${segment}: an init block constructs the row it reaches, so a value cannot name its members. Bind it from a declaration instead.`
157238
157602
  );
157239
157603
  return null;
157240
157604
  }
157605
+ if (initializer)
157606
+ return constructedSlotId(
157607
+ walk,
157608
+ cursor,
157609
+ segments.slice(index),
157610
+ path,
157611
+ subject,
157612
+ fail2
157613
+ );
157241
157614
  fail2(
157242
157615
  `${subject} ${path} stops before segment ${segment}: the row it reaches stores no single-valued members.`
157243
157616
  );
@@ -157249,7 +157622,7 @@ function walkValueSegments(walk, startId, segments, path, subject, fail2) {
157249
157622
  const direct = directBody && typeof bodyId === "string" && (walk.registry.pendingValues.has(bodyId) || storedChild?.recordKind === "value" && storedChild.recordId === bodyId && isObjectRecord(storedChild.data));
157250
157623
  const next = direct ? bodyId : walk.placements().childrenByParentValueId.get(cursor)?.get(segment)?.childValueId;
157251
157624
  if (typeof next !== "string") {
157252
- if (walk.isComputed?.(cursor, segment, walk) === true) {
157625
+ if (isComputedMember(walk, cursor, segment)) {
157253
157626
  fail2(
157254
157627
  `\`${path}\` names a computed member, which has no row to reference.`
157255
157628
  );
@@ -157277,6 +157650,66 @@ function walkValueSegments(walk, startId, segments, path, subject, fail2) {
157277
157650
  }
157278
157651
  return cursor;
157279
157652
  }
157653
+ function constructedSlotId(walk, rootId, segments, path, subject, fail2) {
157654
+ const schema = walk.schema();
157655
+ const placement = walk.placements().placementByChildValueId.get(rootId);
157656
+ if (placement === void 0) {
157657
+ fail2(
157658
+ `${subject} ${path} reaches init-built row ${rootId}, which no row places.`
157659
+ );
157660
+ return null;
157661
+ }
157662
+ const rootMemberId = placement.memberId;
157663
+ if (rootMemberId === null) {
157664
+ fail2(
157665
+ `${subject} ${path} reaches init-built row ${rootId}, which its parent's class declares no member for.`
157666
+ );
157667
+ return null;
157668
+ }
157669
+ let member = schema.member(rootMemberId);
157670
+ const steps = [];
157671
+ for (const segment of segments) {
157672
+ if (member?.kind !== "class") {
157673
+ fail2(
157674
+ `${subject} ${path} stops before segment ${segment}: the row an init block builds there stores no single-valued members.`
157675
+ );
157676
+ return null;
157677
+ }
157678
+ const slot = schema.schemaMember(member.classId, segment);
157679
+ if (slot === void 0) {
157680
+ fail2(
157681
+ `${subject} ${path} has no value at segment ${segment}: class ${member.classId} declares no such member.`
157682
+ );
157683
+ return null;
157684
+ }
157685
+ if (slot.kind === "computed") {
157686
+ fail2(
157687
+ `\`${path}\` names a computed member, which has no row to reference.`
157688
+ );
157689
+ return null;
157690
+ }
157691
+ steps.push({ schemaKey: segment, memberId: slot.id });
157692
+ member = slot;
157693
+ }
157694
+ if (member !== void 0 && hasRowTargetKind(member)) {
157695
+ fail2(
157696
+ `${subject} ${path} names a ${member.kind} an init block builds, which has no row to check against until the push stores it.`
157697
+ );
157698
+ return null;
157699
+ }
157700
+ return constructedSlotValueId(rootId, steps);
157701
+ }
157702
+ function hasRowTargetKind(member) {
157703
+ switch (member.kind) {
157704
+ case "class":
157705
+ case "list":
157706
+ case "set":
157707
+ case "dictionary":
157708
+ return true;
157709
+ default:
157710
+ return false;
157711
+ }
157712
+ }
157280
157713
  function prospectiveStoredValuePlacements(state, registry, manifest) {
157281
157714
  const records3 = new Map(
157282
157715
  Object.values(state).map((record7) => [
@@ -157341,6 +157774,7 @@ var init_root_source = __esm({
157341
157774
  init_project_root();
157342
157775
  init_value_comparison();
157343
157776
  init_members();
157777
+ init_virtual_instance_graph();
157344
157778
  init_value_sources();
157345
157779
  init_source_format();
157346
157780
  init_stored_value_placements();
@@ -160640,7 +161074,8 @@ function computeStatus(workspace, options, conflictedFiles, parseErrors, parseWa
160640
161074
  state: rootPathResolutionState,
160641
161075
  resolveVirtualPath,
160642
161076
  unavailableSlots: rootValues.unavailableSlots,
160643
- registry: valueLowerRegistry
161077
+ registry: valueLowerRegistry,
161078
+ initBuiltSlots: "derive"
160644
161079
  });
160645
161080
  const resolvedDefaultKeys = resolveKeyReferenceMemberDefaultsV4({
160646
161081
  manifest,
@@ -160995,7 +161430,8 @@ function computeStatus(workspace, options, conflictedFiles, parseErrors, parseWa
160995
161430
  state: rootPathResolutionState,
160996
161431
  resolveVirtualPath,
160997
161432
  unavailableSlots: rootValues.unavailableSlots,
160998
- registry: valueLowerRegistry
161433
+ registry: valueLowerRegistry,
161434
+ initBuiltSlots: "refuse"
160999
161435
  })
161000
161436
  }
161001
161437
  );
@@ -181762,7 +182198,7 @@ function collectUnityReferencedProjectFileIds(args) {
181762
182198
  )) {
181763
182199
  instanceEnv.set(paramId, { kind: "member", memberId: boundMemberId });
181764
182200
  }
181765
- const childValueIds = isStringRecord9(storedValue) ? storedValue : {};
182201
+ const childValueIds = isStringRecord10(storedValue) ? storedValue : {};
181766
182202
  for (const entry of schema) {
181767
182203
  if (entry.memberId === null) continue;
181768
182204
  const childMember = substituteWalkMember(
@@ -181825,7 +182261,7 @@ function collectUnityReferencedProjectFileIds(args) {
181825
182261
  return;
181826
182262
  }
181827
182263
  if (isMemberDictionaryBase(member)) {
181828
- const childValueIds = isStringRecord9(storedValue) ? storedValue : {};
182264
+ const childValueIds = isStringRecord10(storedValue) ? storedValue : {};
181829
182265
  const substitutedEntryMember = substituteWalkMember(
181830
182266
  member.entryMemberId,
181831
182267
  args.genericEnv,
@@ -181859,7 +182295,7 @@ function readGenericBindingsFromValue(value) {
181859
182295
  if (value == null) return {};
181860
182296
  if (!isLiteralValueContent(value)) return {};
181861
182297
  const bindings = Reflect.get(value, "genericBindings");
181862
- return isStringRecord9(bindings) ? bindings : {};
182298
+ return isStringRecord10(bindings) ? bindings : {};
181863
182299
  }
181864
182300
  function readClassIdFromMemberValueBase(value) {
181865
182301
  if (value === null) return null;
@@ -181879,7 +182315,7 @@ function readFileIdFromMemberValue(value) {
181879
182315
  if (fileId.trim().length === 0) return null;
181880
182316
  return fileId;
181881
182317
  }
181882
- function isStringRecord9(value) {
182318
+ function isStringRecord10(value) {
181883
182319
  if (value === null) return false;
181884
182320
  if (typeof value !== "object") return false;
181885
182321
  return Object.values(value).every((entry) => typeof entry === "string");
@@ -186416,17 +186852,36 @@ function generateInheritedPropertyInterfaceAdapters(ctx, classDef, genericEnv) {
186416
186852
  continue;
186417
186853
  }
186418
186854
  const source = `((${receiverType})this).${memberName}`;
186419
- const getter = isMemberWithEntries(member) && interfaceValueType.startsWith("NeoReadOnly") ? readExpression(
186855
+ const memberSaved = memberSavedForStorage(
186420
186856
  ctx,
186421
- member,
186422
- schemaKey,
186423
- neoMemberNodeType(member),
186857
+ memberId,
186424
186858
  false,
186425
- receiverType,
186426
- null,
186427
- genericEnv,
186428
186859
  declarationClass.id
186429
- ) : [`return (${interfaceValueType})(object)${source}!;`];
186860
+ );
186861
+ const getter = isMemberWithEntries(member) ? [
186862
+ ...detachedReadExpression(
186863
+ ctx,
186864
+ member,
186865
+ schemaKey,
186866
+ memberSaved,
186867
+ null,
186868
+ genericEnv,
186869
+ declarationClass.id,
186870
+ false
186871
+ ),
186872
+ ...collectionReadExpression(
186873
+ ctx,
186874
+ member,
186875
+ `node.Get<${neoMemberNodeType(member)}>("${escapeCSharpString(schemaKey)}")`,
186876
+ schemaKey,
186877
+ resolveMemberById(ctx, member.entryMemberId, "entryMemberId"),
186878
+ memberSaved,
186879
+ null,
186880
+ genericEnv,
186881
+ interfaceValueType,
186882
+ false
186883
+ )
186884
+ ] : [`return (${interfaceValueType})(object)${source}!;`];
186430
186885
  const hasSetter = isMemberNSPropertyBase(member) && typeof member.setterCode === "string";
186431
186886
  const adapter = [
186432
186887
  `${interfaceValueType} ${interfaceType2}.${memberName}`,
@@ -190369,7 +190824,7 @@ function readExpression(ctx, member, schemaKey, nodeType, saved, ownerClassName,
190369
190824
  )
190370
190825
  ];
190371
190826
  }
190372
- function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberName, genericEnv, ownerClassId) {
190827
+ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberName, genericEnv, ownerClassId, genericBindingSaved = saved) {
190373
190828
  if (ownerClassId === void 0 || !classSupportsDetachedViews(ctx, ownerClassId)) {
190374
190829
  return [];
190375
190830
  }
@@ -190399,7 +190854,13 @@ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberN
190399
190854
  saved,
190400
190855
  genericEnv
190401
190856
  );
190402
- const entryType = csharpValueType(ctx, entryMember, saved, genericEnv);
190857
+ const entryType = csharpValueType(
190858
+ ctx,
190859
+ entryMember,
190860
+ saved,
190861
+ genericEnv,
190862
+ genericBindingSaved
190863
+ );
190403
190864
  if (readEntry2 === null || entryType === null) return [];
190404
190865
  const guardArguments = collectionGuardArguments(
190405
190866
  member,
@@ -190407,10 +190868,10 @@ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberN
190407
190868
  );
190408
190869
  const [viewType, view] = saved ? [
190409
190870
  `NeoList<${entryType}>`,
190410
- `DetachedList<${entryType}>("${key}", entry => ${readEntry2}, (client, child) => ${childConverter(ctx, entryMember, true, writeGuardMemberName != null, genericEnv)}, item => ${entrySerializeExpression(ctx, entryMember, `writableNode.Get<NeoMemberListWritable>("${key}")`, member.name, genericEnv)}${guardArguments})`
190871
+ `DetachedList<${entryType}>("${key}", entry => ${readEntry2}, (client, child) => ${childConverter(ctx, entryMember, true, writeGuardMemberName != null, genericEnv, genericBindingSaved)}, item => ${entrySerializeExpression(ctx, entryMember, `writableNode.Get<NeoMemberListWritable>("${key}")`, member.name, genericEnv, genericBindingSaved)}${guardArguments})`
190411
190872
  ] : [
190412
190873
  `NeoReadOnlyList<${entryType}>`,
190413
- `DetachedReadOnlyList<${entryType}>("${key}", entry => ${readEntry2}, (client, child) => ${childConverter(ctx, entryMember, false, false, genericEnv)})`
190874
+ `DetachedReadOnlyList<${entryType}>("${key}", entry => ${readEntry2}, (client, child) => ${childConverter(ctx, entryMember, false, false, genericEnv, genericBindingSaved)})`
190414
190875
  ];
190415
190876
  return [
190416
190877
  `if (TryReadDetached("${key}", out _))`,
@@ -190947,12 +191408,12 @@ function collectionGuardArguments(member, writeGuardMemberName) {
190947
191408
  const name = escapeCSharpString(writeGuardMemberName);
190948
191409
  return isReadOnlyMember(member) ? `, () => ThrowReadOnlyMembership("${name}"), () => true` : `, () => ThrowIfReadOnly("${name}"), () => IsReadOnly`;
190949
191410
  }
190950
- function collectionReadExpression(ctx, member, getNode, schemaKey, entryMember, saved, writeGuardMemberName, genericEnv, collectionTypeOverride) {
191411
+ function collectionReadExpression(ctx, member, getNode, schemaKey, entryMember, saved, writeGuardMemberName, genericEnv, collectionTypeOverride, genericBindingSaved = saved) {
190951
191412
  const keyCodecArguments = dictionaryKeyCodecArguments(ctx, member);
190952
191413
  if (saved) {
190953
191414
  const entrySaved = collectionEntrySaved(member, entryMember, true);
190954
191415
  const writableNodeType = isMemberDictionaryBase(member) ? "NeoMemberDictionaryWritable" : "NeoMemberListWritable";
190955
- const collectionType2 = collectionTypeOverride ?? csharpValueType(ctx, member, true, genericEnv);
191416
+ const collectionType2 = collectionTypeOverride ?? csharpValueType(ctx, member, true, genericEnv, genericBindingSaved);
190956
191417
  const keyLiteral = `"${escapeCSharpString(schemaKey)}"`;
190957
191418
  const readNode = `writableNode.Get<${writableNodeType}>(${keyLiteral})`;
190958
191419
  const guardArguments = collectionGuardArguments(
@@ -190964,13 +191425,14 @@ function collectionReadExpression(ctx, member, getNode, schemaKey, entryMember,
190964
191425
  entryMember,
190965
191426
  readNode,
190966
191427
  member.name,
190967
- genericEnv
191428
+ genericEnv,
191429
+ genericBindingSaved
190968
191430
  );
190969
191431
  return cachedStoredWrapper(
190970
191432
  schemaKey,
190971
191433
  readNode,
190972
191434
  collectionType2 ?? "object",
190973
- `new ${collectionType2}(client, memberNode, () => writableNode.GetOrCreateCollection<${writableNodeType}>(${keyLiteral}), (client, child) => ${childConverter(ctx, entryMember, entrySaved, entrySaved && writeGuardMemberName != null, genericEnv)}, item => ${serializeExpression}${keyCodecArguments}${guardArguments})`
191435
+ `new ${collectionType2}(client, memberNode, () => writableNode.GetOrCreateCollection<${writableNodeType}>(${keyLiteral}), (client, child) => ${childConverter(ctx, entryMember, entrySaved, entrySaved && writeGuardMemberName != null, genericEnv, genericBindingSaved)}, item => ${serializeExpression}${keyCodecArguments}${guardArguments})`
190974
191436
  );
190975
191437
  }
190976
191438
  const collectionType = collectionTypeOverride ?? csharpValueType(ctx, member, false, genericEnv);
@@ -191092,9 +191554,9 @@ function interfaceValueRead(ctx, member, nodeExpression, readOnly, genericEnv) {
191092
191554
  if (!isRequiredMember(member)) return read;
191093
191555
  return `${read} ?? throw new InvalidOperationException("Required '${escapeCSharpString(member.name)}' holds no class value.")`;
191094
191556
  }
191095
- function entrySerializeExpression(ctx, entryMember, collectionNode, slotLabel2, genericEnv) {
191557
+ function entrySerializeExpression(ctx, entryMember, collectionNode, slotLabel2, genericEnv, genericBindingSaved = true) {
191096
191558
  const throughCodec = entryMember !== null && (isMemberGenericBase(entryMember) || isMemberLookupBase(entryMember) && lookupProjection(ctx, entryMember) !== "class" /* Class */);
191097
- return throughCodec ? `NeoGenericBindings.Resolve<${csharpValueType(ctx, entryMember, true, genericEnv) ?? "object"}>(client, ${collectionNode}).Serialize(item)` : serializeItemExpression(ctx, entryMember, "item", slotLabel2);
191559
+ return throughCodec ? `NeoGenericBindings.Resolve<${csharpValueType(ctx, entryMember, true, genericEnv, genericBindingSaved) ?? "object"}>(client, ${collectionNode}).Serialize(item)` : serializeItemExpression(ctx, entryMember, "item", slotLabel2);
191098
191560
  }
191099
191561
  function lookupSelectionFactory(ctx, member, selection2, saved, writeGuardMemberName, genericEnv) {
191100
191562
  const targetSaved = lookupTargetSaved(ctx, member) ?? saved;
@@ -191210,7 +191672,7 @@ function dialogueLookupReadExpression(member, getNode, saved, writeGuardMemberNa
191210
191672
  "return selected is null ? null : new NeoDialogueReference(client, selected);"
191211
191673
  ];
191212
191674
  }
191213
- function childConverter(ctx, member, saved = false, branchOnReadOnly = false, genericEnv) {
191675
+ function childConverter(ctx, member, saved = false, branchOnReadOnly = false, genericEnv, genericBindingSaved = saved) {
191214
191676
  if (member === null) return "throw new NotSupportedException()";
191215
191677
  if (isMemberDelegateBase(member)) {
191216
191678
  const delegateType = csharpDelegateType(ctx, member, saved, genericEnv) ?? "NeoDelegate<object?>";
@@ -191232,7 +191694,13 @@ function childConverter(ctx, member, saved = false, branchOnReadOnly = false, ge
191232
191694
  return `((NeoMemberAction)child).Bind${actionBindTypeArguments(actionType)}()`;
191233
191695
  }
191234
191696
  if (isMemberGenericBase(member)) {
191235
- const paramType = csharpValueType(ctx, member, saved, genericEnv);
191697
+ const paramType = csharpValueType(
191698
+ ctx,
191699
+ member,
191700
+ saved,
191701
+ genericEnv,
191702
+ genericBindingSaved
191703
+ );
191236
191704
  if (paramType === null) return "throw new NotSupportedException()";
191237
191705
  return `NeoGenericBindings.Resolve<${paramType}>(client, (NeoMember)child).Read((NeoMember)child)`;
191238
191706
  }
@@ -191281,7 +191749,13 @@ function childConverter(ctx, member, saved = false, branchOnReadOnly = false, ge
191281
191749
  }
191282
191750
  if (isClassTypedMember(member)) {
191283
191751
  const typeName = ctx.typeNames.get(member.classId) ?? "NeoNode";
191284
- const constructedSuffix = constructedTypeArgumentsSuffix(ctx, member, true, genericEnv) ?? "";
191752
+ const constructedSuffix = constructedTypeArgumentsSuffix(
191753
+ ctx,
191754
+ member,
191755
+ true,
191756
+ genericEnv,
191757
+ genericBindingSaved
191758
+ ) ?? "";
191285
191759
  const savedTypeRef = `${qualifyGeneratedType(ctx, savedTypeName(typeName))}${constructedSuffix}`;
191286
191760
  const hasWritableFamily = schemaClassHasWritableFamily(ctx, member.classId);
191287
191761
  if (saved && branchOnReadOnly && hasWritableFamily) {
@@ -194863,7 +195337,7 @@ var UNITY_CODEGEN_REVISION;
194863
195337
  var init_unity_codegen_revision = __esm({
194864
195338
  "../src/models/exports/unity-codegen-revision.ts"() {
194865
195339
  "use strict";
194866
- UNITY_CODEGEN_REVISION = "231557c5a40a20ab9e630415d45556845d7561d54e335a4d92c1cdbc1024a705";
195340
+ UNITY_CODEGEN_REVISION = "f748ddae5544d547b4d1139dcdbc86b86b01ab0aae4a9a24656ad8858258b460";
194867
195341
  }
194868
195342
  });
194869
195343
 
@@ -216001,7 +216475,7 @@ var releaseWorkspaceLock = () => void 0;
216001
216475
  async function main() {
216002
216476
  const args = parseArgs(process.argv.slice(2));
216003
216477
  if (args.command === "--version") {
216004
- console.log("0.84.2");
216478
+ console.log("0.84.4");
216005
216479
  return;
216006
216480
  }
216007
216481
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {