@neocompose/cli 0.84.3 → 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.3",
17590
+ cliVersion: "0.84.4",
17591
17591
  projectFileUploadBatchSize: 32,
17592
17592
  documentRecords: {
17593
17593
  member: {
@@ -42195,7 +42195,7 @@ var init_strict_resolver = __esm({
42195
42195
  scope
42196
42196
  )
42197
42197
  );
42198
- const schemaClassInfo = toWireType(targetType, this.project);
42198
+ const schemaClassInfo = this.constructorWireType(targetType, expression);
42199
42199
  if (schemaClassInfo.type !== 7 /* Class */) {
42200
42200
  throw new Error(
42201
42201
  `NeoScript constructor ${className} has non-Class return type ${this.describe(signature.returnType)}.`
@@ -42213,6 +42213,16 @@ var init_strict_resolver = __esm({
42213
42213
  writability: "session" /* Session */
42214
42214
  };
42215
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
+ }
42216
42226
  constructorTargetType(schemaClass2, expression, expected) {
42217
42227
  const typeArguments = expression.typeArguments?.map(
42218
42228
  (argument2) => this.resolveType(argument2)
@@ -42343,7 +42353,7 @@ var init_strict_resolver = __esm({
42343
42353
  scope
42344
42354
  );
42345
42355
  const classType = targetType;
42346
- const schemaClassInfo = toWireType(classType, this.project);
42356
+ const schemaClassInfo = this.constructorWireType(classType, expression);
42347
42357
  if (schemaClassInfo.type !== 7 /* Class */) {
42348
42358
  throw new Error(
42349
42359
  `NeoScript declared constructor ${className} projected a non-Class wire type.`
@@ -43206,6 +43216,8 @@ var init_strict_resolver = __esm({
43206
43216
  {
43207
43217
  collectionPointer: receiver.pointer,
43208
43218
  valuePointer: value.pointer,
43219
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
43220
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
43209
43221
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43210
43222
  },
43211
43223
  { kind: "primitive", name: "int" }
@@ -43235,6 +43247,8 @@ var init_strict_resolver = __esm({
43235
43247
  {
43236
43248
  collectionPointer: receiver.pointer,
43237
43249
  valuePointer: value.pointer,
43250
+ ...isPrimitive(expectedValueType, "float") ? { float: true } : {},
43251
+ ...isPrimitive(expectedValueType, "decimal") ? { decimal: true } : {},
43238
43252
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43239
43253
  },
43240
43254
  { kind: "primitive", name: "bool" }
@@ -43467,6 +43481,7 @@ var init_strict_resolver = __esm({
43467
43481
  info = {
43468
43482
  ...base,
43469
43483
  op: name,
43484
+ ...isPrimitive(collection.valueType, "decimal") ? { decimalEntries: true } : {},
43470
43485
  ...hasReferenceEquality(collection.valueType, this.project) ? { reference: true } : {}
43471
43486
  };
43472
43487
  resultType = {
@@ -52181,7 +52196,9 @@ function subscriptKeyType(receiver) {
52181
52196
  return void 0;
52182
52197
  }
52183
52198
  function validateReferenceExpression(expression, declared, scope, environment, uri, range2, diagnostics) {
52184
- 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" };
52185
52202
  const typeArguments = expression.typeArguments ?? [];
52186
52203
  const names = expression.argumentNames ?? [];
52187
52204
  const idIndex = names.findIndex((name) => name === "id");
@@ -79252,16 +79269,18 @@ var init_runtime_set = __esm({
79252
79269
  "../packages/neoscript-runtime/src/neoscript/runtime-set.ts"() {
79253
79270
  "use strict";
79254
79271
  RuntimeSet = class {
79255
- constructor(source, reference2, enumEntries, slotReferences = null) {
79272
+ constructor(source, reference2, enumEntries, slotReferences = null, decimalEntries = false) {
79256
79273
  this.source = source;
79257
79274
  this.reference = reference2;
79258
79275
  this.enumEntries = enumEntries;
79259
79276
  this.slotReferences = slotReferences;
79277
+ this.decimalEntries = decimalEntries;
79260
79278
  }
79261
79279
  source;
79262
79280
  reference;
79263
79281
  enumEntries;
79264
79282
  slotReferences;
79283
+ decimalEntries;
79265
79284
  entries = /* @__PURE__ */ new Map();
79266
79285
  validations = /* @__PURE__ */ new Map();
79267
79286
  snapshot;
@@ -79271,6 +79290,9 @@ var init_runtime_set = __esm({
79271
79290
  has(key) {
79272
79291
  return this.entries.has(key);
79273
79292
  }
79293
+ *values() {
79294
+ for (const entry of this.entries.values()) yield entry.raw;
79295
+ }
79274
79296
  add(key, raw, reference2) {
79275
79297
  if (this.entries.has(key)) return;
79276
79298
  this.entries.set(key, { raw, reference: reference2 });
@@ -82925,7 +82947,14 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
82925
82947
  for (let index = 0; index < argumentValues.length; index += 1) {
82926
82948
  const parameter4 = parameters[index];
82927
82949
  if (parameter4 === void 0) continue;
82928
- 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
+ );
82929
82958
  }
82930
82959
  try {
82931
82960
  const result = evalBody(
@@ -82935,9 +82964,11 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
82935
82964
  evaluationOptions(runtimeCtx, false)
82936
82965
  );
82937
82966
  if (result.kind === "return") {
82938
- if (getter.typeInfo.type === 20 /* Decimal */ && typeof result.value === "number") {
82939
- result.value = coerceDecimalOperand(result.value, "return");
82940
- }
82967
+ result.value = coerceAssignmentValue(
82968
+ result.value,
82969
+ getter.typeInfo,
82970
+ "return"
82971
+ );
82941
82972
  if (ownsInvocationState) {
82942
82973
  flushRuntimeSets(runtimeCtx);
82943
82974
  result.value = exportRuntimeSetValue(result.value, runtimeCtx);
@@ -83772,7 +83803,11 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
83772
83803
  const parameter4 = action.parameters[index + 2];
83773
83804
  const runtimeTypeInfo = runtimeArgumentTypes[index];
83774
83805
  const value2 = asDeclaredRuntimeSet(
83775
- restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
83806
+ coerceAssignmentValue(
83807
+ restoreExportedReferences(filledArgs[index], runtimeTypeInfo, ctx),
83808
+ runtimeTypeInfo,
83809
+ "function argument"
83810
+ ),
83776
83811
  runtimeTypeInfo,
83777
83812
  ctx
83778
83813
  );
@@ -83806,9 +83841,7 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
83806
83841
  }
83807
83842
  return null;
83808
83843
  }
83809
- if (runtimeReturnType.type === 20 /* Decimal */ && typeof value === "number") {
83810
- value = coerceDecimalOperand(value, "function return");
83811
- }
83844
+ value = coerceAssignmentValue(value, runtimeReturnType, "function return");
83812
83845
  if (!runtimeValueMatchesType(value, runtimeReturnType, ctx)) {
83813
83846
  throw new NSGetterRuntimeError(
83814
83847
  "NSFunction returned a value that does not match its compiled return type."
@@ -84147,9 +84180,11 @@ function evalInstructions(instructions, scope, ctx, options) {
84147
84180
  }
84148
84181
  case "variable" /* variable */: {
84149
84182
  let value = evalPointer(ins.variable.pointer, scope, ctx);
84150
- if (ins.variable.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
84151
- value = coerceDecimalOperand(value, "variable initialization");
84152
- }
84183
+ value = coerceAssignmentValue(
84184
+ value,
84185
+ ins.variable.typeInfo,
84186
+ "variable initialization"
84187
+ );
84153
84188
  value = asDeclaredRuntimeSet(value, ins.variable.typeInfo, ctx);
84154
84189
  scope.setLocal(ins.variable.id, value);
84155
84190
  break;
@@ -84185,9 +84220,11 @@ function evalInstructions(instructions, scope, ctx, options) {
84185
84220
  }
84186
84221
  case "assign" /* assign */: {
84187
84222
  let value = evalPointer(ins.pointer, scope, ctx);
84188
- if (ins.target.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
84189
- value = coerceDecimalOperand(value, "assignment");
84190
- }
84223
+ value = coerceAssignmentValue(
84224
+ value,
84225
+ ins.target.typeInfo,
84226
+ "assignment"
84227
+ );
84191
84228
  if (ins.target.pointer.type === "variable" /* variable */) {
84192
84229
  assertVariableBindingWritable(scope, ins.target.pointer.variableId);
84193
84230
  scope.setLocal(ins.target.pointer.variableId, value);
@@ -85961,6 +85998,21 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85961
85998
  );
85962
85999
  }
85963
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
+ }
85964
86016
  const setEntryMember = mutatesLocalVariable ? null : storedSetEntryMember(targetValue, ctx);
85965
86017
  const isLookupSet = setEntryMember === null && ins.target.typeInfo.type === 9 /* Lookup */;
85966
86018
  if (isLookupSet && Array.isArray(targetValue)) {
@@ -85968,7 +86020,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85968
86020
  targetValue,
85969
86021
  ins.reference === true,
85970
86022
  ins.target.typeInfo.type === 9 /* Lookup */ && (ins.target.typeInfo.entryTypeInfo.type === 8 /* Enum */ || ins.target.typeInfo.entryTypeInfo.type === 18 /* DialogueLookup */),
85971
- ctx
86023
+ ctx,
86024
+ decimalEntries
85972
86025
  );
85973
86026
  }
85974
86027
  const setMatch = setEntryMember !== null && Array.isArray(targetValue) && (ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) ? findStoredSetEntry(targetValue, args[0], setEntryMember, ctx) : null;
@@ -85987,7 +86040,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
85987
86040
  ctx,
85988
86041
  isLookupSet,
85989
86042
  false,
85990
- ins.reference === true
86043
+ ins.reference === true,
86044
+ decimalEntries
85991
86045
  );
85992
86046
  updateCollectionReferenceProvenance(
85993
86047
  targetValue,
@@ -86065,7 +86119,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
86065
86119
  ctx,
86066
86120
  isLookupSet,
86067
86121
  ins.reference !== true && ins.mutation === "Remove" /* Remove */ && isArrayCollection(targetValue) && setEntryMember === null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
86068
- ins.reference === true
86122
+ ins.reference === true,
86123
+ setEntryMember === null && decimalEntries
86069
86124
  );
86070
86125
  updateCollectionReferenceProvenance(
86071
86126
  targetValue,
@@ -86341,21 +86396,28 @@ function asDeclaredRuntimeSet(value, type, ctx) {
86341
86396
  value,
86342
86397
  entry === 7 /* Class */ || entry === 22 /* Interface */ || entry === 6 /* List */ || entry === 5 /* Dictionary */ || entry === 9 /* Lookup */,
86343
86398
  entry === 8 /* Enum */ || entry === 18 /* DialogueLookup */,
86344
- ctx
86399
+ ctx,
86400
+ entry === 20 /* Decimal */
86345
86401
  );
86346
86402
  }
86347
86403
  function runtimeSetKey(value, set, ctx) {
86348
86404
  if (set.slotReferences !== null) return slotReferenceKey(value);
86349
86405
  if (set.enumEntries && Array.isArray(value) && value.length === 1)
86350
86406
  value = value[0];
86351
- return toSetEntryKey(value, null, set.reference, ctx);
86407
+ return toSetEntryKey(value, null, set.reference, ctx, set.decimalEntries);
86352
86408
  }
86353
- function runtimeSet(array3, reference2, enumEntries, ctx) {
86409
+ function runtimeSet(array3, reference2, enumEntries, ctx, decimalEntries = false) {
86354
86410
  const sets = ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
86355
86411
  ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
86356
86412
  const existing = sets.get(array3);
86357
86413
  if (existing !== void 0) return existing;
86358
- const set = new RuntimeSet(array3, reference2, enumEntries);
86414
+ const set = new RuntimeSet(
86415
+ array3,
86416
+ reference2,
86417
+ enumEntries,
86418
+ null,
86419
+ decimalEntries
86420
+ );
86359
86421
  const references = collectionReferences(array3, ctx);
86360
86422
  for (let index = 0; index < array3.length; index++) {
86361
86423
  const raw = array3[index];
@@ -86474,7 +86536,7 @@ function removableEntryRowIds(targetValue, mutation, args, ctx) {
86474
86536
  }
86475
86537
  return rowIds;
86476
86538
  }
86477
- 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) {
86478
86540
  if (targetValue instanceof RuntimeSet) {
86479
86541
  (ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(targetValue);
86480
86542
  switch (mutation) {
@@ -86526,6 +86588,7 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
86526
86588
  case "Remove" /* Remove */:
86527
86589
  if (Array.isArray(targetValue)) {
86528
86590
  const references = resolveRemovalEntries ? collectionReferences(targetValue, ctx) : recordedReferenceEntries(targetValue, ctx) ?? 1 /* Values */;
86591
+ const targetKey = decimal2 ? decimalCollectionKey(args[0]) : args[0];
86529
86592
  let index = -1;
86530
86593
  for (let candidate = 0; candidate < targetValue.length; candidate += 1) {
86531
86594
  const entry = targetValue[candidate];
@@ -86536,10 +86599,8 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
86536
86599
  }
86537
86600
  continue;
86538
86601
  }
86539
- if (jsEqual(
86540
- typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry,
86541
- args[0]
86542
- )) {
86602
+ const value = typeof entry === "string" && isReferenceEntry(references, candidate) ? resolveValueIfId(entry, ctx) : entry;
86603
+ if (jsEqual(decimal2 ? decimalCollectionKey(value) : value, targetKey)) {
86543
86604
  index = candidate;
86544
86605
  break;
86545
86606
  }
@@ -87026,12 +87087,22 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
87026
87087
  case "function" /* function */:
87027
87088
  return evalFunction(pointer.function, scope, ctx);
87028
87089
  case "listLiteral" /* listLiteral */:
87029
- 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
+ );
87030
87097
  case "dictLiteral" /* dictLiteral */: {
87031
87098
  const out = {};
87032
87099
  for (const e of pointer.entries) {
87033
87100
  const k = evalPointer(e.key, scope, ctx);
87034
- 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
+ );
87035
87106
  }
87036
87107
  return out;
87037
87108
  }
@@ -88693,9 +88764,9 @@ function readRecordKey(receiver, k, memberId, ctx) {
88693
88764
  if (receiver === ctx.thisValue && typeof ctx.thisValueRowId === "string") {
88694
88765
  return ctx.thisValueRowId;
88695
88766
  }
88696
- const rowId = findKnownRowIdByValueReference(receiver, ctx);
88697
- if (rowId) return rowId;
88698
- 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;
88699
88770
  }
88700
88771
  const assetMember = resolveAssetRuntimeMember(receiver, k, ctx);
88701
88772
  if (assetMember.kind === "ok") return assetMember.value;
@@ -89993,7 +90064,11 @@ function evalDecimalMathOp(info, fn, scope, ctx) {
89993
90064
  }
89994
90065
  }
89995
90066
  function evalListRepeat(info, scope, ctx) {
89996
- 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
+ );
89997
90072
  const count = numberArg(
89998
90073
  evalPointer(info.countPointer, scope, ctx),
89999
90074
  "List.Repeat count"
@@ -90081,13 +90156,18 @@ function jsEqual(a, b) {
90081
90156
  return a instanceof NSSlotReference && b instanceof NSSlotReference && a.targetId === b.targetId;
90082
90157
  }
90083
90158
  if (a === b) return true;
90084
- if (Array.isArray(a) && Array.isArray(b)) {
90085
- if (a.length !== b.length) return false;
90086
- for (let i2 = 0; i2 < a.length; i2++) {
90087
- 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;
90088
90167
  }
90089
90168
  return true;
90090
90169
  }
90170
+ if (b instanceof RuntimeSet) return false;
90091
90171
  if (typeof a === "object" && typeof b === "object" && a !== null && b !== null && !Array.isArray(a) && !Array.isArray(b)) {
90092
90172
  const aKeys = Object.keys(a);
90093
90173
  const bKeys = Object.keys(b);
@@ -90523,7 +90603,8 @@ function evalCollectionQuery(info, scope, ctx) {
90523
90603
  output,
90524
90604
  info.reference === true,
90525
90605
  info.enumEntries === true,
90526
- ctx
90606
+ ctx,
90607
+ info.decimalEntries === true
90527
90608
  ) : output;
90528
90609
  };
90529
90610
  if (info.op === "OrderBy" || info.op === "OrderByDescending") {
@@ -90575,7 +90656,8 @@ function evalCollectionQuery(info, scope, ctx) {
90575
90656
  entry,
90576
90657
  valueId,
90577
90658
  info.reference === true,
90578
- ctx
90659
+ ctx,
90660
+ info.decimalEntries === true
90579
90661
  );
90580
90662
  if (seenSetKeys.has(setKey)) return 0 /* Continue */;
90581
90663
  seenSetKeys.add(setKey);
@@ -90630,10 +90712,15 @@ function evalCollectionQuery(info, scope, ctx) {
90630
90712
  }
90631
90713
  return finish();
90632
90714
  }
90633
- function toSetEntryKey(entry, valueId, reference2, ctx) {
90715
+ function toSetEntryKey(entry, valueId, reference2, ctx, decimal2 = false) {
90634
90716
  if (reference2) return valueId ?? referenceIdOf(entry, ctx) ?? entry;
90717
+ if (decimal2) return decimalCollectionKey(entry);
90635
90718
  return typeof entry === "object" && entry !== null ? canonicalJsonStringify(entry) : entry;
90636
90719
  }
90720
+ function decimalCollectionKey(value) {
90721
+ if (value === null) return null;
90722
+ return decimalKey(coerceDecimalOperand(value, "decimal collection entry"));
90723
+ }
90637
90724
  function compareCollectionKeys(left, right, keyType) {
90638
90725
  if (left === null) return right === null ? 0 : -1;
90639
90726
  if (right === null) return 1;
@@ -90751,7 +90838,11 @@ function evalFunction(fn, scope, ctx) {
90751
90838
  }
90752
90839
  case "contains" /* contains */: {
90753
90840
  let c = evalPointer(fn.info.collectionPointer, scope, ctx);
90754
- 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");
90755
90846
  if (typeof c === "string") {
90756
90847
  if (typeof target !== "string") {
90757
90848
  throw new NSGetterRuntimeError(
@@ -90784,9 +90875,13 @@ function evalFunction(fn, scope, ctx) {
90784
90875
  return referenceIndexOf(c, target, ctx) !== null;
90785
90876
  }
90786
90877
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
90878
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
90787
90879
  let containsResolvedEntry = false;
90788
90880
  iterateCollection(c, ctx, (entry, _key, valueId) => {
90789
- 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
+ )) {
90790
90885
  containsResolvedEntry = true;
90791
90886
  return 1 /* Break */;
90792
90887
  }
@@ -90799,15 +90894,21 @@ function evalFunction(fn, scope, ctx) {
90799
90894
  evalPointer(fn.info.collectionPointer, scope, ctx),
90800
90895
  "IndexOf receiver"
90801
90896
  );
90802
- 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);
90803
90900
  if (fn.info.reference === true) {
90804
90901
  const index = referenceIndexOf(collection, target, ctx);
90805
90902
  return index === null ? -1 : numberArg(index, "IndexOf index");
90806
90903
  }
90807
90904
  const targetReferenceId = typeof target === "string" ? null : findKnownRowIdByValueReference(target, ctx);
90905
+ const targetKey = fn.info.decimal ? decimalCollectionKey(target) : target;
90808
90906
  let found = -1;
90809
90907
  iterateCollection(collection, ctx, (entry, key, valueId) => {
90810
- 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
+ )) {
90811
90912
  found = numberArg(key, "IndexOf index");
90812
90913
  return 1 /* Break */;
90813
90914
  }
@@ -91015,7 +91116,19 @@ function evalFunction(fn, scope, ctx) {
91015
91116
  );
91016
91117
  iterateCollection(c, ctx, callback);
91017
91118
  }
91018
- 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
+ }
91019
91132
  if (fn.type === "first" /* first */) {
91020
91133
  throw new NSGetterRuntimeError(
91021
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."
@@ -92228,10 +92341,19 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
92228
92341
  }
92229
92342
  return null;
92230
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
+ );
92231
92353
  return (member, init, sourceValueId, genericEnv = instanceEnv) => {
92232
92354
  const memberId = Reflect.get(member, "id");
92233
92355
  const effectiveMemberId = typeof memberId === "string" ? memberId : null;
92234
- 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;
92235
92357
  const compiled = ensureInitializerCompiled({
92236
92358
  init,
92237
92359
  member,
@@ -118854,21 +118976,25 @@ function projectValueHeadPlacementGraph(args) {
118854
118976
  );
118855
118977
  return { ...substituteMember(member, bindings, genericMembers, member) };
118856
118978
  };
118857
- const instanceBindings = (classId, member) => {
118979
+ const instanceBindings = (classId, member, value) => {
118858
118980
  if (classId === null || !genericClassIds.has(classId)) return emptyBindings;
118859
- if (isInterfaceTypedMember(member)) {
118860
- return resolveInstanceEnv(
118861
- classId,
118862
- slotClassArguments(member, classId, implementerIndex()),
118863
- genericClasses
118864
- );
118865
- }
118866
- const arguments_ = member.classArguments;
118981
+ const arguments_ = isInterfaceTypedMember(member) ? slotClassArguments(member, classId, implementerIndex()) : member.classArguments;
118867
118982
  if (arguments_ != null && !isGenericBindingsRecord(arguments_))
118868
118983
  throw new Error(
118869
118984
  `Class placement "${classId}" has malformed generic arguments.`
118870
118985
  );
118871
- 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;
118872
118998
  };
118873
118999
  const unorderedByContainer = /* @__PURE__ */ new Map();
118874
119000
  for (const value of values.values()) {
@@ -119013,7 +119139,7 @@ function projectValueHeadPlacementGraph(args) {
119013
119139
  }
119014
119140
  result.set(item.valueId, projection);
119015
119141
  args.contextualMembers?.set(item.valueId, member);
119016
- const childBindings = classId === null ? item.bindings ?? emptyBindings : instanceBindings(classId, member);
119142
+ const childBindings = classId === null ? item.bindings ?? emptyBindings : instanceBindings(classId, member, value);
119017
119143
  if ((member.kind === 5 /* Dictionary */ || member.kind === 6 /* List */ || member.kind === 28 /* Set */) && childBindings.size > 0) {
119018
119144
  if (!isMemberBase(member))
119019
119145
  throw new Error(
@@ -119213,6 +119339,9 @@ function joinPath(parent, child2) {
119213
119339
  function placementsEqual(left, right) {
119214
119340
  return JSON.stringify(left) === JSON.stringify(right);
119215
119341
  }
119342
+ function isStringRecord7(value) {
119343
+ return isRecord6(value) && Object.values(value).every((entry) => typeof entry === "string");
119344
+ }
119216
119345
  function isRecord6(value) {
119217
119346
  return typeof value === "object" && value !== null && !Array.isArray(value);
119218
119347
  }
@@ -124498,6 +124627,61 @@ var init_stored_closure_captures = __esm({
124498
124627
  }
124499
124628
  });
124500
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
+
124501
124685
  // ../src/models/project/world-layer-compatibility-error.ts
124502
124686
  var WorldLayerCompatibilityError;
124503
124687
  var init_world_layer_compatibility_error = __esm({
@@ -126505,9 +126689,9 @@ function assertNumberRange(member, value, path) {
126505
126689
  }
126506
126690
  }
126507
126691
  function stringRecord3(value) {
126508
- return isStringRecord7(value) ? value : null;
126692
+ return isStringRecord8(value) ? value : null;
126509
126693
  }
126510
- function isStringRecord7(value) {
126694
+ function isStringRecord8(value) {
126511
126695
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
126512
126696
  return false;
126513
126697
  }
@@ -128143,8 +128327,7 @@ function materializePreparedInstanceInitializers(args) {
128143
128327
  compiledDocument,
128144
128328
  compiledDocument.variants ?? []
128145
128329
  );
128146
- let currentReader = null;
128147
- const requireCurrentReader = () => currentReader ??= new EffectiveValueReader(materializationScope.document);
128330
+ let compareConstruction;
128148
128331
  let ownedValueCollector;
128149
128332
  let valueHashes;
128150
128333
  const liveValueHashes = () => valueHashes ??= indexLiveContentHashesByRecordId(
@@ -128210,16 +128393,28 @@ function materializePreparedInstanceInitializers(args) {
128210
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.`
128211
128394
  );
128212
128395
  }
128213
- if (replayedCreationDataMatches({
128214
- // The synthetic variant binding members are part of the ownership
128215
- // scope that compiled and evaluated this initializer. Stored replay
128216
- // closes its generic slot from the same ephemeral member id, so its
128217
- // expansion must read that scoped document too.
128218
- 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({
128219
128413
  currentRoot: existingConstructedRoot,
128414
+ currentArguments: isLiteralValueContent(existingConstructedRoot) ? existingConstructedRoot.constructorArgs : void 0,
128220
128415
  rootMember: member,
128221
128416
  replayRoot: materialized.root,
128222
- replayCreated: materialized.createdValues
128417
+ replayRows
128223
128418
  })) {
128224
128419
  replayOnlyIndexes.push(site.index);
128225
128420
  batch.upsert([existingConstructedRoot]);
@@ -128340,46 +128535,6 @@ function materializePreparedInstanceInitializers(args) {
128340
128535
  args.prepared.splice(index, 1);
128341
128536
  }
128342
128537
  }
128343
- function replayedCreationDataMatches(args) {
128344
- if (!isLiteralValueContent(args.currentRoot) || !isLiteralValueContent(args.replayRoot)) {
128345
- return false;
128346
- }
128347
- const replayArgs = args.replayRoot.constructorArgs;
128348
- if (replayArgs !== void 0 && replayArgs !== null) {
128349
- const currentArgs = args.currentRoot.constructorArgs;
128350
- if (currentArgs === void 0 || currentArgs === null || !constructorArgumentsSemanticallyEqual({
128351
- currentReader: args.currentReader,
128352
- currentRoot: args.currentRoot,
128353
- rootMember: args.rootMember,
128354
- current: currentArgs,
128355
- replayRoot: args.replayRoot,
128356
- replayCreated: args.replayCreated,
128357
- replay: replayArgs
128358
- })) {
128359
- return false;
128360
- }
128361
- }
128362
- return true;
128363
- }
128364
- function constructorArgumentsSemanticallyEqual(args) {
128365
- const current = args.currentReader;
128366
- const replayRows = /* @__PURE__ */ new Map([
128367
- [args.replayRoot.id, args.replayRoot]
128368
- ]);
128369
- for (const row of args.replayCreated) replayRows.set(row.id, row);
128370
- const replay = current.withRowOverrides(replayRows);
128371
- const currentNormalized = current.normalizeConstructorArguments(
128372
- args.current,
128373
- args.currentRoot,
128374
- args.rootMember
128375
- );
128376
- const replayNormalized = replay.normalizeConstructorArguments(
128377
- args.replay,
128378
- args.replayRoot,
128379
- args.rootMember
128380
- );
128381
- return effectiveValuesEqual(currentNormalized, replayNormalized);
128382
- }
128383
128538
  function completeLocalizedTextCreateEnvelopes(args) {
128384
128539
  const createsLocalizedText = args.changes.some(
128385
128540
  (change) => change.recordKind === "localized-text" && change.operation === "create"
@@ -131423,7 +131578,7 @@ var init_project_version_schema_commit = __esm({
131423
131578
  init_declared_binding_targets();
131424
131579
  init_stored_closure_captures();
131425
131580
  init_document_initializer_compiler();
131426
- init_effective_value_comparison();
131581
+ init_construction_replay_equality();
131427
131582
  init_classes();
131428
131583
  init_constructor_parameter_settlement();
131429
131584
  init_generics();
@@ -137913,7 +138068,7 @@ function toWorldReferenceClassRecord(value) {
137913
138068
  return {
137914
138069
  id: id2,
137915
138070
  extendsClassId: nullableStringField(value, "extendsClassId"),
137916
- schema: isStringRecord8(value.schema) ? value.schema : void 0,
138071
+ schema: isStringRecord9(value.schema) ? value.schema : void 0,
137917
138072
  system: isPlainRecord8(value.system) ? value.system : null
137918
138073
  };
137919
138074
  }
@@ -137931,7 +138086,7 @@ function worldReferenceValueClassId(value) {
137931
138086
  if (value === void 0) return null;
137932
138087
  return typeof value.classId === "string" && value.classId.length > 0 ? value.classId : null;
137933
138088
  }
137934
- function isStringRecord8(value) {
138089
+ function isStringRecord9(value) {
137935
138090
  if (!isPlainRecord8(value)) return false;
137936
138091
  return Object.values(value).every((entry) => typeof entry === "string");
137937
138092
  }
@@ -147051,15 +147206,27 @@ function retainConstructionArguments(context, row, schemaClass2, expression, sou
147051
147206
  const constructorArgs2 = row.constructorArgs;
147052
147207
  if (!isObjectRecord(constructorArgs2)) return;
147053
147208
  if (row.instanceConstructorId === null) return;
147054
- const constructor2 = storedValueConstructor(
147055
- context,
147056
- schemaClass2,
147057
- 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
147058
147225
  );
147059
147226
  const authoredArguments = constructorArgumentExpressions(expression);
147060
147227
  const argumentEnvironment = valueGenericEnvironment(row, environment);
147061
- for (let index = 0; index < constructor2.arguments.length; index += 1) {
147062
- const argument2 = constructor2.arguments[index];
147228
+ for (let index = 0; index < argumentsValue.length; index += 1) {
147229
+ const argument2 = argumentsValue[index];
147063
147230
  if (argument2 === void 0) continue;
147064
147231
  const valueId = constructorArgs2[`__arg_${index}__`];
147065
147232
  if (typeof valueId !== "string") continue;
@@ -147845,6 +148012,7 @@ function lowerRawMemberTypeName(context, memberId) {
147845
148012
  if (member.kind === 8 /* Enum */ && typeof member.enumId === "string") {
147846
148013
  return context.enumNames.get(member.enumId) ?? null;
147847
148014
  }
148015
+ if (member.kind === 9 /* Lookup */) return "Reference";
147848
148016
  if (member.kind === 6 /* List */) return "List";
147849
148017
  if (member.kind === 28 /* Set */) return "Set";
147850
148018
  if (member.kind === 5 /* Dictionary */) return "Dictionary";
@@ -147859,6 +148027,8 @@ function lowerSchemaMemberTypeName(context, member) {
147859
148027
  return context.referenceTypes().interfaceImplementers().interface(member.interfaceId)?.name ?? null;
147860
148028
  case "enum":
147861
148029
  return context.enumNames.get(member.enumId) ?? null;
148030
+ case "lookup":
148031
+ return "Reference";
147862
148032
  case "list":
147863
148033
  return "List";
147864
148034
  case "set":
@@ -150859,10 +151029,15 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150859
151029
  throw new Error(
150860
151030
  `Stored constructor argument cannot be typed by interface type parameter ${type.genericParamId} of ${type.ownerInterfaceId}.`
150861
151031
  );
150862
- 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;
150863
151038
  return storedConstructorArgumentSource(
150864
151039
  context,
150865
- storedGenericArgumentType(context, type, environment),
151040
+ argumentType,
150866
151041
  value,
150867
151042
  environment,
150868
151043
  visited,
@@ -150870,6 +151045,7 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
150870
151045
  partial,
150871
151046
  constructorOwnsGraph
150872
151047
  );
151048
+ }
150873
151049
  case "interface":
150874
151050
  case "list":
150875
151051
  case "set":
@@ -151066,8 +151242,14 @@ function schemaTypeForBindingMember(context, memberId, environment, visited = /*
151066
151242
  };
151067
151243
  case "lookup": {
151068
151244
  if (member.declaredType !== null) {
151069
- const target = referenceReadType2(context, member.declaredType);
151070
- 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 };
151071
151253
  }
151072
151254
  if (member.collectionMemberId === null) {
151073
151255
  throw new Error(
@@ -151636,7 +151818,8 @@ function resolveGenericValueMember(context, member, environment) {
151636
151818
  }
151637
151819
  return {
151638
151820
  ...bindingMember,
151639
- id: member.id,
151821
+ // Lookup emission reads the binding's declared target and collection.
151822
+ id: bindingMember.kind === 9 /* Lookup */ ? bindingMemberId : member.id,
151640
151823
  name: member.name,
151641
151824
  defaultValue: member.defaultValue,
151642
151825
  ...member.payload === 1 /* Partial */ ? { payload: 1 /* Partial */ } : {}
@@ -151714,7 +151897,8 @@ function resolveGenericSchemaMember(context, member, environment) {
151714
151897
  }
151715
151898
  const resolved = {
151716
151899
  ...bindingMember,
151717
- id: member.id,
151900
+ // Deferred reference checks resolve this concrete lookup declaration.
151901
+ id: bindingMember.kind === "lookup" ? bindingMemberId : member.id,
151718
151902
  name: member.name,
151719
151903
  defaultValue: member.defaultValue
151720
151904
  };
@@ -153373,8 +153557,15 @@ function reconcileMaterializedInitializersV4(args) {
153373
153557
  );
153374
153558
  }
153375
153559
  let currentRows;
153376
- let currentReader;
153560
+ let compareConstruction;
153377
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
+ };
153378
153569
  const rebuilds = [];
153379
153570
  for (const reconciliation of constructions.values()) {
153380
153571
  if (!replayableValueIds.has(reconciliation.valueId)) continue;
@@ -153426,8 +153617,14 @@ function reconcileMaterializedInitializersV4(args) {
153426
153617
  currentState().document,
153427
153618
  replayDocument
153428
153619
  );
153429
- currentReader ??= new EffectiveValueReader(
153430
- 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
+ }
153431
153628
  );
153432
153629
  const replay = replayRows.get(reconciliation.valueId);
153433
153630
  if (replay === void 0) {
@@ -153457,13 +153654,12 @@ function reconcileMaterializedInitializersV4(args) {
153457
153654
  );
153458
153655
  continue;
153459
153656
  }
153460
- if (reconciliation.kind === "storedArguments" && storedArgumentsMatch({
153461
- reader: currentReader,
153462
- stored: reconciliation.storedConstructorArgs,
153657
+ if (reconciliation.kind === "storedArguments" && compareConstruction({
153463
153658
  currentRoot,
153464
- replay,
153659
+ currentArguments: reconciliation.storedConstructorArgs,
153660
+ replayRoot: replay,
153465
153661
  replayRows,
153466
- owner
153662
+ rootMember: owner
153467
153663
  })) {
153468
153664
  continue;
153469
153665
  }
@@ -153475,11 +153671,10 @@ function reconcileMaterializedInitializersV4(args) {
153475
153671
  `Cannot rebuild construction for value "${reconciliation.valueId}": its pulled row is missing.`
153476
153672
  );
153477
153673
  }
153478
- ownedValues ??= createOwnedValueDeletionCollector(replayDocument);
153479
153674
  rebuilds.push({
153480
153675
  valueId: reconciliation.valueId,
153481
153676
  row: rebuiltConstructionRow(stored, reconciliation.code),
153482
- ownedValueIds: ownedValues.collect({
153677
+ ownedValueIds: storedOwnedValues().collect({
153483
153678
  rootIds: [reconciliation.valueId],
153484
153679
  rootMembers: /* @__PURE__ */ new Map([[reconciliation.valueId, owner]])
153485
153680
  })
@@ -153522,22 +153717,6 @@ function sameCompiledProgram(left, right) {
153522
153717
  return literal3 && key === "value" ? isDeepStrictEqual(left[key], right[key]) : sameCompiledProgram(left[key], right[key]);
153523
153718
  });
153524
153719
  }
153525
- function storedArgumentsMatch(args) {
153526
- const replayArgs = isLiteralValueContent(args.replay) ? args.replay.constructorArgs : void 0;
153527
- if (!isObjectRecord(replayArgs)) return false;
153528
- const [storedArgs, replayedArgs] = withoutSharedArguments(
153529
- args.stored,
153530
- replayArgs
153531
- );
153532
- return effectiveValuesEqual(
153533
- args.reader.normalizeConstructorArguments(
153534
- storedArgs,
153535
- args.currentRoot,
153536
- args.owner
153537
- ),
153538
- args.reader.withRowOverrides(args.replayRows).normalizeConstructorArguments(replayedArgs, args.replay, args.owner)
153539
- );
153540
- }
153541
153720
  function rebuiltConstructionRow(data, code) {
153542
153721
  return { ...withoutMaterializedInstanceFields(data), init: { code } };
153543
153722
  }
@@ -153652,16 +153831,6 @@ function storedRowsWithRenamedKeys(before, after) {
153652
153831
  }
153653
153832
  return rows;
153654
153833
  }
153655
- function withoutSharedArguments(stored, replayed) {
153656
- const storedRest = { ...stored };
153657
- const replayedRest = { ...replayed };
153658
- for (const [slot, value] of Object.entries(stored)) {
153659
- if (typeof value !== "string" || replayed[slot] !== value) continue;
153660
- delete storedRest[slot];
153661
- delete replayedRest[slot];
153662
- }
153663
- return [storedRest, replayedRest];
153664
- }
153665
153834
  function pulledStateDocumentV4(workspace) {
153666
153835
  const state = workspace.state.records;
153667
153836
  const remembered = pulledStateDocuments.get(state);
@@ -154128,7 +154297,7 @@ var init_local_initializer_materialization = __esm({
154128
154297
  init_stored_closure_captures();
154129
154298
  init_initializer_dependencies();
154130
154299
  init_initializer_replay();
154131
- init_effective_value_comparison();
154300
+ init_construction_replay_equality();
154132
154301
  init_constructor_argument_ownership();
154133
154302
  init_neo_script_recompile_scope();
154134
154303
  init_compiler_adapter();
@@ -182029,7 +182198,7 @@ function collectUnityReferencedProjectFileIds(args) {
182029
182198
  )) {
182030
182199
  instanceEnv.set(paramId, { kind: "member", memberId: boundMemberId });
182031
182200
  }
182032
- const childValueIds = isStringRecord9(storedValue) ? storedValue : {};
182201
+ const childValueIds = isStringRecord10(storedValue) ? storedValue : {};
182033
182202
  for (const entry of schema) {
182034
182203
  if (entry.memberId === null) continue;
182035
182204
  const childMember = substituteWalkMember(
@@ -182092,7 +182261,7 @@ function collectUnityReferencedProjectFileIds(args) {
182092
182261
  return;
182093
182262
  }
182094
182263
  if (isMemberDictionaryBase(member)) {
182095
- const childValueIds = isStringRecord9(storedValue) ? storedValue : {};
182264
+ const childValueIds = isStringRecord10(storedValue) ? storedValue : {};
182096
182265
  const substitutedEntryMember = substituteWalkMember(
182097
182266
  member.entryMemberId,
182098
182267
  args.genericEnv,
@@ -182126,7 +182295,7 @@ function readGenericBindingsFromValue(value) {
182126
182295
  if (value == null) return {};
182127
182296
  if (!isLiteralValueContent(value)) return {};
182128
182297
  const bindings = Reflect.get(value, "genericBindings");
182129
- return isStringRecord9(bindings) ? bindings : {};
182298
+ return isStringRecord10(bindings) ? bindings : {};
182130
182299
  }
182131
182300
  function readClassIdFromMemberValueBase(value) {
182132
182301
  if (value === null) return null;
@@ -182146,7 +182315,7 @@ function readFileIdFromMemberValue(value) {
182146
182315
  if (fileId.trim().length === 0) return null;
182147
182316
  return fileId;
182148
182317
  }
182149
- function isStringRecord9(value) {
182318
+ function isStringRecord10(value) {
182150
182319
  if (value === null) return false;
182151
182320
  if (typeof value !== "object") return false;
182152
182321
  return Object.values(value).every((entry) => typeof entry === "string");
@@ -186683,18 +186852,36 @@ function generateInheritedPropertyInterfaceAdapters(ctx, classDef, genericEnv) {
186683
186852
  continue;
186684
186853
  }
186685
186854
  const source = `((${receiverType})this).${memberName}`;
186686
- const getter = isMemberWithEntries(member) ? collectionReadExpression(
186855
+ const memberSaved = memberSavedForStorage(
186687
186856
  ctx,
186688
- member,
186689
- `node.Get<${neoMemberNodeType(member)}>("${escapeCSharpString(schemaKey)}")`,
186690
- schemaKey,
186691
- resolveMemberById(ctx, member.entryMemberId, "entryMemberId"),
186692
- memberSavedForStorage(ctx, memberId, false, declarationClass.id),
186693
- null,
186694
- genericEnv,
186695
- interfaceValueType,
186696
- false
186697
- ) : [`return (${interfaceValueType})(object)${source}!;`];
186857
+ memberId,
186858
+ false,
186859
+ declarationClass.id
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}!;`];
186698
186885
  const hasSetter = isMemberNSPropertyBase(member) && typeof member.setterCode === "string";
186699
186886
  const adapter = [
186700
186887
  `${interfaceValueType} ${interfaceType2}.${memberName}`,
@@ -190637,7 +190824,7 @@ function readExpression(ctx, member, schemaKey, nodeType, saved, ownerClassName,
190637
190824
  )
190638
190825
  ];
190639
190826
  }
190640
- function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberName, genericEnv, ownerClassId) {
190827
+ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberName, genericEnv, ownerClassId, genericBindingSaved = saved) {
190641
190828
  if (ownerClassId === void 0 || !classSupportsDetachedViews(ctx, ownerClassId)) {
190642
190829
  return [];
190643
190830
  }
@@ -190667,7 +190854,13 @@ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberN
190667
190854
  saved,
190668
190855
  genericEnv
190669
190856
  );
190670
- const entryType = csharpValueType(ctx, entryMember, saved, genericEnv);
190857
+ const entryType = csharpValueType(
190858
+ ctx,
190859
+ entryMember,
190860
+ saved,
190861
+ genericEnv,
190862
+ genericBindingSaved
190863
+ );
190671
190864
  if (readEntry2 === null || entryType === null) return [];
190672
190865
  const guardArguments = collectionGuardArguments(
190673
190866
  member,
@@ -190675,10 +190868,10 @@ function detachedReadExpression(ctx, member, schemaKey, saved, writeGuardMemberN
190675
190868
  );
190676
190869
  const [viewType, view] = saved ? [
190677
190870
  `NeoList<${entryType}>`,
190678
- `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})`
190679
190872
  ] : [
190680
190873
  `NeoReadOnlyList<${entryType}>`,
190681
- `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)})`
190682
190875
  ];
190683
190876
  return [
190684
190877
  `if (TryReadDetached("${key}", out _))`,
@@ -191556,7 +191749,13 @@ function childConverter(ctx, member, saved = false, branchOnReadOnly = false, ge
191556
191749
  }
191557
191750
  if (isClassTypedMember(member)) {
191558
191751
  const typeName = ctx.typeNames.get(member.classId) ?? "NeoNode";
191559
- const constructedSuffix = constructedTypeArgumentsSuffix(ctx, member, true, genericEnv) ?? "";
191752
+ const constructedSuffix = constructedTypeArgumentsSuffix(
191753
+ ctx,
191754
+ member,
191755
+ true,
191756
+ genericEnv,
191757
+ genericBindingSaved
191758
+ ) ?? "";
191560
191759
  const savedTypeRef = `${qualifyGeneratedType(ctx, savedTypeName(typeName))}${constructedSuffix}`;
191561
191760
  const hasWritableFamily = schemaClassHasWritableFamily(ctx, member.classId);
191562
191761
  if (saved && branchOnReadOnly && hasWritableFamily) {
@@ -195138,7 +195337,7 @@ var UNITY_CODEGEN_REVISION;
195138
195337
  var init_unity_codegen_revision = __esm({
195139
195338
  "../src/models/exports/unity-codegen-revision.ts"() {
195140
195339
  "use strict";
195141
- UNITY_CODEGEN_REVISION = "e875228ee779f868c2c818eb9e245604cd074598712ffd3f8394f460317b1a28";
195340
+ UNITY_CODEGEN_REVISION = "f748ddae5544d547b4d1139dcdbc86b86b01ab0aae4a9a24656ad8858258b460";
195142
195341
  }
195143
195342
  });
195144
195343
 
@@ -216276,7 +216475,7 @@ var releaseWorkspaceLock = () => void 0;
216276
216475
  async function main() {
216277
216476
  const args = parseArgs(process.argv.slice(2));
216278
216477
  if (args.command === "--version") {
216279
- console.log("0.84.3");
216478
+ console.log("0.84.4");
216280
216479
  return;
216281
216480
  }
216282
216481
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {