@neocompose/cli 0.56.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/neo.mjs CHANGED
@@ -1359,7 +1359,7 @@ function indexLocals(tokens, pairs, lexed, diagnostics) {
1359
1359
  }
1360
1360
  const loop = tryParseLoopLocal(tokens, index, pairs, lexed, diagnostics);
1361
1361
  if (loop) {
1362
- locals.push(loop.local);
1362
+ locals.push(...loop.locals);
1363
1363
  index = loop.resumeTokenIndex;
1364
1364
  continue;
1365
1365
  }
@@ -1793,7 +1793,7 @@ function tryParseLoopLocal(tokens, start, pairs, lexed, diagnostics) {
1793
1793
  });
1794
1794
  }
1795
1795
  return {
1796
- local: { ...declaration.local, scopeEnd },
1796
+ locals: [{ ...declaration.local, scopeEnd }],
1797
1797
  resumeTokenIndex: declaration.endTokenIndex
1798
1798
  };
1799
1799
  }
@@ -1805,22 +1805,65 @@ function tryParseLoopLocal(tokens, start, pairs, lexed, diagnostics) {
1805
1805
  const inIndex = start + 2 + inOffset;
1806
1806
  const name = tokens[inIndex - 1];
1807
1807
  const first = tokens[start + 2];
1808
- if (!name || name.kind !== "identifier" || !first) return null;
1808
+ if (!first) return null;
1809
1809
  const inferred = first.kind === "identifier" && first.text === NEOSCRIPT_INFERRED_LOCAL_KEYWORD;
1810
+ const receiver = tokens.slice(inIndex + 1, closeIndex);
1811
+ const local = (token, typeTokens, key) => ({
1812
+ name: token.text,
1813
+ nameRange: token.range,
1814
+ typeTokens,
1815
+ inferred,
1816
+ ...inferred ? { contextualKeywordRange: first.range } : {},
1817
+ initializerTokens: receiver,
1818
+ collectionIteration: true,
1819
+ ...key ? { collectionIterationKey: true } : {},
1820
+ declarationRange: lexed.source.range(first.start, token.end),
1821
+ scopeStart: tokens[closeIndex]?.end ?? token.end,
1822
+ scopeEnd,
1823
+ lambdaParameter: false
1824
+ });
1825
+ const tupleOpenIndex = start + (inferred ? 3 : 2);
1826
+ const tupleOpen = tokens[tupleOpenIndex];
1827
+ if (tupleOpen?.kind === "punctuation" && tupleOpen.text === "(") {
1828
+ const tupleCloseIndex = pairs.get(tupleOpenIndex);
1829
+ if (tupleCloseIndex !== inIndex - 1) return null;
1830
+ let commaIndex = -1;
1831
+ let angleDepth = 0;
1832
+ for (let cursor = tupleOpenIndex + 1; cursor < tupleCloseIndex; cursor++) {
1833
+ const text = tokens[cursor]?.text;
1834
+ if (text === "<") angleDepth++;
1835
+ if (text === ">") angleDepth--;
1836
+ if (text === "," && angleDepth === 0) {
1837
+ commaIndex = cursor;
1838
+ break;
1839
+ }
1840
+ }
1841
+ if (commaIndex < 0) return null;
1842
+ const keyName = tokens[commaIndex - 1];
1843
+ const valueName = tokens[tupleCloseIndex - 1];
1844
+ if (keyName?.kind !== "identifier" || valueName?.kind !== "identifier")
1845
+ return null;
1846
+ return {
1847
+ locals: [
1848
+ local(
1849
+ keyName,
1850
+ inferred ? [] : tokens.slice(tupleOpenIndex + 1, commaIndex - 1),
1851
+ true
1852
+ ),
1853
+ local(
1854
+ valueName,
1855
+ inferred ? [] : tokens.slice(commaIndex + 1, tupleCloseIndex - 1),
1856
+ false
1857
+ )
1858
+ ],
1859
+ resumeTokenIndex: inIndex - 1
1860
+ };
1861
+ }
1862
+ if (!name || name.kind !== "identifier") return null;
1810
1863
  return {
1811
- local: {
1812
- name: name.text,
1813
- nameRange: name.range,
1814
- typeTokens: inferred ? [] : tokens.slice(start + 2, inIndex - 1),
1815
- inferred,
1816
- ...inferred ? { contextualKeywordRange: first.range } : {},
1817
- initializerTokens: tokens.slice(inIndex + 1, closeIndex),
1818
- collectionIteration: true,
1819
- declarationRange: lexed.source.range(first.start, name.end),
1820
- scopeStart: tokens[closeIndex]?.end ?? name.end,
1821
- scopeEnd,
1822
- lambdaParameter: false
1823
- },
1864
+ locals: [
1865
+ local(name, inferred ? [] : tokens.slice(start + 2, inIndex - 1), false)
1866
+ ],
1824
1867
  resumeTokenIndex: inIndex - 1
1825
1868
  };
1826
1869
  }
@@ -2877,14 +2920,25 @@ var init_executable_parser = __esm({
2877
2920
  const token = this.expect("keyword", "foreach");
2878
2921
  this.expect("punctuation", "(");
2879
2922
  const inferred = this.peek().kind === "identifier" && this.peek().text === NEOSCRIPT_INFERRED_LOCAL_KEYWORD;
2923
+ if (inferred) this.next();
2924
+ const deconstructed = this.peek().kind === "punctuation" && this.peek().text === "(";
2925
+ if (deconstructed) this.next();
2880
2926
  let type;
2881
2927
  if (inferred) {
2882
- this.next();
2883
2928
  type = null;
2884
2929
  } else {
2885
2930
  type = this.parseType();
2886
2931
  }
2887
- const name = this.expect("identifier");
2932
+ const firstName = this.expect("identifier");
2933
+ let key;
2934
+ let name = firstName;
2935
+ if (deconstructed) {
2936
+ key = { name: firstName.text, type };
2937
+ this.expect("punctuation", ",");
2938
+ type = inferred ? null : this.parseType();
2939
+ name = this.expect("identifier");
2940
+ this.expect("punctuation", ")");
2941
+ }
2888
2942
  this.expect("keyword", "in");
2889
2943
  const collection = this.parseExpr();
2890
2944
  this.expect("punctuation", ")");
@@ -2892,6 +2946,7 @@ var init_executable_parser = __esm({
2892
2946
  kind: "forEach",
2893
2947
  type,
2894
2948
  name: name.text,
2949
+ ...key ? { key } : {},
2895
2950
  collection,
2896
2951
  body: this.parseStatementBody(),
2897
2952
  pos: at(token)
@@ -5834,6 +5889,9 @@ function collectionParts(type) {
5834
5889
  function collectionPartsFor(expression) {
5835
5890
  return collectionParts(expression.type);
5836
5891
  }
5892
+ function isCollectionPath(expression) {
5893
+ return expression.kind === "ident" || expression.kind === "member" && !expression.optional && isCollectionPath(expression.receiver);
5894
+ }
5837
5895
  function collectionOperationValueType(expression, collection) {
5838
5896
  if (isLookupSelectionCollection(expression, collection)) {
5839
5897
  return { kind: "primitive", name: "string" };
@@ -6934,6 +6992,12 @@ var init_strict_resolver = __esm({
6934
6992
  };
6935
6993
  }
6936
6994
  case "forEach": {
6995
+ if (statement.key && !isCollectionPath(statement.collection)) {
6996
+ throw new CompileError(
6997
+ "Assign the dictionary to a local before deconstructing it in foreach.",
6998
+ statement.collection.pos
6999
+ );
7000
+ }
6937
7001
  const collection = this.resolveExpression(statement.collection, scope);
6938
7002
  if (isNullable(collection.type)) {
6939
7003
  throw new CompileError(
@@ -6948,36 +7012,88 @@ var init_strict_resolver = __esm({
6948
7012
  statement.collection.pos
6949
7013
  );
6950
7014
  }
7015
+ if (statement.key && parts.kind !== "dictionary") {
7016
+ throw new CompileError(
7017
+ `foreach key/value deconstruction requires a Dictionary, got ${this.describe(collection.type)}`,
7018
+ statement.collection.pos
7019
+ );
7020
+ }
6951
7021
  this.assertLocalNameAvailable(statement.name, scope, statement.pos);
6952
- const inferredType = parts.valueType;
6953
- const bindingType = statement.type ? this.resolveType(statement.type) : inferredType;
6954
- if (statement.type) {
7022
+ if (statement.key) {
7023
+ this.assertLocalNameAvailable(
7024
+ statement.key.name,
7025
+ scope,
7026
+ statement.pos
7027
+ );
7028
+ if (statement.key.name === statement.name) {
7029
+ throw new CompileError(
7030
+ "foreach key and value need different names.",
7031
+ statement.pos
7032
+ );
7033
+ }
7034
+ }
7035
+ const inferredType = statement.key ? parts.keyType : parts.valueType;
7036
+ const declared = statement.key ? statement.key.type : statement.type;
7037
+ const bindingType = declared ? this.resolveType(declared) : inferredType;
7038
+ if (declared) {
6955
7039
  this.requireAssignable(
6956
7040
  inferredType,
6957
7041
  bindingType,
6958
7042
  statement.pos,
6959
- "foreach iterator"
7043
+ statement.key ? "foreach key" : "foreach iterator"
6960
7044
  );
6961
7045
  }
6962
7046
  const binding = variable(
6963
- statement.name,
7047
+ statement.key?.name ?? statement.name,
6964
7048
  bindingType,
6965
7049
  void 0,
6966
7050
  this.project
6967
7051
  );
7052
+ const iterationCollection = statement.key ? this.selectDictionaryKeys(collection, parts) : collection;
6968
7053
  const bindingWritability = collection.entryWritability ?? collection.writability ?? "runtime" /* Runtime */;
7054
+ const collectionWriteRoot = this.expressionWriteRoot(collection, scope);
6969
7055
  const loopScope = new Scope(scope);
6970
7056
  loopScope.define(
6971
7057
  scopeVariable(
6972
- statement.name,
7058
+ statement.key?.name ?? statement.name,
6973
7059
  binding,
6974
7060
  bindingType,
6975
7061
  bindingWritability,
6976
7062
  bindingWritability,
6977
- collection.writeRoot ?? this.writeThroughRoot(collection.pointer, scope),
7063
+ collectionWriteRoot,
6978
7064
  "foreach"
6979
7065
  )
6980
7066
  );
7067
+ if (statement.key) {
7068
+ const valueType = statement.type ? this.resolveType(statement.type) : parts.valueType;
7069
+ if (statement.type) {
7070
+ this.requireAssignable(
7071
+ parts.valueType,
7072
+ valueType,
7073
+ statement.pos,
7074
+ "foreach value"
7075
+ );
7076
+ }
7077
+ const indexed = this.resolveIndex(
7078
+ statement.collection,
7079
+ { kind: "ident", name: statement.key.name, pos: statement.pos },
7080
+ loopScope,
7081
+ statement.pos,
7082
+ false
7083
+ );
7084
+ loopScope.define({
7085
+ name: statement.name,
7086
+ type: valueType,
7087
+ variableId: statement.name,
7088
+ pointer: indexed.pointer,
7089
+ ...indexed.writability ? {
7090
+ writability: indexed.writability,
7091
+ ownership: indexed.writability
7092
+ } : {},
7093
+ writeRoot: collectionWriteRoot,
7094
+ readonlyBinding: "foreach"
7095
+ });
7096
+ }
6981
7097
  const iterationScope = new Scope(loopScope);
6982
7098
  invalidateLoopEntryNarrowingsAssignedBy(
6983
7099
  iterationScope,
@@ -7025,8 +7141,8 @@ var init_strict_resolver = __esm({
7025
7141
  readonly: true,
7026
7142
  writability: bindingWritability
7027
7143
  },
7028
- collectionPointer: collection.pointer,
7029
- collectionTypeInfo: collection.wireType ?? toWireType(collection.type, this.project),
7144
+ collectionPointer: iterationCollection.pointer,
7145
+ collectionTypeInfo: iterationCollection.wireType ?? toWireType(iterationCollection.type, this.project),
7030
7146
  instructions
7031
7147
  };
7032
7148
  }
@@ -7468,6 +7584,8 @@ var init_strict_resolver = __esm({
7468
7584
  let label = "foreach iterator";
7469
7585
  if (local.readonlyBinding === "catch") label = "catch parameter";
7470
7586
  if (local.readonlyBinding === "capture") label = "captured value";
7587
+ if (local.readonlyBinding === "enumKey")
7588
+ label = "enum dictionary key parameter";
7471
7589
  throw new CompileError(
7472
7590
  `Cannot assign to ${label} '${local.name}' because it is read-only.`,
7473
7591
  statement.pos
@@ -11631,6 +11749,67 @@ var init_strict_resolver = __esm({
11631
11749
  }
11632
11750
  return value.pointer;
11633
11751
  }
11752
+ selectDictionaryKeys(dictionary, parts) {
11753
+ const key = this.collectionLambdaParameter(
11754
+ "__foreach_key__",
11755
+ parts.keyType,
11756
+ parts,
11757
+ 0
11758
+ );
11759
+ const value = variable(
11760
+ "__foreach_value__",
11761
+ parts.valueType,
11762
+ void 0,
11763
+ this.project
11764
+ );
11765
+ const alias = this.enumDictionaryKeyPointer(key, parts.keyType, parts, 0);
11766
+ const fn = {
11767
+ compilerRevision: NEOSCRIPT_COMPILER_REVISION,
11768
+ parameters: [key, value],
11769
+ instructions: [
11770
+ {
11771
+ type: "return" /* Return */,
11772
+ pointer: alias ?? {
11773
+ type: "variable" /* Variable */,
11774
+ variableId: key.id
11775
+ }
11776
+ }
11777
+ ],
11778
+ typeInfo: toWireType(parts.keyType, this.project)
11779
+ };
11780
+ return intrinsic(
11781
+ "select" /* Select */,
11782
+ { collectionPointer: dictionary.pointer, function: fn },
11783
+ { kind: "list", elementType: parts.keyType, readOnly: true }
11784
+ );
11785
+ }
11786
+ collectionLambdaParameter(name, type, collection, index) {
11787
+ const rawType = this.isEnumDictionaryKey(type, collection, index) ? { kind: "primitive", name: "string" } : type;
11788
+ return variable(name, rawType, void 0, this.project);
11789
+ }
11790
+ isEnumDictionaryKey(type, collection, index) {
11791
+ return collection.kind === "dictionary" && index === 0 && type.kind === "named" && this.project.typeById.get(type.typeId)?.kind === "enum";
11792
+ }
11793
+ enumDictionaryKeyPointer(parameter4, type, collection, index) {
11794
+ if (!this.isEnumDictionaryKey(type, collection, index)) return void 0;
11795
+ const wire = toWireType(
11796
+ {
11797
+ kind: "list",
11798
+ elementType: { kind: "primitive", name: "string" }
11799
+ },
11800
+ this.project
11801
+ );
11802
+ if (wire.type !== 6 /* List */) {
11803
+ throw new Error("Enum key alias requires a list wire type.");
11804
+ }
11805
+ return {
11806
+ type: "listLiteral" /* ListLiteral */,
11807
+ typeInfo: wire,
11808
+ entries: [
11809
+ { type: "variable" /* Variable */, variableId: parameter4.id }
11810
+ ]
11811
+ };
11812
+ }
11634
11813
  resolveCollectionLambda(ast, collection, returnType, outerScope, pos) {
11635
11814
  if (ast.kind !== "lambda") {
11636
11815
  throw new CompileError(
@@ -11658,16 +11837,30 @@ var init_strict_resolver = __esm({
11658
11837
  parameter4.pos,
11659
11838
  "lambda parameter"
11660
11839
  );
11661
- const item = variable(parameter4.name, declared, void 0, this.project);
11662
- scope.define(
11663
- scopeVariable(
11840
+ const item = this.collectionLambdaParameter(
11841
+ parameter4.name,
11842
+ declared,
11843
+ collection,
11844
+ index
11845
+ );
11846
+ const alias = this.enumDictionaryKeyPointer(
11847
+ item,
11848
+ declared,
11849
+ collection,
11850
+ index
11851
+ );
11852
+ scope.define({
11853
+ ...scopeVariable(
11664
11854
  parameter4.name,
11665
11855
  item,
11666
11856
  declared,
11667
11857
  void 0,
11668
- "runtime" /* Runtime */
11669
- )
11670
- );
11858
+ "runtime" /* Runtime */,
11859
+ void 0,
11860
+ alias ? "enumKey" : void 0
11861
+ ),
11862
+ ...alias ? { pointer: alias } : {}
11863
+ });
11671
11864
  return item;
11672
11865
  });
11673
11866
  this.functionControlBoundaries.push({
@@ -11714,16 +11907,30 @@ var init_strict_resolver = __esm({
11714
11907
  this.assertLocalNameAvailable(parameter4.name, scope, parameter4.pos);
11715
11908
  const type = parameter4.type ? this.resolveType(parameter4.type) : requiredAt(parameterTypes, index);
11716
11909
  const isValueParameter = index === valueParameterIndex;
11717
- scope.define(
11718
- scopeVariable(
11910
+ const item = this.collectionLambdaParameter(
11911
+ parameter4.name,
11912
+ type,
11913
+ collection,
11914
+ index
11915
+ );
11916
+ const alias = this.enumDictionaryKeyPointer(
11917
+ item,
11918
+ type,
11919
+ collection,
11920
+ index
11921
+ );
11922
+ scope.define({
11923
+ ...scopeVariable(
11719
11924
  parameter4.name,
11720
- variable(parameter4.name, type, void 0, this.project),
11925
+ item,
11721
11926
  type,
11722
11927
  isValueParameter ? sourceWritability : "runtime" /* Runtime */,
11723
11928
  isValueParameter ? sourceWritability : "runtime" /* Runtime */,
11724
- isValueParameter ? sourceWriteRoot : "local"
11725
- )
11726
- );
11929
+ isValueParameter ? sourceWriteRoot : "local",
11930
+ alias ? "enumKey" : void 0
11931
+ ),
11932
+ ...alias ? { pointer: alias } : {}
11933
+ });
11727
11934
  });
11728
11935
  let inferred = null;
11729
11936
  let inferredWritability = null;
@@ -14252,7 +14459,9 @@ function inferLocalType(local, snapshot) {
14252
14459
  tokens[0]?.start ?? snapshot.source.offsetAt(local.nameRange.end)
14253
14460
  );
14254
14461
  if (!local.collectionIteration) return inferred;
14255
- if (inferred.kind === "dictionary") return inferred.valueType;
14462
+ if (inferred.kind === "dictionary") {
14463
+ return local.collectionIterationKey ? inferred.keyType : inferred.valueType;
14464
+ }
14256
14465
  if (inferred.kind === "list" || inferred.kind === "set") {
14257
14466
  return inferred.elementType;
14258
14467
  }
@@ -22707,6 +22916,7 @@ function collectIdentifierReads(expression, names) {
22707
22916
  walk(statement.collection, visible);
22708
22917
  const inner = new Set(visible);
22709
22918
  inner.delete(statement.name);
22919
+ if (statement.key) inner.delete(statement.key.name);
22710
22920
  for (const bodyStatement of statement.body) {
22711
22921
  walkStatement(bodyStatement, inner);
22712
22922
  }
@@ -38029,6 +38239,12 @@ function normalizeDocumentFields(recordKind, value) {
38029
38239
  }
38030
38240
  }
38031
38241
  }
38242
+ if (recordKind === "class" && Array.isArray(normalized.genericParams)) {
38243
+ for (const parameter4 of normalized.genericParams) {
38244
+ if (!isRecord(parameter4) || !isRecord(parameter4.constraint)) continue;
38245
+ if (parameter4.constraint.kind === 0) delete parameter4.constraint.kind;
38246
+ }
38247
+ }
38032
38248
  omitRedundantDeclarationOrder(recordKind, normalized);
38033
38249
  return normalized;
38034
38250
  }
@@ -45095,6 +45311,109 @@ var init_project_manifest = __esm({
45095
45311
  }
45096
45312
  });
45097
45313
 
45314
+ // src/project-source/source-format.ts
45315
+ function quoteNeoString(value) {
45316
+ return JSON.stringify(value);
45317
+ }
45318
+ function indentNeoSource(value, spaces) {
45319
+ return indentLines(value, spaces, true);
45320
+ }
45321
+ function indentNeoSourceNonEmptyLines(value, spaces) {
45322
+ return indentLines(value, spaces, false);
45323
+ }
45324
+ function indentLines(value, spaces, indentEmptyLines) {
45325
+ const prefix = " ".repeat(spaces);
45326
+ return value.split("\n").map(
45327
+ (line) => indentEmptyLines || line.length > 0 ? `${prefix}${line}` : line
45328
+ ).join("\n");
45329
+ }
45330
+ function formatNeoNumber(value) {
45331
+ if (!Number.isFinite(value)) {
45332
+ throw new Error(`Cannot emit non-finite Neo number ${String(value)}.`);
45333
+ }
45334
+ const source = String(value);
45335
+ const match = /^(?<sign>-?)(?<integer>\d+)(?:\.(?<fraction>\d+))?[eE](?<exponent>[+-]?\d+)$/u.exec(
45336
+ source
45337
+ );
45338
+ if (match?.groups === void 0) return source;
45339
+ const sign = match.groups.sign ?? "";
45340
+ const integer3 = match.groups.integer ?? "";
45341
+ const fraction = match.groups.fraction ?? "";
45342
+ const digits = `${integer3}${fraction}`;
45343
+ const decimalIndex = integer3.length + Number(match.groups.exponent);
45344
+ if (decimalIndex <= 0) {
45345
+ return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
45346
+ }
45347
+ if (decimalIndex >= digits.length) {
45348
+ return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
45349
+ }
45350
+ return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
45351
+ }
45352
+ function invariantCaseKey(value) {
45353
+ return value.toLowerCase();
45354
+ }
45355
+ var init_source_format = __esm({
45356
+ "src/project-source/source-format.ts"() {
45357
+ "use strict";
45358
+ init_machine_strings();
45359
+ }
45360
+ });
45361
+
45362
+ // src/project-source/dictionary-enum-keys.ts
45363
+ function lowerDictionaryKey(expression, keyEnum, path) {
45364
+ if (expression.kind === "litString") {
45365
+ if (keyEnum?.optionsByName.has(expression.value)) {
45366
+ throw new Error(
45367
+ `Dictionary key ${JSON.stringify(expression.value)} at ${path} names an option in enum ${JSON.stringify(keyEnum.name)}. Write .${expression.value} or its option ID.`
45368
+ );
45369
+ }
45370
+ return expression.value;
45371
+ }
45372
+ if (keyEnum === null) {
45373
+ throw new Error(`Dictionary ${path} requires string keys.`);
45374
+ }
45375
+ let optionName;
45376
+ if (expression.kind === "contextualEnum") {
45377
+ optionName = expression.name;
45378
+ } else if (expression.kind === "member" && expression.receiver.kind === "ident") {
45379
+ if (expression.receiver.name !== keyEnum.name) {
45380
+ throw new Error(
45381
+ `Dictionary key at ${path} names enum ${JSON.stringify(expression.receiver.name)}, expected ${JSON.stringify(keyEnum.name)}.`
45382
+ );
45383
+ }
45384
+ optionName = expression.name;
45385
+ } else {
45386
+ throw new Error(
45387
+ `Dictionary key at ${path} must be .Option, ${keyEnum.name}.Option, or a quoted option ID.`
45388
+ );
45389
+ }
45390
+ const optionId = keyEnum.optionsByName.get(optionName);
45391
+ if (optionId === void 0) {
45392
+ throw new Error(
45393
+ `Enum ${JSON.stringify(keyEnum.name)} has no option ${JSON.stringify(optionName)} at ${path}.`
45394
+ );
45395
+ }
45396
+ return optionId;
45397
+ }
45398
+ function emitDictionaryKey(key, options) {
45399
+ const name = options?.get(key)?.name;
45400
+ return name === void 0 ? quoteNeoString(key) : `.${name}`;
45401
+ }
45402
+ function orderedDictionaryEntries(value, options) {
45403
+ return Object.entries(value).sort(([left], [right]) => {
45404
+ const leftOrder = options?.get(left)?.order ?? Infinity;
45405
+ const rightOrder = options?.get(right)?.order ?? Infinity;
45406
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
45407
+ return compareCodePoints(left, right);
45408
+ });
45409
+ }
45410
+ var init_dictionary_enum_keys = __esm({
45411
+ "src/project-source/dictionary-enum-keys.ts"() {
45412
+ "use strict";
45413
+ init_source_format();
45414
+ }
45415
+ });
45416
+
45098
45417
  // ../src/models/system-record-id.ts
45099
45418
  function isSystemRecordId(id2) {
45100
45419
  return id2.startsWith(SYSTEM_RECORD_ID_PREFIX2);
@@ -45153,54 +45472,6 @@ var init_declaration_path = __esm({
45153
45472
  }
45154
45473
  });
45155
45474
 
45156
- // src/project-source/source-format.ts
45157
- function quoteNeoString(value) {
45158
- return JSON.stringify(value);
45159
- }
45160
- function indentNeoSource(value, spaces) {
45161
- return indentLines(value, spaces, true);
45162
- }
45163
- function indentNeoSourceNonEmptyLines(value, spaces) {
45164
- return indentLines(value, spaces, false);
45165
- }
45166
- function indentLines(value, spaces, indentEmptyLines) {
45167
- const prefix = " ".repeat(spaces);
45168
- return value.split("\n").map(
45169
- (line) => indentEmptyLines || line.length > 0 ? `${prefix}${line}` : line
45170
- ).join("\n");
45171
- }
45172
- function formatNeoNumber(value) {
45173
- if (!Number.isFinite(value)) {
45174
- throw new Error(`Cannot emit non-finite Neo number ${String(value)}.`);
45175
- }
45176
- const source = String(value);
45177
- const match = /^(?<sign>-?)(?<integer>\d+)(?:\.(?<fraction>\d+))?[eE](?<exponent>[+-]?\d+)$/u.exec(
45178
- source
45179
- );
45180
- if (match?.groups === void 0) return source;
45181
- const sign = match.groups.sign ?? "";
45182
- const integer3 = match.groups.integer ?? "";
45183
- const fraction = match.groups.fraction ?? "";
45184
- const digits = `${integer3}${fraction}`;
45185
- const decimalIndex = integer3.length + Number(match.groups.exponent);
45186
- if (decimalIndex <= 0) {
45187
- return `${sign}0.${"0".repeat(-decimalIndex)}${digits}`;
45188
- }
45189
- if (decimalIndex >= digits.length) {
45190
- return `${sign}${digits}${"0".repeat(decimalIndex - digits.length)}`;
45191
- }
45192
- return `${sign}${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
45193
- }
45194
- function invariantCaseKey(value) {
45195
- return value.toLowerCase();
45196
- }
45197
- var init_source_format = __esm({
45198
- "src/project-source/source-format.ts"() {
45199
- "use strict";
45200
- init_machine_strings();
45201
- }
45202
- });
45203
-
45204
45475
  // src/project-source/ui-action-source.ts
45205
45476
  function isCompleteUIAction(rawAction) {
45206
45477
  const action = object(rawAction);
@@ -52927,7 +53198,7 @@ function assertReadOnlyMembersValid(document) {
52927
53198
  `Read-only member "${member.name}" (${member.id}) must declare Immutable storage; ${ownerContext}.`
52928
53199
  );
52929
53200
  }
52930
- if (isAbstractMember(member) !== true && resolved.kind !== 21 /* Generic */ && resolved.defaultValue === void 0) {
53201
+ if (isAbstractMember(resolved) !== true && resolved.kind !== 21 /* Generic */ && resolved.defaultValue === void 0) {
52931
53202
  throw new Error(
52932
53203
  `Read-only member "${member.name}" (${member.id}) requires an explicit defaultValue; ${ownerContext}.`
52933
53204
  );
@@ -52967,7 +53238,7 @@ function assertReadOnlyMembersValid(document) {
52967
53238
  `Read-only member "${member.name}" (${member.id}) must be value-bearing in every closed Generic placement; ${ownerContext}.`
52968
53239
  );
52969
53240
  }
52970
- if (isAbstractMember(member) === true) continue;
53241
+ if (isAbstractMember(resolved) === true) continue;
52971
53242
  if (effective.defaultValue == null) {
52972
53243
  throw new Error(
52973
53244
  `Read-only member "${member.name}" (${member.id}) requires an explicit field defaultValue in every closed Generic placement; ${ownerContext}.`
@@ -52984,7 +53255,7 @@ function assertReadOnlyMembersValid(document) {
52984
53255
  );
52985
53256
  }
52986
53257
  }
52987
- if (isAbstractMember(member) === true) continue;
53258
+ if (isAbstractMember(resolved) === true) continue;
52988
53259
  assertOwnedSchemaIsImmutable({
52989
53260
  member,
52990
53261
  memberId: member.id,
@@ -53209,6 +53480,25 @@ function virtualValueId(instanceRootId, sourceIdentity3) {
53209
53480
  )
53210
53481
  );
53211
53482
  }
53483
+ function virtualSourceIdentityHead(sourceIdentity3) {
53484
+ const pathStart = sourceIdentity3.indexOf(":$");
53485
+ return pathStart < 0 ? sourceIdentity3 : sourceIdentity3.slice(0, pathStart);
53486
+ }
53487
+ function hasPendingVirtualSourceIdentity(sourceIdentity3) {
53488
+ const head = virtualSourceIdentityHead(sourceIdentity3);
53489
+ return head.startsWith("path:__pending__:") || head.startsWith("__pending__:");
53490
+ }
53491
+ function rewriteVirtualSourceIdentity(sourceIdentity3, rewriteId) {
53492
+ const head = virtualSourceIdentityHead(sourceIdentity3);
53493
+ const path = sourceIdentity3.slice(head.length);
53494
+ if (head.startsWith("path:__pending__:")) {
53495
+ return `path:${rewriteId(head.slice("path:".length))}${path}`;
53496
+ }
53497
+ if (head.startsWith("__pending__:")) {
53498
+ return `${rewriteId(head)}${path}`;
53499
+ }
53500
+ return sourceIdentity3;
53501
+ }
53212
53502
  function pendingVirtualValueId(pendingInstanceRootId, sourceIdentity3) {
53213
53503
  return `${PENDING_VIRTUAL_VALUE_PREFIX}${encodeURIComponent(pendingInstanceRootId)}:${encodeURIComponent(sourceIdentity3)}`;
53214
53504
  }
@@ -57815,6 +58105,7 @@ function emitProjectSourcesV4(manifest, options = {}) {
57815
58105
  classes: new Map(manifest.classes.map((entry) => [entry.id, entry])),
57816
58106
  interfaces: new Map(manifest.interfaces.map((entry) => [entry.id, entry])),
57817
58107
  enums: new Map(manifest.enums.map((entry) => [entry.id, entry])),
58108
+ dictionaryKeyOptions: /* @__PURE__ */ new Map(),
57818
58109
  members: new Map(manifest.members.map((entry) => [entry.id, entry])),
57819
58110
  constructorsById: new Map(
57820
58111
  manifest.constructors.map((entry) => [entry.id, entry])
@@ -58833,6 +59124,18 @@ function initDefaultSource(member) {
58833
59124
  if (!("init" in value)) return void 0;
58834
59125
  return value.init.code;
58835
59126
  }
59127
+ function dictionaryOptions(context, enumId) {
59128
+ const cached = context.dictionaryKeyOptions.get(enumId);
59129
+ if (cached !== void 0) return cached;
59130
+ const result = new Map(
59131
+ required(context.enums, enumId, "enum").options.map((option, order) => [
59132
+ option.id,
59133
+ { name: option.name, order }
59134
+ ])
59135
+ );
59136
+ context.dictionaryKeyOptions.set(enumId, result);
59137
+ return result;
59138
+ }
58836
59139
  function renderDefaultValue(context, member, wrapper, enclosingClassId) {
58837
59140
  const value = wrapper.value;
58838
59141
  if (value === null) return "null";
@@ -58861,8 +59164,10 @@ function renderDefaultValue(context, member, wrapper, enclosingClassId) {
58861
59164
  member.entryMemberId,
58862
59165
  "dictionary entry"
58863
59166
  );
58864
- return `{ ${Object.entries(value).map(
58865
- ([key, item]) => `${quote(key)}: ${renderNestedValue(context, entry, item, enclosingClassId)}`
59167
+ const keyOptions = member.key.kind === "enum" ? dictionaryOptions(context, member.key.enumId) : null;
59168
+ const entries = keyOptions ? orderedDictionaryEntries(value, keyOptions) : Object.entries(value);
59169
+ return `{ ${entries.map(
59170
+ ([key, item]) => `${emitDictionaryKey(key, keyOptions)}: ${renderNestedValue(context, entry, item, enclosingClassId)}`
58866
59171
  ).join(", ")} }`;
58867
59172
  }
58868
59173
  if (member.kind === "class" && isObject3(value)) {
@@ -59478,6 +59783,7 @@ var SPECIALIZED_RELATION_PROPERTIES;
59478
59783
  var init_emitter = __esm({
59479
59784
  "src/project-source/emitter.ts"() {
59480
59785
  "use strict";
59786
+ init_dictionary_enum_keys();
59481
59787
  init_declaration_path();
59482
59788
  init_src();
59483
59789
  init_source_format();
@@ -68646,6 +68952,76 @@ var init_unattributable_reads = __esm({
68646
68952
  }
68647
68953
  });
68648
68954
 
68955
+ // ../src/runtime/neoscript/NSGetterRuntimeError.ts
68956
+ var NSGetterRuntimeError, UncompiledInitializerRuntimeError;
68957
+ var init_NSGetterRuntimeError = __esm({
68958
+ "../src/runtime/neoscript/NSGetterRuntimeError.ts"() {
68959
+ "use strict";
68960
+ NSGetterRuntimeError = class extends Error {
68961
+ constructor(message, options) {
68962
+ super(message, options);
68963
+ this.name = "NSGetterRuntimeError";
68964
+ }
68965
+ };
68966
+ UncompiledInitializerRuntimeError = class extends NSGetterRuntimeError {
68967
+ constructor(memberId, memberName, initializer = null, valueId = null) {
68968
+ super(
68969
+ `Initializer for '${memberName}' has no compiled body; push the project so the server compiles it.`
68970
+ );
68971
+ this.memberId = memberId;
68972
+ this.initializer = initializer;
68973
+ this.valueId = valueId;
68974
+ this.name = "UncompiledInitializerRuntimeError";
68975
+ }
68976
+ memberId;
68977
+ initializer;
68978
+ valueId;
68979
+ };
68980
+ }
68981
+ });
68982
+
68983
+ // ../src/runtime/neoscript/initializer-dependencies.ts
68984
+ function materializeInitializerDependencies(pending, materialize) {
68985
+ const active = /* @__PURE__ */ new Set();
68986
+ for (const rootId of pending) {
68987
+ const stack = [rootId];
68988
+ active.add(rootId);
68989
+ while (stack.length > 0) {
68990
+ const valueId = stack[stack.length - 1];
68991
+ try {
68992
+ materialize(valueId);
68993
+ pending.delete(valueId);
68994
+ active.delete(valueId);
68995
+ stack.pop();
68996
+ } catch (error) {
68997
+ if (!(error instanceof PendingInitializerDependency)) throw error;
68998
+ if (!pending.has(error.valueId)) throw error;
68999
+ if (active.has(error.valueId)) {
69000
+ throw new Error(
69001
+ `Initializer dependency cycle: ${[...stack, error.valueId].join(" -> ")}.`
69002
+ );
69003
+ }
69004
+ active.add(error.valueId);
69005
+ stack.push(error.valueId);
69006
+ }
69007
+ }
69008
+ }
69009
+ }
69010
+ var PendingInitializerDependency;
69011
+ var init_initializer_dependencies = __esm({
69012
+ "../src/runtime/neoscript/initializer-dependencies.ts"() {
69013
+ "use strict";
69014
+ init_NSGetterRuntimeError();
69015
+ PendingInitializerDependency = class extends NSGetterRuntimeError {
69016
+ constructor(valueId) {
69017
+ super(`Initializer dependency "${valueId}" has not been materialized.`);
69018
+ this.valueId = valueId;
69019
+ }
69020
+ valueId;
69021
+ };
69022
+ }
69023
+ });
69024
+
68649
69025
  // ../src/runtime/neoscript/cell-pattern.ts
68650
69026
  function integer2(value, name, minimum = -2147483648) {
68651
69027
  if (typeof value !== "number" || !Number.isInteger(value)) {
@@ -70581,37 +70957,9 @@ var init_NeoScriptScope = __esm({
70581
70957
  }
70582
70958
  });
70583
70959
 
70584
- // ../src/runtime/neoscript/NSGetterRuntimeError.ts
70585
- var NSGetterRuntimeError, UncompiledInitializerRuntimeError;
70586
- var init_NSGetterRuntimeError = __esm({
70587
- "../src/runtime/neoscript/NSGetterRuntimeError.ts"() {
70588
- "use strict";
70589
- NSGetterRuntimeError = class extends Error {
70590
- constructor(message, options) {
70591
- super(message, options);
70592
- this.name = "NSGetterRuntimeError";
70593
- }
70594
- };
70595
- UncompiledInitializerRuntimeError = class extends NSGetterRuntimeError {
70596
- constructor(memberId, memberName, initializer = null, valueId = null) {
70597
- super(
70598
- `Initializer for '${memberName}' has no compiled body; push the project so the server compiles it.`
70599
- );
70600
- this.memberId = memberId;
70601
- this.initializer = initializer;
70602
- this.valueId = valueId;
70603
- this.name = "UncompiledInitializerRuntimeError";
70604
- }
70605
- memberId;
70606
- initializer;
70607
- valueId;
70608
- };
70609
- }
70610
- });
70611
-
70612
70960
  // ../src/runtime/neoscript/evaluateNSGetter.ts
70613
70961
  function isCatchableNeoScriptRuntimeError(error) {
70614
- return error instanceof NSGetterRuntimeError && !(error instanceof UncompiledInitializerRuntimeError) && !(error instanceof NonCatchableNSGetterRuntimeError);
70962
+ return error instanceof NSGetterRuntimeError && !(error instanceof UncompiledInitializerRuntimeError) && !(error instanceof PendingInitializerDependency) && !(error instanceof NonCatchableNSGetterRuntimeError);
70615
70963
  }
70616
70964
  function makeUnindexedEvaluatorLookups(members, storedValues) {
70617
70965
  const values = expandPackedValueRows(storedValues);
@@ -73910,7 +74258,7 @@ function evalStaticMember(memberId, ctx) {
73910
74258
  `Static member '${member.name}' is bound to missing value '${targetId}'.`
73911
74259
  );
73912
74260
  }
73913
- return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(row.value, ctx) : resolveLocalizedRowValueForMember(row, member, ctx);
74261
+ return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(readRowValue(row, ctx), ctx) : resolveLocalizedRowValueForMember(row, member, ctx);
73914
74262
  }
73915
74263
  function evalPointer(pointer, scope, ctx) {
73916
74264
  switch (pointer.type) {
@@ -73950,7 +74298,7 @@ function evalPointer(pointer, scope, ctx) {
73950
74298
  `Missing value reference: ${pointer.valueId}`
73951
74299
  );
73952
74300
  }
73953
- return row.value;
74301
+ return readRowValue(row, ctx);
73954
74302
  }
73955
74303
  case "variant" /* variant */:
73956
74304
  return {
@@ -74328,7 +74676,7 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver) {
74328
74676
  `NeoDelegate target '${member.name}' has missing receiver value '${value.valueId}'.`
74329
74677
  );
74330
74678
  }
74331
- receiver = row.value;
74679
+ receiver = readRowValue(row, ctx);
74332
74680
  } else if (ownerReceiver !== null && ownerReceiver !== void 0) {
74333
74681
  receiver = listenerReceiverOnOwner(member.id, ownerReceiver, ctx);
74334
74682
  }
@@ -75363,6 +75711,20 @@ function dispatchSchemaMember(receiver, schemaKey, ctx) {
75363
75711
  if (typeof receiver !== "object" || receiver === null) {
75364
75712
  return { kind: "no-info", matchedMember: false };
75365
75713
  }
75714
+ if (ctx.vm.databaseVM?.onInitializerRead !== void 0 && receiver === ctx.rootValue) {
75715
+ const root = PROJECT_ROOTS.find((root2) => root2.key === schemaKey);
75716
+ if (root !== void 0) {
75717
+ const memberId = ctx.vm.project[root.projectField];
75718
+ let bindings;
75719
+ if (root.storage === 2 /* Save */)
75720
+ bindings = ctx.__saveStaticBindings;
75721
+ if (root.storage === 3 /* Session */)
75722
+ bindings = ctx.__sessionStaticBindings;
75723
+ const targetId = bindings?.has(memberId) ? bindings.get(memberId) : evalMemberById(ctx.vm, memberId)?.valueId;
75724
+ if (typeof targetId === "string")
75725
+ ctx.vm.databaseVM.onInitializerRead(targetId);
75726
+ }
75727
+ }
75366
75728
  const member = resolveRuntimeSchemaMember(receiver, schemaKey, ctx);
75367
75729
  if (!member) return { kind: "no-info", matchedMember: false };
75368
75730
  if (member.kind === 10 /* NSProperty */) {
@@ -75688,20 +76050,27 @@ function unwrapSingleLookupValue(value, ctx) {
75688
76050
  ctx.__valueOverlay
75689
76051
  );
75690
76052
  if (next) {
75691
- return next.value;
76053
+ return readRowValue(next, ctx);
75692
76054
  }
75693
76055
  }
75694
76056
  return value;
75695
76057
  }
76058
+ function readRowValue(row, ctx) {
76059
+ const onInitializerRead = ctx.vm.databaseVM?.onInitializerRead;
76060
+ if (onInitializerRead !== void 0 && isInitValueContent(row)) {
76061
+ onInitializerRead(row.id);
76062
+ }
76063
+ return row.value;
76064
+ }
75696
76065
  function resolveLocalizedRowValue(row, ctx) {
75697
- const value = row.value;
76066
+ const value = readRowValue(row, ctx);
75698
76067
  if (typeof value !== "string") return value;
75699
76068
  const member = memberForValueRow(row, ctx);
75700
76069
  if (member === null) return value;
75701
76070
  return resolveLocalizedRowValueForMember(row, member, ctx);
75702
76071
  }
75703
76072
  function resolveLocalizedRowValueForMember(row, member, ctx) {
75704
- const value = row.value;
76073
+ const value = readRowValue(row, ctx);
75705
76074
  if (typeof value !== "string") return value;
75706
76075
  if (!isMemberString(member)) return value;
75707
76076
  if (isLocalizedStringMember(member) === false) return value;
@@ -76003,7 +76372,7 @@ function evaluateSystemNative(memberId, receiver, args, ctx) {
76003
76372
  `Tile placement '${tile.placementValueId}' is missing.`
76004
76373
  );
76005
76374
  }
76006
- return { handled: true, value: row.value };
76375
+ return { handled: true, value: readRowValue(row, ctx) };
76007
76376
  }
76008
76377
  return evaluateCellPatternNative(memberId, receiver, args, {
76009
76378
  readPattern: (value) => readCellPattern(value, ctx),
@@ -78813,7 +79182,7 @@ function resolveVariantGraph(selection2, ctx) {
78813
79182
  `Variant '${record6.name}' has no root value row '${record6.valueId}'.`
78814
79183
  );
78815
79184
  }
78816
- const root = row.value;
79185
+ const root = readRowValue(row, ctx);
78817
79186
  if (typeof root !== "object" || root === null || Array.isArray(root)) {
78818
79187
  throw new NSGetterRuntimeError(
78819
79188
  `Variant '${record6.name}' root row is not a class record.`
@@ -78886,19 +79255,21 @@ function resolveVariantRowParameter(args) {
78886
79255
  ctx.__runtimeSessionValues,
78887
79256
  ctx.__valueOverlay
78888
79257
  );
78889
- const isOrderedEntry = Array.isArray(collection?.value) ? collection.value.includes(rowId) : false;
79258
+ const collectionValue = collection === null ? null : readRowValue(collection, ctx);
79259
+ const isOrderedEntry = Array.isArray(collectionValue) ? collectionValue.includes(rowId) : false;
78890
79260
  const isUnorderedEntry = row.containerId === binding.collectionValueId;
78891
79261
  if (!isOrderedEntry && !isUnorderedEntry) {
78892
79262
  throw new NSGetterRuntimeError(
78893
79263
  `Lookup variant '${graph.name}' row '${rowId}' is not an entry of collection '${binding.collectionValueId}'.`
78894
79264
  );
78895
79265
  }
78896
- if (explicitPointer !== void 0 && rowValue !== row.value) {
79266
+ const resolvedRowValue = readRowValue(row, ctx);
79267
+ if (explicitPointer !== void 0 && rowValue !== resolvedRowValue) {
78897
79268
  throw new NSGetterRuntimeError(
78898
79269
  `Lookup variant '${graph.name}' received a value that does not resolve to bound row '${rowId}'.`
78899
79270
  );
78900
79271
  }
78901
- return [row.value];
79272
+ return [resolvedRowValue];
78902
79273
  }
78903
79274
  function invokeVariantClosure(args) {
78904
79275
  const { closureValueId, ctx, label, lexicalThis, parameters } = args;
@@ -80306,7 +80677,7 @@ function constructorCollectionEntryValue(value, ctx, resolveStoredId) {
80306
80677
  ctx.__runtimeSessionValues,
80307
80678
  ctx.__valueOverlay
80308
80679
  );
80309
- return row === null ? value : row.value;
80680
+ return row === null ? value : readRowValue(row, ctx);
80310
80681
  }
80311
80682
  function retainOnlyCreatedRowsReachableFrom(rootId, createdValues, ctx) {
80312
80683
  const byId = new Map(createdValues.map((row) => [row.id, row]));
@@ -80716,14 +81087,16 @@ function readOptionalMember(receiver, key, ctx) {
80716
81087
  const record6 = receiver;
80717
81088
  if (!Object.prototype.hasOwnProperty.call(record6, key)) return null;
80718
81089
  return resolveValueIfId(record6[key], ctx);
80719
- } catch {
81090
+ } catch (error) {
81091
+ if (error instanceof PendingInitializerDependency) throw error;
80720
81092
  return null;
80721
81093
  }
80722
81094
  }
80723
81095
  function collectionEntriesOrEmpty(value, ctx) {
80724
81096
  try {
80725
81097
  return collectionEntries(value, ctx);
80726
- } catch {
81098
+ } catch (error) {
81099
+ if (error instanceof PendingInitializerDependency) throw error;
80727
81100
  return [];
80728
81101
  }
80729
81102
  }
@@ -80816,6 +81189,8 @@ var DELEGATE_LEXICAL_THIS, DELEGATE_LEXICAL_ROOT, NonCatchableNSGetterRuntimeErr
80816
81189
  var init_evaluateNSGetter = __esm({
80817
81190
  "../src/runtime/neoscript/evaluateNSGetter.ts"() {
80818
81191
  "use strict";
81192
+ init_project_root_members();
81193
+ init_initializer_dependencies();
80819
81194
  init_unattributable_reads();
80820
81195
  init_value_row_owner_members();
80821
81196
  init_src();
@@ -84137,7 +84512,8 @@ function createHeadlessVirtualInstanceResolver(args) {
84137
84512
  readsByRootId.set(rootId, reads);
84138
84513
  remember(graph, rows);
84139
84514
  return rows;
84140
- } catch {
84515
+ } catch (error) {
84516
+ if (error instanceof PendingInitializerDependency) throw error;
84141
84517
  failedRootIds.add(rootId);
84142
84518
  return emptyRows;
84143
84519
  } finally {
@@ -84253,6 +84629,7 @@ var KEPT_ROW_SAMPLE_LIMIT, CORPUS_SCANNING_MEMBER_KINDS, VirtualExpansionUnsuppo
84253
84629
  var init_virtual_instance_graph = __esm({
84254
84630
  "../src/runtime/virtual-instance-graph.ts"() {
84255
84631
  "use strict";
84632
+ init_initializer_dependencies();
84256
84633
  init_constructor_argument_ownership();
84257
84634
  init_classes();
84258
84635
  init_constructor_parameter_settlement();
@@ -84320,6 +84697,7 @@ function initializerEvaluatorLookups(document, readTracking) {
84320
84697
  const lookups2 = {
84321
84698
  memberById: (id2) => databaseVM.memberById(id2),
84322
84699
  valueById: (id2) => databaseVM.valueById(id2),
84700
+ onInitializerRead: databaseVM.onInitializerRead,
84323
84701
  localizedTextById: (id2) => databaseVM.localizedTextById?.(id2) ?? null,
84324
84702
  ...databaseVM.hasStoredValueId === void 0 ? {} : {
84325
84703
  hasStoredValueId: (id2) => databaseVM.hasStoredValueId?.(id2) ?? false
@@ -84475,7 +84853,7 @@ function indexedInitializerEvaluatorLookups(document, key, revision) {
84475
84853
  });
84476
84854
  return lookups;
84477
84855
  }
84478
- function createInitializerMaterializationBatch(authoredDocument) {
84856
+ function createInitializerMaterializationBatch(authoredDocument, pendingInitializerIds) {
84479
84857
  const indexed = createInitializerBatchLookups(authoredDocument);
84480
84858
  const unorderedListEntryIds2 = indexed.snapshot().unorderedListEntryIds;
84481
84859
  let materializedIndex;
@@ -84526,6 +84904,9 @@ function createInitializerMaterializationBatch(authoredDocument) {
84526
84904
  globalReads.delete(entry);
84527
84905
  };
84528
84906
  return {
84907
+ get valuesById() {
84908
+ return indexed.valuesById;
84909
+ },
84529
84910
  upsert(rows) {
84530
84911
  const previousRows = [];
84531
84912
  const touched = /* @__PURE__ */ new Set();
@@ -84600,6 +84981,12 @@ function createInitializerMaterializationBatch(authoredDocument) {
84600
84981
  });
84601
84982
  const lookups = {
84602
84983
  ...base,
84984
+ ...pendingInitializerIds === void 0 ? {} : {
84985
+ onInitializerRead: (id2) => {
84986
+ if (pendingInitializerIds.has(id2))
84987
+ throw new PendingInitializerDependency(id2);
84988
+ }
84989
+ },
84603
84990
  valueById: (id2) => base.valueById(id2) ?? expandedById.get(id2) ?? virtual().valueById(id2),
84604
84991
  rowForValueReference: (value) => base.rowForValueReference(value) ?? expandedByReference.get(value) ?? virtual().rowForValueReference(value),
84605
84992
  virtualInstanceRowsForValue: (id2) => {
@@ -84666,7 +85053,8 @@ function buildInitializerRootValueWithLookups(document, lookups, tracking) {
84666
85053
  continue;
84667
85054
  }
84668
85055
  tracking?.valueDependencies?.add(targetId);
84669
- rootValue[root.key] = lookups.valueById(targetId)?.value ?? null;
85056
+ const row = lookups.valueById(targetId);
85057
+ rootValue[root.key] = row?.value ?? null;
84670
85058
  }
84671
85059
  return rootValue;
84672
85060
  }
@@ -84823,6 +85211,7 @@ var evaluatorLookupsByDocument, headlessResolversByLookupKey, indexedEvaluatorLo
84823
85211
  var init_evaluateInitializer = __esm({
84824
85212
  "../src/runtime/neoscript/evaluateInitializer.ts"() {
84825
85213
  "use strict";
85214
+ init_initializer_dependencies();
84826
85215
  init_deep_clone_plain_data();
84827
85216
  init_members();
84828
85217
  init_instance_provenance();
@@ -93044,7 +93433,9 @@ function validateWorldPlacementSidecars(args) {
93044
93433
  `Placement value "${args.placement.id}" under layer link "${args.linkValueId}" must store a class record.`
93045
93434
  );
93046
93435
  }
93047
- const assetClassId = args.isTile ? requiredValueClassId(args.placement, "tile") : optionalNonEmptyString(record6.assetClassId);
93436
+ const hasObjectSidecar = !args.isTile && WORLD_PLACEMENT_SIDECAR_KEYS.some((key) => Object.hasOwn(record6, key));
93437
+ const objectClassId = hasObjectSidecar ? record6.assetClassId : args.placement.classId;
93438
+ const assetClassId = args.isTile ? requiredValueClassId(args.placement, "tile") : optionalNonEmptyString(objectClassId);
93048
93439
  if (assetClassId === null) {
93049
93440
  throw new Error(
93050
93441
  `Class-backed placement value "${args.placement.id}" is missing assetClassId.`
@@ -93093,10 +93484,10 @@ function validateWorldPlacementSidecars(args) {
93093
93484
  assetClassId,
93094
93485
  placementId: args.placement.id,
93095
93486
  variantId: optionalNonEmptyString(
93096
- args.isTile ? getField(args.placement, "instanceVariantId") : record6.variantId
93487
+ args.isTile || !hasObjectSidecar ? getField(args.placement, "instanceVariantId") : record6.variantId
93097
93488
  ),
93098
93489
  rowValueId: optionalNonEmptyString(
93099
- args.isTile ? getField(args.placement, "instanceVariantRowValueId") : record6.rowValueId
93490
+ args.isTile || !hasObjectSidecar ? getField(args.placement, "instanceVariantRowValueId") : record6.rowValueId
93100
93491
  ),
93101
93492
  context: args.context
93102
93493
  });
@@ -95076,6 +95467,121 @@ var init_member_access_modifier_validation = __esm({
95076
95467
  }
95077
95468
  });
95078
95469
 
95470
+ // ../src/database/project-version-write-changes.ts
95471
+ function applyProjectVersionWriteChanges(document, changes) {
95472
+ return projectVersionDocumentWithChanges(document, changes, false);
95473
+ }
95474
+ function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
95475
+ const projectRows = (rows, kind) => {
95476
+ const relevant = changes.filter((change) => change.recordKind === kind);
95477
+ if (reuseUnchangedBuckets && relevant.length === 0) return rows;
95478
+ return applyArrayChanges(rows, relevant);
95479
+ };
95480
+ const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
95481
+ const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
95482
+ const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
95483
+ const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
95484
+ const projected = {
95485
+ localizedTexts: projectRows(
95486
+ document.localizedTexts ?? [],
95487
+ "localized-text"
95488
+ ),
95489
+ localizationConfig: applySingletonChange(
95490
+ document.localizationConfig,
95491
+ changes,
95492
+ "localization-config"
95493
+ ),
95494
+ project: applySingletonChange(document.project, changes, "project"),
95495
+ members: projectRows(document.members, "member"),
95496
+ classes: projectRows(document.classes, "class"),
95497
+ // P43 §6. Declared constructors participate in the post-transaction
95498
+ // document so the whole-graph validator and every body compile see the
95499
+ // same constructor surface the transaction is about to persist.
95500
+ constructors: projectRows(document.constructors ?? [], "constructor"),
95501
+ // P67 §2.1. Same reason as constructors: without these buckets the
95502
+ // whole-graph validator, the variant ownership roots, and every body
95503
+ // compile would grade the transaction against the pre-transaction
95504
+ // variant set — so a newly pushed variant's closures would compile
95505
+ // against a document that does not contain it.
95506
+ variants: projectRows(document.variants ?? [], "variant"),
95507
+ variantFolders: projectRows(
95508
+ document.variantFolders ?? [],
95509
+ "variant-folder"
95510
+ ),
95511
+ values: projectRows(document.values ?? [], "value"),
95512
+ // Project-file staging finalizes pending uploads before schema
95513
+ // preparation. Defaults and authored instance graphs may reference a file
95514
+ // created by the same source transaction, so every construction pass must
95515
+ // see that finalized row in its post-write document.
95516
+ projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
95517
+ // Import-setting templates are part of the same file graph. A new file
95518
+ // may select a new template in one source transaction, and default-value
95519
+ // materialization validates that relationship immediately against this
95520
+ // post-write document.
95521
+ textureTemplates: projectRows(
95522
+ document.textureTemplates ?? [],
95523
+ "unity-texture-template"
95524
+ ),
95525
+ audioClipTemplates: projectRows(
95526
+ document.audioClipTemplates ?? [],
95527
+ "unity-audio-clip-template"
95528
+ ),
95529
+ internalRecordRelations: projectRows(
95530
+ document.internalRecordRelations ?? [],
95531
+ "internal-record-relation"
95532
+ ),
95533
+ enums: projectRows(document.enums, "enum"),
95534
+ interfaces: projectRows(document.interfaces, "interface"),
95535
+ dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
95536
+ dialogueRecords,
95537
+ dialogueNodes
95538
+ ),
95539
+ dialogueGroups: projectRows(
95540
+ document.dialogueGroups ?? [],
95541
+ "dialogue-group"
95542
+ ),
95543
+ migrations: projectRows(document.migrations ?? [], "migration")
95544
+ };
95545
+ return {
95546
+ ...document,
95547
+ ...projected,
95548
+ ...dialogueRecords === void 0 ? {} : { dialogueRecords },
95549
+ ...dialogueNodes === void 0 ? {} : { dialogueNodes }
95550
+ // The document spread above carries every bucket the caller's view declares
95551
+ // beyond the projected ones, so the result is the same view; TypeScript
95552
+ // cannot prove that of an object literal built over a type parameter.
95553
+ };
95554
+ }
95555
+ function applySingletonChange(current, changes, recordKind) {
95556
+ const change = changes.find(
95557
+ (candidate) => candidate.recordKind === recordKind
95558
+ );
95559
+ if (change === void 0) return current;
95560
+ if (change.operation === "delete" || change.nextData === void 0) {
95561
+ throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
95562
+ }
95563
+ return change.nextData;
95564
+ }
95565
+ function applyArrayChanges(current, changes) {
95566
+ const byId = new Map(current.map((record6) => [record6.id, record6]));
95567
+ for (const change of changes) {
95568
+ if (change.operation === "delete") {
95569
+ byId.delete(change.recordId);
95570
+ continue;
95571
+ }
95572
+ if (change.nextData !== void 0) {
95573
+ byId.set(change.recordId, change.nextData);
95574
+ }
95575
+ }
95576
+ return [...byId.values()];
95577
+ }
95578
+ var init_project_version_write_changes = __esm({
95579
+ "../src/database/project-version-write-changes.ts"() {
95580
+ "use strict";
95581
+ init_projectDocumentDialogueMaterialization();
95582
+ }
95583
+ });
95584
+
95079
95585
  // ../src/database/member-localization-normalization.ts
95080
95586
  function planMemberLocalizationNormalization(input, now = 0) {
95081
95587
  const before = expandPackedDocumentValues(input);
@@ -95366,7 +95872,7 @@ var init_member_localization_normalization = __esm({
95366
95872
  init_constructor_argument_ownership();
95367
95873
  init_variant_value_graph();
95368
95874
  init_packed_value_write_fold();
95369
- init_project_version_schema_commit();
95875
+ init_project_version_write_changes();
95370
95876
  init_packed_value_encoding();
95371
95877
  init_inheritance();
95372
95878
  init_members();
@@ -98052,37 +98558,49 @@ function materializePreparedInstanceInitializers(args) {
98052
98558
  materializationScope.document.localizedTexts.map((text) => text.id)
98053
98559
  );
98054
98560
  const replayOnlyIndexes = [];
98561
+ const pendingSites = /* @__PURE__ */ new Map();
98055
98562
  for (const [valueId, site] of sites) {
98056
98563
  const existingRoot = existingValueById.get(valueId);
98057
- const existingConstructedRoot = existingRoot !== void 0 && isLiteralValueContent(existingRoot) && (typeof existingRoot.classId === "string" || existingRoot.constructorArgs !== void 0 && existingRoot.constructorArgs !== null);
98058
- if (rootKinds.get(valueId) === "declaration" && !existingConstructedRoot) {
98564
+ const existingConstructedRoot = existingRoot !== void 0 && isLiteralValueContent(existingRoot) && (typeof existingRoot.classId === "string" || existingRoot.constructorArgs !== void 0 && existingRoot.constructorArgs !== null) ? existingRoot : void 0;
98565
+ if (rootKinds.get(valueId) === "declaration" && !existingConstructedRoot)
98059
98566
  continue;
98060
- }
98567
+ pendingSites.set(valueId, { ...site, existingConstructedRoot });
98568
+ }
98569
+ const pendingInitializerIds = new Set(pendingSites.keys());
98570
+ if (pendingInitializerIds.size === 0) return;
98571
+ const batch = createInitializerMaterializationBatch(
98572
+ materializationScope.document,
98573
+ pendingInitializerIds
98574
+ );
98575
+ materializeInitializerDependencies(pendingInitializerIds, (valueId) => {
98576
+ const site = pendingSites.get(valueId);
98577
+ const existingConstructedRoot = site.existingConstructedRoot;
98061
98578
  const member = owners.get(valueId);
98062
98579
  if (member === void 0) {
98063
98580
  throw new Error(
98064
98581
  `Value "${valueId}" carries an initializer but no ownership path resolves its declared member.`
98065
98582
  );
98066
98583
  }
98584
+ const currentDocument = batch.document();
98067
98585
  const materialized = materializeInitializerValue2({
98068
98586
  // Every site that survives the declaration-default guard is source for
98069
98587
  // a persisted instance construction. The trusted replay mode both
98070
98588
  // admits Immutable storage and installs the concrete generic slot; the
98071
98589
  // CLI uses the same mode on the first push, so it cannot be conditional
98072
98590
  // on a literal row already existing.
98073
- document: materializationScope.document,
98591
+ document: currentDocument,
98074
98592
  member,
98075
98593
  row: site.row,
98076
98594
  storedConstructionReplay: true
98077
98595
  });
98078
- if (existingConstructedRoot) {
98079
- if (!isLiteralValueContent(materialized.root) || existingRoot.classId !== materialized.root.classId || !replayedCreationDataMatches({
98596
+ if (existingConstructedRoot !== void 0) {
98597
+ if (!isLiteralValueContent(materialized.root) || existingConstructedRoot.classId !== materialized.root.classId || !replayedCreationDataMatches({
98080
98598
  // The synthetic variant binding members are part of the ownership
98081
98599
  // scope that compiled and evaluated this initializer. Stored replay
98082
98600
  // closes its generic slot from the same ephemeral member id, so its
98083
98601
  // expansion must read that scoped document too.
98084
98602
  currentReader: requireCurrentReader(),
98085
- currentRoot: existingRoot,
98603
+ currentRoot: existingConstructedRoot,
98086
98604
  rootMember: member,
98087
98605
  replayRoot: materialized.root,
98088
98606
  replayCreated: materialized.createdValues
@@ -98092,10 +98610,11 @@ function materializePreparedInstanceInitializers(args) {
98092
98610
  );
98093
98611
  }
98094
98612
  replayOnlyIndexes.push(site.index);
98095
- continue;
98613
+ batch.upsert([existingConstructedRoot]);
98614
+ return;
98096
98615
  }
98097
98616
  const baseline = materializeInitializerValue2({
98098
- document: materializationScope.document,
98617
+ document: currentDocument,
98099
98618
  member,
98100
98619
  row: {
98101
98620
  ...site.row,
@@ -98106,7 +98625,7 @@ function materializePreparedInstanceInitializers(args) {
98106
98625
  });
98107
98626
  const sparse2 = sparsifyConstructedInstance({
98108
98627
  localizedTextIds,
98109
- document: materializationScope.document,
98628
+ document: currentDocument,
98110
98629
  rootMember: member,
98111
98630
  constructed: {
98112
98631
  root: materialized.root,
@@ -98122,7 +98641,7 @@ function materializePreparedInstanceInitializers(args) {
98122
98641
  pinnedRootSchemaKeys: materialized.pinnedRootSchemaKeys
98123
98642
  });
98124
98643
  const original = args.prepared[site.index];
98125
- if (original === void 0) continue;
98644
+ if (original === void 0) return;
98126
98645
  args.prepared[site.index] = {
98127
98646
  ...original,
98128
98647
  nextData: sparse2.root
@@ -98163,7 +98682,8 @@ function materializePreparedInstanceInitializers(args) {
98163
98682
  });
98164
98683
  existingValueById.set(created.id, created);
98165
98684
  }
98166
- }
98685
+ batch.upsert([sparse2.root, ...sparse2.createdChildren]);
98686
+ });
98167
98687
  for (const index of replayOnlyIndexes.sort((left, right) => right - left)) {
98168
98688
  args.prepared.splice(index, 1);
98169
98689
  }
@@ -100590,16 +101110,38 @@ function prepareServerOwnedValueInitializerBodies(args) {
100590
101110
  }
100591
101111
  }
100592
101112
  function collectDelegateSweepRows(args) {
100593
- if (args.targetIds.size === 0) return [];
101113
+ const closureRows = [];
101114
+ const inlineRows = [];
101115
+ if (args.targetIds.size === 0) return { closureRows, inlineRows };
100594
101116
  const preparedValueIds = indexChangesByRecordId(args.prepared, "value");
100595
- const sweepRows = [];
100596
101117
  for (const value of args.postDocument.values) {
100597
101118
  if (!args.targetIds.has(value.id)) continue;
100598
101119
  if (preparedValueIds.has(value.id)) continue;
100599
101120
  const row = delegateValueRow(value);
100600
- if (row !== null) sweepRows.push(row);
101121
+ if (row !== null) {
101122
+ closureRows.push(row);
101123
+ continue;
101124
+ }
101125
+ const inlineRow = inlineDelegateSweepRow(value);
101126
+ if (inlineRow !== null) inlineRows.push(inlineRow);
101127
+ }
101128
+ return { closureRows, inlineRows };
101129
+ }
101130
+ function inlineDelegateSweepRow(value) {
101131
+ if (!isMemberValue(value) || !isLiteralValueContent(value)) return null;
101132
+ const constructorArgs = asRecord4(
101133
+ value.constructorArgs
101134
+ );
101135
+ if (constructorArgs === null) return null;
101136
+ let sourceArgs = null;
101137
+ for (const [key, argument2] of Object.entries(constructorArgs)) {
101138
+ const closure = asRecord4(argument2);
101139
+ if (typeof closure?.code !== "string") continue;
101140
+ if (!("action" in closure)) continue;
101141
+ sourceArgs ??= { ...constructorArgs };
101142
+ sourceArgs[key] = { code: closure.code };
100601
101143
  }
100602
- return sweepRows;
101144
+ return sourceArgs === null ? null : { ...value, constructorArgs: sourceArgs };
100603
101145
  }
100604
101146
  function delegateValueRow(value) {
100605
101147
  if (!isMemberValue(value) || !isLiteralValueContent(value)) return null;
@@ -100746,8 +101288,8 @@ function prepareServerOwnedDelegateValueBodies(args) {
100746
101288
  const withInlineArgs = inlineDelegateArgumentRow(change.nextData);
100747
101289
  if (withInlineArgs !== null) inlineArgumentRows.set(index, withInlineArgs);
100748
101290
  }
100749
- const sweepRows = collectDelegateSweepRows(args);
100750
- if (explicitRows.size === 0 && sweepRows.length === 0 && inlineArgumentRows.size === 0) {
101291
+ const { closureRows: sweepRows, inlineRows: inlineSweepRows } = collectDelegateSweepRows(args);
101292
+ if (explicitRows.size === 0 && sweepRows.length === 0 && inlineArgumentRows.size === 0 && inlineSweepRows.length === 0) {
100751
101293
  return;
100752
101294
  }
100753
101295
  const committedDocument = applyProjectVersionWriteChanges(
@@ -100756,7 +101298,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
100756
101298
  );
100757
101299
  const targetIds = valueIdsFromRows(
100758
101300
  [...explicitRows.values(), ...inlineArgumentRows.values()],
100759
- sweepRows
101301
+ [...sweepRows, ...inlineSweepRows]
100760
101302
  );
100761
101303
  const rootOwnerByValueId = /* @__PURE__ */ new Map();
100762
101304
  const delegateScope = withVariantOwnershipRoots(
@@ -100831,7 +101373,7 @@ function prepareServerOwnedDelegateValueBodies(args) {
100831
101373
  };
100832
101374
  }
100833
101375
  }
100834
- if (sweepRows.length === 0) return;
101376
+ if (sweepRows.length === 0 && inlineSweepRows.length === 0) return;
100835
101377
  const currentById = new Map(
100836
101378
  args.document.values.map((value) => [value.id, value])
100837
101379
  );
@@ -100841,40 +101383,65 @@ function prepareServerOwnedDelegateValueBodies(args) {
100841
101383
  prepared: args.prepared,
100842
101384
  contentHashHeads: args.contentHashHeads
100843
101385
  });
101386
+ const refresh = (id2, compiled) => {
101387
+ const current = currentById.get(id2);
101388
+ if (current === void 0 || canonicallyEqual2(current, compiled)) return;
101389
+ const contentHash = baseHashFor(id2);
101390
+ if (contentHash === void 0) {
101391
+ throw new Error(
101392
+ `Cannot safely refresh the compiled NeoDelegate closure for value "${id2}": its current content hash is unavailable.`
101393
+ );
101394
+ }
101395
+ args.prepared.push({
101396
+ recordKind: "value",
101397
+ recordId: id2,
101398
+ operation: "update",
101399
+ nextData: compiled,
101400
+ intent: createProjectVersionIntent("value.update", {
101401
+ source: "server-neoscript-recompile"
101402
+ }),
101403
+ ...contentHash === null ? {} : { expectedBaseContentHash: contentHash }
101404
+ });
101405
+ };
100844
101406
  for (const row of sweepRows) {
100845
101407
  const compiled = { ...row, value: { ...row.value } };
100846
101408
  try {
100847
101409
  compileOne(delegateScope.document, compiled);
100848
101410
  } catch (postWriteError) {
100849
- const current2 = delegateValueRow(
101411
+ const current = delegateValueRow(
100850
101412
  structuredClone(currentById.get(row.id))
100851
101413
  );
100852
- if (current2 === null) throw postWriteError;
101414
+ if (current === null) throw postWriteError;
100853
101415
  try {
100854
- compileOne(args.document, current2);
101416
+ compileOne(args.document, current);
100855
101417
  } catch (preWriteError) {
100856
101418
  if (sameCompileFailure(preWriteError, postWriteError)) continue;
100857
101419
  }
100858
101420
  throw postWriteError;
100859
101421
  }
100860
- const current = currentById.get(row.id);
100861
- if (current === void 0 || canonicallyEqual2(current, compiled)) continue;
100862
- const contentHash = baseHashFor(row.id);
100863
- if (contentHash === void 0) {
100864
- throw new Error(
100865
- `Cannot safely refresh the compiled NeoDelegate closure for value "${row.id}": its current content hash is unavailable.`
100866
- );
101422
+ refresh(row.id, compiled);
101423
+ }
101424
+ const compileInlineOne = (document, row) => compileInlineDelegateConstructorArguments({
101425
+ document,
101426
+ row,
101427
+ ownerMember: ownerByValueId.get(row.id),
101428
+ rootOwner: rootOwnerByValueId.get(row.id) ?? null
101429
+ });
101430
+ for (const row of inlineSweepRows) {
101431
+ let compiledArgs;
101432
+ try {
101433
+ compiledArgs = compileInlineOne(delegateScope.document, row);
101434
+ } catch (postWriteError) {
101435
+ const current = inlineDelegateSweepRow(currentById.get(row.id));
101436
+ if (current === null) throw postWriteError;
101437
+ try {
101438
+ compileInlineOne(args.document, current);
101439
+ } catch (preWriteError) {
101440
+ if (sameCompileFailure(preWriteError, postWriteError)) continue;
101441
+ }
101442
+ throw postWriteError;
100867
101443
  }
100868
- args.prepared.push({
100869
- recordKind: "value",
100870
- recordId: row.id,
100871
- operation: "update",
100872
- nextData: compiled,
100873
- intent: createProjectVersionIntent("value.update", {
100874
- source: "server-neoscript-recompile"
100875
- }),
100876
- ...contentHash === null ? {} : { expectedBaseContentHash: contentHash }
100877
- });
101444
+ refresh(row.id, { ...row, constructorArgs: compiledArgs });
100878
101445
  }
100879
101446
  }
100880
101447
  function prepareServerOwnedConstructorBodies(args) {
@@ -101129,113 +101696,6 @@ function assertUniqueChanges(changes) {
101129
101696
  }
101130
101697
  }
101131
101698
  }
101132
- function applyProjectVersionWriteChanges(document, changes) {
101133
- return projectVersionDocumentWithChanges(document, changes, false);
101134
- }
101135
- function projectVersionDocumentWithChanges(document, changes, reuseUnchangedBuckets) {
101136
- const projectRows = (rows, kind) => {
101137
- const relevant = changes.filter((change) => change.recordKind === kind);
101138
- if (reuseUnchangedBuckets && relevant.length === 0) return rows;
101139
- return applyArrayChanges(rows, relevant);
101140
- };
101141
- const hasGranularDialogueRecords = document.dialogueRecords !== void 0 || changes.some((change) => change.recordKind === "dialogue");
101142
- const hasGranularDialogueNodes = document.dialogueNodes !== void 0 || changes.some((change) => change.recordKind === "dialogue-node");
101143
- const dialogueRecords = hasGranularDialogueRecords ? projectRows(document.dialogueRecords ?? [], "dialogue") : void 0;
101144
- const dialogueNodes = hasGranularDialogueNodes ? projectRows(document.dialogueNodes ?? [], "dialogue-node") : void 0;
101145
- const projected = {
101146
- localizedTexts: projectRows(
101147
- document.localizedTexts ?? [],
101148
- "localized-text"
101149
- ),
101150
- localizationConfig: applySingletonChange(
101151
- document.localizationConfig,
101152
- changes,
101153
- "localization-config"
101154
- ),
101155
- project: applySingletonChange(document.project, changes, "project"),
101156
- members: projectRows(document.members, "member"),
101157
- classes: projectRows(document.classes, "class"),
101158
- // P43 §6. Declared constructors participate in the post-transaction
101159
- // document so the whole-graph validator and every body compile see the
101160
- // same constructor surface the transaction is about to persist.
101161
- constructors: projectRows(document.constructors ?? [], "constructor"),
101162
- // P67 §2.1. Same reason as constructors: without these buckets the
101163
- // whole-graph validator, the variant ownership roots, and every body
101164
- // compile would grade the transaction against the pre-transaction
101165
- // variant set — so a newly pushed variant's closures would compile
101166
- // against a document that does not contain it.
101167
- variants: projectRows(document.variants ?? [], "variant"),
101168
- variantFolders: projectRows(
101169
- document.variantFolders ?? [],
101170
- "variant-folder"
101171
- ),
101172
- values: projectRows(document.values ?? [], "value"),
101173
- // Project-file staging finalizes pending uploads before schema
101174
- // preparation. Defaults and authored instance graphs may reference a file
101175
- // created by the same source transaction, so every construction pass must
101176
- // see that finalized row in its post-write document.
101177
- projectFiles: projectRows(document.projectFiles ?? [], "project-file"),
101178
- // Import-setting templates are part of the same file graph. A new file
101179
- // may select a new template in one source transaction, and default-value
101180
- // materialization validates that relationship immediately against this
101181
- // post-write document.
101182
- textureTemplates: projectRows(
101183
- document.textureTemplates ?? [],
101184
- "unity-texture-template"
101185
- ),
101186
- audioClipTemplates: projectRows(
101187
- document.audioClipTemplates ?? [],
101188
- "unity-audio-clip-template"
101189
- ),
101190
- internalRecordRelations: projectRows(
101191
- document.internalRecordRelations ?? [],
101192
- "internal-record-relation"
101193
- ),
101194
- enums: projectRows(document.enums, "enum"),
101195
- interfaces: projectRows(document.interfaces, "interface"),
101196
- dialogues: dialogueRecords === void 0 || dialogueNodes === void 0 || dialogueRecords === document.dialogueRecords && dialogueNodes === document.dialogueNodes ? document.dialogues : materializeDialogues(
101197
- dialogueRecords,
101198
- dialogueNodes
101199
- ),
101200
- dialogueGroups: projectRows(
101201
- document.dialogueGroups ?? [],
101202
- "dialogue-group"
101203
- ),
101204
- migrations: projectRows(document.migrations ?? [], "migration")
101205
- };
101206
- return {
101207
- ...document,
101208
- ...projected,
101209
- ...dialogueRecords === void 0 ? {} : { dialogueRecords },
101210
- ...dialogueNodes === void 0 ? {} : { dialogueNodes }
101211
- // The document spread above carries every bucket the caller's view declares
101212
- // beyond the projected ones, so the result is the same view; TypeScript
101213
- // cannot prove that of an object literal built over a type parameter.
101214
- };
101215
- }
101216
- function applySingletonChange(current, changes, recordKind) {
101217
- const change = changes.find(
101218
- (candidate) => candidate.recordKind === recordKind
101219
- );
101220
- if (change === void 0) return current;
101221
- if (change.operation === "delete" || change.nextData === void 0) {
101222
- throw new Error(`Schema commit cannot delete the ${recordKind} record.`);
101223
- }
101224
- return change.nextData;
101225
- }
101226
- function applyArrayChanges(current, changes) {
101227
- const byId = new Map(current.map((record6) => [record6.id, record6]));
101228
- for (const change of changes) {
101229
- if (change.operation === "delete") {
101230
- byId.delete(change.recordId);
101231
- continue;
101232
- }
101233
- if (change.nextData !== void 0) {
101234
- byId.set(change.recordId, change.nextData);
101235
- }
101236
- }
101237
- return [...byId.values()];
101238
- }
101239
101699
  function asRecord4(value) {
101240
101700
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
101241
101701
  return null;
@@ -101426,11 +101886,11 @@ var init_project_version_schema_commit = __esm({
101426
101886
  init_variants2();
101427
101887
  init_effective_value_reader();
101428
101888
  init_materialize_values();
101889
+ init_initializer_dependencies();
101429
101890
  init_neoscript2();
101430
101891
  init_evaluateInitializer();
101431
101892
  init_virtual_instance_graph();
101432
101893
  init_virtual_instance_values();
101433
- init_projectDocumentDialogueMaterialization();
101434
101894
  init_valueHeadPlacementGraph();
101435
101895
  init_canonical_json();
101436
101896
  init_compile_ns_property();
@@ -101455,6 +101915,7 @@ var init_project_version_schema_commit = __esm({
101455
101915
  init_project_version_relation_sweep_trigger();
101456
101916
  init_project_version_static_value_writes();
101457
101917
  init_project_version_transaction_planning();
101918
+ init_project_version_write_changes();
101458
101919
  init_value_row_owner_members();
101459
101920
  init_variant_value_graph();
101460
101921
  SERVER_COMPILATION_PROJECT_CACHE_LIMIT = 4;
@@ -101562,6 +102023,7 @@ var init_animation_clips = __esm({
101562
102023
  "../src/models/animation/animation-clips.ts"() {
101563
102024
  "use strict";
101564
102025
  init_inheritance();
102026
+ init_read_class_member();
101565
102027
  init_generics();
101566
102028
  init_world_system_classes();
101567
102029
  init_member_kinds();
@@ -102580,14 +103042,7 @@ var init_animation_clips = __esm({
102580
103042
  * when it is dangling, then the member default, then the retained value row.
102581
103043
  */
102582
103044
  listFieldIds(parent, field) {
102583
- const mapped = isRecord6(parent.value) ? parent.value[field.schemaKey] : null;
102584
- if (typeof mapped === "string") {
102585
- return this.valueById.get(mapped)?.value;
102586
- }
102587
- if (field.member.defaultValue !== void 0) {
102588
- return field.member.defaultValue.value;
102589
- }
102590
- return typeof field.member.valueId === "string" ? this.valueById.get(field.member.valueId)?.value : void 0;
103045
+ return this.fieldValue(parent, field);
102591
103046
  }
102592
103047
  /** Class a list's rows carry when a row omits its own `classId`. */
102593
103048
  listEntryClassId(member) {
@@ -102637,11 +103092,21 @@ var init_animation_clips = __esm({
102637
103092
  }
102638
103093
  scalarField(parent, classId, memberId) {
102639
103094
  const field = this.requireField(classId, memberId, `Class "${classId}"`);
102640
- const mapped = isRecord6(parent.value) ? parent.value[field.schemaKey] : null;
102641
- if (typeof mapped === "string") {
102642
- return this.valueById.get(mapped)?.value;
103095
+ return this.fieldValue(parent, field);
103096
+ }
103097
+ fieldValue(parent, field) {
103098
+ const slot = readClassMember({
103099
+ member: field.member,
103100
+ schemaKey: field.schemaKey,
103101
+ record: isRecord6(parent.value) ? parent.value : {},
103102
+ expandedRecord: () => null,
103103
+ mode: "declaration"
103104
+ });
103105
+ if (slot.kind === "declaration") return slot.content.value;
103106
+ if (slot.kind === "value") {
103107
+ return typeof slot.value === "string" ? this.valueById.get(slot.value)?.value : slot.value;
102643
103108
  }
102644
- return field.member.defaultValue?.value;
103109
+ return typeof field.member.valueId === "string" ? this.valueById.get(field.member.valueId)?.value : void 0;
102645
103110
  }
102646
103111
  requireNodeClassId(node, expectedWorldKind) {
102647
103112
  if (typeof node.classId !== "string" || !this.classHasWorldKind(node.classId, expectedWorldKind)) {
@@ -102680,7 +103145,13 @@ var init_animation_clips = __esm({
102680
103145
  );
102681
103146
  if (entry === void 0) return null;
102682
103147
  const member = this.memberById.get(entry.memberId);
102683
- return member === void 0 ? null : { ...entry, member };
103148
+ return member === void 0 ? null : {
103149
+ ...entry,
103150
+ member: {
103151
+ ...member,
103152
+ ...resolveMember2(member, this.document.members)
103153
+ }
103154
+ };
102684
103155
  }
102685
103156
  requireField(classId, memberId, label) {
102686
103157
  const field = this.field(classId, memberId);
@@ -104279,7 +104750,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
104279
104750
  `Read-only member "${member.name}" (${member.id}) must declare Immutable storage; ${ownerLabel}.`
104280
104751
  );
104281
104752
  }
104282
- if (!isAbstractMember(member) && resolved.kind !== 21 && (resolved.defaultValue === void 0 || resolved.defaultValue === null)) {
104753
+ if (!isAbstractMember(resolved) && resolved.kind !== 21 && (resolved.defaultValue === void 0 || resolved.defaultValue === null)) {
104283
104754
  throw new Error(
104284
104755
  `Read-only member "${member.name}" (${member.id}) requires an explicit defaultValue; ${ownerLabel}.`
104285
104756
  );
@@ -104343,7 +104814,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
104343
104814
  `Read-only member "${member.name}" (${member.id}) must be value-bearing in every closed Generic placement; ${ownerLabel}.`
104344
104815
  );
104345
104816
  }
104346
- if (isAbstractMember(member)) return;
104817
+ if (isAbstractMember(inherited)) return;
104347
104818
  if (owned.defaultValue === void 0 || owned.defaultValue === null) {
104348
104819
  throw new Error(
104349
104820
  `Read-only member "${member.name}" (${member.id}) requires an explicit defaultValue from every closed Generic binding; ${ownerLabel}.`
@@ -104361,7 +104832,7 @@ function assertProjectInterfaceDocumentValid(view, options = {}) {
104361
104832
  }
104362
104833
  }
104363
104834
  }
104364
- if (rawOwned.id === member.id && isAbstractMember(member)) return;
104835
+ if (rawOwned.id === member.id && isAbstractMember(inherited)) return;
104365
104836
  if (owned.storage === 2 /* Save */ || owned.storage === 3 /* Session */ || owned.storage === 4 /* Writable */) {
104366
104837
  throw new Error(
104367
104838
  `Read-only member "${member.name}" has a non-Immutable owned default child "${owned.name}"; ${ownerLabel}.`
@@ -106506,7 +106977,10 @@ function assertProjectVersionWholeGraphWritesValid(args) {
106506
106977
  assertStagedInternalRecordRelationsValid(args.document, projected, changes);
106507
106978
  assertStagedWorldContentLayerBindingsValid(args.document, projected, changes);
106508
106979
  assertAnimationClipDocumentValid(
106509
- materializeDeclarationInitializersForAnimationValidation(projected),
106980
+ materializeDeclarationInitializersForAnimationValidation(
106981
+ projected,
106982
+ args.animationValidationMemberIds
106983
+ ),
106510
106984
  args.animationValidationMemberIds === void 0 ? void 0 : { memberIds: args.animationValidationMemberIds }
106511
106985
  );
106512
106986
  if (args.operation === void 0 || !isSystemOwnedProjectVersionOperation(args.operation)) {
@@ -106624,7 +107098,71 @@ function valueDematerializationRefusal(args) {
106624
107098
  }
106625
107099
  return null;
106626
107100
  }
106627
- function materializeDeclarationInitializersForAnimationValidation(document) {
107101
+ function animationRootsInValidationScope(args) {
107102
+ const {
107103
+ document,
107104
+ valuesById,
107105
+ animationFamilyClassIds,
107106
+ animationRoots,
107107
+ scopeMemberIds
107108
+ } = args;
107109
+ if (scopeMemberIds === void 0 || animationRoots.length === 0) {
107110
+ return animationRoots;
107111
+ }
107112
+ const segmentIds = new Set(
107113
+ [...valuesById.values()].flatMap(
107114
+ (row) => typeof row.classId === "string" && animationFamilyClassIds.get(row.classId) === "animationSegment" ? [row.id] : []
107115
+ )
107116
+ );
107117
+ const placements = findSemanticOwnerPlacementsForValues(
107118
+ document,
107119
+ /* @__PURE__ */ new Set([...animationRoots.map((row) => row.id), ...segmentIds]),
107120
+ void 0,
107121
+ true
107122
+ );
107123
+ const segmentAncestors = /* @__PURE__ */ new Set();
107124
+ for (const segmentId of segmentIds) {
107125
+ let id2 = segmentId;
107126
+ while (id2 !== null && !segmentAncestors.has(id2)) {
107127
+ segmentAncestors.add(id2);
107128
+ id2 = placements.get(id2)?.parentValueId ?? null;
107129
+ }
107130
+ }
107131
+ const insideValidatedRootById = /* @__PURE__ */ new Map();
107132
+ return animationRoots.filter((row) => {
107133
+ if (segmentAncestors.has(row.id)) return true;
107134
+ let id2 = row.id;
107135
+ const path = [];
107136
+ const seen = /* @__PURE__ */ new Set();
107137
+ let insideValidatedRoot = false;
107138
+ while (id2 !== null && !seen.has(id2)) {
107139
+ const cached = insideValidatedRootById.get(id2);
107140
+ if (cached !== void 0) {
107141
+ insideValidatedRoot = cached;
107142
+ break;
107143
+ }
107144
+ if (segmentIds.has(id2)) {
107145
+ insideValidatedRoot = true;
107146
+ break;
107147
+ }
107148
+ seen.add(id2);
107149
+ path.push(id2);
107150
+ const placement = placements.get(id2);
107151
+ if (placement === void 0) break;
107152
+ if (placement.parentValueId === null) {
107153
+ const memberId = getField(placement.member, "id");
107154
+ insideValidatedRoot = typeof memberId === "string" && scopeMemberIds.has(memberId);
107155
+ break;
107156
+ }
107157
+ id2 = placement.parentValueId;
107158
+ }
107159
+ for (const valueId of path) {
107160
+ insideValidatedRootById.set(valueId, insideValidatedRoot);
107161
+ }
107162
+ return insideValidatedRoot;
107163
+ });
107164
+ }
107165
+ function materializeDeclarationInitializersForAnimationValidation(document, scopeMemberIds) {
106628
107166
  const animationFamilyClassIds = animationFamilyClassKinds(document.classes);
106629
107167
  const initializers = document.values.filter(
106630
107168
  (value) => isInitValueContent(value)
@@ -106637,12 +107175,13 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106637
107175
  if (initializers.length === 0 && defaultInitializerMemberIds.size === 0) {
106638
107176
  return document;
106639
107177
  }
107178
+ const initializerRootOwners = /* @__PURE__ */ new Map();
106640
107179
  const rootKinds = /* @__PURE__ */ new Map();
106641
107180
  const owners = resolveSemanticOwnerMembersForValues(
106642
107181
  document,
106643
107182
  new Set(initializers.map((value) => value.id)),
106644
107183
  void 0,
106645
- void 0,
107184
+ initializerRootOwners,
106646
107185
  rootKinds
106647
107186
  );
106648
107187
  const valuesById = new Map(
@@ -106651,6 +107190,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106651
107190
  const materializationBatch = createInitializerMaterializationBatch(document);
106652
107191
  let members = document.members;
106653
107192
  const deferred = /* @__PURE__ */ new Set();
107193
+ const parameterizedDeclarationMemberIds = /* @__PURE__ */ new Set();
106654
107194
  if (defaultInitializerMemberIds.size > 0) {
106655
107195
  members = document.members.map((member) => {
106656
107196
  if (!defaultInitializerMemberIds.has(member.id)) return member;
@@ -106658,6 +107198,7 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106658
107198
  if (!isInitValueContent(defaultValue)) return member;
106659
107199
  const parameters = defaultValue.init.compiled?.parameters;
106660
107200
  if (parameters === void 0 || parameters.length > 2) {
107201
+ parameterizedDeclarationMemberIds.add(member.id);
106661
107202
  const deferredMember = { ...member };
106662
107203
  delete deferredMember.defaultValue;
106663
107204
  delete deferredMember.valueId;
@@ -106696,6 +107237,11 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106696
107237
  const parameters = row.init.compiled?.parameters;
106697
107238
  if (parameters === void 0 || parameters.length > 2) {
106698
107239
  deferred.add(row.id);
107240
+ const rootOwner = initializerRootOwners.get(row.id);
107241
+ const rootOwnerId = rootOwner === void 0 ? void 0 : getField(rootOwner, "id");
107242
+ if (typeof rootOwnerId === "string") {
107243
+ parameterizedDeclarationMemberIds.add(rootOwnerId);
107244
+ }
106699
107245
  continue;
106700
107246
  }
106701
107247
  const materialized = materializeInitializerValue2({
@@ -106712,6 +107258,73 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106712
107258
  valuesById.set(created.id, created);
106713
107259
  }
106714
107260
  }
107261
+ const expandedRows = /* @__PURE__ */ new Map();
107262
+ const classesById = new Map(
107263
+ document.classes.map((entry) => [entry.id, entry])
107264
+ );
107265
+ const membersById = new Map(
107266
+ document.members.map((entry) => [entry.id, entry])
107267
+ );
107268
+ const classNeedsExpansion = /* @__PURE__ */ new Map();
107269
+ const memberHasParameterizedDefault = /* @__PURE__ */ new Map();
107270
+ const reachesParameterizedDefault = (memberId) => {
107271
+ const path = [];
107272
+ const visited = /* @__PURE__ */ new Set();
107273
+ let currentId = memberId;
107274
+ let result = false;
107275
+ while (currentId !== void 0 && !visited.has(currentId)) {
107276
+ const cached = memberHasParameterizedDefault.get(currentId);
107277
+ if (cached !== void 0) {
107278
+ result = cached;
107279
+ break;
107280
+ }
107281
+ if (parameterizedDeclarationMemberIds.has(currentId)) {
107282
+ result = true;
107283
+ break;
107284
+ }
107285
+ visited.add(currentId);
107286
+ path.push(currentId);
107287
+ currentId = membersById.get(currentId)?.extendsMemberId;
107288
+ }
107289
+ for (const id2 of path) memberHasParameterizedDefault.set(id2, result);
107290
+ return result;
107291
+ };
107292
+ const inheritsParameterizedDefault = (classId) => {
107293
+ const cached = classNeedsExpansion.get(classId);
107294
+ if (cached !== void 0) return cached;
107295
+ const schemaClass2 = classesById.get(classId);
107296
+ if (schemaClass2 === void 0) return false;
107297
+ classNeedsExpansion.set(classId, false);
107298
+ for (const memberId of Object.values(schemaClass2.schema)) {
107299
+ if (reachesParameterizedDefault(memberId)) {
107300
+ classNeedsExpansion.set(classId, true);
107301
+ return true;
107302
+ }
107303
+ }
107304
+ const result = typeof schemaClass2.extendsClassId === "string" && inheritsParameterizedDefault(schemaClass2.extendsClassId);
107305
+ classNeedsExpansion.set(classId, result);
107306
+ return result;
107307
+ };
107308
+ const animationRoots = parameterizedDeclarationMemberIds.size === 0 ? [] : [...valuesById.values()].filter(
107309
+ (row) => isLiteralValueContent(row) && isVirtualInstanceRootShape(row) && typeof row.classId === "string" && animationFamilyClassIds.has(row.classId) && inheritsParameterizedDefault(row.classId)
107310
+ );
107311
+ const rootsToExpand = animationRootsInValidationScope({
107312
+ document,
107313
+ valuesById,
107314
+ animationFamilyClassIds,
107315
+ animationRoots,
107316
+ scopeMemberIds
107317
+ });
107318
+ if (rootsToExpand.length > 0) {
107319
+ const lookups = initializerEvaluatorLookups(
107320
+ materializationBatch.document()
107321
+ );
107322
+ for (const root of rootsToExpand) {
107323
+ for (const row of lookups.virtualInstanceRowsForValue(root.id)) {
107324
+ expandedRows.set(row.id, row);
107325
+ }
107326
+ }
107327
+ }
106715
107328
  if (deferred.size > 0) {
106716
107329
  for (const id2 of deferred) valuesById.delete(id2);
106717
107330
  members = members.map((member) => {
@@ -106803,6 +107416,9 @@ function materializeDeclarationInitializersForAnimationValidation(document) {
106803
107416
  }
106804
107417
  }
106805
107418
  }
107419
+ for (const [id2, row] of expandedRows) {
107420
+ if (!deferred.has(id2)) valuesById.set(id2, row);
107421
+ }
106806
107422
  return { ...document, members, values: [...valuesById.values()] };
106807
107423
  }
106808
107424
  function containsDirectValueId(value, ids) {
@@ -107537,10 +108153,11 @@ var init_project_version_whole_graph_validation = __esm({
107537
108153
  init_project_root_members();
107538
108154
  init_project_schema_identifier_validation();
107539
108155
  init_packed_value_write_fold();
107540
- init_project_version_schema_commit();
108156
+ init_project_version_write_changes();
107541
108157
  init_project_version_system_protection_writes();
107542
108158
  init_reserved_record_id_validation();
107543
108159
  init_members();
108160
+ init_instance_provenance();
107544
108161
  init_generics();
107545
108162
  init_inheritance();
107546
108163
  init_neoscript();
@@ -110872,29 +111489,25 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
110872
111489
  }
110873
111490
  case "litDict": {
110874
111491
  const valueType = expected.arguments[1] ?? expected;
111492
+ const keyType = expected.arguments[0];
111493
+ const keyEnumId = context.enumIdsByName.get(keyType?.name ?? "");
111494
+ const keyEnum = keyEnumId === void 0 ? null : {
111495
+ name: keyType.name,
111496
+ optionsByName: context.enumOptionsByName.get(keyEnumId) ?? /* @__PURE__ */ new Map()
111497
+ };
110875
111498
  const value = {};
110876
111499
  for (const entry of expression.entries) {
110877
111500
  if (positionRequiresEvaluation(
110878
111501
  context,
110879
111502
  entry.key,
110880
- DICTIONARY_KEY_TYPE,
111503
+ keyType ?? expected,
110881
111504
  ownerClass
110882
111505
  )) {
110883
111506
  throw new Error(
110884
- `Dictionary key at ${path} is a computed expression. Dictionary keys must be string literals.`
111507
+ `Dictionary key at ${path} is a computed expression. Dictionary keys must be ${keyEnum === null ? "string literals" : "enum options or quoted option IDs"}.`
110885
111508
  );
110886
111509
  }
110887
- const key = lowerExpressionValue(
110888
- context,
110889
- entry.key,
110890
- DICTIONARY_KEY_TYPE,
110891
- ownerClass,
110892
- path,
110893
- genericEnvironment,
110894
- sourceText
110895
- );
110896
- if (typeof key !== "string")
110897
- throw new Error("Dictionary keys must be strings.");
111510
+ const key = lowerDictionaryKey(entry.key, keyEnum, path);
110898
111511
  value[key] = lowerExpressionValue(
110899
111512
  context,
110900
111513
  entry.value,
@@ -112017,7 +112630,7 @@ function variantPathSegments2(expression) {
112017
112630
  if (segments.length < 3) return null;
112018
112631
  return segments;
112019
112632
  }
112020
- var UNSET_LIST_COLUMN_WIDTH, EMPTY_GENERIC_TYPE_ENVIRONMENT, DICTIONARY_KEY_TYPE, STRUCTURED_LEAF_COMPONENT_TYPE, primitiveMemberKinds;
112633
+ var UNSET_LIST_COLUMN_WIDTH, EMPTY_GENERIC_TYPE_ENVIRONMENT, STRUCTURED_LEAF_COMPONENT_TYPE, primitiveMemberKinds;
112021
112634
  var init_lower_members = __esm({
112022
112635
  "src/project-source/lower-members.ts"() {
112023
112636
  "use strict";
@@ -112036,13 +112649,9 @@ var init_lower_members = __esm({
112036
112649
  init_member_kind_type_names();
112037
112650
  init_source_diagnostics();
112038
112651
  init_key_reference_spelling();
112652
+ init_dictionary_enum_keys();
112039
112653
  UNSET_LIST_COLUMN_WIDTH = -1;
112040
112654
  EMPTY_GENERIC_TYPE_ENVIRONMENT = /* @__PURE__ */ new Map();
112041
- DICTIONARY_KEY_TYPE = {
112042
- name: "string",
112043
- nullable: false,
112044
- arguments: []
112045
- };
112046
112655
  STRUCTURED_LEAF_COMPONENT_TYPE = {
112047
112656
  name: "float",
112048
112657
  nullable: false,
@@ -116300,6 +116909,23 @@ var init_neoscript_build_cache = __esm({
116300
116909
  });
116301
116910
 
116302
116911
  // src/project-source/local-initializer-materialization.ts
116912
+ function initializerRecompileTargets(args) {
116913
+ return collectNeoScriptRecompileTargets({
116914
+ currentDocument: args.currentDocument,
116915
+ postDocument: args.postDocument,
116916
+ forceRecompile: args.forceRecompile,
116917
+ changes: args.changes.map((change) => {
116918
+ const operation = "operation" in change ? change.operation : change.kind;
116919
+ return {
116920
+ recordKind: change.recordKind,
116921
+ recordId: change.recordId,
116922
+ operation,
116923
+ ...operation === "delete" ? { deleted: true } : {},
116924
+ ...change.nextData === void 0 ? {} : { nextData: change.nextData }
116925
+ };
116926
+ })
116927
+ });
116928
+ }
116303
116929
  function materializedInitializerReconciliationFailuresV4(args) {
116304
116930
  if (args.reconciliations.size === 0) return [];
116305
116931
  const records2 = reconciliationRecords(
@@ -116310,17 +116936,11 @@ function materializedInitializerReconciliationFailuresV4(args) {
116310
116936
  const document = readPulledProjectDocumentV4(records2);
116311
116937
  const currentRecords = reconciliationRecords(args.workspace, []);
116312
116938
  const currentDocument = readPulledProjectDocumentV4(currentRecords);
116313
- const recompileTargets = collectNeoScriptRecompileTargets({
116939
+ const recompileTargets = initializerRecompileTargets({
116314
116940
  currentDocument,
116315
116941
  postDocument: document,
116316
116942
  forceRecompile: args.forceRecompile,
116317
- changes: args.changes.map((change) => ({
116318
- recordKind: change.recordKind,
116319
- recordId: change.recordId,
116320
- operation: change.kind,
116321
- ...change.kind === "delete" ? { deleted: true } : {},
116322
- ...change.nextData === void 0 ? {} : { nextData: change.nextData }
116323
- }))
116943
+ changes: args.changes
116324
116944
  });
116325
116945
  const reconciliationByValueId = /* @__PURE__ */ new Map();
116326
116946
  const candidateValueIds = /* @__PURE__ */ new Set();
@@ -116393,8 +117013,14 @@ function materializedInitializerReconciliationFailuresV4(args) {
116393
117013
  let compilationProject;
116394
117014
  if (replayableValueIds.size > 0) {
116395
117015
  compilationProject = args.useBuildCaches === false ? createNeoScriptCompilationProject(document) : loadOrBuildNeoScriptProjectV1(args.workspace.root, document);
117016
+ compilePulledProjectDocumentForEvaluationV4(
117017
+ document,
117018
+ compilationProject,
117019
+ recompileTargets
117020
+ );
116396
117021
  }
116397
- const replayContext = replayableValueIds.size > 0 ? createPulledConstructionReplayContext({ document }) : void 0;
117022
+ const replayDocument = replayableValueIds.size > 0 ? { ...document } : document;
117023
+ const replayContext = replayableValueIds.size > 0 ? createPulledConstructionReplayContext({ document: replayDocument }) : void 0;
116398
117024
  let currentRows;
116399
117025
  let currentReader;
116400
117026
  const failures = [];
@@ -116429,7 +117055,7 @@ function materializedInitializerReconciliationFailuresV4(args) {
116429
117055
  const replayRows = /* @__PURE__ */ new Map();
116430
117056
  for (const [id2, row] of replayStoredConstructionV4({
116431
117057
  records: records2,
116432
- document,
117058
+ document: replayDocument,
116433
117059
  replayContext,
116434
117060
  valueId: reconciliation.valueId,
116435
117061
  code: reconciliation.code,
@@ -116443,9 +117069,9 @@ function materializedInitializerReconciliationFailuresV4(args) {
116443
117069
  }
116444
117070
  replayRows.set(id2, row);
116445
117071
  }
116446
- assertPulledConstructorsCompiled(document, replayContext);
117072
+ assertPulledConstructorsCompiled(replayDocument, replayContext);
116447
117073
  currentRows ??= new Map(currentDocument.values.map((row) => [row.id, row]));
116448
- currentReader ??= new EffectiveValueReader(document, currentRows);
117074
+ currentReader ??= new EffectiveValueReader(replayDocument, currentRows);
116449
117075
  const replay = replayRows.get(reconciliation.valueId);
116450
117076
  const replayArgs = replay !== void 0 && isLiteralValueContent(replay) ? replay.constructorArgs : void 0;
116451
117077
  const currentRoot = currentRows.get(reconciliation.valueId);
@@ -116503,10 +117129,10 @@ function materializeInitializersLocallyV4(args) {
116503
117129
  readPulledProjectDocumentV4(records2),
116504
117130
  variantOwnershipRootRecords(records2)
116505
117131
  );
116506
- let document = variantScope.document;
117132
+ const authoredDocument = variantScope.document;
116507
117133
  const rootKinds = /* @__PURE__ */ new Map();
116508
117134
  const rootOwners = resolveSemanticOwnerMembersForValues(
116509
- document,
117135
+ authoredDocument,
116510
117136
  sourceRoots,
116511
117137
  variantScope.roots,
116512
117138
  void 0,
@@ -116514,19 +117140,73 @@ function materializeInitializersLocallyV4(args) {
116514
117140
  );
116515
117141
  const roots = [];
116516
117142
  const localizedTextIds = new Set(
116517
- document.localizedTexts?.map((text) => text.id)
117143
+ authoredDocument.localizedTexts?.map((text) => text.id)
116518
117144
  );
116519
- let compilationProject;
116520
- for (const sourceValueId of [...sourceRoots].sort()) {
116521
- if (rootKinds.get(sourceValueId) === "declaration") continue;
117145
+ const pendingRoots = new Set(
117146
+ [...sourceRoots].filter((id2) => rootKinds.get(id2) !== "declaration").sort()
117147
+ );
117148
+ if (pendingRoots.size === 0) return { roots };
117149
+ const compilationProject = createNeoScriptCompilationProject(authoredDocument);
117150
+ const changedBodies = {
117151
+ memberIds: /* @__PURE__ */ new Set(),
117152
+ constructorIds: /* @__PURE__ */ new Set()
117153
+ };
117154
+ for (const change of args.changes) {
117155
+ if (change.operation === "delete") continue;
117156
+ if (change.recordKind === "member") {
117157
+ changedBodies.memberIds.add(change.recordId);
117158
+ } else if (change.recordKind === "constructor") {
117159
+ changedBodies.constructorIds.add(change.recordId);
117160
+ }
117161
+ }
117162
+ const needsDependentBodies = args.forceRecompile === true || args.changes.some(
117163
+ (change) => ["class", "member", "constructor", "enum", "interface"].includes(
117164
+ change.recordKind
117165
+ )
117166
+ );
117167
+ if (needsDependentBodies) {
117168
+ const currentDocument = readPulledProjectDocumentV4(
117169
+ reconciliationRecords(args.workspace, [])
117170
+ );
117171
+ const dependentBodies = initializerRecompileTargets({
117172
+ currentDocument,
117173
+ postDocument: authoredDocument,
117174
+ changes: args.changes,
117175
+ forceRecompile: args.forceRecompile
117176
+ });
117177
+ for (const id2 of dependentBodies.memberIds) changedBodies.memberIds.add(id2);
117178
+ for (const id2 of dependentBodies.constructorIds) {
117179
+ changedBodies.constructorIds.add(id2);
117180
+ }
117181
+ }
117182
+ compilePulledProjectDocumentForEvaluationV4(
117183
+ authoredDocument,
117184
+ compilationProject,
117185
+ changedBodies
117186
+ );
117187
+ assertPulledConstructorsCompiled(authoredDocument);
117188
+ const batch = createInitializerMaterializationBatch(
117189
+ authoredDocument,
117190
+ pendingRoots
117191
+ );
117192
+ const compiledInitializers = /* @__PURE__ */ new Map();
117193
+ materializeInitializerDependencies(pendingRoots, (sourceValueId) => {
117194
+ const batchDocument = batch.document();
117195
+ const document = {
117196
+ ...authoredDocument,
117197
+ values: batchDocument.values,
117198
+ databaseVM: batchDocument.databaseVM
117199
+ };
116522
117200
  const rootOwner = rootOwners.get(sourceValueId);
116523
117201
  if (rootOwner === void 0) {
116524
117202
  throw new Error(
116525
117203
  `CLI initializer materialization cannot resolve the owning member for root "${sourceValueId}".`
116526
117204
  );
116527
117205
  }
116528
- compilationProject ??= createNeoScriptCompilationProject(document);
116529
- const replayContext = createPulledConstructionReplayContext({ document });
117206
+ const replayContext = createPulledConstructionReplayContext({
117207
+ document,
117208
+ valuesById: batch.valuesById
117209
+ });
116530
117210
  const code = initializerCode(records2, sourceValueId);
116531
117211
  let compiledInitializer;
116532
117212
  let pinnedRootSchemaKeys = /* @__PURE__ */ new Set();
@@ -116538,8 +117218,10 @@ function materializeInitializersLocallyV4(args) {
116538
117218
  compilationProject,
116539
117219
  replayContext,
116540
117220
  member: rootOwner,
117221
+ compiledInitializer: compiledInitializers.get(sourceValueId),
116541
117222
  onCompiledInitializer: (init) => {
116542
117223
  compiledInitializer = init;
117224
+ compiledInitializers.set(sourceValueId, init);
116543
117225
  },
116544
117226
  onPinnedRootSchemaKeys: (schemaKeys) => {
116545
117227
  pinnedRootSchemaKeys = schemaKeys;
@@ -116573,6 +117255,7 @@ function materializeInitializersLocallyV4(args) {
116573
117255
  compilationProject,
116574
117256
  replayContext,
116575
117257
  member: rootOwner,
117258
+ compiledInitializer,
116576
117259
  omitConstructionFields: true
116577
117260
  });
116578
117261
  const baselineRoot = baseline.get(sourceValueId);
@@ -116606,15 +117289,9 @@ function materializeInitializersLocallyV4(args) {
116606
117289
  // class default, so the evaluated construction's own field list is what
116607
117290
  // pins rows against collapse. The server commit pins the same set.
116608
117291
  pinnedRootSchemaKeys,
116609
- virtualValueIdForSource: (instanceRootId, sourceIdentity3) => isPendingId(instanceRootId) ? pendingVirtualValueId(instanceRootId, sourceIdentity3) : virtualValueId(instanceRootId, sourceIdentity3)
117292
+ virtualValueIdForSource: (instanceRootId, sourceIdentity3) => isPendingId(instanceRootId) || hasPendingVirtualSourceIdentity(sourceIdentity3) ? pendingVirtualValueId(instanceRootId, sourceIdentity3) : virtualValueId(instanceRootId, sourceIdentity3)
116610
117293
  });
116611
117294
  const evaluatedRows = [sparse2.root, ...sparse2.createdChildren];
116612
- const valuesById = new Map(document.values.map((row) => [row.id, row]));
116613
- for (const row of evaluatedRows) valuesById.set(row.id, row);
116614
- const materializedDocument = {
116615
- ...document,
116616
- values: [...valuesById.values()]
116617
- };
116618
117295
  roots.push({
116619
117296
  sourceValueId,
116620
117297
  rows: evaluatedRows.map((row) => ({ ...row }))
@@ -116628,8 +117305,8 @@ function materializeInitializersLocallyV4(args) {
116628
117305
  data: row
116629
117306
  });
116630
117307
  }
116631
- document = materializedDocument;
116632
- }
117308
+ batch.upsert(evaluatedRows);
117309
+ });
116633
117310
  return { roots };
116634
117311
  }
116635
117312
  function prospectiveInitializerRecordsV4(args) {
@@ -116778,6 +117455,8 @@ function variantOwnershipRootRecords(records2) {
116778
117455
  var init_local_initializer_materialization = __esm({
116779
117456
  "src/project-source/local-initializer-materialization.ts"() {
116780
117457
  "use strict";
117458
+ init_evaluateInitializer();
117459
+ init_initializer_dependencies();
116781
117460
  init_initializer_replay();
116782
117461
  init_effective_value_comparison();
116783
117462
  init_constructor_argument_ownership();
@@ -117695,6 +118374,7 @@ function computeWorkspaceStatus(workspace, options) {
117695
118374
  try {
117696
118375
  localInitializerMaterialization = materializeInitializersLocallyV4({
117697
118376
  workspace,
118377
+ forceRecompile: options.forceRecompile,
117698
118378
  changes: changes.map((change) => ({
117699
118379
  recordKind: change.recordKind,
117700
118380
  recordId: change.recordId,
@@ -117827,9 +118507,11 @@ function replayAnimationDeclarationInitializersV4(records2, document, fallbackDo
117827
118507
  ...document.values.map((row) => [row.id, row])
117828
118508
  ]);
117829
118509
  for (const { row, code } of initializers) {
117830
- if (rootKinds.get(row.id) !== "declaration") continue;
117831
118510
  const owner = owners.get(row.id);
117832
118511
  if (owner === void 0) continue;
118512
+ if (rootKinds.get(row.id) !== "declaration" && !isStaticMember(owner)) {
118513
+ continue;
118514
+ }
117833
118515
  const declaredClassId = typeof row.classId === "string" ? row.classId : Reflect.get(owner, "classId");
117834
118516
  if (typeof declaredClassId !== "string") continue;
117835
118517
  if (!classBelongsToAnimationFamily(document.classesById, declaredClassId)) {
@@ -118801,6 +119483,7 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
118801
119483
  }
118802
119484
  }
118803
119485
  const status = computeWorkspaceStatus(workspace, {
119486
+ forceRecompile: args.forceRecompile,
118804
119487
  skipProjectBinaryInspection: true,
118805
119488
  useBuildCaches: false,
118806
119489
  writeProjectAnalysisCache: () => void 0,
@@ -118966,7 +119649,18 @@ function derivedAssignment(pendingId2) {
118966
119649
  if (virtualIdentity !== null) {
118967
119650
  return {
118968
119651
  ownerLocator: virtualIdentity.instanceRootId,
118969
- derive: (ownerId) => virtualValueId(ownerId, virtualIdentity.sourceIdentity),
119652
+ derive: (ownerId, assignments) => virtualValueId(
119653
+ ownerId,
119654
+ rewriteVirtualSourceIdentity(virtualIdentity.sourceIdentity, (id2) => {
119655
+ const assigned = assignments.get(id2);
119656
+ if (assigned === void 0) {
119657
+ throw new ProjectSourceCommitVerificationError(
119658
+ `Virtual value assignment ${pendingId2} names source ${id2}, which has no pending id assignment.`
119659
+ );
119660
+ }
119661
+ return assigned;
119662
+ })
119663
+ ),
118970
119664
  label: "Virtual value assignment",
118971
119665
  ownerNoun: "instance root"
118972
119666
  };
@@ -118983,7 +119677,7 @@ function assertDerivedAssignmentsAreDerived(assignments) {
118983
119677
  `${derivation.label} ${pendingId2} names ${derivation.ownerNoun} ${derivation.ownerLocator}, which has no pending id assignment.`
118984
119678
  );
118985
119679
  }
118986
- const derived = derivation.derive(ownerId);
119680
+ const derived = derivation.derive(ownerId, assignments);
118987
119681
  if (assignedId !== derived) {
118988
119682
  throw new ProjectSourceCommitVerificationError(
118989
119683
  `${derivation.label} ${pendingId2} is ${assignedId}, but ${derivation.ownerNoun} ${ownerId} owns ${derived}.`
@@ -119013,24 +119707,51 @@ function positionIndependentAssignments(assignments) {
119013
119707
  }
119014
119708
  return resolved;
119015
119709
  }
119016
- function relocatedAssignment(pendingId2, assignments, byPosition) {
119710
+ function relocatedAssignment(pendingId2, assignments, byPosition, used) {
119017
119711
  const key = positionIndependentPendingKey(pendingId2);
119018
119712
  const relocated = key === null ? void 0 : byPosition.get(key);
119019
119713
  if (relocated !== void 0) return relocated;
119714
+ for (const [owner, rebuild] of [
119715
+ [pendingMemberValueMemberId(pendingId2), pendingMemberValueId],
119716
+ [pendingEntryMemberDeclaringId(pendingId2), pendingEntryMemberId],
119717
+ [
119718
+ pendingRequiredConstructorClassId(pendingId2),
119719
+ pendingRequiredConstructorId
119720
+ ]
119721
+ ]) {
119722
+ if (owner === null) continue;
119723
+ const relocatedOwner = assignments.has(owner) ? owner : relocatedAssignment(owner, assignments, byPosition, used);
119724
+ if (relocatedOwner === null) return null;
119725
+ const rebuilt = rebuild(relocatedOwner);
119726
+ return assignments.has(rebuilt) ? rebuilt : null;
119727
+ }
119020
119728
  const virtual = pendingVirtualValueIdentity(pendingId2);
119021
119729
  if (virtual === null) return null;
119022
119730
  let relocatedRoot = virtual.instanceRootId;
119023
- if (!assignments.has(relocatedRoot)) {
119024
- const rootKey = positionIndependentPendingKey(relocatedRoot);
119025
- if (rootKey === null) return null;
119026
- const canonicalRoot = byPosition.get(rootKey);
119027
- if (canonicalRoot === void 0) return null;
119731
+ if (isPendingId(relocatedRoot) && !assignments.has(relocatedRoot)) {
119732
+ const canonicalRoot = relocatedAssignment(
119733
+ relocatedRoot,
119734
+ assignments,
119735
+ byPosition,
119736
+ used
119737
+ );
119738
+ if (canonicalRoot === null) return null;
119028
119739
  relocatedRoot = canonicalRoot;
119029
119740
  }
119030
- const relocatedVirtual = pendingVirtualValueId(
119031
- relocatedRoot,
119032
- virtual.sourceIdentity
119741
+ const sourceIdentity3 = rewriteVirtualSourceIdentity(
119742
+ virtual.sourceIdentity,
119743
+ (sourceId3) => {
119744
+ const relocatedSource = assignments.has(sourceId3) ? sourceId3 : relocatedAssignment(sourceId3, assignments, byPosition, used);
119745
+ if (relocatedSource === null) {
119746
+ throw new ProjectSourceCommitVerificationError(
119747
+ `Virtual value ${pendingId2} names source ${sourceId3}, which has no pending id assignment.`
119748
+ );
119749
+ }
119750
+ used.add(relocatedSource);
119751
+ return relocatedSource;
119752
+ }
119033
119753
  );
119754
+ const relocatedVirtual = pendingVirtualValueId(relocatedRoot, sourceIdentity3);
119034
119755
  return assignments.has(relocatedVirtual) ? relocatedVirtual : null;
119035
119756
  }
119036
119757
  function rewritePending(value, assignments, used, positionless) {
@@ -119041,7 +119762,12 @@ function rewritePending(value, assignments, used, positionless) {
119041
119762
  return exact;
119042
119763
  }
119043
119764
  if (value.startsWith("__pending__:")) {
119044
- const relocated = relocatedAssignment(value, assignments, positionless);
119765
+ const relocated = relocatedAssignment(
119766
+ value,
119767
+ assignments,
119768
+ positionless,
119769
+ used
119770
+ );
119045
119771
  if (relocated !== null) {
119046
119772
  used.add(relocated);
119047
119773
  return assignments.get(relocated);
@@ -119903,7 +120629,7 @@ function createPulledConstructionReplayContext(args) {
119903
120629
  return {
119904
120630
  document: args.document,
119905
120631
  constructorsValidated: false,
119906
- valuesById: new Map(args.document.values.map((value) => [value.id, value]))
120632
+ valuesById: args.valuesById ?? new Map(args.document.values.map((value) => [value.id, value]))
119907
120633
  };
119908
120634
  }
119909
120635
  function describePulledProjectBodyCompileError(error) {
@@ -119979,26 +120705,27 @@ function replayStoredConstructionV4(args) {
119979
120705
  delete envelope.init;
119980
120706
  const candidate = {
119981
120707
  ...envelope,
119982
- init: { code: args.code }
120708
+ init: args.compiledInitializer ?? { code: args.code }
119983
120709
  };
119984
- compileValueRowInitializerBody({
119985
- project: document.project,
119986
- projectFiles: document.projectFiles,
119987
- members: document.members,
119988
- classes: document.classes,
119989
- enums: document.enums,
119990
- interfaces: document.interfaces,
119991
- constructors: document.constructors,
119992
- member: compileMember,
119993
- valueRow: candidate,
119994
- valueId: args.valueId,
119995
- // Instance calls are self-contained. Declaration calls inherit the class
119996
- // header parameters that are in lexical scope at their source site.
119997
- initializerOwnerClass: args.initializerOwnerClass ?? null,
119998
- lexicalThisClass: args.lexicalThisClass ?? null,
119999
- storedConstructionReplay: true,
120000
- ...compilationProject === void 0 ? {} : { compilationProject }
120001
- });
120710
+ if (args.compiledInitializer === void 0)
120711
+ compileValueRowInitializerBody({
120712
+ project: document.project,
120713
+ projectFiles: document.projectFiles,
120714
+ members: document.members,
120715
+ classes: document.classes,
120716
+ enums: document.enums,
120717
+ interfaces: document.interfaces,
120718
+ constructors: document.constructors,
120719
+ member: compileMember,
120720
+ valueRow: candidate,
120721
+ valueId: args.valueId,
120722
+ // Instance calls are self-contained. Declaration calls inherit the class
120723
+ // header parameters that are in lexical scope at their source site.
120724
+ initializerOwnerClass: args.initializerOwnerClass ?? null,
120725
+ lexicalThisClass: args.lexicalThisClass ?? null,
120726
+ storedConstructionReplay: true,
120727
+ ...compilationProject === void 0 ? {} : { compilationProject }
120728
+ });
120002
120729
  if (!isMemberValue(candidate) || !isInitValueContent(candidate)) {
120003
120730
  throw new Error(
120004
120731
  `Construction replay for value "${args.valueId}" did not compile an initializer row.`
@@ -120076,7 +120803,7 @@ function compilePulledUncompiledConstructorsV4(document, compilationProject, rep
120076
120803
  }
120077
120804
  assertPulledConstructorsCompiled(document, replayContext);
120078
120805
  }
120079
- function compilePulledProjectDocumentForEvaluationV4(document, compilationProject) {
120806
+ function compilePulledProjectDocumentForEvaluationV4(document, compilationProject, targets) {
120080
120807
  const sharedCompilationProject = compilationProject ?? createNeoScriptCompilationProject({
120081
120808
  project: document.project,
120082
120809
  projectFiles: document.projectFiles,
@@ -120098,11 +120825,15 @@ function compilePulledProjectDocumentForEvaluationV4(document, compilationProjec
120098
120825
  compilationProject: sharedCompilationProject
120099
120826
  };
120100
120827
  for (const constructor2 of compileArgs.constructors) {
120828
+ if (targets !== void 0 && !targets.constructorIds.has(constructor2.id) && !hasPendingNeoScriptDerivation("constructor", constructor2))
120829
+ continue;
120101
120830
  compileConstructorRecord({ ...compileArgs, constructor: constructor2 });
120102
120831
  }
120103
120832
  assertPulledConstructorsCompiled(document);
120104
120833
  const memberIndex = documentMemberCompilationIndex(document);
120105
120834
  for (const member of compileArgs.members) {
120835
+ if (targets !== void 0 && !targets.memberIds.has(member.id) && !hasPendingNeoScriptDerivation("member", member))
120836
+ continue;
120106
120837
  try {
120107
120838
  compileAuthoredMemberBodies({
120108
120839
  ...compileArgs,
@@ -120289,6 +121020,7 @@ var init_initializer_replay = __esm({
120289
121020
  init_server_preparation_preflight();
120290
121021
  init_projection();
120291
121022
  init_constructors2();
121023
+ init_neo_script_derived_bodies();
120292
121024
  init_compiler_adapter();
120293
121025
  pulledBodyCompileSites = /* @__PURE__ */ new WeakMap();
120294
121026
  recentPulledDocuments = [];
@@ -120382,6 +121114,7 @@ function buildValueEmitContext(records2, manifest, options = {}) {
120382
121114
  ownerClassIds: memberOwnerClassIdIndex(classes),
120383
121115
  values,
120384
121116
  enums,
121117
+ dictionaryKeyOptions: /* @__PURE__ */ new Map(),
120385
121118
  localizedTexts,
120386
121119
  mainLocale: projectMainLocale(records2),
120387
121120
  symbolsByValueId,
@@ -120945,6 +121678,7 @@ function buildValueLowerContext(state, manifest, options = {}) {
120945
121678
  new Map(entry.options.map((option) => [option.name, option.id]))
120946
121679
  ])
120947
121680
  ),
121681
+ enumNames: new Map(manifest.enums.map((entry) => [entry.id, entry.name])),
120948
121682
  staticValueIdsBySymbol: staticTargets,
120949
121683
  get rootValueTargetsByPath() {
120950
121684
  return rootValueTargets ??= rootValueTargetsByPath(
@@ -121575,15 +122309,17 @@ function lowerMemberDefaultSourcesV4(state, analysis, manifest, options = {}) {
121575
122309
  `Member default ${label} was classified as an owned literal graph but lowered as an initializer.`
121576
122310
  );
121577
122311
  }
121578
- if (storedDefault !== null && canonicallyEqual(seed.value, storedDefault.value) && (seed.classId ?? null) === (typeof storedDefaultClassId === "string" ? storedDefaultClassId : null) && (seed.values === void 0 || seed.values.length === 0) && (seed.bindingMembers === void 0 || seed.bindingMembers.length === 0) && (seed.localizedTexts === void 0 || seed.localizedTexts.length === 0)) {
122312
+ const emptyInlineClassDefault = member.kind === "class" && isObjectRecord2(seed.value) && Object.keys(seed.value).length === 0 && (seed.constructorArgs === void 0 || Object.keys(seed.constructorArgs).length === 0) && seed.instanceConstructorId == null && seed.instanceVariantId == null && seed.instanceVariantRowValueId == null;
122313
+ const matchesStoredDefault = storedDefault !== null && canonicallyEqual(seed.value, storedDefault.value) && (seed.classId ?? null) === (typeof storedDefaultClassId === "string" ? storedDefaultClassId : null);
122314
+ if ((emptyInlineClassDefault || matchesStoredDefault) && (seed.values === void 0 || seed.values.length === 0) && (seed.bindingMembers === void 0 || seed.bindingMembers.length === 0) && (seed.localizedTexts === void 0 || seed.localizedTexts.length === 0)) {
121579
122315
  for (const id2 of context.pendingValues.keys()) {
121580
122316
  if (!pendingValueIdsBeforeSeed.has(id2)) {
121581
122317
  deletePendingValue(context, id2);
121582
122318
  }
121583
122319
  }
121584
122320
  memberDefaultValues.set(memberId, {
121585
- value: storedDefault.value,
121586
- classId: typeof storedDefaultClassId === "string" ? storedDefaultClassId : null
122321
+ value: seed.value,
122322
+ classId: seed.classId
121587
122323
  });
121588
122324
  continue;
121589
122325
  }
@@ -122280,24 +123016,21 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
122280
123016
  throw new Error(`Default value ${binding.label} requires {...}.`);
122281
123017
  }
122282
123018
  const entryMember = requiredMember(context, member.entryMemberId);
123019
+ const keyEnum = dictionaryKeyEnum(context, member);
122283
123020
  const baseBody = backed.body;
122284
123021
  const body = {};
122285
123022
  const entrySlices = topLevelEntrySlices(binding.initializer, "{", "}");
122286
123023
  let entryIndex = 0;
122287
123024
  for (const entry of expression.entries) {
122288
- if (entry.key.kind !== "litString") {
122289
- throw new Error(
122290
- `Default dictionary ${binding.label} requires string keys.`
122291
- );
122292
- }
122293
- const existingId = isObjectRecord2(baseBody) ? baseBody[entry.key.value] : void 0;
123025
+ const key = lowerDictionaryKey(entry.key, keyEnum, binding.label);
123026
+ const existingId = isObjectRecord2(baseBody) ? baseBody[key] : void 0;
122294
123027
  const entryId = typeof existingId === "string" ? existingId : annotatedValue(entry.value).id;
122295
123028
  if (entryId === null || entryId === void 0) {
122296
123029
  throw new Error(
122297
- `Default dictionary ${binding.label}[${JSON.stringify(entry.key.value)}] has no existing owned value row. Creating new default rows from source is not implemented by this slice.`
123030
+ `Default dictionary ${binding.label}[${JSON.stringify(key)}] has no existing owned value row. Creating new default rows from source is not implemented by this slice.`
122298
123031
  );
122299
123032
  }
122300
- body[entry.key.value] = lowerValueRow(
123033
+ body[key] = lowerValueRow(
122301
123034
  context,
122302
123035
  entryMember,
122303
123036
  entry.value,
@@ -122901,19 +123634,18 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
122901
123634
  throw new Error(`Dictionary value ${path} requires {...}.`);
122902
123635
  }
122903
123636
  const entryMember = requiredMember(context, resolvedMember.entryMemberId);
123637
+ const keyEnum = dictionaryKeyEnum(context, resolvedMember);
122904
123638
  const body = {};
122905
123639
  const entrySlices = authoredSlice === void 0 ? [] : topLevelEntrySlices(authoredSlice, "{", "}");
122906
123640
  let entryIndex = 0;
122907
123641
  for (const entry of expression.entries) {
122908
- if (entry.key.kind !== "litString") {
122909
- throw new Error(`Dictionary value ${path} requires string keys.`);
122910
- }
122911
- body[entry.key.value] = lowerSeedChild(
123642
+ const key = lowerDictionaryKey(entry.key, keyEnum, path);
123643
+ body[key] = lowerSeedChild(
122912
123644
  context,
122913
123645
  entryMember,
122914
123646
  entry.value,
122915
123647
  source,
122916
- `${path}[${JSON.stringify(entry.key.value)}]`,
123648
+ `${path}[${JSON.stringify(key)}]`,
122917
123649
  rows,
122918
123650
  localizedTexts,
122919
123651
  void 0,
@@ -124532,32 +125264,31 @@ function lowerDictionaryValue(context, member, expression, base, source, inherit
124532
125264
  throw new Error("Dictionary values require {...}.");
124533
125265
  }
124534
125266
  const baseBody = isObjectRecord2(base.value) ? base.value : {};
125267
+ const keyEnum = dictionaryKeyEnum(context, member);
124535
125268
  const entryMember = requiredMember(context, member.entryMemberId);
124536
125269
  const environment = valueGenericEnvironment(base, inheritedEnvironment);
124537
125270
  const body = {};
124538
125271
  for (const entry of expression.entries) {
124539
- if (entry.key.kind !== "litString") {
124540
- throw new Error("Dictionary source keys must be strings.");
124541
- }
124542
- const existingId = baseBody[entry.key.value];
125272
+ const key = lowerDictionaryKey(entry.key, keyEnum, member.name);
125273
+ const existingId = baseBody[key];
124543
125274
  const symbolId = sourceValueSymbol(context, entry.value);
124544
125275
  if (symbolId !== null) {
124545
125276
  if (symbolId !== existingId) {
124546
125277
  throw new Error(
124547
- `Dictionary ${member.name}[${JSON.stringify(entry.key.value)}] changes value placement from ${String(existingId)} to ${symbolId}. The atomic placement transaction is not implemented by this slice.`
125278
+ `Dictionary ${member.name}[${JSON.stringify(key)}] changes value placement from ${String(existingId)} to ${symbolId}. The atomic placement transaction is not implemented by this slice.`
124548
125279
  );
124549
125280
  }
124550
- body[entry.key.value] = symbolId;
125281
+ body[key] = symbolId;
124551
125282
  continue;
124552
125283
  }
124553
125284
  const explicitId = annotatedValue(entry.value).id;
124554
125285
  const valueId = explicitId ?? existingId;
124555
125286
  if (typeof valueId !== "string") {
124556
125287
  throw new Error(
124557
- `Dictionary ${member.name}[${JSON.stringify(entry.key.value)}] has no existing row. New dictionary entries are not implemented by this slice.`
125288
+ `Dictionary ${member.name}[${JSON.stringify(key)}] has no existing row. New dictionary entries are not implemented by this slice.`
124558
125289
  );
124559
125290
  }
124560
- body[entry.key.value] = lowerValueRow(
125291
+ body[key] = lowerValueRow(
124561
125292
  context,
124562
125293
  entryMember,
124563
125294
  entry.value,
@@ -125786,6 +126517,20 @@ function requiredMember(context, id2) {
125786
126517
  if (member === void 0) throw new Error(`Missing member ${id2}.`);
125787
126518
  return member;
125788
126519
  }
126520
+ function dictionaryKeyEnum(context, member) {
126521
+ if (member.key.kind === "string") return null;
126522
+ const name = context.enumNames.get(member.key.enumId);
126523
+ const optionsByName = context.enumOptions.get(member.key.enumId);
126524
+ if (name === void 0) {
126525
+ throw new Error(`Unknown dictionary key enum ${member.key.enumId}.`);
126526
+ }
126527
+ if (optionsByName === void 0) {
126528
+ throw new Error(
126529
+ `Dictionary key enum ${member.key.enumId} has no option index.`
126530
+ );
126531
+ }
126532
+ return { name, optionsByName };
126533
+ }
125789
126534
  function requiredClassByName(context, name) {
125790
126535
  const schemaClass2 = context.classesByName.get(name);
125791
126536
  if (schemaClass2 === void 0) throw new Error(`Unknown class ${name}.`);
@@ -126928,14 +127673,13 @@ ${ids.map(
126928
127673
  if (!isObjectRecord2(row.value)) {
126929
127674
  return storedRowIdentitySource(valueId, writeIdentity, "{}");
126930
127675
  }
126931
- const entries = Object.entries(row.value).sort(
126932
- ([left], [right]) => compareCodePoints(left, right)
126933
- );
127676
+ const keyOptions = dictionaryOptions2(context, type.keyEnumId);
127677
+ const entries = orderedDictionaryEntries(row.value, keyOptions);
126934
127678
  const expression = entries.length === 0 ? "{}" : `{
126935
127679
  ${entries.flatMap(
126936
127680
  ([key, id2]) => typeof id2 === "string" ? [
126937
127681
  indentNeoSourceNonEmptyLines(
126938
- `${quote5(key)}: ${storedTypedRowSource(
127682
+ `${emitDictionaryKey(key, keyOptions)}: ${storedTypedRowSource(
126939
127683
  context,
126940
127684
  type.entryType,
126941
127685
  id2,
@@ -127359,22 +128103,29 @@ function dictionaryValue(context, member, value, visited, inheritedEnvironment)
127359
128103
  if (entryMember === void 0)
127360
128104
  throw new Error(`Dictionary entry member was not pulled.`);
127361
128105
  const environment = valueGenericEnvironment(value, inheritedEnvironment);
127362
- const entries = Object.entries(body).sort(
127363
- ([left], [right]) => compareCodePoints(left, right)
128106
+ const keyOptions = dictionaryOptions2(
128107
+ context,
128108
+ typeof member.keyEnumId === "string" ? member.keyEnumId : null
127364
128109
  );
128110
+ const entries = orderedDictionaryEntries(body, keyOptions);
127365
128111
  if (entries.length === 0) return "{}";
127366
128112
  return `{
127367
128113
  ${entries.flatMap(
127368
128114
  ([key, id2]) => typeof id2 === "string" ? [
127369
128115
  indentNeoSourceNonEmptyLines(
127370
- `${quote5(key)}: ${emitValue(context, entryMember, id2, {
127371
- environment,
127372
- definitionSite: !context.symbolsByValueId.has(id2),
127373
- // Dictionary keys, like class schema keys, recover entry
127374
- // identity from the owning row. Only list entries need an id.
127375
- writeIdentity: false,
127376
- visited
127377
- })}`,
128116
+ `${emitDictionaryKey(key, keyOptions)}: ${emitValue(
128117
+ context,
128118
+ entryMember,
128119
+ id2,
128120
+ {
128121
+ environment,
128122
+ definitionSite: !context.symbolsByValueId.has(id2),
128123
+ // Dictionary keys, like class schema keys, recover entry
128124
+ // identity from the owning row. Only list entries need an id.
128125
+ writeIdentity: false,
128126
+ visited
128127
+ }
128128
+ )}`,
127378
128129
  2
127379
128130
  )
127380
128131
  ] : []
@@ -127681,6 +128432,32 @@ function enumOptionNames(value) {
127681
128432
  }
127682
128433
  return result;
127683
128434
  }
128435
+ function dictionaryOptions2(context, enumId) {
128436
+ if (enumId === null) return null;
128437
+ const cached = context.dictionaryKeyOptions.get(enumId);
128438
+ if (cached !== void 0) return cached;
128439
+ const schemaEnum = context.enums.get(enumId);
128440
+ if (schemaEnum === void 0) {
128441
+ throw new Error(`Dictionary key enum ${enumId} was not pulled.`);
128442
+ }
128443
+ const options = isObjectRecord2(schemaEnum.options) ? schemaEnum.options : {};
128444
+ const keys = appendMissingKeys(
128445
+ optionalStringArray(schemaEnum.optionKeyOrder),
128446
+ Object.keys(options)
128447
+ );
128448
+ const result = /* @__PURE__ */ new Map();
128449
+ for (const [order, key] of keys.entries()) {
128450
+ const option = options[key];
128451
+ if (!isObjectRecord2(option)) continue;
128452
+ const id2 = typeof option.id === "string" ? option.id : key;
128453
+ const name = typeof option.name === "string" ? option.name : key;
128454
+ const entry = { name, order };
128455
+ result.set(id2, entry);
128456
+ result.set(key, entry);
128457
+ }
128458
+ context.dictionaryKeyOptions.set(enumId, result);
128459
+ return result;
128460
+ }
127684
128461
  function dataById(records2, kind) {
127685
128462
  return new Map(
127686
128463
  [...records2.values()].flatMap(
@@ -127765,6 +128542,7 @@ var init_value_sources = __esm({
127765
128542
  init_local_values();
127766
128543
  init_initializer_reference_spellings();
127767
128544
  init_lower_members();
128545
+ init_dictionary_enum_keys();
127768
128546
  init_lower_variants();
127769
128547
  init_member_kind_type_names();
127770
128548
  init_member_records();
@@ -130887,7 +131665,7 @@ function assignPendingIds(changes, authoredValueSeeds, reconstructed3, localInit
130887
131665
  const instanceRootId = isPendingId(pendingVirtual.instanceRootId) ? assign(pendingVirtual.instanceRootId) : pendingVirtual.instanceRootId;
130888
131666
  const derived = virtualValueId(
130889
131667
  instanceRootId,
130890
- pendingVirtual.sourceIdentity
131668
+ rewriteVirtualSourceIdentity(pendingVirtual.sourceIdentity, assign)
130891
131669
  );
130892
131670
  assigned.set(pendingId2, derived);
130893
131671
  return derived;
@@ -132312,7 +133090,8 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
132312
133090
  const localInitializerMaterialization = status.localInitializerMaterialization ?? materializeInitializersLocallyV4({
132313
133091
  workspace,
132314
133092
  changes: pendingTransportChanges,
132315
- authoredValueSeeds: pendingTransportSeeds
133093
+ authoredValueSeeds: pendingTransportSeeds,
133094
+ forceRecompile: options.forceRecompile
132316
133095
  });
132317
133096
  onPhase("Assigning pending value identities\u2026");
132318
133097
  const pendingAssignment = assignPendingIds(
@@ -132355,6 +133134,7 @@ async function prepareLocalPushArtifactsV4(workspace, status, onPhase = () => vo
132355
133134
  changes: transportChanges,
132356
133135
  authoredValueSeeds: transportSeeds,
132357
133136
  initializerMaterialization: pendingAssignment.localInitializerMaterialization ?? { roots: [] },
133137
+ forceRecompile: options.forceRecompile,
132358
133138
  pendingIdAssignments: Object.fromEntries(pendingAssignment.assigned),
132359
133139
  stagedFiles: preparedFiles
132360
133140
  });
@@ -139485,7 +140265,7 @@ var init_registry2 = __esm({
139485
140265
  "schema-contract/registry.mjs"() {
139486
140266
  "use strict";
139487
140267
  PROJECT_SCHEMA_CONTRACT = Object.freeze({
139488
- cliVersion: "0.56.0",
140268
+ cliVersion: "0.57.0",
139489
140269
  projectFileUploadBatchSize: 32,
139490
140270
  documentRecords: {
139491
140271
  member: {
@@ -147306,7 +148086,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
147306
148086
  async function main() {
147307
148087
  const args = parseArgs(process.argv.slice(2));
147308
148088
  if (args.command === "--version") {
147309
- console.log("0.56.0");
148089
+ console.log("0.57.0");
147310
148090
  return;
147311
148091
  }
147312
148092
  if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {