@neocompose/cli 0.76.1 → 0.76.3

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.
@@ -879,6 +879,351 @@ var require_ignore = __commonJS({
879
879
  // src/test-worker.ts
880
880
  import { parentPort } from "node:worker_threads";
881
881
 
882
+ // ../node_modules/uuid/dist-node/regex.js
883
+ var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
884
+
885
+ // ../node_modules/uuid/dist-node/validate.js
886
+ function validate(uuid) {
887
+ return typeof uuid === "string" && regex_default.test(uuid);
888
+ }
889
+ var validate_default = validate;
890
+
891
+ // ../node_modules/uuid/dist-node/parse.js
892
+ function parse(uuid) {
893
+ if (!validate_default(uuid)) {
894
+ throw TypeError("Invalid UUID");
895
+ }
896
+ let v;
897
+ return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
898
+ }
899
+ var parse_default = parse;
900
+
901
+ // ../node_modules/uuid/dist-node/stringify.js
902
+ var byteToHex = [];
903
+ for (let i = 0; i < 256; ++i) {
904
+ byteToHex.push((i + 256).toString(16).slice(1));
905
+ }
906
+ function unsafeStringify(arr, offset = 0) {
907
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
908
+ }
909
+
910
+ // ../node_modules/uuid/dist-node/rng.js
911
+ var rnds8 = new Uint8Array(16);
912
+ function rng() {
913
+ return crypto.getRandomValues(rnds8);
914
+ }
915
+
916
+ // ../node_modules/uuid/dist-node/v35.js
917
+ function stringToBytes(str) {
918
+ str = unescape(encodeURIComponent(str));
919
+ const bytes = new Uint8Array(str.length);
920
+ for (let i = 0; i < str.length; ++i) {
921
+ bytes[i] = str.charCodeAt(i);
922
+ }
923
+ return bytes;
924
+ }
925
+ var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
926
+ var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
927
+ function v35(version, hash, value, namespace, buf, offset) {
928
+ const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
929
+ const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
930
+ if (typeof namespace === "string") {
931
+ namespace = parse_default(namespace);
932
+ }
933
+ if (namespace?.length !== 16) {
934
+ throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
935
+ }
936
+ let bytes = new Uint8Array(16 + valueBytes.length);
937
+ bytes.set(namespaceBytes);
938
+ bytes.set(valueBytes, namespaceBytes.length);
939
+ bytes = hash(bytes);
940
+ bytes[6] = bytes[6] & 15 | version;
941
+ bytes[8] = bytes[8] & 63 | 128;
942
+ if (buf) {
943
+ offset ??= 0;
944
+ if (offset < 0 || offset + 16 > buf.length) {
945
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
946
+ }
947
+ for (let i = 0; i < 16; ++i) {
948
+ buf[offset + i] = bytes[i];
949
+ }
950
+ return buf;
951
+ }
952
+ return unsafeStringify(bytes);
953
+ }
954
+
955
+ // ../node_modules/uuid/dist-node/v4.js
956
+ function v4(options, buf, offset) {
957
+ if (!buf && !options && crypto.randomUUID) {
958
+ return crypto.randomUUID();
959
+ }
960
+ return _v4(options, buf, offset);
961
+ }
962
+ function _v4(options, buf, offset) {
963
+ options = options || {};
964
+ const rnds = options.random ?? options.rng?.() ?? rng();
965
+ if (rnds.length < 16) {
966
+ throw new Error("Random bytes length must be >= 16");
967
+ }
968
+ rnds[6] = rnds[6] & 15 | 64;
969
+ rnds[8] = rnds[8] & 63 | 128;
970
+ if (buf) {
971
+ offset = offset || 0;
972
+ if (offset < 0 || offset + 16 > buf.length) {
973
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
974
+ }
975
+ for (let i = 0; i < 16; ++i) {
976
+ buf[offset + i] = rnds[i];
977
+ }
978
+ return buf;
979
+ }
980
+ return unsafeStringify(rnds);
981
+ }
982
+ var v4_default = v4;
983
+
984
+ // ../node_modules/uuid/dist-node/sha1.js
985
+ import { createHash } from "node:crypto";
986
+ function sha1(bytes) {
987
+ if (Array.isArray(bytes)) {
988
+ bytes = Buffer.from(bytes);
989
+ } else if (typeof bytes === "string") {
990
+ bytes = Buffer.from(bytes, "utf8");
991
+ }
992
+ return createHash("sha1").update(bytes).digest();
993
+ }
994
+ var sha1_default = sha1;
995
+
996
+ // ../node_modules/uuid/dist-node/v5.js
997
+ function v5(value, namespace, buf, offset) {
998
+ return v35(80, sha1_default, value, namespace, buf, offset);
999
+ }
1000
+ v5.DNS = DNS;
1001
+ v5.URL = URL2;
1002
+ var v5_default = v5;
1003
+
1004
+ // ../packages/models/src/core/world-system-kinds.generated.ts
1005
+ var NeoWorldSystemClassKind = {
1006
+ CellPattern: "cellPattern",
1007
+ TileGrid: "tileGrid",
1008
+ SortingLayer: "sortingLayer",
1009
+ TileLayer: "tileLayer",
1010
+ ObjectLayer: "objectLayer",
1011
+ Tile: "tile",
1012
+ ObjectBase: "objectBase",
1013
+ ObjectCollider: "objectCollider",
1014
+ SortingGroup: "sortingGroup",
1015
+ LayerGroupBase: "layerGroupBase",
1016
+ SpriteObject: "spriteObject",
1017
+ PlacementTile: "placementTile",
1018
+ TileLayerLink: "tileLayerLink",
1019
+ ObjectLayerLink: "objectLayerLink",
1020
+ Object: "object",
1021
+ SmartTile: "smartTile",
1022
+ SmartTileRule: "smartTileRule",
1023
+ SmartTileNeighbor: "smartTileNeighbor",
1024
+ AnimationFrameBase: "animationFrameBase",
1025
+ AnimationClip: "animationClip",
1026
+ AnimationFrame: "animationFrame",
1027
+ AnimationSegmentFrame: "animationSegmentFrame",
1028
+ AnimationSegment: "animationSegment",
1029
+ SpriteAnimationSegment: "spriteAnimationSegment",
1030
+ AnimationChildOverride: "animationChildOverride",
1031
+ AnimationTrack: "animationTrack",
1032
+ AnimationChildTrack: "animationChildTrack",
1033
+ AnimationSegmentTrack: "animationSegmentTrack",
1034
+ SpriteAnimationSegmentTrack: "spriteAnimationSegmentTrack",
1035
+ Variant: "variant",
1036
+ VariantFolder: "variantFolder",
1037
+ LookupVariant: "lookupVariant",
1038
+ LookupVariantFolder: "lookupVariantFolder"
1039
+ };
1040
+ var NEO_WORLD_SYSTEM_CLASS_KIND_VALUES = new Set(
1041
+ Object.values(NeoWorldSystemClassKind)
1042
+ );
1043
+ function isNeoWorldSystemClassKind(value) {
1044
+ if (typeof value !== "string") return false;
1045
+ return NEO_WORLD_SYSTEM_CLASS_KIND_VALUES.has(value);
1046
+ }
1047
+
1048
+ // ../packages/models/src/core/core-types.ts
1049
+ var SystemDisallowedOperation = {
1050
+ /**
1051
+ * Blocks project-author edits to the record's schema/configuration.
1052
+ */
1053
+ EditRecord: "editRecord",
1054
+ /**
1055
+ * Blocks project-author deletion of the record.
1056
+ */
1057
+ DeleteRecord: "deleteRecord",
1058
+ /**
1059
+ * Removes the record from normal creation/selection affordances.
1060
+ */
1061
+ SelectRecord: "selectRecord",
1062
+ /**
1063
+ * Blocks replacing the value row attached to a member as a whole.
1064
+ */
1065
+ ReplaceValue: "replaceValue"
1066
+ };
1067
+ var SystemProtectionKind = {
1068
+ WorldAuthoring: "worldAuthoring",
1069
+ DialogueMemorySchema: "dialogueMemorySchema",
1070
+ DialogueMemoryContainer: "dialogueMemoryContainer",
1071
+ DialoguePriorityDefault: "dialoguePriorityDefault",
1072
+ PolicyImmutable: "policyImmutable",
1073
+ PolicyDeleteBlocked: "policyDeleteBlocked",
1074
+ ScriptRuntime: "scriptRuntime"
1075
+ };
1076
+ function isWithId(value) {
1077
+ return typeof value?.id === "string";
1078
+ }
1079
+ function isIWithTimestamps(value) {
1080
+ const v = value;
1081
+ if (v === null || v === void 0) {
1082
+ return false;
1083
+ }
1084
+ return isEpochMillis(v.createdAt) && isEpochMillis(v.updatedAt);
1085
+ }
1086
+ function isEpochMillis(value) {
1087
+ if (typeof value !== "number") return false;
1088
+ return Number.isFinite(value);
1089
+ }
1090
+ function isSystemProtectionKind(value) {
1091
+ return value === SystemProtectionKind.WorldAuthoring || value === SystemProtectionKind.DialogueMemorySchema || value === SystemProtectionKind.DialogueMemoryContainer || value === SystemProtectionKind.DialoguePriorityDefault || value === SystemProtectionKind.PolicyImmutable || value === SystemProtectionKind.PolicyDeleteBlocked || value === SystemProtectionKind.ScriptRuntime;
1092
+ }
1093
+ function isSystemMetadata(value) {
1094
+ const v = value;
1095
+ if (typeof v !== "object") return false;
1096
+ if (v === null) return false;
1097
+ if (!isSystemProtectionKind(v.kind)) return false;
1098
+ if (v.worldKind !== void 0 && v.worldKind !== null) {
1099
+ return isNeoWorldSystemClassKind(v.worldKind);
1100
+ }
1101
+ return true;
1102
+ }
1103
+ function isWithName(value) {
1104
+ return typeof value?.name === "string";
1105
+ }
1106
+
1107
+ // ../packages/models/src/core/auth-ownership-types.ts
1108
+ var ActorKind = {
1109
+ /**
1110
+ * `better-auth` user identities.
1111
+ */
1112
+ user: "user",
1113
+ /**
1114
+ * `better-auth` organization identities.
1115
+ */
1116
+ organization: "organization",
1117
+ /**
1118
+ * Used for denoting records created by a system.
1119
+ */
1120
+ system: "system"
1121
+ };
1122
+ function isActorIdentifier(value) {
1123
+ if (typeof value !== "object") return false;
1124
+ if (value === null) return false;
1125
+ const candidate = value;
1126
+ if (!isActorKind(candidate.kind)) return false;
1127
+ return typeof candidate.id === "string" && candidate.id.trim().length > 0;
1128
+ }
1129
+ function isActorKind(value) {
1130
+ return value === ActorKind.user || value === ActorKind.organization || value === ActorKind.system;
1131
+ }
1132
+
1133
+ // ../packages/models/src/core/structural-narrow.ts
1134
+ function isObject(value) {
1135
+ if (typeof value !== "object") return false;
1136
+ return value !== null;
1137
+ }
1138
+ function hasField(value, field) {
1139
+ if (!isObject(value)) return false;
1140
+ return field in value;
1141
+ }
1142
+ function getOptionalString(value, field) {
1143
+ if (!hasField(value, field)) return void 0;
1144
+ const v = value[field];
1145
+ if (typeof v !== "string") return void 0;
1146
+ return v;
1147
+ }
1148
+ function getField(value, field) {
1149
+ if (!hasField(value, field)) return void 0;
1150
+ return value[field];
1151
+ }
1152
+ function isOptionalNullableType(value, isType) {
1153
+ if (value === null || value === void 0) return true;
1154
+ return isType(value);
1155
+ }
1156
+ function isNullableType(value, isType) {
1157
+ if (value === null) return true;
1158
+ return isType(value);
1159
+ }
1160
+ function isRequiredType(value, isType) {
1161
+ if (value === null || value === void 0) return false;
1162
+ return isType(value);
1163
+ }
1164
+ function isString(value) {
1165
+ return typeof value === "string";
1166
+ }
1167
+ function isNumber(value) {
1168
+ return typeof value === "number";
1169
+ }
1170
+ function isFiniteNumberGreaterThanOrEqualToZero(value) {
1171
+ if (!isNumber(value)) return false;
1172
+ if (!Number.isFinite(value)) return false;
1173
+ return value >= 0;
1174
+ }
1175
+ function isBoolean(value) {
1176
+ return typeof value === "boolean";
1177
+ }
1178
+ function isOptionalNullableString(value) {
1179
+ return isOptionalNullableType(value, isString);
1180
+ }
1181
+ function isNullableFiniteNumberGreaterThanOrEqualToZero(value) {
1182
+ return isNullableType(value, isFiniteNumberGreaterThanOrEqualToZero);
1183
+ }
1184
+ function setOwnField(record4, key, value) {
1185
+ Object.defineProperty(record4, key, {
1186
+ value,
1187
+ enumerable: true,
1188
+ configurable: true,
1189
+ writable: true
1190
+ });
1191
+ }
1192
+
1193
+ // ../packages/models/src/common/collections.ts
1194
+ function indexById(records2) {
1195
+ const indexed = /* @__PURE__ */ new Map();
1196
+ for (const record4 of records2) indexed.set(record4.id, record4);
1197
+ return indexed;
1198
+ }
1199
+ function setsEqual(left, right) {
1200
+ if (left === right) return true;
1201
+ if (left.size !== right.size) return false;
1202
+ for (const value of left) {
1203
+ if (!right.has(value)) return false;
1204
+ }
1205
+ return true;
1206
+ }
1207
+ async function forEachConcurrently(items, limit, work) {
1208
+ const queue = items[Symbol.iterator]();
1209
+ await Promise.all(
1210
+ Array.from({ length: limit }, async () => {
1211
+ for (let next = queue.next(); next.done !== true; next = queue.next()) {
1212
+ await work(next.value);
1213
+ }
1214
+ })
1215
+ );
1216
+ }
1217
+
1218
+ // ../packages/models/src/docs-text.ts
1219
+ var DOCS_TEXT_MAX_UTF8_BYTES = 16384;
1220
+ var textEncoder = new TextEncoder();
1221
+ function isValidDocsText(value) {
1222
+ if (value === void 0) return true;
1223
+ if (typeof value !== "string") return false;
1224
+ return textEncoder.encode(value).byteLength <= DOCS_TEXT_MAX_UTF8_BYTES;
1225
+ }
1226
+
882
1227
  // ../packages/models/src/members/member-storage.ts
883
1228
  function isMemberStorageKind(value) {
884
1229
  return value === 0 /* Inherit */ || value === 1 /* Immutable */ || value === 2 /* Save */ || value === 3 /* Session */ || value === 4 /* Writable */ || value === 5 /* User */;
@@ -923,6 +1268,198 @@ function createWritableAncestorLookup(memberById) {
923
1268
  return lookup;
924
1269
  }
925
1270
 
1271
+ // ../packages/models/src/classes/classes.ts
1272
+ function isAbstractClass(value) {
1273
+ return value?.modifier === 1 /* Abstract */;
1274
+ }
1275
+ function isGenericParamConstraint(value) {
1276
+ const v = value;
1277
+ if (!v || typeof v !== "object") return false;
1278
+ if (v.kind === void 0 || v.kind === 0 /* Class */) {
1279
+ if (typeof v.classId !== "string") return false;
1280
+ if (v.classId.length === 0) return false;
1281
+ if (v.enumId !== void 0) return false;
1282
+ const argumentsValue = v.classArguments;
1283
+ return argumentsValue === void 0 || isGenericBindingsRecord(argumentsValue);
1284
+ }
1285
+ if (v.kind === 1 /* Enum */) {
1286
+ if (typeof v.enumId !== "string") return false;
1287
+ if (v.enumId.length === 0) return false;
1288
+ return v.classId === void 0;
1289
+ }
1290
+ return false;
1291
+ }
1292
+ function isClassGenericConstraint(value) {
1293
+ return value.kind === void 0 || value.kind === 0 /* Class */;
1294
+ }
1295
+ function isEnumGenericConstraint(value) {
1296
+ return value.kind === 1 /* Enum */;
1297
+ }
1298
+ function isGenericParamDeclaration(value) {
1299
+ const v = value;
1300
+ if (!v || typeof v !== "object") return false;
1301
+ if (typeof v.id !== "string") return false;
1302
+ if (v.id.length === 0) return false;
1303
+ if (typeof v.name !== "string") return false;
1304
+ if (v.name.length === 0) return false;
1305
+ if (v.constraint === void 0) return true;
1306
+ return isGenericParamConstraint(v.constraint);
1307
+ }
1308
+ function isGenericBinding(value) {
1309
+ const v = value;
1310
+ if (!v || typeof v !== "object") return false;
1311
+ if (Object.hasOwn(v, "defaultValue")) return false;
1312
+ if (v.kind === void 0 || v.kind === 0 /* Generic */) {
1313
+ if (typeof v.genericParamId !== "string") return false;
1314
+ if (v.genericParamId.length === 0) return false;
1315
+ return v.memberId === void 0;
1316
+ }
1317
+ if (v.kind === 1 /* Member */) {
1318
+ if (typeof v.memberId !== "string") return false;
1319
+ if (v.memberId.length === 0) return false;
1320
+ return v.genericParamId === void 0;
1321
+ }
1322
+ return false;
1323
+ }
1324
+ function isForwardedGenericBinding(value) {
1325
+ return value.kind === void 0 || value.kind === 0 /* Generic */;
1326
+ }
1327
+ function isMemberGenericBinding(value) {
1328
+ return value.kind === 1 /* Member */;
1329
+ }
1330
+ function isGenericBindingsRecord(value) {
1331
+ if (value === null) return false;
1332
+ if (typeof value !== "object") return false;
1333
+ if (Array.isArray(value)) return false;
1334
+ return Object.values(value).every(isGenericBinding);
1335
+ }
1336
+ var RETIRED_CONSTRUCTOR_PROJECTIONS_FIELD = "constructorProjections";
1337
+ function hasRetiredConstructorProjectionsTombstone(value) {
1338
+ return value !== null && typeof value === "object" && Object.hasOwn(value, RETIRED_CONSTRUCTOR_PROJECTIONS_FIELD);
1339
+ }
1340
+ function isNeoSchemaClassBase(value) {
1341
+ if (hasRetiredConstructorProjectionsTombstone(value)) {
1342
+ return false;
1343
+ }
1344
+ const v = value;
1345
+ return typeof v?.name === "string" && isValidDocsText(v.docsText) && isClassSchema(v?.schema) && isOptionalSchemaKeyOrder(v?.schemaKeyOrder) && (v.implementsInterfaceIds === void 0 || Array.isArray(v.implementsInterfaceIds) && v.implementsInterfaceIds.every(
1346
+ (interfaceId) => typeof interfaceId === "string" && interfaceId.length > 0
1347
+ )) && (v.uiVisibility === void 0 || v.uiVisibility === 0 /* Visible */ || v.uiVisibility === 1 /* Hidden */) && (v.modifier === void 0 || v.modifier === 0 /* Open */ || v.modifier === 1 /* Abstract */ || v.modifier === 2 /* Sealed */) && (v.allowedStorage === void 0 || isClassAllowedStorage(v.allowedStorage)) && (v.allowedStorageKeys === void 0 || Array.isArray(v.allowedStorageKeys) && v.allowedStorageKeys.every((key) => typeof key === "string")) && (v.genericParams === void 0 || Array.isArray(v.genericParams) && v.genericParams.every(isGenericParamDeclaration)) && (v.extendsGenericBindings === void 0 || isGenericBindingsRecord(v.extendsGenericBindings)) && (v.constructorIds === void 0 || Array.isArray(v.constructorIds) && v.constructorIds.every(
1348
+ (constructorId) => typeof constructorId === "string" && constructorId.length > 0
1349
+ ) && new Set(v.constructorIds).size === v.constructorIds.length) && (v.requiredConstructorId === void 0 || typeof v.requiredConstructorId === "string" && v.requiredConstructorId.length > 0 && (v.constructorIds ?? []).length === 0) && (v.targetMemberId === void 0 || typeof v.targetMemberId === "string" && v.targetMemberId.length > 0) && (v.system === void 0 || isSystemMetadata(v.system));
1350
+ }
1351
+ function resolveAllowedStorage(classId, classes, draft) {
1352
+ const visited = /* @__PURE__ */ new Set();
1353
+ const lookup = (id) => draft && draft.id === id ? draft : classes.find((candidate) => candidate.id === id);
1354
+ let current = lookup(classId);
1355
+ while (current) {
1356
+ if (visited.has(current.id)) return null;
1357
+ visited.add(current.id);
1358
+ if (current.allowedStorage != null) return current.allowedStorage;
1359
+ if (!current.extendsClassId) return null;
1360
+ current = lookup(current.extendsClassId);
1361
+ }
1362
+ return null;
1363
+ }
1364
+ function classInheritsWorldKind(classId, expectedKind, classesById) {
1365
+ let current = classesById.get(classId);
1366
+ for (let remaining = classesById.size; current !== void 0 && remaining > 0; remaining--) {
1367
+ if (current.system?.worldKind === expectedKind) return true;
1368
+ current = current.extendsClassId ? classesById.get(current.extendsClassId) : void 0;
1369
+ }
1370
+ return false;
1371
+ }
1372
+ function resolveWorldSystemClassKind(classId, classes, draft) {
1373
+ const visited = /* @__PURE__ */ new Set();
1374
+ const lookup = (id) => draft && draft.id === id ? draft : classes.find((candidate) => candidate.id === id);
1375
+ let current = lookup(classId);
1376
+ while (current) {
1377
+ if (visited.has(current.id)) return null;
1378
+ visited.add(current.id);
1379
+ if (current.system?.worldKind != null) return current.system.worldKind;
1380
+ if (!current.extendsClassId) return null;
1381
+ current = lookup(current.extendsClassId);
1382
+ }
1383
+ return null;
1384
+ }
1385
+ function indexWorldSystemClassKinds(classes, classesById = indexById(classes)) {
1386
+ const kinds = /* @__PURE__ */ new Map();
1387
+ for (const schemaClass2 of classes) {
1388
+ if (schemaClass2.system?.worldKind != null) {
1389
+ kinds.set(schemaClass2.id, schemaClass2.system.worldKind);
1390
+ } else if (schemaClass2.extendsClassId === void 0) {
1391
+ kinds.set(schemaClass2.id, null);
1392
+ }
1393
+ }
1394
+ const resolving = /* @__PURE__ */ new Set();
1395
+ for (const schemaClass2 of classes) {
1396
+ if (kinds.has(schemaClass2.id)) continue;
1397
+ const path = [];
1398
+ let current = schemaClass2;
1399
+ let resolved = null;
1400
+ while (current !== void 0) {
1401
+ if (kinds.has(current.id)) {
1402
+ resolved = kinds.get(current.id) ?? null;
1403
+ break;
1404
+ }
1405
+ if (resolving.has(current.id)) {
1406
+ resolved = null;
1407
+ break;
1408
+ }
1409
+ resolving.add(current.id);
1410
+ path.push(current);
1411
+ current = current.extendsClassId === void 0 ? void 0 : classesById.get(current.extendsClassId);
1412
+ }
1413
+ for (const candidate of path) {
1414
+ resolving.delete(candidate.id);
1415
+ kinds.set(candidate.id, resolved);
1416
+ }
1417
+ }
1418
+ return kinds;
1419
+ }
1420
+ function dedupeSchemaKeyOrder(order) {
1421
+ const seen = /* @__PURE__ */ new Set();
1422
+ const result = [];
1423
+ for (const schemaKey of order) {
1424
+ if (seen.has(schemaKey)) continue;
1425
+ seen.add(schemaKey);
1426
+ result.push(schemaKey);
1427
+ }
1428
+ return result;
1429
+ }
1430
+ function getClassSchemaKeyOrder(schemaClass2) {
1431
+ const schemaKeys = Object.keys(schemaClass2.schema);
1432
+ if (schemaClass2.schemaKeyOrder === void 0) return schemaKeys;
1433
+ const orderedKeys2 = dedupeSchemaKeyOrder(schemaClass2.schemaKeyOrder);
1434
+ const seen = new Set(orderedKeys2);
1435
+ for (const schemaKey of schemaKeys) {
1436
+ if (seen.has(schemaKey)) continue;
1437
+ seen.add(schemaKey);
1438
+ orderedKeys2.push(schemaKey);
1439
+ }
1440
+ return orderedKeys2;
1441
+ }
1442
+ function isClassSchema(value) {
1443
+ if (value === null) return false;
1444
+ if (typeof value !== "object") return false;
1445
+ if (Array.isArray(value)) return false;
1446
+ return Object.values(value).every(
1447
+ (schemaValue) => typeof schemaValue === "string"
1448
+ );
1449
+ }
1450
+ function isOptionalSchemaKeyOrder(value) {
1451
+ if (value === void 0) return true;
1452
+ if (!Array.isArray(value)) return false;
1453
+ return value.every((key) => typeof key === "string");
1454
+ }
1455
+ function isNeoSchemaClassProps(value) {
1456
+ const v = value;
1457
+ return isNeoSchemaClassBase(value) && typeof v?.id === "string" && isEpochMillis(v?.createdAt) && isEpochMillis(v?.updatedAt) && typeof v?.projectId === "string";
1458
+ }
1459
+ function isNeoSchemaClass(value) {
1460
+ return isNeoSchemaClassProps(value);
1461
+ }
1462
+
926
1463
  // ../packages/models/src/members/member-kind-enum.ts
927
1464
  var MemberKind = /* @__PURE__ */ ((MemberKind8) => {
928
1465
  MemberKind8[MemberKind8["Null"] = 0] = "Null";
@@ -1125,128 +1662,6 @@ function memberKindSupportsDistribution(kind) {
1125
1662
  return memberKindSupportsStorage(kind);
1126
1663
  }
1127
1664
 
1128
- // ../node_modules/uuid/dist-node/regex.js
1129
- var regex_default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/i;
1130
-
1131
- // ../node_modules/uuid/dist-node/validate.js
1132
- function validate(uuid) {
1133
- return typeof uuid === "string" && regex_default.test(uuid);
1134
- }
1135
- var validate_default = validate;
1136
-
1137
- // ../node_modules/uuid/dist-node/parse.js
1138
- function parse(uuid) {
1139
- if (!validate_default(uuid)) {
1140
- throw TypeError("Invalid UUID");
1141
- }
1142
- let v;
1143
- return Uint8Array.of((v = parseInt(uuid.slice(0, 8), 16)) >>> 24, v >>> 16 & 255, v >>> 8 & 255, v & 255, (v = parseInt(uuid.slice(9, 13), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(14, 18), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(19, 23), 16)) >>> 8, v & 255, (v = parseInt(uuid.slice(24, 36), 16)) / 1099511627776 & 255, v / 4294967296 & 255, v >>> 24 & 255, v >>> 16 & 255, v >>> 8 & 255, v & 255);
1144
- }
1145
- var parse_default = parse;
1146
-
1147
- // ../node_modules/uuid/dist-node/stringify.js
1148
- var byteToHex = [];
1149
- for (let i = 0; i < 256; ++i) {
1150
- byteToHex.push((i + 256).toString(16).slice(1));
1151
- }
1152
- function unsafeStringify(arr, offset = 0) {
1153
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
1154
- }
1155
-
1156
- // ../node_modules/uuid/dist-node/rng.js
1157
- var rnds8 = new Uint8Array(16);
1158
- function rng() {
1159
- return crypto.getRandomValues(rnds8);
1160
- }
1161
-
1162
- // ../node_modules/uuid/dist-node/v35.js
1163
- function stringToBytes(str) {
1164
- str = unescape(encodeURIComponent(str));
1165
- const bytes = new Uint8Array(str.length);
1166
- for (let i = 0; i < str.length; ++i) {
1167
- bytes[i] = str.charCodeAt(i);
1168
- }
1169
- return bytes;
1170
- }
1171
- var DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
1172
- var URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
1173
- function v35(version, hash, value, namespace, buf, offset) {
1174
- const valueBytes = typeof value === "string" ? stringToBytes(value) : value;
1175
- const namespaceBytes = typeof namespace === "string" ? parse_default(namespace) : namespace;
1176
- if (typeof namespace === "string") {
1177
- namespace = parse_default(namespace);
1178
- }
1179
- if (namespace?.length !== 16) {
1180
- throw TypeError("Namespace must be array-like (16 iterable integer values, 0-255)");
1181
- }
1182
- let bytes = new Uint8Array(16 + valueBytes.length);
1183
- bytes.set(namespaceBytes);
1184
- bytes.set(valueBytes, namespaceBytes.length);
1185
- bytes = hash(bytes);
1186
- bytes[6] = bytes[6] & 15 | version;
1187
- bytes[8] = bytes[8] & 63 | 128;
1188
- if (buf) {
1189
- offset ??= 0;
1190
- if (offset < 0 || offset + 16 > buf.length) {
1191
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1192
- }
1193
- for (let i = 0; i < 16; ++i) {
1194
- buf[offset + i] = bytes[i];
1195
- }
1196
- return buf;
1197
- }
1198
- return unsafeStringify(bytes);
1199
- }
1200
-
1201
- // ../node_modules/uuid/dist-node/v4.js
1202
- function v4(options, buf, offset) {
1203
- if (!buf && !options && crypto.randomUUID) {
1204
- return crypto.randomUUID();
1205
- }
1206
- return _v4(options, buf, offset);
1207
- }
1208
- function _v4(options, buf, offset) {
1209
- options = options || {};
1210
- const rnds = options.random ?? options.rng?.() ?? rng();
1211
- if (rnds.length < 16) {
1212
- throw new Error("Random bytes length must be >= 16");
1213
- }
1214
- rnds[6] = rnds[6] & 15 | 64;
1215
- rnds[8] = rnds[8] & 63 | 128;
1216
- if (buf) {
1217
- offset = offset || 0;
1218
- if (offset < 0 || offset + 16 > buf.length) {
1219
- throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
1220
- }
1221
- for (let i = 0; i < 16; ++i) {
1222
- buf[offset + i] = rnds[i];
1223
- }
1224
- return buf;
1225
- }
1226
- return unsafeStringify(rnds);
1227
- }
1228
- var v4_default = v4;
1229
-
1230
- // ../node_modules/uuid/dist-node/sha1.js
1231
- import { createHash } from "node:crypto";
1232
- function sha1(bytes) {
1233
- if (Array.isArray(bytes)) {
1234
- bytes = Buffer.from(bytes);
1235
- } else if (typeof bytes === "string") {
1236
- bytes = Buffer.from(bytes, "utf8");
1237
- }
1238
- return createHash("sha1").update(bytes).digest();
1239
- }
1240
- var sha1_default = sha1;
1241
-
1242
- // ../node_modules/uuid/dist-node/v5.js
1243
- function v5(value, namespace, buf, offset) {
1244
- return v35(80, sha1_default, value, namespace, buf, offset);
1245
- }
1246
- v5.DNS = DNS;
1247
- v5.URL = URL2;
1248
- var v5_default = v5;
1249
-
1250
1665
  // ../packages/models/src/project/project-root-members.ts
1251
1666
  var PROJECT_ROOTS = [
1252
1667
  {
@@ -1295,178 +1710,6 @@ function projectRootMembersInDisplayOrder(project) {
1295
1710
  }));
1296
1711
  }
1297
1712
 
1298
- // ../packages/models/src/core/structural-narrow.ts
1299
- function isObject(value) {
1300
- if (typeof value !== "object") return false;
1301
- return value !== null;
1302
- }
1303
- function hasField(value, field) {
1304
- if (!isObject(value)) return false;
1305
- return field in value;
1306
- }
1307
- function getOptionalString(value, field) {
1308
- if (!hasField(value, field)) return void 0;
1309
- const v = value[field];
1310
- if (typeof v !== "string") return void 0;
1311
- return v;
1312
- }
1313
- function getField(value, field) {
1314
- if (!hasField(value, field)) return void 0;
1315
- return value[field];
1316
- }
1317
- function isOptionalNullableType(value, isType) {
1318
- if (value === null || value === void 0) return true;
1319
- return isType(value);
1320
- }
1321
- function isNullableType(value, isType) {
1322
- if (value === null) return true;
1323
- return isType(value);
1324
- }
1325
- function isRequiredType(value, isType) {
1326
- if (value === null || value === void 0) return false;
1327
- return isType(value);
1328
- }
1329
- function isString(value) {
1330
- return typeof value === "string";
1331
- }
1332
- function isNumber(value) {
1333
- return typeof value === "number";
1334
- }
1335
- function isFiniteNumberGreaterThanOrEqualToZero(value) {
1336
- if (!isNumber(value)) return false;
1337
- if (!Number.isFinite(value)) return false;
1338
- return value >= 0;
1339
- }
1340
- function isBoolean(value) {
1341
- return typeof value === "boolean";
1342
- }
1343
- function isOptionalNullableString(value) {
1344
- return isOptionalNullableType(value, isString);
1345
- }
1346
- function isNullableFiniteNumberGreaterThanOrEqualToZero(value) {
1347
- return isNullableType(value, isFiniteNumberGreaterThanOrEqualToZero);
1348
- }
1349
- function setOwnField(record4, key, value) {
1350
- Object.defineProperty(record4, key, {
1351
- value,
1352
- enumerable: true,
1353
- configurable: true,
1354
- writable: true
1355
- });
1356
- }
1357
-
1358
- // ../packages/models/src/core/world-system-kinds.generated.ts
1359
- var NeoWorldSystemClassKind = {
1360
- CellPattern: "cellPattern",
1361
- TileGrid: "tileGrid",
1362
- SortingLayer: "sortingLayer",
1363
- TileLayer: "tileLayer",
1364
- ObjectLayer: "objectLayer",
1365
- Tile: "tile",
1366
- ObjectBase: "objectBase",
1367
- ObjectCollider: "objectCollider",
1368
- SortingGroup: "sortingGroup",
1369
- LayerGroupBase: "layerGroupBase",
1370
- SpriteObject: "spriteObject",
1371
- PlacementTile: "placementTile",
1372
- TileLayerLink: "tileLayerLink",
1373
- ObjectLayerLink: "objectLayerLink",
1374
- Object: "object",
1375
- SmartTile: "smartTile",
1376
- SmartTileRule: "smartTileRule",
1377
- SmartTileNeighbor: "smartTileNeighbor",
1378
- AnimationFrameBase: "animationFrameBase",
1379
- AnimationClip: "animationClip",
1380
- AnimationFrame: "animationFrame",
1381
- AnimationSegmentFrame: "animationSegmentFrame",
1382
- AnimationSegment: "animationSegment",
1383
- SpriteAnimationSegment: "spriteAnimationSegment",
1384
- AnimationChildOverride: "animationChildOverride",
1385
- AnimationTrack: "animationTrack",
1386
- AnimationChildTrack: "animationChildTrack",
1387
- AnimationSegmentTrack: "animationSegmentTrack",
1388
- SpriteAnimationSegmentTrack: "spriteAnimationSegmentTrack",
1389
- Variant: "variant",
1390
- VariantFolder: "variantFolder",
1391
- LookupVariant: "lookupVariant",
1392
- LookupVariantFolder: "lookupVariantFolder"
1393
- };
1394
- var NEO_WORLD_SYSTEM_CLASS_KIND_VALUES = new Set(
1395
- Object.values(NeoWorldSystemClassKind)
1396
- );
1397
- function isNeoWorldSystemClassKind(value) {
1398
- if (typeof value !== "string") return false;
1399
- return NEO_WORLD_SYSTEM_CLASS_KIND_VALUES.has(value);
1400
- }
1401
-
1402
- // ../packages/models/src/core/core-types.ts
1403
- var SystemDisallowedOperation = {
1404
- /**
1405
- * Blocks project-author edits to the record's schema/configuration.
1406
- */
1407
- EditRecord: "editRecord",
1408
- /**
1409
- * Blocks project-author deletion of the record.
1410
- */
1411
- DeleteRecord: "deleteRecord",
1412
- /**
1413
- * Removes the record from normal creation/selection affordances.
1414
- */
1415
- SelectRecord: "selectRecord",
1416
- /**
1417
- * Blocks replacing the value row attached to a member as a whole.
1418
- */
1419
- ReplaceValue: "replaceValue"
1420
- };
1421
- var SystemProtectionKind = {
1422
- WorldAuthoring: "worldAuthoring",
1423
- DialogueMemorySchema: "dialogueMemorySchema",
1424
- DialogueMemoryContainer: "dialogueMemoryContainer",
1425
- DialoguePriorityDefault: "dialoguePriorityDefault",
1426
- PolicyImmutable: "policyImmutable",
1427
- PolicyDeleteBlocked: "policyDeleteBlocked",
1428
- ScriptRuntime: "scriptRuntime"
1429
- };
1430
- function isWithId(value) {
1431
- return typeof value?.id === "string";
1432
- }
1433
- function isIWithTimestamps(value) {
1434
- const v = value;
1435
- if (v === null || v === void 0) {
1436
- return false;
1437
- }
1438
- return isEpochMillis(v.createdAt) && isEpochMillis(v.updatedAt);
1439
- }
1440
- function isEpochMillis(value) {
1441
- if (typeof value !== "number") return false;
1442
- return Number.isFinite(value);
1443
- }
1444
- function isSystemProtectionKind(value) {
1445
- return value === SystemProtectionKind.WorldAuthoring || value === SystemProtectionKind.DialogueMemorySchema || value === SystemProtectionKind.DialogueMemoryContainer || value === SystemProtectionKind.DialoguePriorityDefault || value === SystemProtectionKind.PolicyImmutable || value === SystemProtectionKind.PolicyDeleteBlocked || value === SystemProtectionKind.ScriptRuntime;
1446
- }
1447
- function isSystemMetadata(value) {
1448
- const v = value;
1449
- if (typeof v !== "object") return false;
1450
- if (v === null) return false;
1451
- if (!isSystemProtectionKind(v.kind)) return false;
1452
- if (v.worldKind !== void 0 && v.worldKind !== null) {
1453
- return isNeoWorldSystemClassKind(v.worldKind);
1454
- }
1455
- return true;
1456
- }
1457
- function isWithName(value) {
1458
- return typeof value?.name === "string";
1459
- }
1460
-
1461
- // ../packages/models/src/docs-text.ts
1462
- var DOCS_TEXT_MAX_UTF8_BYTES = 16384;
1463
- var textEncoder = new TextEncoder();
1464
- function isValidDocsText(value) {
1465
- if (value === void 0) return true;
1466
- if (typeof value !== "string") return false;
1467
- return textEncoder.encode(value).byteLength <= DOCS_TEXT_MAX_UTF8_BYTES;
1468
- }
1469
-
1470
1713
  // ../packages/models/src/members/float32.ts
1471
1714
  function isFloat32(value) {
1472
1715
  return typeof value === "number" && Number.isFinite(value) && Math.fround(value) === value;
@@ -1936,6 +2179,7 @@ var NEOSCRIPT_OPERATORS = [
1936
2179
  var STRING_TYPE2 = { kind: "primitive", name: "string" };
1937
2180
  var INT_TYPE2 = { kind: "primitive", name: "int" };
1938
2181
  var FLOAT_TYPE = { kind: "primitive", name: "float" };
2182
+ var DECIMAL_TYPE = { kind: "primitive", name: "decimal" };
1939
2183
  var BOOL_TYPE2 = { kind: "primitive", name: "bool" };
1940
2184
  var IMAGE_REF_TYPE = {
1941
2185
  kind: "primitive",
@@ -1945,6 +2189,7 @@ var SPRITE_INFO_TYPE = {
1945
2189
  kind: "primitive",
1946
2190
  name: "SpriteInfo"
1947
2191
  };
2192
+ var VECTOR2_TYPE = { kind: "primitive", name: "Vector2" };
1948
2193
  var FLOAT_OPTIONAL_TYPE = {
1949
2194
  kind: "primitive",
1950
2195
  name: "float",
@@ -2123,6 +2368,156 @@ var NEOSCRIPT_GLOBALS = [
2123
2368
  "Returns whether a dialogue pointer has been visited."
2124
2369
  )
2125
2370
  ];
2371
+ function scalarMethod(receiver, name, returnType, parameters, documentation) {
2372
+ return {
2373
+ id: `builtin:${receiver}:${name}`,
2374
+ name,
2375
+ kind: "method",
2376
+ type: returnType,
2377
+ returnType,
2378
+ parameters,
2379
+ documentation
2380
+ };
2381
+ }
2382
+ var NEOSCRIPT_SCALAR_METHODS = {
2383
+ string: [
2384
+ scalarMethod(
2385
+ "string",
2386
+ "Contains",
2387
+ BOOL_TYPE2,
2388
+ [parameter("substring", STRING_TYPE2)],
2389
+ "Returns true when the string contains the substring."
2390
+ ),
2391
+ scalarMethod(
2392
+ "string",
2393
+ "Replace",
2394
+ STRING_TYPE2,
2395
+ [parameter("search", STRING_TYPE2), parameter("replacement", STRING_TYPE2)],
2396
+ "Returns a new string with every non-overlapping occurrence replaced using ordinal, case-sensitive matching. An empty search throws an error."
2397
+ ),
2398
+ scalarMethod(
2399
+ "string",
2400
+ "ToLower",
2401
+ STRING_TYPE2,
2402
+ [],
2403
+ "Returns the string converted to lowercase."
2404
+ ),
2405
+ scalarMethod(
2406
+ "string",
2407
+ "ToUpper",
2408
+ STRING_TYPE2,
2409
+ [],
2410
+ "Returns the string converted to uppercase."
2411
+ ),
2412
+ scalarMethod(
2413
+ "string",
2414
+ "Trim",
2415
+ STRING_TYPE2,
2416
+ [],
2417
+ "Returns the string without leading and trailing whitespace."
2418
+ ),
2419
+ scalarMethod(
2420
+ "string",
2421
+ "StartsWith",
2422
+ BOOL_TYPE2,
2423
+ [parameter("prefix", STRING_TYPE2)],
2424
+ "Returns true when the string starts with the prefix."
2425
+ ),
2426
+ scalarMethod(
2427
+ "string",
2428
+ "EndsWith",
2429
+ BOOL_TYPE2,
2430
+ [parameter("suffix", STRING_TYPE2)],
2431
+ "Returns true when the string ends with the suffix."
2432
+ )
2433
+ ],
2434
+ decimal: [
2435
+ scalarMethod(
2436
+ "decimal",
2437
+ "ToFloat",
2438
+ FLOAT_TYPE,
2439
+ [],
2440
+ "Returns the nearest float to this decimal."
2441
+ ),
2442
+ scalarMethod(
2443
+ "decimal",
2444
+ "Round",
2445
+ DECIMAL_TYPE,
2446
+ [parameter("digits", INT_TYPE2)],
2447
+ "Returns this decimal rounded half-to-even to the given number of fractional digits."
2448
+ ),
2449
+ scalarMethod(
2450
+ "decimal",
2451
+ "Divide",
2452
+ DECIMAL_TYPE,
2453
+ [parameter("divisor", DECIMAL_TYPE), parameter("digits", INT_TYPE2)],
2454
+ "Returns this decimal divided by the divisor, rounded half-to-even to the given number of fractional digits."
2455
+ )
2456
+ ],
2457
+ float: [
2458
+ scalarMethod(
2459
+ "float",
2460
+ "ToDecimal",
2461
+ DECIMAL_TYPE,
2462
+ [parameter("digits", INT_TYPE2)],
2463
+ "Returns this float as a decimal with the given number of fractional digits."
2464
+ )
2465
+ ],
2466
+ ImageRef: [
2467
+ scalarMethod(
2468
+ "ImageRef",
2469
+ "Slice",
2470
+ SPRITE_INFO_TYPE,
2471
+ [parameter("index", INT_TYPE2)],
2472
+ "Returns the sprite at the given slice index of this image."
2473
+ )
2474
+ ]
2475
+ };
2476
+ var NEOSCRIPT_CLASS_ID_MEMBER = "Id";
2477
+ var NEOSCRIPT_ON_CHANGED_MEMBER = "OnChanged";
2478
+ var NEOSCRIPT_CLASS_ID_SYMBOL = property(
2479
+ "class",
2480
+ NEOSCRIPT_CLASS_ID_MEMBER,
2481
+ STRING_TYPE2,
2482
+ "The stable id of this class value."
2483
+ );
2484
+ function neoScriptScalarMethod(receiver, name) {
2485
+ return NEOSCRIPT_SCALAR_METHODS[receiver]?.find(
2486
+ (method2) => method2.name === name
2487
+ );
2488
+ }
2489
+ var NEOSCRIPT_PRIMITIVE_DERIVED_MEMBERS = {
2490
+ SpriteInfo: [
2491
+ property("SpriteInfo", "FileName", STRING_TYPE2, "Asset file name."),
2492
+ property("SpriteInfo", "Name", STRING_TYPE2, "Sprite name."),
2493
+ property("SpriteInfo", "Size", VECTOR2_TYPE, "Sprite size."),
2494
+ property("SpriteInfo", "Pivot", VECTOR2_TYPE, "Sprite pivot."),
2495
+ property(
2496
+ "SpriteInfo",
2497
+ "Slices",
2498
+ { kind: "list", elementType: SPRITE_INFO_TYPE, readOnly: true },
2499
+ "All slices in the source asset."
2500
+ )
2501
+ ],
2502
+ AudioClipInfo: [
2503
+ property("AudioClipInfo", "FileId", STRING_TYPE2, "Asset file id."),
2504
+ property("AudioClipInfo", "Name", STRING_TYPE2, "Audio clip name."),
2505
+ property(
2506
+ "AudioClipInfo",
2507
+ "DurationSeconds",
2508
+ FLOAT_OPTIONAL_TYPE,
2509
+ "Audio duration in seconds when known."
2510
+ )
2511
+ ],
2512
+ NeoDialogueReference: [
2513
+ property("NeoDialogueReference", "id", STRING_TYPE2, "Dialogue id.")
2514
+ ]
2515
+ };
2516
+ function neoScriptPrimitiveDerivedMember(receiver, name) {
2517
+ return NEOSCRIPT_PRIMITIVE_DERIVED_MEMBERS[receiver]?.find(
2518
+ (member) => member.name === name
2519
+ );
2520
+ }
2126
2521
  function property(owner, name, type, documentation, writable = false) {
2127
2522
  return {
2128
2523
  id: `builtin:${owner}:property:${name}`,
@@ -2187,53 +2582,21 @@ var NEOSCRIPT_BUILTIN_TYPE_SYMBOLS = [
2187
2582
  // `FileId` and `SliceIndex` come from the field table above — they are
2188
2583
  // the writable, addressable fields, not derived properties (D11).
2189
2584
  ...structuredLeafFieldProperties("SpriteInfo"),
2190
- property("SpriteInfo", "FileName", STRING_TYPE2, "Asset file name."),
2191
- property("SpriteInfo", "Name", STRING_TYPE2, "Sprite name."),
2192
- property(
2193
- "SpriteInfo",
2194
- "Size",
2195
- { kind: "named", typeId: "builtin:Vector2" },
2196
- "Sprite size."
2197
- ),
2198
- property(
2199
- "SpriteInfo",
2200
- "Pivot",
2201
- { kind: "named", typeId: "builtin:Vector2" },
2202
- "Sprite pivot."
2203
- ),
2204
- property(
2205
- "SpriteInfo",
2206
- "Slices",
2207
- {
2208
- kind: "list",
2209
- elementType: { kind: "named", typeId: "builtin:SpriteInfo" },
2210
- readOnly: true
2211
- },
2212
- "All slices in the source asset."
2213
- )
2585
+ ...NEOSCRIPT_PRIMITIVE_DERIVED_MEMBERS.SpriteInfo
2214
2586
  ]
2215
2587
  },
2216
2588
  {
2217
2589
  id: "builtin:AudioClipInfo",
2218
2590
  name: "AudioClipInfo",
2219
2591
  kind: "builtin",
2220
- members: [
2221
- property("AudioClipInfo", "FileId", STRING_TYPE2, "Asset file id."),
2222
- property("AudioClipInfo", "Name", STRING_TYPE2, "Audio clip name."),
2223
- property(
2224
- "AudioClipInfo",
2225
- "DurationSeconds",
2226
- FLOAT_OPTIONAL_TYPE,
2227
- "Audio duration in seconds when known."
2228
- )
2229
- ]
2592
+ members: NEOSCRIPT_PRIMITIVE_DERIVED_MEMBERS.AudioClipInfo
2230
2593
  },
2231
2594
  {
2232
2595
  id: "builtin:NeoDialogueReference",
2233
2596
  name: "NeoDialogueReference",
2234
2597
  kind: "builtin",
2235
2598
  members: [
2236
- property("NeoDialogueReference", "id", STRING_TYPE2, "Dialogue id."),
2599
+ ...NEOSCRIPT_PRIMITIVE_DERIVED_MEMBERS.NeoDialogueReference,
2237
2600
  ...neoScriptDialogueReferenceMethods("builtin:NeoDialogueReference")
2238
2601
  ]
2239
2602
  },
@@ -3776,223 +4139,6 @@ function typeInfosInvariantlyEqual(left, right) {
3776
4139
  return true;
3777
4140
  }
3778
4141
 
3779
- // ../packages/models/src/common/collections.ts
3780
- function indexById(records2) {
3781
- const indexed = /* @__PURE__ */ new Map();
3782
- for (const record4 of records2) indexed.set(record4.id, record4);
3783
- return indexed;
3784
- }
3785
- function setsEqual(left, right) {
3786
- if (left === right) return true;
3787
- if (left.size !== right.size) return false;
3788
- for (const value of left) {
3789
- if (!right.has(value)) return false;
3790
- }
3791
- return true;
3792
- }
3793
- async function forEachConcurrently(items, limit, work) {
3794
- const queue = items[Symbol.iterator]();
3795
- await Promise.all(
3796
- Array.from({ length: limit }, async () => {
3797
- for (let next = queue.next(); next.done !== true; next = queue.next()) {
3798
- await work(next.value);
3799
- }
3800
- })
3801
- );
3802
- }
3803
-
3804
- // ../packages/models/src/classes/classes.ts
3805
- function isAbstractClass(value) {
3806
- return value?.modifier === 1 /* Abstract */;
3807
- }
3808
- function isGenericParamConstraint(value) {
3809
- const v = value;
3810
- if (!v || typeof v !== "object") return false;
3811
- if (v.kind === void 0 || v.kind === 0 /* Class */) {
3812
- if (typeof v.classId !== "string") return false;
3813
- if (v.classId.length === 0) return false;
3814
- if (v.enumId !== void 0) return false;
3815
- const argumentsValue = v.classArguments;
3816
- return argumentsValue === void 0 || isGenericBindingsRecord(argumentsValue);
3817
- }
3818
- if (v.kind === 1 /* Enum */) {
3819
- if (typeof v.enumId !== "string") return false;
3820
- if (v.enumId.length === 0) return false;
3821
- return v.classId === void 0;
3822
- }
3823
- return false;
3824
- }
3825
- function isClassGenericConstraint(value) {
3826
- return value.kind === void 0 || value.kind === 0 /* Class */;
3827
- }
3828
- function isEnumGenericConstraint(value) {
3829
- return value.kind === 1 /* Enum */;
3830
- }
3831
- function isGenericParamDeclaration(value) {
3832
- const v = value;
3833
- if (!v || typeof v !== "object") return false;
3834
- if (typeof v.id !== "string") return false;
3835
- if (v.id.length === 0) return false;
3836
- if (typeof v.name !== "string") return false;
3837
- if (v.name.length === 0) return false;
3838
- if (v.constraint === void 0) return true;
3839
- return isGenericParamConstraint(v.constraint);
3840
- }
3841
- function isGenericBinding(value) {
3842
- const v = value;
3843
- if (!v || typeof v !== "object") return false;
3844
- if (Object.hasOwn(v, "defaultValue")) return false;
3845
- if (v.kind === void 0 || v.kind === 0 /* Generic */) {
3846
- if (typeof v.genericParamId !== "string") return false;
3847
- if (v.genericParamId.length === 0) return false;
3848
- return v.memberId === void 0;
3849
- }
3850
- if (v.kind === 1 /* Member */) {
3851
- if (typeof v.memberId !== "string") return false;
3852
- if (v.memberId.length === 0) return false;
3853
- return v.genericParamId === void 0;
3854
- }
3855
- return false;
3856
- }
3857
- function isForwardedGenericBinding(value) {
3858
- return value.kind === void 0 || value.kind === 0 /* Generic */;
3859
- }
3860
- function isMemberGenericBinding(value) {
3861
- return value.kind === 1 /* Member */;
3862
- }
3863
- function isGenericBindingsRecord(value) {
3864
- if (value === null) return false;
3865
- if (typeof value !== "object") return false;
3866
- if (Array.isArray(value)) return false;
3867
- return Object.values(value).every(isGenericBinding);
3868
- }
3869
- var RETIRED_CONSTRUCTOR_PROJECTIONS_FIELD = "constructorProjections";
3870
- function hasRetiredConstructorProjectionsTombstone(value) {
3871
- return value !== null && typeof value === "object" && Object.hasOwn(value, RETIRED_CONSTRUCTOR_PROJECTIONS_FIELD);
3872
- }
3873
- function isNeoSchemaClassBase(value) {
3874
- if (hasRetiredConstructorProjectionsTombstone(value)) {
3875
- return false;
3876
- }
3877
- const v = value;
3878
- return typeof v?.name === "string" && isValidDocsText(v.docsText) && isClassSchema(v?.schema) && isOptionalSchemaKeyOrder(v?.schemaKeyOrder) && (v.implementsInterfaceIds === void 0 || Array.isArray(v.implementsInterfaceIds) && v.implementsInterfaceIds.every(
3879
- (interfaceId) => typeof interfaceId === "string" && interfaceId.length > 0
3880
- )) && (v.uiVisibility === void 0 || v.uiVisibility === 0 /* Visible */ || v.uiVisibility === 1 /* Hidden */) && (v.modifier === void 0 || v.modifier === 0 /* Open */ || v.modifier === 1 /* Abstract */ || v.modifier === 2 /* Sealed */) && (v.allowedStorage === void 0 || isClassAllowedStorage(v.allowedStorage)) && (v.allowedStorageKeys === void 0 || Array.isArray(v.allowedStorageKeys) && v.allowedStorageKeys.every((key) => typeof key === "string")) && (v.genericParams === void 0 || Array.isArray(v.genericParams) && v.genericParams.every(isGenericParamDeclaration)) && (v.extendsGenericBindings === void 0 || isGenericBindingsRecord(v.extendsGenericBindings)) && (v.constructorIds === void 0 || Array.isArray(v.constructorIds) && v.constructorIds.every(
3881
- (constructorId) => typeof constructorId === "string" && constructorId.length > 0
3882
- ) && new Set(v.constructorIds).size === v.constructorIds.length) && (v.requiredConstructorId === void 0 || typeof v.requiredConstructorId === "string" && v.requiredConstructorId.length > 0 && (v.constructorIds ?? []).length === 0) && (v.targetMemberId === void 0 || typeof v.targetMemberId === "string" && v.targetMemberId.length > 0) && (v.system === void 0 || isSystemMetadata(v.system));
3883
- }
3884
- function resolveAllowedStorage(classId, classes, draft) {
3885
- const visited = /* @__PURE__ */ new Set();
3886
- const lookup = (id) => draft && draft.id === id ? draft : classes.find((candidate) => candidate.id === id);
3887
- let current = lookup(classId);
3888
- while (current) {
3889
- if (visited.has(current.id)) return null;
3890
- visited.add(current.id);
3891
- if (current.allowedStorage != null) return current.allowedStorage;
3892
- if (!current.extendsClassId) return null;
3893
- current = lookup(current.extendsClassId);
3894
- }
3895
- return null;
3896
- }
3897
- function classInheritsWorldKind(classId, expectedKind, classesById) {
3898
- let current = classesById.get(classId);
3899
- for (let remaining = classesById.size; current !== void 0 && remaining > 0; remaining--) {
3900
- if (current.system?.worldKind === expectedKind) return true;
3901
- current = current.extendsClassId ? classesById.get(current.extendsClassId) : void 0;
3902
- }
3903
- return false;
3904
- }
3905
- function resolveWorldSystemClassKind(classId, classes, draft) {
3906
- const visited = /* @__PURE__ */ new Set();
3907
- const lookup = (id) => draft && draft.id === id ? draft : classes.find((candidate) => candidate.id === id);
3908
- let current = lookup(classId);
3909
- while (current) {
3910
- if (visited.has(current.id)) return null;
3911
- visited.add(current.id);
3912
- if (current.system?.worldKind != null) return current.system.worldKind;
3913
- if (!current.extendsClassId) return null;
3914
- current = lookup(current.extendsClassId);
3915
- }
3916
- return null;
3917
- }
3918
- function indexWorldSystemClassKinds(classes, classesById = indexById(classes)) {
3919
- const kinds = /* @__PURE__ */ new Map();
3920
- for (const schemaClass2 of classes) {
3921
- if (schemaClass2.system?.worldKind != null) {
3922
- kinds.set(schemaClass2.id, schemaClass2.system.worldKind);
3923
- } else if (schemaClass2.extendsClassId === void 0) {
3924
- kinds.set(schemaClass2.id, null);
3925
- }
3926
- }
3927
- const resolving = /* @__PURE__ */ new Set();
3928
- for (const schemaClass2 of classes) {
3929
- if (kinds.has(schemaClass2.id)) continue;
3930
- const path = [];
3931
- let current = schemaClass2;
3932
- let resolved = null;
3933
- while (current !== void 0) {
3934
- if (kinds.has(current.id)) {
3935
- resolved = kinds.get(current.id) ?? null;
3936
- break;
3937
- }
3938
- if (resolving.has(current.id)) {
3939
- resolved = null;
3940
- break;
3941
- }
3942
- resolving.add(current.id);
3943
- path.push(current);
3944
- current = current.extendsClassId === void 0 ? void 0 : classesById.get(current.extendsClassId);
3945
- }
3946
- for (const candidate of path) {
3947
- resolving.delete(candidate.id);
3948
- kinds.set(candidate.id, resolved);
3949
- }
3950
- }
3951
- return kinds;
3952
- }
3953
- function dedupeSchemaKeyOrder(order) {
3954
- const seen = /* @__PURE__ */ new Set();
3955
- const result = [];
3956
- for (const schemaKey of order) {
3957
- if (seen.has(schemaKey)) continue;
3958
- seen.add(schemaKey);
3959
- result.push(schemaKey);
3960
- }
3961
- return result;
3962
- }
3963
- function getClassSchemaKeyOrder(schemaClass2) {
3964
- const schemaKeys = Object.keys(schemaClass2.schema);
3965
- if (schemaClass2.schemaKeyOrder === void 0) return schemaKeys;
3966
- const orderedKeys2 = dedupeSchemaKeyOrder(schemaClass2.schemaKeyOrder);
3967
- const seen = new Set(orderedKeys2);
3968
- for (const schemaKey of schemaKeys) {
3969
- if (seen.has(schemaKey)) continue;
3970
- seen.add(schemaKey);
3971
- orderedKeys2.push(schemaKey);
3972
- }
3973
- return orderedKeys2;
3974
- }
3975
- function isClassSchema(value) {
3976
- if (value === null) return false;
3977
- if (typeof value !== "object") return false;
3978
- if (Array.isArray(value)) return false;
3979
- return Object.values(value).every(
3980
- (schemaValue) => typeof schemaValue === "string"
3981
- );
3982
- }
3983
- function isOptionalSchemaKeyOrder(value) {
3984
- if (value === void 0) return true;
3985
- if (!Array.isArray(value)) return false;
3986
- return value.every((key) => typeof key === "string");
3987
- }
3988
- function isNeoSchemaClassProps(value) {
3989
- const v = value;
3990
- return isNeoSchemaClassBase(value) && typeof v?.id === "string" && isEpochMillis(v?.createdAt) && isEpochMillis(v?.updatedAt) && typeof v?.projectId === "string";
3991
- }
3992
- function isNeoSchemaClass(value) {
3993
- return isNeoSchemaClassProps(value);
3994
- }
3995
-
3996
4142
  // ../packages/models/src/members/structured-leaf-fields.ts
3997
4143
  var STRUCTURED_LEAF_FIELDS = {
3998
4144
  [11 /* Sprite */]: [
@@ -6288,32 +6434,6 @@ function referencedValueIdCandidates(value) {
6288
6434
  return [];
6289
6435
  }
6290
6436
 
6291
- // ../packages/models/src/core/auth-ownership-types.ts
6292
- var ActorKind = {
6293
- /**
6294
- * `better-auth` user identities.
6295
- */
6296
- user: "user",
6297
- /**
6298
- * `better-auth` organization identities.
6299
- */
6300
- organization: "organization",
6301
- /**
6302
- * Used for denoting records created by a system.
6303
- */
6304
- system: "system"
6305
- };
6306
- function isActorIdentifier(value) {
6307
- if (typeof value !== "object") return false;
6308
- if (value === null) return false;
6309
- const candidate = value;
6310
- if (!isActorKind(candidate.kind)) return false;
6311
- return typeof candidate.id === "string" && candidate.id.trim().length > 0;
6312
- }
6313
- function isActorKind(value) {
6314
- return value === ActorKind.user || value === ActorKind.organization || value === ActorKind.system;
6315
- }
6316
-
6317
6437
  // ../packages/models/src/members/member-change-listeners.ts
6318
6438
  function editChangeListenerSet(explicit, inherited, edit, options = { inheritedComplete: true }) {
6319
6439
  if (edit.kind === "reset") {
@@ -8534,6 +8654,16 @@ function firstUnboundParamId(env) {
8534
8654
  }
8535
8655
  return null;
8536
8656
  }
8657
+ function findGenericParamDeclaration(genericParamId, classes) {
8658
+ for (const schemaClass2 of classes) {
8659
+ for (const param of schemaClass2.genericParams ?? []) {
8660
+ if (param.id === genericParamId) {
8661
+ return { param, declaringClass: schemaClass2 };
8662
+ }
8663
+ }
8664
+ }
8665
+ return null;
8666
+ }
8537
8667
  function referencedGenericParams(member, members, seen = /* @__PURE__ */ new Set()) {
8538
8668
  const result = /* @__PURE__ */ new Set();
8539
8669
  collectReferencedGenericParams(member, members, seen, result);
@@ -8765,6 +8895,88 @@ function substituteNestedTypeInfo(typeInfo, env, members) {
8765
8895
  );
8766
8896
  });
8767
8897
  }
8898
+ function substituteInheritedCallableTypeInfo(typeInfo, env, classes, members) {
8899
+ return mapGenericTypeInfo(typeInfo, (generic) => {
8900
+ const entry = env.get(generic.genericParamId);
8901
+ if (entry === void 0) return generic;
8902
+ if (entry.kind === "unbound") {
8903
+ const forwarded = forwardedParamTypeInfo(entry.paramId, classes);
8904
+ return forwarded === null ? generic : { ...forwarded, required: generic.required };
8905
+ }
8906
+ const bound = openBindingTypeInfo(
8907
+ callableBindingMember(entry.memberId, generic.genericParamId, members),
8908
+ env,
8909
+ classes,
8910
+ members
8911
+ );
8912
+ return { ...bound, required: bound.required && generic.required };
8913
+ });
8914
+ }
8915
+ function forwardedParamTypeInfo(genericParamId, classes) {
8916
+ const declaration = findGenericParamDeclaration(genericParamId, classes);
8917
+ if (declaration === null) return null;
8918
+ return {
8919
+ type: 21 /* Generic */,
8920
+ required: true,
8921
+ ownerClassId: declaration.declaringClass.id,
8922
+ genericParamId
8923
+ };
8924
+ }
8925
+ function openBindingTypeInfo(member, env, classes, members) {
8926
+ const resolved = resolveMember(member, members);
8927
+ const nested = (memberId) => openBindingTypeInfo(
8928
+ callableBindingMember(memberId, resolved.name, members),
8929
+ env,
8930
+ classes,
8931
+ members
8932
+ );
8933
+ const param = (genericParamId) => {
8934
+ const entry = env.get(genericParamId);
8935
+ if (entry?.kind === "member") return nested(entry.memberId);
8936
+ if (entry?.kind === "unbound") {
8937
+ return forwardedParamTypeInfo(entry.paramId, classes);
8938
+ }
8939
+ return null;
8940
+ };
8941
+ if (isMemberGenericBase(resolved)) {
8942
+ return param(resolved.genericParamId) ?? genericBindingTypeInfo(resolved, env, members);
8943
+ }
8944
+ const required = isRequiredMember(resolved);
8945
+ if (isMemberClassBase(resolved)) {
8946
+ const typeArguments = {};
8947
+ for (const [parameterId, argument2] of Object.entries(
8948
+ resolved.classArguments ?? {}
8949
+ )) {
8950
+ const argumentType = isForwardedGenericBinding(argument2) ? param(argument2.genericParamId) : nested(argument2.memberId);
8951
+ if (argumentType === null) {
8952
+ return genericBindingTypeInfo(resolved, env, members);
8953
+ }
8954
+ typeArguments[parameterId] = argumentType;
8955
+ }
8956
+ return {
8957
+ type: 7 /* Class */,
8958
+ required,
8959
+ classId: resolved.classId,
8960
+ ...Object.keys(typeArguments).length === 0 ? {} : { typeArguments }
8961
+ };
8962
+ }
8963
+ if (isMemberListBase(resolved)) {
8964
+ return {
8965
+ type: 6 /* List */,
8966
+ required,
8967
+ entryTypeInfo: nested(resolved.entryMemberId)
8968
+ };
8969
+ }
8970
+ if (isMemberDictionaryBase(resolved)) {
8971
+ return {
8972
+ type: 5 /* Dictionary */,
8973
+ required,
8974
+ entryTypeInfo: nested(resolved.entryMemberId),
8975
+ ...resolved.keyEnumId == null ? {} : { keyEnumId: resolved.keyEnumId }
8976
+ };
8977
+ }
8978
+ return genericBindingTypeInfo(resolved, env, members);
8979
+ }
8768
8980
  function callableBindingMember(memberId, slotName, members) {
8769
8981
  const binding = memberIndexFor(members).get(memberId);
8770
8982
  if (binding === void 0) {
@@ -9366,13 +9578,16 @@ function constructionMembers(classId, context) {
9366
9578
  }
9367
9579
  function createMemberDefaultConstructionChecker(document2) {
9368
9580
  const context = contextFor(document2);
9369
- return (member, genericEnv = /* @__PURE__ */ new Map()) => {
9581
+ return (member, genericEnv = /* @__PURE__ */ new Map(), readValueIds) => {
9370
9582
  const previousEnv = context.env;
9583
+ const previousReads = context.readValueIds;
9371
9584
  context.env = genericEnv;
9585
+ context.readValueIds = readValueIds;
9372
9586
  try {
9373
9587
  return defaultSettlesConstruction(member, context, /* @__PURE__ */ new Set());
9374
9588
  } finally {
9375
9589
  context.env = previousEnv;
9590
+ context.readValueIds = previousReads;
9376
9591
  }
9377
9592
  };
9378
9593
  }
@@ -9483,6 +9698,7 @@ function valueSettlesConstruction(member, body, context, path, storedRow = false
9483
9698
  }
9484
9699
  function suppliedValueSettlesConstruction(member, value, context, path) {
9485
9700
  if (typeof value === "string") {
9701
+ context.readValueIds?.add(value);
9486
9702
  let row;
9487
9703
  if (context.document.valueById !== void 0) {
9488
9704
  row = context.document.valueById(value);
@@ -10548,74 +10764,84 @@ function recordStorageKeyDeclaration(sink, valueId, member) {
10548
10764
  if (declaration === STORAGE_KEY_INHERIT) return;
10549
10765
  sink.set(valueId, declaration);
10550
10766
  }
10551
- function createDefaultValueResolutionCache() {
10767
+ function createDefaultSchemaResolutionCache() {
10552
10768
  return {
10553
10769
  memberByIdIndex: null,
10554
10770
  instanceEnvironmentByKey: /* @__PURE__ */ new Map(),
10555
- materializationPlanByClassAndEnvironment: /* @__PURE__ */ new Map(),
10556
10771
  resolvedMemberById: /* @__PURE__ */ new Map(),
10557
10772
  storedSchemaByClassId: /* @__PURE__ */ new Map(),
10558
- validatedInitializerContainers: /* @__PURE__ */ new WeakSet(),
10773
+ validatedInitializerContainers: /* @__PURE__ */ new WeakSet()
10774
+ };
10775
+ }
10776
+ function createDefaultValueResolutionCache(schema = createDefaultSchemaResolutionCache()) {
10777
+ return {
10778
+ schema,
10779
+ materializationPlanByClassAndEnvironment: /* @__PURE__ */ new Map(),
10559
10780
  memberDefaultConstructionChecker: null
10560
10781
  };
10561
10782
  }
10562
10783
  function withIndexedDefaultValueDocument(document2, options = {}) {
10563
10784
  const cache = options.cache ?? createDefaultValueResolutionCache();
10564
- if (cache.memberByIdIndex === null && options.memberById === void 0 && document2.memberById === void 0) {
10565
- cache.memberByIdIndex = new Map(
10785
+ const schemaCache = cache.schema;
10786
+ if (schemaCache.memberByIdIndex === null && options.memberById === void 0 && document2.memberById === void 0) {
10787
+ schemaCache.memberByIdIndex = new Map(
10566
10788
  document2.members.map((member) => [member.id, member])
10567
10789
  );
10568
10790
  }
10569
10791
  const indexed = {
10570
10792
  ...document2,
10571
- memberById: (id) => options.memberById?.(id) ?? document2.memberById?.(id) ?? cache.memberByIdIndex?.get(id) ?? null,
10793
+ memberById: (id) => options.memberById?.(id) ?? document2.memberById?.(id) ?? schemaCache.memberByIdIndex?.get(id) ?? null,
10572
10794
  resolvedMember: (member) => {
10573
10795
  const memberId = "id" in member ? member.id : void 0;
10574
10796
  if (typeof memberId !== "string") {
10575
10797
  return resolveMember(member, document2.members);
10576
10798
  }
10577
- const cached = cache.resolvedMemberById.get(memberId);
10799
+ const cached = schemaCache.resolvedMemberById.get(memberId);
10578
10800
  if (cached !== void 0) return cached;
10579
10801
  const resolved = resolveMember(member, document2.members);
10580
- cache.resolvedMemberById.set(memberId, resolved);
10802
+ schemaCache.resolvedMemberById.set(memberId, resolved);
10581
10803
  return resolved;
10582
10804
  },
10583
10805
  storedInstanceSchema: (classId) => {
10584
- const cached = cache.storedSchemaByClassId.get(classId);
10806
+ const cached = schemaCache.storedSchemaByClassId.get(classId);
10585
10807
  if (cached !== void 0) return cached;
10586
10808
  const schema = resolvedClassSchema(
10587
10809
  classId,
10588
10810
  document2.classes,
10589
10811
  document2.members
10590
10812
  ).surface;
10591
- cache.storedSchemaByClassId.set(classId, schema);
10813
+ schemaCache.storedSchemaByClassId.set(classId, schema);
10592
10814
  return schema;
10593
10815
  },
10594
10816
  instanceEnv: (classId, classArguments2) => {
10595
10817
  const key = `${classId}:${JSON.stringify(classArguments2 ?? null)}`;
10596
- const cached = cache.instanceEnvironmentByKey.get(key);
10818
+ const cached = schemaCache.instanceEnvironmentByKey.get(key);
10597
10819
  if (cached !== void 0) return cached;
10598
10820
  const environment = resolveInstanceEnv(
10599
10821
  classId,
10600
10822
  classArguments2,
10601
10823
  document2.classes
10602
10824
  );
10603
- cache.instanceEnvironmentByKey.set(key, environment);
10825
+ schemaCache.instanceEnvironmentByKey.set(key, environment);
10604
10826
  return environment;
10605
10827
  },
10606
10828
  isInitValueContent: (value) => {
10607
10829
  if (typeof value !== "object" || value === null) return false;
10608
- if (cache.validatedInitializerContainers.has(value)) return true;
10830
+ if (schemaCache.validatedInitializerContainers.has(value)) return true;
10609
10831
  if (!isInitValueContent(value)) return false;
10610
- cache.validatedInitializerContainers.add(value);
10832
+ schemaCache.validatedInitializerContainers.add(value);
10611
10833
  return true;
10612
10834
  },
10613
- memberDefaultSettlesConstruction: (member, environment) => {
10835
+ memberDefaultSettlesConstruction: (member, environment, readValueIds) => {
10614
10836
  cache.memberDefaultConstructionChecker ??= createMemberDefaultConstructionChecker({
10615
10837
  ...indexed,
10616
10838
  constructors: document2.constructors ?? []
10617
10839
  });
10618
- return cache.memberDefaultConstructionChecker(member, environment);
10840
+ return cache.memberDefaultConstructionChecker(
10841
+ member,
10842
+ environment,
10843
+ readValueIds
10844
+ );
10619
10845
  },
10620
10846
  createValueRow: options.createValueRow ?? document2.createValueRow
10621
10847
  };
@@ -10667,12 +10893,20 @@ function buildDefaultClassMaterializationPlan(document2, classId, instanceEnv) {
10667
10893
  ...document2,
10668
10894
  constructors: document2.constructors ?? []
10669
10895
  });
10670
- return storedSchemaOf(document2, classId).flatMap(
10896
+ const reads = {
10897
+ valueIds: /* @__PURE__ */ new Set(),
10898
+ containerIds: /* @__PURE__ */ new Set()
10899
+ };
10900
+ const entries = storedSchemaOf(document2, classId).flatMap(
10671
10901
  (entry) => {
10672
10902
  if (entry.memberId === null) return [];
10673
10903
  const childMember = findMemberInDocument(document2, entry.memberId);
10674
10904
  if (!memberKindOwnsStoredValue(childMember.kind)) return [];
10675
- if (instanceEnv.size === 0 && isConstantMember(document2, resolvedInDocument(document2, childMember)))
10905
+ if (instanceEnv.size === 0 && isConstantMember(
10906
+ document2,
10907
+ resolvedInDocument(document2, childMember),
10908
+ reads
10909
+ ))
10676
10910
  return [];
10677
10911
  const member = substituteMember(
10678
10912
  childMember,
@@ -10684,14 +10918,19 @@ function buildDefaultClassMaterializationPlan(document2, classId, instanceEnv) {
10684
10918
  {
10685
10919
  schemaKey: entry.schemaKey,
10686
10920
  member,
10687
- defaultSettlesConstruction: settlesConstruction(member, instanceEnv),
10921
+ defaultSettlesConstruction: settlesConstruction(
10922
+ member,
10923
+ instanceEnv,
10924
+ reads.valueIds
10925
+ ),
10688
10926
  directScalarBody: directScalarDefaultBody(document2, member)
10689
10927
  }
10690
10928
  ];
10691
10929
  }
10692
10930
  );
10931
+ return { entries, reads };
10693
10932
  }
10694
- function isConstantMember(document2, resolved) {
10933
+ function isConstantMember(document2, resolved, reads) {
10695
10934
  if (isStaticMember(resolved)) return false;
10696
10935
  const fixedness = fixednessOf(resolved, 0 /* Writable */);
10697
10936
  if (fixedness === 0 /* Writable */) return false;
@@ -10704,7 +10943,8 @@ function isConstantMember(document2, resolved) {
10704
10943
  document: document2,
10705
10944
  rows: /* @__PURE__ */ new Set(),
10706
10945
  declarations: /* @__PURE__ */ new Set(),
10707
- classes: /* @__PURE__ */ new Set()
10946
+ classes: /* @__PURE__ */ new Set(),
10947
+ reads
10708
10948
  },
10709
10949
  resolved,
10710
10950
  declared,
@@ -10778,6 +11018,8 @@ function declarationVaries(walk, member, body, rowId, scope) {
10778
11018
  return owned !== Object.keys(value).length;
10779
11019
  }
10780
11020
  if (isMemberListBase(member)) {
11021
+ if (rowId !== null && listKindOf(member) === 1 /* Unordered */)
11022
+ walk.reads?.containerIds.add(rowId);
10781
11023
  const entryIds = listKindOf(member) !== 1 /* Unordered */ ? value : rowId === null ? [] : document2.unorderedListEntryIds?.(rowId) ?? (walk.membership ??= buildUnorderedListMembershipIndex(
10782
11024
  document2.values
10783
11025
  )).get(rowId) ?? [];
@@ -10810,6 +11052,7 @@ function rowVaries(walk, member, valueId, scope) {
10810
11052
  const key = scopeKey(valueId, scope);
10811
11053
  if (walk.rows.has(key)) return false;
10812
11054
  walk.rows.add(key);
11055
+ walk.reads?.valueIds.add(valueId);
10813
11056
  const { document: document2 } = walk;
10814
11057
  const row = document2.valueById?.(valueId) ?? (walk.rowById ??= new Map(
10815
11058
  document2.values.map((value) => [value.id, value])
@@ -11113,6 +11356,7 @@ function buildDefaultMemberValueCore(args, resolvedMember) {
11113
11356
  effectiveClassId,
11114
11357
  childEnv
11115
11358
  );
11359
+ args.document.recordPlanReads?.(materializationPlan.reads);
11116
11360
  const record4 = member.payload === 1 /* Partial */ ? {} : cloneDefaultClassRecord({
11117
11361
  document: args.document,
11118
11362
  projectId: args.projectId,
@@ -11306,7 +11550,7 @@ function completeDefaultClassRecord(args) {
11306
11550
  member: resolvedChildMember,
11307
11551
  defaultSettlesConstruction: defaultSettlesConstruction2,
11308
11552
  directScalarBody
11309
- } of args.member.payload === 1 /* Partial */ ? [] : args.materializationPlan) {
11553
+ } of args.member.payload === 1 /* Partial */ ? [] : args.materializationPlan.entries) {
11310
11554
  if (storageKeyReferencesParentClass(
11311
11555
  normalizeStorageKeyDeclaration(resolvedChildMember.storageKey)
11312
11556
  )) {
@@ -11626,6 +11870,7 @@ function cloneDefaultValueForMemberCore(args, sourceValue) {
11626
11870
  effectiveClassId,
11627
11871
  childEnv
11628
11872
  );
11873
+ args.document.recordPlanReads?.(materializationPlan.reads);
11629
11874
  const anchorsParentClassPartition = sourceValue.constructorArgs == null && completeDefaultClassRecord({
11630
11875
  ...args,
11631
11876
  member,
@@ -12510,6 +12755,230 @@ var EffectiveStorageResolver = class {
12510
12755
  }
12511
12756
  };
12512
12757
 
12758
+ // ../packages/models/src/interfaces/interface-graph.ts
12759
+ var CircularInterfaceExtensionError = class extends Error {
12760
+ constructor(interfaceId, chain) {
12761
+ super(
12762
+ `Circular interface extension detected at "${interfaceId}"; chain: ${chain.join(" -> ")}`
12763
+ );
12764
+ this.interfaceId = interfaceId;
12765
+ this.chain = chain;
12766
+ this.name = "CircularInterfaceExtensionError";
12767
+ }
12768
+ interfaceId;
12769
+ chain;
12770
+ };
12771
+ function resolveInterfaceClosure(interfaceId, interfaces) {
12772
+ const byId = new Map(
12773
+ interfaces.map((neoInterface) => [neoInterface.id, neoInterface])
12774
+ );
12775
+ const result = [];
12776
+ const emitted = /* @__PURE__ */ new Set();
12777
+ const visiting = [];
12778
+ const visitingSet = /* @__PURE__ */ new Set();
12779
+ const visit = (id) => {
12780
+ if (visitingSet.has(id)) {
12781
+ throw new CircularInterfaceExtensionError(id, [...visiting, id]);
12782
+ }
12783
+ if (emitted.has(id)) return;
12784
+ const neoInterface = byId.get(id);
12785
+ if (!neoInterface) return;
12786
+ visiting.push(id);
12787
+ visitingSet.add(id);
12788
+ result.push(neoInterface);
12789
+ emitted.add(id);
12790
+ for (const parentId of neoInterface.extendsInterfaceIds ?? []) {
12791
+ visit(parentId);
12792
+ }
12793
+ visiting.pop();
12794
+ visitingSet.delete(id);
12795
+ };
12796
+ visit(interfaceId);
12797
+ return result;
12798
+ }
12799
+ function resolveImplementedInterfaces(classId, classes, interfaces) {
12800
+ const result = [];
12801
+ const seen = /* @__PURE__ */ new Set();
12802
+ for (const schemaClass2 of resolveInheritanceChain(classId, classes)) {
12803
+ for (const interfaceId of schemaClass2.implementsInterfaceIds ?? []) {
12804
+ for (const neoInterface of resolveInterfaceClosure(
12805
+ interfaceId,
12806
+ interfaces
12807
+ )) {
12808
+ if (seen.has(neoInterface.id)) continue;
12809
+ seen.add(neoInterface.id);
12810
+ result.push(neoInterface);
12811
+ }
12812
+ }
12813
+ }
12814
+ return result;
12815
+ }
12816
+ function classImplementsInterface(classId, interfaceId, classes, interfaces) {
12817
+ return resolveImplementedInterfaces(classId, classes, interfaces).some(
12818
+ (neoInterface) => neoInterface.id === interfaceId
12819
+ );
12820
+ }
12821
+
12822
+ // ../packages/manifest/src/value-comparison.ts
12823
+ function isObjectRecord(value) {
12824
+ return typeof value === "object" && value !== null && !Array.isArray(value);
12825
+ }
12826
+
12827
+ // ../packages/neoscript-runtime/src/values/canonical-json.ts
12828
+ function canonicalJsonStringify(value) {
12829
+ return JSON.stringify(toCanonicalJsonValue(value));
12830
+ }
12831
+ function toCanonicalJsonValue(value) {
12832
+ if (value === null) return null;
12833
+ if (value === void 0) return void 0;
12834
+ if (value instanceof Date) return value.toISOString();
12835
+ if (typeof value === "string") return value;
12836
+ if (typeof value === "boolean") return value;
12837
+ if (typeof value === "number") {
12838
+ if (!Number.isFinite(value)) {
12839
+ throw new Error("Cannot canonicalize a non-finite number.");
12840
+ }
12841
+ return value;
12842
+ }
12843
+ if (typeof value === "bigint") {
12844
+ throw new Error("Cannot canonicalize bigint values.");
12845
+ }
12846
+ if (typeof value === "symbol") {
12847
+ throw new Error("Cannot canonicalize symbol values.");
12848
+ }
12849
+ if (typeof value === "function") {
12850
+ throw new Error("Cannot canonicalize function values.");
12851
+ }
12852
+ if (Array.isArray(value)) {
12853
+ return value.map((item) => {
12854
+ const canonicalItem = toCanonicalJsonValue(item);
12855
+ if (canonicalItem === void 0) return null;
12856
+ return canonicalItem;
12857
+ });
12858
+ }
12859
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
12860
+ const canonicalObject = {};
12861
+ for (const [key, entryValue] of entries) {
12862
+ const canonicalValue = toCanonicalJsonValue(entryValue);
12863
+ if (canonicalValue === void 0) continue;
12864
+ canonicalObject[key] = canonicalValue;
12865
+ }
12866
+ return canonicalObject;
12867
+ }
12868
+
12869
+ // ../src/database/compiled-construction-types.ts
12870
+ function compiledConstructionTypeMembers(members, bodies, projectId) {
12871
+ const created = [];
12872
+ let existingIds;
12873
+ const byType = /* @__PURE__ */ new Map();
12874
+ const key = (type) => canonicalJsonStringify(type);
12875
+ const intern = (type) => {
12876
+ const signature = key(type);
12877
+ const existing = byType.get(signature);
12878
+ if (existing !== void 0) return existing;
12879
+ if (type.type === 21 /* Generic */ || type.type === NS_TYPE_UNKNOWN)
12880
+ return null;
12881
+ const id = v5_default(
12882
+ `neo:compiled-construction-type:${projectId}:${signature}`,
12883
+ v5_default.URL
12884
+ );
12885
+ existingIds ??= new Set(members.map((member) => member.id));
12886
+ if (existingIds.has(id)) {
12887
+ byType.set(signature, id);
12888
+ return id;
12889
+ }
12890
+ const common = {
12891
+ id,
12892
+ projectId,
12893
+ createdAt: 0,
12894
+ updatedAt: 0,
12895
+ name: "Type argument",
12896
+ kind: type.type,
12897
+ requirement: type.required ? 1 /* Required */ : 0 /* Optional */
12898
+ };
12899
+ const fields = (() => {
12900
+ if (type.type === 6 /* List */ || type.type === 5 /* Dictionary */) {
12901
+ const entryMemberId = intern(type.entryTypeInfo);
12902
+ if (entryMemberId === null) return null;
12903
+ return {
12904
+ entryMemberId,
12905
+ ...type.keyEnumId === void 0 ? {} : { keyKind: 1 /* Enum */, keyEnumId: type.keyEnumId }
12906
+ };
12907
+ } else if (type.type === 7 /* Class */) {
12908
+ const classArguments2 = {};
12909
+ for (const [parameter3, argument2] of Object.entries(
12910
+ type.typeArguments ?? {}
12911
+ )) {
12912
+ const memberId = intern(argument2);
12913
+ if (memberId === null) return null;
12914
+ classArguments2[parameter3] = {
12915
+ kind: 1 /* Member */,
12916
+ memberId
12917
+ };
12918
+ }
12919
+ return {
12920
+ classId: type.classId,
12921
+ ...Object.keys(classArguments2).length === 0 ? {} : { classArguments: classArguments2 }
12922
+ };
12923
+ } else if (type.type === 8 /* Enum */) {
12924
+ return { enumId: type.enumId };
12925
+ } else if (type.type === 25 /* NSDelegate */) {
12926
+ return {
12927
+ returnTypeInfo: type.returnTypeInfo,
12928
+ argumentTypes: type.argumentTypes
12929
+ };
12930
+ } else if (type.type === 26 /* NSAction */) {
12931
+ return { argumentTypes: type.argumentTypes };
12932
+ } else if (type.type === 22 /* Interface */ || type.type === 9 /* Lookup */ || type.type === 18 /* DialogueLookup */) {
12933
+ return null;
12934
+ } else {
12935
+ return {};
12936
+ }
12937
+ })();
12938
+ if (fields === null) return null;
12939
+ created.push({ ...common, ...fields });
12940
+ existingIds.add(id);
12941
+ byType.set(signature, id);
12942
+ return id;
12943
+ };
12944
+ const visited = /* @__PURE__ */ new Set();
12945
+ const visit = (value) => {
12946
+ if (value === null || typeof value !== "object" || visited.has(value))
12947
+ return;
12948
+ visited.add(value);
12949
+ const argumentsValue = getField(
12950
+ getField(value, "schemaClassInfo"),
12951
+ "typeArguments"
12952
+ );
12953
+ if (argumentsValue !== null && typeof argumentsValue === "object") {
12954
+ for (const type of Object.values(argumentsValue))
12955
+ if (isNSTypeInfo(type)) intern(type);
12956
+ }
12957
+ for (const child of Object.values(value)) visit(child);
12958
+ };
12959
+ for (const body of bodies) visit(body);
12960
+ return created;
12961
+ }
12962
+ function withCompiledConstructionTypes(document2, body) {
12963
+ const members = document2.members;
12964
+ const projectId = getField(document2.project, "id");
12965
+ if (!Array.isArray(members)) {
12966
+ throw new Error("Construction type descriptors require a member array.");
12967
+ }
12968
+ if (!members.every(
12969
+ (member) => typeof getField(member, "id") === "string"
12970
+ )) {
12971
+ throw new Error(
12972
+ "Construction type descriptors require an ID on every member record."
12973
+ );
12974
+ }
12975
+ if (typeof projectId !== "string") {
12976
+ throw new Error("Construction type descriptors require a project ID.");
12977
+ }
12978
+ const created = compiledConstructionTypeMembers(members, [body], projectId);
12979
+ return created.length === 0 ? document2 : { ...document2, members: [...members, ...created] };
12980
+ }
12981
+
12513
12982
  // ../packages/neoscript-runtime/src/neoscript/debug.ts
12514
12983
  function snapshotNeoScriptFrames(state) {
12515
12984
  const frames = state.frames.slice(-64).reverse().map((frame) => Object.freeze({ ...frame }));
@@ -13475,8 +13944,7 @@ var PendingInitializerDependency = class extends NSGetterRuntimeError {
13475
13944
  var OWNERSHIP_CHAIN_PREFIXES = [
13476
13945
  "generic-parent-resolution:",
13477
13946
  "member-owner-resolution:",
13478
- "owned-value-parents:",
13479
- "declaration-owner-resolution:"
13947
+ "owned-value-parents:"
13480
13948
  ];
13481
13949
  var CONTAINER_ENTRIES_PREFIX = "container-entries:";
13482
13950
  function ownershipChainRead(kind, rowId) {
@@ -13485,10 +13953,6 @@ function ownershipChainRead(kind, rowId) {
13485
13953
  function containerEntriesRead(containerId) {
13486
13954
  return `${CONTAINER_ENTRIES_PREFIX}${containerId}`;
13487
13955
  }
13488
- var OWNERSHIP_CHAIN_READ = ownershipChainRead(
13489
- "member-owner-resolution",
13490
- "*"
13491
- );
13492
13956
  function classifyUnattributableRead(reason) {
13493
13957
  for (const prefix of OWNERSHIP_CHAIN_PREFIXES) {
13494
13958
  if (reason.startsWith(prefix)) {
@@ -13519,12 +13983,13 @@ function valueIdsWithSourceChains(targetValueIds, valuesById) {
13519
13983
  }
13520
13984
  return result;
13521
13985
  }
13522
- function initializerOwnerContext(document2, valueId, rootOwners, valuesById) {
13986
+ function initializerOwnerContext(document2, valueId, rootOwners, valuesById, recordValueRead) {
13523
13987
  const visited = /* @__PURE__ */ new Set();
13524
13988
  let currentId = valueId;
13525
13989
  let lexicalRoot = rootOwners.get(valueId);
13526
13990
  while (currentId !== null && !visited.has(currentId)) {
13527
13991
  visited.add(currentId);
13992
+ recordValueRead?.(currentId);
13528
13993
  const sourceValueId = valuesById.get(currentId)?.sourceValueId;
13529
13994
  if (typeof sourceValueId !== "string") break;
13530
13995
  currentId = sourceValueId;
@@ -14720,9 +15185,8 @@ var InitializerReadSet = class {
14720
15185
  /**
14721
15186
  * The unattributable reads by scope, for a fork of the same document to
14722
15187
  * re-attribute; see {@link classifyUnattributableRead}. Ownership-chain
14723
- * reads collapse to one flag: their inputs are already in `valueIds`.
15188
+ * reads need no record: their inputs are already in `valueIds`.
14724
15189
  */
14725
- hasOwnershipChainRead = false;
14726
15190
  containerEntryReadIds = /* @__PURE__ */ new Set();
14727
15191
  corpusReadReasons = /* @__PURE__ */ new Set();
14728
15192
  recordUnattributableValueRead = (reason) => {
@@ -14730,7 +15194,6 @@ var InitializerReadSet = class {
14730
15194
  const read = classifyUnattributableRead(reason);
14731
15195
  switch (read.scope) {
14732
15196
  case "ownership-chain" /* OwnershipChain */:
14733
- this.hasOwnershipChainRead = true;
14734
15197
  return;
14735
15198
  case "container" /* Container */:
14736
15199
  this.containerEntryReadIds.add(read.containerId);
@@ -14775,17 +15238,61 @@ function getWorldGridQueryIndex(source) {
14775
15238
  building.delete(source.cacheKey);
14776
15239
  }
14777
15240
  }
15241
+ function readsAny(reads, ids) {
15242
+ for (const id of ids) if (reads.has(id)) return true;
15243
+ return false;
15244
+ }
14778
15245
  var WorldGridQueryIndex = class {
14779
- constructor(grids, placements, geometryReads, metrics) {
15246
+ constructor(grids, placements, geometryReads, kinds, placedRecordIds, metrics) {
14780
15247
  this.grids = grids;
14781
15248
  this.placements = placements;
14782
15249
  this.geometryReads = geometryReads;
15250
+ this.kinds = kinds;
15251
+ this.placedRecordIds = placedRecordIds;
14783
15252
  this.metrics = metrics;
14784
15253
  }
14785
15254
  grids;
14786
15255
  placements;
14787
15256
  geometryReads;
15257
+ kinds;
15258
+ placedRecordIds;
14788
15259
  metrics;
15260
+ /**
15261
+ * Whether edits to these rows can change the index. Ownership-chain reads
15262
+ * need no flag: every ancestor they visit is in `geometryReads.valueIds`.
15263
+ * Discovery checks every row's effective class without recording a read,
15264
+ * so a changed row it could now index as a grid counts as well. A record it
15265
+ * classed by placement keeps that placement through its own writes, so only
15266
+ * its stamp can change.
15267
+ */
15268
+ readsValues(valueIds, classIdOf, stampOf) {
15269
+ const reads = this.geometryReads;
15270
+ if (reads.corpusReadReasons.size > 0) return true;
15271
+ for (const id of valueIds) {
15272
+ if (reads.valueIds.has(id)) return true;
15273
+ const classId = this.placedRecordIds.has(id) ? stampOf(id) : classIdOf(id);
15274
+ if (classId !== null && this.kinds.get(classId) === NeoWorldSystemClassKind.TileGrid)
15275
+ return true;
15276
+ }
15277
+ return false;
15278
+ }
15279
+ /** Whether entry changes in these containers can change the index. */
15280
+ readsContainers(containerIds) {
15281
+ const reads = this.geometryReads;
15282
+ for (const id of containerIds) {
15283
+ if (reads.containerIds.has(id)) return true;
15284
+ if (reads.containerEntryReadIds.has(id)) return true;
15285
+ }
15286
+ return false;
15287
+ }
15288
+ /** Whether edits to these localized texts can change the index. */
15289
+ readsLocalizedTexts(textIds) {
15290
+ return readsAny(this.geometryReads.localizedTextIds, textIds);
15291
+ }
15292
+ /** Whether edits to these variants can change the index. */
15293
+ readsVariants(variantIds) {
15294
+ return readsAny(this.geometryReads.variantIds, variantIds);
15295
+ }
14789
15296
  placement(valueId, reads) {
14790
15297
  reads?.add({ kind: "placement", valueId });
14791
15298
  const matches = this.placements.get(valueId) ?? [];
@@ -14949,8 +15456,13 @@ function buildIndex(source) {
14949
15456
  occupiedCells += 1;
14950
15457
  };
14951
15458
  const discoveryReads = new InitializerReadSet();
15459
+ const placedRecordIds = /* @__PURE__ */ new Set();
14952
15460
  for (const root of source.rows) {
14953
- const grid = typeof root.classId !== "string" ? source.readRow(root.id, discoveryReads) : root;
15461
+ let grid = root;
15462
+ if (typeof root.classId !== "string") {
15463
+ if (record(root.value) !== null) placedRecordIds.add(root.id);
15464
+ grid = source.readRow(root.id, discoveryReads);
15465
+ }
14954
15466
  if (typeof grid?.classId !== "string" || kinds.get(grid.classId) !== NeoWorldSystemClassKind.TileGrid)
14955
15467
  continue;
14956
15468
  const effectiveGrid = readRow(root.id);
@@ -15043,11 +15555,18 @@ function buildIndex(source) {
15043
15555
  }
15044
15556
  }
15045
15557
  }
15046
- return new WorldGridQueryIndex(grids, placements, reads, {
15047
- rowsScanned: source.rows.length,
15048
- placementsIndexed,
15049
- occupiedCells
15050
- });
15558
+ return new WorldGridQueryIndex(
15559
+ grids,
15560
+ placements,
15561
+ reads,
15562
+ kinds,
15563
+ placedRecordIds,
15564
+ {
15565
+ rowsScanned: source.rows.length,
15566
+ placementsIndexed,
15567
+ occupiedCells
15568
+ }
15569
+ );
15051
15570
  }
15052
15571
  function record(value) {
15053
15572
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -15495,70 +16014,6 @@ function floatFromDecimalString(value) {
15495
16014
  return Number(value);
15496
16015
  }
15497
16016
 
15498
- // ../packages/models/src/interfaces/interface-graph.ts
15499
- var CircularInterfaceExtensionError = class extends Error {
15500
- constructor(interfaceId, chain) {
15501
- super(
15502
- `Circular interface extension detected at "${interfaceId}"; chain: ${chain.join(" -> ")}`
15503
- );
15504
- this.interfaceId = interfaceId;
15505
- this.chain = chain;
15506
- this.name = "CircularInterfaceExtensionError";
15507
- }
15508
- interfaceId;
15509
- chain;
15510
- };
15511
- function resolveInterfaceClosure(interfaceId, interfaces) {
15512
- const byId = new Map(
15513
- interfaces.map((neoInterface) => [neoInterface.id, neoInterface])
15514
- );
15515
- const result = [];
15516
- const emitted = /* @__PURE__ */ new Set();
15517
- const visiting = [];
15518
- const visitingSet = /* @__PURE__ */ new Set();
15519
- const visit = (id) => {
15520
- if (visitingSet.has(id)) {
15521
- throw new CircularInterfaceExtensionError(id, [...visiting, id]);
15522
- }
15523
- if (emitted.has(id)) return;
15524
- const neoInterface = byId.get(id);
15525
- if (!neoInterface) return;
15526
- visiting.push(id);
15527
- visitingSet.add(id);
15528
- result.push(neoInterface);
15529
- emitted.add(id);
15530
- for (const parentId of neoInterface.extendsInterfaceIds ?? []) {
15531
- visit(parentId);
15532
- }
15533
- visiting.pop();
15534
- visitingSet.delete(id);
15535
- };
15536
- visit(interfaceId);
15537
- return result;
15538
- }
15539
- function resolveImplementedInterfaces(classId, classes, interfaces) {
15540
- const result = [];
15541
- const seen = /* @__PURE__ */ new Set();
15542
- for (const schemaClass2 of resolveInheritanceChain(classId, classes)) {
15543
- for (const interfaceId of schemaClass2.implementsInterfaceIds ?? []) {
15544
- for (const neoInterface of resolveInterfaceClosure(
15545
- interfaceId,
15546
- interfaces
15547
- )) {
15548
- if (seen.has(neoInterface.id)) continue;
15549
- seen.add(neoInterface.id);
15550
- result.push(neoInterface);
15551
- }
15552
- }
15553
- }
15554
- return result;
15555
- }
15556
- function classImplementsInterface(classId, interfaceId, classes, interfaces) {
15557
- return resolveImplementedInterfaces(classId, classes, interfaces).some(
15558
- (neoInterface) => neoInterface.id === interfaceId
15559
- );
15560
- }
15561
-
15562
16017
  // ../packages/models/src/members/read-class-member.ts
15563
16018
  function readClassMember(args) {
15564
16019
  const { member, schemaKey } = args;
@@ -16577,8 +17032,8 @@ function evaluatorResolutionCache(ctx) {
16577
17032
  compiledFunctionByMemberId: /* @__PURE__ */ new Map(),
16578
17033
  compiledGetterByMemberId: /* @__PURE__ */ new Map(),
16579
17034
  compiledSetterByMemberId: /* @__PURE__ */ new Map(),
16580
- defaultValueResolutionCache: createDefaultValueResolutionCache(),
16581
- validatedConstructorDescriptorByInfo: /* @__PURE__ */ new WeakMap(),
17035
+ defaultSchema: createDefaultSchemaResolutionCache(),
17036
+ valueGenerations: /* @__PURE__ */ new WeakMap(),
16582
17037
  effectiveStorageResolver: void 0
16583
17038
  };
16584
17039
  resolutionCacheByMembers.set(members, {
@@ -16617,6 +17072,24 @@ function cachedInstanceEnv(classId, classArguments2, ctx) {
16617
17072
  function cachedIsInitValueContent(value, ctx) {
16618
17073
  return evaluatorDefaultValueDocument(ctx).isInitValueContent(value);
16619
17074
  }
17075
+ function evaluatorValueGeneration(ctx) {
17076
+ const { values, databaseVM } = ctx.vm;
17077
+ const valueGeneration = databaseVM?.valueGeneration;
17078
+ const resolution = evaluatorResolutionCache(ctx);
17079
+ const key = databaseVM ?? values;
17080
+ const entry = resolution.valueGenerations.get(key);
17081
+ if (entry !== void 0 && entry.values === values && entry.valueGeneration === valueGeneration) {
17082
+ return entry;
17083
+ }
17084
+ const generation = {
17085
+ values,
17086
+ valueGeneration,
17087
+ defaults: createDefaultValueResolutionCache(resolution.defaultSchema),
17088
+ constructorDescriptors: /* @__PURE__ */ new WeakMap()
17089
+ };
17090
+ resolution.valueGenerations.set(key, generation);
17091
+ return generation;
17092
+ }
16620
17093
  function evaluatorDefaultValueDocument(ctx) {
16621
17094
  if (ctx.__defaultValueDocument !== void 0) {
16622
17095
  return ctx.__defaultValueDocument;
@@ -16637,7 +17110,7 @@ function evaluatorDefaultValueDocument(ctx) {
16637
17110
  projectFiles: ctx.vm.projectFiles ?? [],
16638
17111
  textureTemplates: ctx.vm.textureTemplates ?? []
16639
17112
  },
16640
- { cache: evaluatorResolutionCache(ctx).defaultValueResolutionCache }
17113
+ { cache: evaluatorValueGeneration(ctx).defaults }
16641
17114
  );
16642
17115
  ctx.__defaultValueDocument = document2;
16643
17116
  return document2;
@@ -19088,8 +19561,12 @@ function bindOmittedConstantSlot(destination, member, value, ctx) {
19088
19561
  if (isMemberClassBase(member) || isMemberListBase(member) || isMemberDictionaryBase(member))
19089
19562
  return false;
19090
19563
  const resolved = resolveMember(member, ctx.vm.members);
19091
- if (!isConstantMember(constructorDefaultValueDocument(ctx, member), resolved))
19092
- return false;
19564
+ const decision = constantMemberDecision(
19565
+ constructorDefaultValueDocument(ctx, member),
19566
+ resolved
19567
+ );
19568
+ recordDeclarationReads(ctx, decision.reads);
19569
+ if (!decision.constant) return false;
19093
19570
  const { createdValues } = construction;
19094
19571
  const staged = createdValues.length;
19095
19572
  const row = materializeConstructorArgumentValue({
@@ -21472,6 +21949,17 @@ function ensureVirtualExpansionIndexed(rows, ctx, existingIndexes) {
21472
21949
  indexes3.indexedVirtualRowSets.add(rows);
21473
21950
  }
21474
21951
  var constantDeclarationRoots = /* @__PURE__ */ new WeakMap();
21952
+ function recordDeclarationReads(ctx, reads) {
21953
+ for (const id of reads.valueIds) ctx.valueDependencies?.add(id);
21954
+ for (const id of reads.containerIds) ctx.containerDependencies?.add(id);
21955
+ }
21956
+ function constantMemberDecision(document2, member) {
21957
+ const reads = {
21958
+ valueIds: /* @__PURE__ */ new Set(),
21959
+ containerIds: /* @__PURE__ */ new Set()
21960
+ };
21961
+ return { constant: isConstantMember(document2, member, reads), reads };
21962
+ }
21475
21963
  function readDeclarationDefault(member, ctx) {
21476
21964
  if (member?.defaultValue === void 0 || member.defaultValue === null) {
21477
21965
  return { matched: false };
@@ -21486,16 +21974,20 @@ function readDeclarationDefault(member, ctx) {
21486
21974
  constantDeclarationRoots.set(session, shared);
21487
21975
  }
21488
21976
  }
21489
- const known = shared?.get(member.id);
21490
- if (typeof known === "string" && session?.has(known) === true) {
21977
+ let known = shared?.get(member.id);
21978
+ if (known !== void 0) recordDeclarationReads(ctx, known.reads);
21979
+ if (known?.root !== void 0 && session?.has(known.root) === true) {
21491
21980
  return {
21492
21981
  matched: true,
21493
- value: resolveValueIfIdForMember(known, member, ctx)
21982
+ value: resolveValueIfIdForMember(known.root, member, ctx)
21494
21983
  };
21495
21984
  }
21496
21985
  const document2 = constructorDefaultValueDocument(ctx, member);
21497
- const constant = shared !== void 0 && known !== false && (known !== void 0 || isConstantMember(document2, member));
21498
- if (shared !== void 0 && !constant) shared.set(member.id, false);
21986
+ if (shared !== void 0 && known === void 0) {
21987
+ known = constantMemberDecision(document2, member);
21988
+ recordDeclarationReads(ctx, known.reads);
21989
+ shared.set(member.id, known);
21990
+ }
21499
21991
  const created = [];
21500
21992
  const closeFrame = pushConstructionFrame(ctx, `${member.name} declaration`);
21501
21993
  try {
@@ -21521,7 +22013,7 @@ function readDeclarationDefault(member, ctx) {
21521
22013
  )
21522
22014
  });
21523
22015
  stageConstructedRows([root, ...created], ctx);
21524
- if (constant) shared?.set(member.id, root.id);
22016
+ if (known?.constant === true) known.root = root.id;
21525
22017
  return {
21526
22018
  matched: true,
21527
22019
  value: resolveValueIfIdForMember(root.id, member, ctx)
@@ -21845,6 +22337,10 @@ function resolveMemberForValueRow(row, ctx, visited) {
21845
22337
  function worldGridQueryIndexForContext(context) {
21846
22338
  const ctx = withEvaluationRuntime(context, []);
21847
22339
  const vm = ctx.vm;
22340
+ const database = vm.databaseVM;
22341
+ const overlayRevision = ctx.__valueOverlay instanceof LazyValueOverlay ? ctx.__valueOverlay.worldRevision : 0;
22342
+ if (overlayRevision === 0 && database?.worldGridQueryIndex !== void 0)
22343
+ return database.worldGridQueryIndex();
21848
22344
  const readContexts = /* @__PURE__ */ new WeakMap();
21849
22345
  let geometryOverlay;
21850
22346
  const readContext = (reads) => {
@@ -21867,24 +22363,26 @@ function worldGridQueryIndexForContext(context) {
21867
22363
  readContexts.set(reads, next);
21868
22364
  return next;
21869
22365
  };
21870
- const overlayRevision = ctx.__valueOverlay instanceof LazyValueOverlay ? ctx.__valueOverlay.worldRevision : 0;
22366
+ const recording = (reads, read) => database?.recordVirtualInstanceReads === void 0 ? read() : database.recordVirtualInstanceReads(reads, read);
22367
+ const host = vm.worldQueryCache;
21871
22368
  return getWorldGridQueryIndex({
21872
- cacheKey: overlayRevision > 0 && ctx.__valueOverlay !== void 0 ? ctx.__valueOverlay : vm.worldQueryCache?.key ?? vm.databaseVM?.evaluatorIndexes ?? vm.values,
22369
+ cacheKey: overlayRevision > 0 && ctx.__valueOverlay !== void 0 ? ctx.__valueOverlay : host?.key ?? vm.databaseVM?.evaluatorIndexes ?? vm.values,
21873
22370
  revision: [
21874
- ...vm.worldQueryCache?.revision ?? vm.databaseVM?.worldQueryRevision ?? [],
21875
- vm.values,
21876
- vm.classes,
21877
- vm.members,
21878
- vm.internalRecordRelations,
21879
- vm.variants,
21880
- vm.variantFolders,
21881
- vm.schemaRevision,
22371
+ ...host?.revision ?? [
22372
+ vm.values,
22373
+ vm.classes,
22374
+ vm.members,
22375
+ vm.internalRecordRelations,
22376
+ vm.variants,
22377
+ vm.variantFolders,
22378
+ vm.schemaRevision
22379
+ ],
21882
22380
  ...overlayRevision === 0 ? [] : [ctx.__valueOverlay, overlayRevision]
21883
22381
  ],
21884
22382
  rows: vm.values,
21885
22383
  classes: vm.classes,
21886
22384
  relations: vm.internalRecordRelations ?? [],
21887
- readRow(id, reads) {
22385
+ readRow: (id, reads) => recording(reads, () => {
21888
22386
  const current = readContext(reads);
21889
22387
  const row = evalValueById(
21890
22388
  current,
@@ -21895,8 +22393,8 @@ function worldGridQueryIndexForContext(context) {
21895
22393
  if (row === null || typeof row.classId === "string") return row;
21896
22394
  const classId = classIdForValueRow(row, current);
21897
22395
  return classId === void 0 ? row : { ...row, classId };
21898
- },
21899
- readField(id, key, reads) {
22396
+ }),
22397
+ readField: (id, key, reads) => recording(reads, () => {
21900
22398
  const current = readContext(reads);
21901
22399
  const row = evalValueById(
21902
22400
  current,
@@ -21915,8 +22413,8 @@ function worldGridQueryIndexForContext(context) {
21915
22413
  thisValue: row.value,
21916
22414
  thisValueRowId: row.id
21917
22415
  });
21918
- },
21919
- valueId(value, reads) {
22416
+ }),
22417
+ valueId: (value, reads) => recording(reads, () => {
21920
22418
  const current = readContext(reads);
21921
22419
  if (typeof value === "string" && evalValueById(
21922
22420
  current,
@@ -21926,7 +22424,7 @@ function worldGridQueryIndexForContext(context) {
21926
22424
  ) !== null)
21927
22425
  return value;
21928
22426
  return trackedRowForValueReference(value, current)?.id ?? null;
21929
- }
22427
+ })
21930
22428
  });
21931
22429
  }
21932
22430
  function readSystemNativeField(value, key, ctx) {
@@ -23565,7 +24063,7 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
23565
24063
  }
23566
24064
  const genericSlot = ctx.__constructionGenericSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
23567
24065
  const slotArguments = genericSlot?.classId === classId ? genericSlot.classArguments : void 0;
23568
- const descriptorCache = evaluatorResolutionCache(ctx).validatedConstructorDescriptorByInfo;
24066
+ const descriptorCache = evaluatorValueGeneration(ctx).constructorDescriptors;
23569
24067
  const descriptorCacheKey = `${requireEveryRequiredField}:${ctx.storedConstructionReplay === true}:${JSON.stringify(slotArguments ?? info.schemaClassInfo.typeArguments ?? null)}`;
23570
24068
  const cachedDescriptor = descriptorCache.get(info)?.get(descriptorCacheKey);
23571
24069
  if (cachedDescriptor !== void 0) return cachedDescriptor;
@@ -24183,6 +24681,8 @@ function constructClassValue(info, scope, ctx) {
24183
24681
  }
24184
24682
  }
24185
24683
  function constructorDefaultValueDocument(ctx, syntheticMember) {
24684
+ const database = ctx.vm.databaseVM;
24685
+ const entryIdsOf = database?.unorderedListEntryIds?.bind(database);
24186
24686
  return {
24187
24687
  listenerDefaultCapture: ctx.listenerDefaultCapture,
24188
24688
  beforeValueAllocation: ctx.beforeValueAllocation,
@@ -24195,11 +24695,24 @@ function constructorDefaultValueDocument(ctx, syntheticMember) {
24195
24695
  // immutable base plus its indexes avoids copying and linearly scanning
24196
24696
  // the entire project for every constructor replay.
24197
24697
  values: ctx.vm.values,
24198
- memberById: ctx.vm.databaseVM?.memberById,
24199
- valueById: ctx.vm.databaseVM?.defaultValueById ?? ctx.vm.databaseVM?.valueById,
24698
+ memberById: database?.memberById,
24699
+ // The declaration rows a default clones are reads of this evaluation.
24700
+ ...database === void 0 ? {} : {
24701
+ valueById: (id) => {
24702
+ ctx.valueDependencies?.add(id);
24703
+ return database.defaultValueById !== void 0 ? database.defaultValueById(id) : database.valueById(id);
24704
+ }
24705
+ },
24706
+ ...entryIdsOf === void 0 ? {} : {
24707
+ unorderedListEntryIds: (containerId) => {
24708
+ ctx.containerDependencies?.add(containerId);
24709
+ return entryIdsOf(containerId);
24710
+ }
24711
+ },
24200
24712
  resolvedMember: (member) => member === syntheticMember ? syntheticMember : cachedResolvedMember(member, ctx),
24201
24713
  storedInstanceSchema: (nestedClassId) => cachedStoredInstanceSchema(nestedClassId, ctx),
24202
24714
  storedInstanceMaterializationPlan: (nestedClassId, instanceEnv) => cachedStoredInstanceMaterializationPlan(nestedClassId, instanceEnv, ctx),
24715
+ recordPlanReads: (reads) => recordDeclarationReads(ctx, reads),
24203
24716
  instanceEnv: (nestedClassId, classArguments2) => cachedInstanceEnv(nestedClassId, classArguments2, ctx),
24204
24717
  isInitValueContent: (value) => cachedIsInitValueContent(value, ctx),
24205
24718
  createValueRow: (projectId, body) => buildNewValue(
@@ -24849,6 +25362,11 @@ function evaluateInitializerInContext(init, member, ctx, createdValues, argument
24849
25362
  sessionValueExport: "defer"
24850
25363
  }
24851
25364
  );
25365
+ } catch (error) {
25366
+ const ownerId = compileMemberId ?? Reflect.get(member, "id");
25367
+ if (error instanceof NSGetterRuntimeError && sourceValueId === null && typeof ownerId === "string")
25368
+ error.sourceOwnerId ??= ownerId;
25369
+ throw error;
24852
25370
  } finally {
24853
25371
  closeFrame();
24854
25372
  }
@@ -27728,10 +28246,15 @@ function lookupDeclaredTypeInfo(member, collectionTypeInfo) {
27728
28246
  }
27729
28247
 
27730
28248
  // ../packages/neoscript-runtime/src/values/member-declared-type-info.ts
27731
- function resolveMemberDeclaredTypeInfo(member, members) {
27732
- return resolveMemberDeclaredTypeInfoInternal(member, members, /* @__PURE__ */ new Set());
28249
+ function resolveMemberDeclaredTypeInfo(member, members, ownerClass = null) {
28250
+ return resolveMemberDeclaredTypeInfoInternal(
28251
+ member,
28252
+ members,
28253
+ /* @__PURE__ */ new Set(),
28254
+ ownerClass
28255
+ );
27733
28256
  }
27734
- function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
28257
+ function resolveMemberDeclaredTypeInfoInternal(member, members, seen, ownerClass) {
27735
28258
  const resolved = resolveMember(member, members);
27736
28259
  const memberId = getField(resolved, "id");
27737
28260
  if (typeof memberId === "string" && seen.has(memberId)) return null;
@@ -27749,7 +28272,8 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
27749
28272
  const argumentType = resolveMemberDeclaredTypeInfoInternal(
27750
28273
  argumentMember,
27751
28274
  members,
27752
- nextSeen
28275
+ nextSeen,
28276
+ ownerClass
27753
28277
  );
27754
28278
  return argumentType === null ? [] : [[genericParamId, argumentType]];
27755
28279
  }
@@ -27815,7 +28339,8 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
27815
28339
  const entryTypeInfo = resolveMemberDeclaredTypeInfoInternal(
27816
28340
  entry,
27817
28341
  members,
27818
- nextSeen
28342
+ nextSeen,
28343
+ ownerClass
27819
28344
  );
27820
28345
  if (entryTypeInfo === null) return null;
27821
28346
  return {
@@ -27832,12 +28357,29 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
27832
28357
  if (collection === void 0) return null;
27833
28358
  return lookupDeclaredTypeInfo(
27834
28359
  resolved,
27835
- resolveMemberDeclaredTypeInfoInternal(collection, members, nextSeen)
28360
+ resolveMemberDeclaredTypeInfoInternal(
28361
+ collection,
28362
+ members,
28363
+ nextSeen,
28364
+ ownerClass
28365
+ )
27836
28366
  );
27837
28367
  }
27838
28368
  if (resolved.kind === 9 /* Lookup */) return null;
27839
28369
  if (!memberKindSupportsStorage(resolved.kind)) return null;
27840
- if (resolved.kind === 21 /* Generic */) return null;
28370
+ if (isMemberGenericBase(resolved)) {
28371
+ if (ownerClass === null) return null;
28372
+ const declaration = ownerClass.genericParams?.find(
28373
+ (parameter3) => parameter3.id === resolved.genericParamId
28374
+ );
28375
+ if (declaration === void 0) return null;
28376
+ return {
28377
+ type: 21 /* Generic */,
28378
+ required: isRequiredMember(resolved),
28379
+ ownerClassId: ownerClass.id,
28380
+ genericParamId: declaration.id
28381
+ };
28382
+ }
27841
28383
  return {
27842
28384
  type: resolved.kind,
27843
28385
  required: isRequiredMember(resolved)
@@ -29419,11 +29961,8 @@ var Parser = class _Parser {
29419
29961
  * always opens with a type expression, which can be:
29420
29962
  * - A primitive keyword: int / float / bool / string
29421
29963
  * - `Dictionary` keyword followed by `<`
29422
- * - An identifier (Class or Enum) with `[]` suffix or
29423
- * followed by another identifier (the var name).
29424
- *
29425
- * We don't fully parse the type here — we just decide whether to commit
29426
- * to the varDecl path or fall through to an expression statement.
29964
+ * - Any other type the type grammar parses (`Item[]`, `Box<int>?`,
29965
+ * `NeoDelegate<int, int>`) followed by the var name and `=`.
29427
29966
  */
29428
29967
  looksLikeVarDecl() {
29429
29968
  const t = this.peek();
@@ -29440,25 +29979,53 @@ var Parser = class _Parser {
29440
29979
  return true;
29441
29980
  }
29442
29981
  if (!isIdentifier(t)) return false;
29443
- let j = this.i + 1;
29444
- const tk = (k) => this.tokens[k];
29445
- while (tk(j)?.kind === "punctuation" && tk(j)?.text === "[" && tk(j + 1)?.kind === "punctuation" && tk(j + 1)?.text === "]") {
29446
- j += 2;
29447
- }
29448
- if (tk(j)?.kind === "operator" && tk(j)?.text === "?") {
29449
- j += 1;
29450
- }
29451
- const name = tk(j);
29452
- if (name !== void 0 && isIdentifier(name) && tk(j + 1)?.kind === "operator" && tk(j + 1)?.text === "=") {
29453
- return true;
29982
+ const end = this.typeEnd();
29983
+ const name = this.tokens[end];
29984
+ const equals = this.tokens[end + 1];
29985
+ return end >= 0 && name !== void 0 && isIdentifier(name) && equals?.kind === "operator" && equals.text === "=";
29986
+ }
29987
+ /**
29988
+ * Token index just past the type that starts at the cursor, or -1 when the
29989
+ * type grammar rejects it. The cursor does not move. Editor recovery shares
29990
+ * this with declaration lookahead so both agree on every type form.
29991
+ */
29992
+ typeEnd(options = {}) {
29993
+ const start = this.i;
29994
+ this.probingType = true;
29995
+ try {
29996
+ return this.parseTypeOrFail(options) ? this.i : -1;
29997
+ } catch {
29998
+ return -1;
29999
+ } finally {
30000
+ this.probingType = false;
30001
+ this.i = start;
29454
30002
  }
29455
- return false;
30003
+ }
30004
+ /**
30005
+ * True while `typeEnd` probes. Lookahead runs at every identifier on editor
30006
+ * paths, so a rejected type returns null instead of constructing an error.
30007
+ */
30008
+ probingType = false;
30009
+ /** A type-grammar failure: null while probing, otherwise a CompileError. */
30010
+ typeFailure(message, token) {
30011
+ if (this.probingType) return null;
30012
+ throw new CompileError(message, at(token));
30013
+ }
30014
+ /** `expect` inside the type grammar: false while probing a mismatch. */
30015
+ expectTypeToken(kind, text) {
30016
+ if (this.probingType && !tokenMatches(this.peek(), kind, text))
30017
+ return false;
30018
+ this.expect(kind, text);
30019
+ return true;
29456
30020
  }
29457
30021
  // ------------------------------------------------------------------
29458
30022
  // Types
29459
30023
  // ------------------------------------------------------------------
29460
30024
  /** Parses a type annotation (used in varDecls and Dictionary generics). */
29461
30025
  parseType(options = {}) {
30026
+ return this.parseTypeOrFail(options);
30027
+ }
30028
+ parseTypeOrFail(options) {
29462
30029
  const startPos = at(this.peek());
29463
30030
  let inner;
29464
30031
  const t = this.peek();
@@ -29472,17 +30039,18 @@ var Parser = class _Parser {
29472
30039
  };
29473
30040
  } else if (t.kind === "type" && (t.text === "Dictionary" || t.text === "List" || t.text === "Set")) {
29474
30041
  this.next();
29475
- this.expect("operator", "<");
30042
+ if (!this.expectTypeToken("operator", "<")) return null;
29476
30043
  if (t.text === "Dictionary") {
29477
- const key = this.parseType();
30044
+ const key = this.parseTypeOrFail({});
30045
+ if (!key) return null;
29478
30046
  if (this.peek().text === ">")
29479
- throw new CompileError(
30047
+ return this.typeFailure(
29480
30048
  "Dictionary requires a key type and a value type, for example Dictionary<string, int>.",
29481
- at(this.peek())
30049
+ this.peek()
29482
30050
  );
29483
- this.expect("punctuation", ",");
29484
- const value = this.parseType();
29485
- this.expect("operator", ">");
30051
+ if (!this.expectTypeToken("punctuation", ",")) return null;
30052
+ const value = this.parseTypeOrFail({});
30053
+ if (!value || !this.expectTypeToken("operator", ">")) return null;
29486
30054
  inner = {
29487
30055
  kind: "dict",
29488
30056
  key,
@@ -29491,8 +30059,8 @@ var Parser = class _Parser {
29491
30059
  pos: startPos
29492
30060
  };
29493
30061
  } else {
29494
- const element = this.parseType();
29495
- this.expect("operator", ">");
30062
+ const element = this.parseTypeOrFail({});
30063
+ if (!element || !this.expectTypeToken("operator", ">")) return null;
29496
30064
  inner = {
29497
30065
  kind: t.text === "List" ? "list" : "set",
29498
30066
  element,
@@ -29504,10 +30072,12 @@ var Parser = class _Parser {
29504
30072
  this.next();
29505
30073
  const typeArguments = [];
29506
30074
  if (this.eat("operator", "<")) {
29507
- typeArguments.push(this.parseType());
29508
- while (this.eat("punctuation", ","))
29509
- typeArguments.push(this.parseType());
29510
- this.expect("operator", ">");
30075
+ do {
30076
+ const argument2 = typeArguments.length === 0 && t.text === "NeoDelegate" ? this.parseDelegateReturnType() : this.parseTypeOrFail({});
30077
+ if (!argument2) return null;
30078
+ typeArguments.push(argument2);
30079
+ } while (this.eat("punctuation", ","));
30080
+ if (!this.expectTypeToken("operator", ">")) return null;
29511
30081
  }
29512
30082
  inner = {
29513
30083
  kind: "named",
@@ -29517,7 +30087,7 @@ var Parser = class _Parser {
29517
30087
  pos: startPos
29518
30088
  };
29519
30089
  } else {
29520
- throw new CompileError(`Expected a type, got ${describeToken(t)}`, at(t));
30090
+ return this.typeFailure(`Expected a type, got ${describeToken(t)}`, t);
29521
30091
  }
29522
30092
  while (this.peek().kind === "punctuation" && this.peek().text === "[" && this.peek(1).kind === "punctuation" && this.peek(1).text === "]") {
29523
30093
  const arrPos = at(this.peek());
@@ -29536,6 +30106,14 @@ var Parser = class _Parser {
29536
30106
  }
29537
30107
  return inner;
29538
30108
  }
30109
+ /** `NeoDelegate<void, …>`: the return slot is the one type that may be `void`. */
30110
+ parseDelegateReturnType() {
30111
+ const t = this.peek();
30112
+ if (t.kind !== "keyword" || t.text !== "void")
30113
+ return this.parseTypeOrFail({});
30114
+ this.next();
30115
+ return { kind: "primitive", name: "void", required: true, pos: at(t) };
30116
+ }
29539
30117
  /**
29540
30118
  * `is T ? a : b` is ambiguous at the token level because `?` is also the
29541
30119
  * nullable type suffix. A colon at the same delimiter depth makes it the
@@ -29890,7 +30468,7 @@ var Parser = class _Parser {
29890
30468
  }
29891
30469
  while (true) {
29892
30470
  let name = null;
29893
- if ((isIdentifier(this.peek()) || this.peek().kind === "keyword" && (this.peek().text === "default" || isValidNeoProjectIdentifier(this.peek().text))) && this.peek(1).kind === "punctuation" && this.peek(1).text === ":") {
30471
+ if (isCallArgumentLabelToken(this.peek()) && this.peek(1).kind === "punctuation" && this.peek(1).text === ":") {
29894
30472
  name = this.next().text;
29895
30473
  this.next();
29896
30474
  }
@@ -30373,6 +30951,9 @@ function at(token) {
30373
30951
  function tokenMatches(token, kind, text) {
30374
30952
  return (kind === "identifier" ? isIdentifier(token) : token.kind === kind) && (text === void 0 || token.text === text);
30375
30953
  }
30954
+ function isCallArgumentLabelToken(token) {
30955
+ return isIdentifier(token) || token.kind === "keyword" && (token.text === "default" || isValidNeoProjectIdentifier(token.text));
30956
+ }
30376
30957
  function isIdentifier(token) {
30377
30958
  return token.kind === "identifier" || token.kind === "type" && token.text !== "int" && token.text !== "float" && token.text !== "decimal" && token.text !== "bool" && token.text !== "string" && token.text !== "Dictionary" && token.text !== "List" && token.text !== "Set";
30378
30959
  }
@@ -30484,6 +31065,41 @@ function declarationInitializerContext(document2) {
30484
31065
  });
30485
31066
  return created;
30486
31067
  }
31068
+ var defaultValuePlansByDocument = /* @__PURE__ */ new WeakMap();
31069
+ function defaultValuePlans(document2) {
31070
+ const key = document2.databaseVM ?? initializerEvaluatorCacheKey(document2);
31071
+ const revision = initializerEvaluatorCacheRevision(document2);
31072
+ const valueGeneration = document2.databaseVM?.valueGeneration;
31073
+ const cached = defaultValuePlansByDocument.get(key);
31074
+ if (cached !== void 0 && (revision === void 0 ? cached.members === document2.members && cached.classes === document2.classes && cached.values === document2.values && cached.constructors === document2.constructors : cached.revision === revision && cached.valueGeneration === valueGeneration)) {
31075
+ return cached.plans;
31076
+ }
31077
+ const lookups = initializerEvaluatorLookups(document2);
31078
+ const plans = withIndexedDefaultValueDocument({
31079
+ project: document2.project,
31080
+ members: document2.members,
31081
+ classes: document2.classes,
31082
+ enums: document2.enums,
31083
+ values: document2.values,
31084
+ constructors: document2.constructors,
31085
+ projectFiles: document2.projectFiles,
31086
+ textureTemplates: document2.textureTemplates,
31087
+ memberById: lookups.memberById,
31088
+ valueById: lookups.defaultValueById ?? lookups.valueById,
31089
+ // A host database without list membership falls back to `values`.
31090
+ unorderedListEntryIds: document2.databaseVM?.unorderedListEntryIds === void 0 && document2.databaseVM !== void 0 ? void 0 : lookups.unorderedListEntryIds
31091
+ });
31092
+ defaultValuePlansByDocument.set(key, {
31093
+ members: document2.members,
31094
+ classes: document2.classes,
31095
+ values: document2.values,
31096
+ constructors: document2.constructors,
31097
+ revision,
31098
+ valueGeneration,
31099
+ plans
31100
+ });
31101
+ return plans;
31102
+ }
30487
31103
  function evaluateInitializerMaterialization(args) {
30488
31104
  const createdValues = [];
30489
31105
  const storageKeyDeclarations = /* @__PURE__ */ new Map();
@@ -30591,9 +31207,6 @@ function materializeInitializerValue(args) {
30591
31207
  function materializeMemberDefaultValue(args) {
30592
31208
  const createdValues = [];
30593
31209
  const storageKeyDeclarations = /* @__PURE__ */ new Map();
30594
- args.readTracking?.recordUnattributableValueRead(
30595
- ownershipChainRead("declaration-owner-resolution", args.envelope.id)
30596
- );
30597
31210
  const declarationArguments = (member, init, sourceValueId) => {
30598
31211
  const { valuesById, rootOwners } = declarationInitializerContext(
30599
31212
  args.document
@@ -30602,7 +31215,8 @@ function materializeMemberDefaultValue(args) {
30602
31215
  args.document,
30603
31216
  sourceValueId,
30604
31217
  rootOwners,
30605
- valuesById
31218
+ valuesById,
31219
+ (id) => args.readTracking?.valueIds.add(id)
30606
31220
  ).ownerClass : typeof Reflect.get(member, "id") === "string" ? findSchemaPlacement(
30607
31221
  String(Reflect.get(member, "id")),
30608
31222
  args.document.classes
@@ -30624,15 +31238,38 @@ function materializeMemberDefaultValue(args) {
30624
31238
  );
30625
31239
  };
30626
31240
  let lookups;
31241
+ const evaluatorLookups = () => lookups ??= initializerEvaluatorLookups(args.document, args.readTracking);
31242
+ const plans = args.readTracking !== void 0 && args.document.databaseVM === void 0 ? void 0 : defaultValuePlans(args.document);
30627
31243
  const built = buildDefaultMemberValue({
30628
31244
  document: {
30629
31245
  ...args.document,
31246
+ // The declaration rows a default clones are reads of this
31247
+ // materialization, like any row its initializers read.
30630
31248
  valueById: (id) => {
30631
- lookups ??= initializerEvaluatorLookups(
30632
- args.document,
30633
- args.readTracking
30634
- );
30635
- return (lookups.defaultValueById ?? lookups.valueById)(id);
31249
+ args.readTracking?.valueIds.add(id);
31250
+ const database = evaluatorLookups();
31251
+ return database.defaultValueById !== void 0 ? database.defaultValueById(id) : database.valueById(id);
31252
+ },
31253
+ unorderedListEntryIds: (containerId) => {
31254
+ args.readTracking?.containerIds.add(containerId);
31255
+ const entryIds = evaluatorLookups().unorderedListEntryIds?.(containerId);
31256
+ if (entryIds === void 0) {
31257
+ throw new Error(
31258
+ `Initializer lookups resolve no unordered-list membership for container "${containerId}".`
31259
+ );
31260
+ }
31261
+ return entryIds;
31262
+ },
31263
+ // Not `resolvedMember`: its id-keyed cache would answer for the
31264
+ // caller's rewritten copy of a member with the stored original.
31265
+ ...plans === void 0 ? {} : {
31266
+ instanceEnv: plans.instanceEnv,
31267
+ storedInstanceMaterializationPlan: plans.storedInstanceMaterializationPlan
31268
+ },
31269
+ recordPlanReads: (reads) => {
31270
+ for (const id of reads.valueIds) args.readTracking?.valueIds.add(id);
31271
+ for (const id of reads.containerIds)
31272
+ args.readTracking?.containerIds.add(id);
30636
31273
  }
30637
31274
  },
30638
31275
  projectId: args.envelope.projectId,
@@ -30711,10 +31348,6 @@ function buildVirtualInstanceMaterializedIndex(args) {
30711
31348
  })
30712
31349
  };
30713
31350
  }
30714
- var CORPUS_SCANNING_MEMBER_KINDS = /* @__PURE__ */ new Set([
30715
- 9 /* Lookup */,
30716
- 18 /* DialogueLookup */
30717
- ]);
30718
31351
  function derivesContentFromMemberDefault(args) {
30719
31352
  const member = args.member;
30720
31353
  if (!isMemberClassBase(member)) return false;
@@ -30778,43 +31411,50 @@ var VirtualExpansionUnsupportedError = class extends Error {
30778
31411
  this.name = "VirtualExpansionUnsupportedError";
30779
31412
  }
30780
31413
  };
30781
- function expandStoredInstance(args) {
30782
- const recorder = args.readRecorder ?? null;
30783
- const readTracking = recorder === null ? void 0 : new InitializerReadSet();
30784
- const trackMaterialization = readTracking === void 0 ? (materialize) => materialize() : (materialize) => {
31414
+ function materializationReadTracking(recorder) {
31415
+ if (recorder === void 0)
31416
+ return { readTracking: void 0, trackMaterialization: (m) => m() };
31417
+ const readTracking = new InitializerReadSet();
31418
+ const trackMaterialization = (materialize) => {
30785
31419
  try {
30786
31420
  return materialize();
30787
31421
  } finally {
30788
31422
  for (const valueId of readTracking.valueIds) {
30789
- recorder?.recordValueRead(valueId);
31423
+ recorder.recordValueRead(valueId);
30790
31424
  }
30791
31425
  for (const textId of readTracking.localizedTextIds) {
30792
- recorder?.recordLocalizedTextRead(textId);
31426
+ recorder.recordLocalizedTextRead(textId);
30793
31427
  }
30794
31428
  for (const variantId of readTracking.variantIds) {
30795
- recorder?.recordVariantRead(variantId);
31429
+ recorder.recordVariantRead(variantId);
30796
31430
  }
30797
31431
  for (const memberId of readTracking.staticMemberIds) {
30798
- recorder?.recordStaticMemberRead(memberId);
31432
+ recorder.recordStaticMemberRead(memberId);
30799
31433
  }
30800
31434
  for (const containerId of readTracking.containerIds) {
30801
- recorder?.recordContainerMembershipRead(containerId);
31435
+ recorder.recordContainerMembershipRead(containerId);
30802
31436
  }
30803
31437
  for (const read of readTracking.worldQueries) {
30804
- recorder?.recordWorldQueryRead?.(read);
31438
+ recorder.recordWorldQueryRead?.(read);
30805
31439
  }
30806
- if (readTracking.hasOwnershipChainRead) {
30807
- recorder?.recordGlobalRead(OWNERSHIP_CHAIN_READ);
31440
+ if (readTracking.hasValuePlacementRead) {
31441
+ recorder.recordValuePlacementRead();
30808
31442
  }
30809
31443
  for (const containerId of readTracking.containerEntryReadIds) {
30810
- recorder?.recordGlobalRead(containerEntriesRead(containerId));
31444
+ recorder.recordContainerMembershipRead(containerId);
30811
31445
  }
30812
31446
  for (const reason of readTracking.corpusReadReasons) {
30813
- recorder?.recordGlobalRead(reason);
31447
+ recorder.recordGlobalRead(reason);
30814
31448
  }
30815
31449
  }
30816
31450
  };
30817
- recorder?.recordValueRead(args.instanceRoot.id);
31451
+ return { readTracking, trackMaterialization };
31452
+ }
31453
+ function expandStoredInstance(args) {
31454
+ const { readTracking, trackMaterialization } = materializationReadTracking(
31455
+ args.readRecorder
31456
+ );
31457
+ args.readRecorder?.recordValueRead(args.instanceRoot.id);
30818
31458
  const rootMember = resolveMember(args.rootMember, args.document.members);
30819
31459
  if (!isMemberClassBase(rootMember)) {
30820
31460
  throw new Error(
@@ -30850,11 +31490,6 @@ function expandStoredInstance(args) {
30850
31490
  `Virtual expansion root "${args.instanceRoot.id}" is missing required constructor arguments.`
30851
31491
  );
30852
31492
  }
30853
- const constructorArguments = storedConstructorReplayArguments(
30854
- requiredConstructor,
30855
- storedArgs,
30856
- instanceRoot.id
30857
- );
30858
31493
  const {
30859
31494
  value: _value,
30860
31495
  classId: _classId,
@@ -30875,6 +31510,34 @@ function expandStoredInstance(args) {
30875
31510
  instanceRoot
30876
31511
  );
30877
31512
  const replayMember = closedRootMember === rootMember ? rootMember : { ...closedRootMember, classId };
31513
+ let environment;
31514
+ const constructorArguments = storedConstructorReplayArguments(
31515
+ requiredConstructor === null ? null : {
31516
+ ...requiredConstructor,
31517
+ argumentTypes: requiredConstructor.argumentTypes.map((argument2) => {
31518
+ if (argument2.type !== 21 /* Generic */) return argument2;
31519
+ environment ??= resolveInstanceEnv(
31520
+ classId,
31521
+ replayMember.classArguments,
31522
+ args.document.classes
31523
+ );
31524
+ const type = substituteInheritedCallableTypeInfo(
31525
+ argument2,
31526
+ environment,
31527
+ args.document.classes,
31528
+ args.document.members
31529
+ );
31530
+ if (type.type === NS_TYPE_VOID) {
31531
+ throw new Error(
31532
+ `Constructor parameter "${argument2.name}" on "${classId}" cannot have type void.`
31533
+ );
31534
+ }
31535
+ return { ...type, name: argument2.name };
31536
+ })
31537
+ },
31538
+ storedArgs,
31539
+ instanceRoot.id
31540
+ );
30878
31541
  const replay = (fields) => {
30879
31542
  const init = storedConstructorReplayInitializer({
30880
31543
  classId,
@@ -30939,11 +31602,7 @@ function expandStoredInstance(args) {
30939
31602
  function resolveVirtualInstanceGraph(args) {
30940
31603
  const expansion = args.expansionIndex ?? indexExpansion(args);
30941
31604
  const recorder = args.readRecorder ?? null;
30942
- if (recorder !== null) {
30943
- recorder.recordValueRead(args.instanceRoot.id);
30944
- const unattributable = firstUnattributableExpansionMember(expansion);
30945
- if (unattributable !== null) recorder.recordGlobalRead(unattributable);
30946
- }
31605
+ recorder?.recordValueRead(args.instanceRoot.id);
30947
31606
  const materializedById = args.materializedIndex?.rowsById ?? new Map(
30948
31607
  (args.materializedRows ?? args.document.values).map((row) => [
30949
31608
  row.id,
@@ -31498,15 +32157,6 @@ function mergeExpandedAndMaterializedRow(expanded, materialized) {
31498
32157
  if (merged.sourceValueId === materialized.id) delete merged.sourceValueId;
31499
32158
  return merged;
31500
32159
  }
31501
- function firstUnattributableExpansionMember(expansion) {
31502
- for (const node of expansion.nodesByPath.values()) {
31503
- const member = node.member;
31504
- if (CORPUS_SCANNING_MEMBER_KINDS.has(member.kind)) {
31505
- return `corpus-scanning-member-kind:${node.memberId}`;
31506
- }
31507
- }
31508
- return null;
31509
- }
31510
32160
  function prepareStoredClassValueResolution(args) {
31511
32161
  let listenerDefaults;
31512
32162
  let copiedListeners;
@@ -31518,9 +32168,10 @@ function prepareStoredClassValueResolution(args) {
31518
32168
  ...args.document,
31519
32169
  // Construction checks share the existing schema index across every nested default.
31520
32170
  memberById: args.document.memberById ?? ((id) => schema.member(id) ?? null),
31521
- evaluatorCache: {
31522
- key: initializerEvaluatorCacheKey(args.document),
31523
- revision: initializerEvaluatorCacheRevision(args.document)
32171
+ // The same rows under a fresh object: share its evaluator caches.
32172
+ evaluatorCache: args.document.evaluatorCache ?? {
32173
+ key: args.document,
32174
+ revision: void 0
31524
32175
  },
31525
32176
  listenerDefaultCapture: {
31526
32177
  begin: () => {
@@ -31596,27 +32247,32 @@ function expandStoredClassValue(args) {
31596
32247
  }
31597
32248
  const classId = root.classId ?? member.classId;
31598
32249
  args.readRecorder?.recordValueRead(root.id);
31599
- args.readRecorder?.recordGlobalRead("declaration-default");
31600
- const materialized = materializeMemberDefaultValue({
31601
- saveStaticBindings: args.saveStaticBindings,
31602
- sessionStaticBindings: args.sessionStaticBindings,
31603
- evaluateInitializer: args.evaluateInitializer,
31604
- document: args.document,
31605
- member: closeClassArgumentsFromRowStamp(
31606
- {
31607
- ...member,
31608
- classId,
31609
- defaultValue: derivesContentFromMemberDefault({
31610
- member,
31611
- instanceRoot: root,
31612
- effectiveClassId: classId
31613
- }) ? member.defaultValue : void 0
31614
- },
31615
- root
31616
- ),
31617
- envelope: root,
31618
- declarationRoot: true
31619
- });
32250
+ const { readTracking, trackMaterialization } = materializationReadTracking(
32251
+ args.readRecorder
32252
+ );
32253
+ const materialized = trackMaterialization(
32254
+ () => materializeMemberDefaultValue({
32255
+ ...readTracking === void 0 ? {} : { readTracking },
32256
+ saveStaticBindings: args.saveStaticBindings,
32257
+ sessionStaticBindings: args.sessionStaticBindings,
32258
+ evaluateInitializer: args.evaluateInitializer,
32259
+ document: args.document,
32260
+ member: closeClassArgumentsFromRowStamp(
32261
+ {
32262
+ ...member,
32263
+ classId,
32264
+ defaultValue: derivesContentFromMemberDefault({
32265
+ member,
32266
+ instanceRoot: root,
32267
+ effectiveClassId: classId
32268
+ }) ? member.defaultValue : void 0
32269
+ },
32270
+ root
32271
+ ),
32272
+ envelope: root,
32273
+ declarationRoot: true
32274
+ })
32275
+ );
31620
32276
  return {
31621
32277
  root: { ...root, classId, value: materialized.root.value },
31622
32278
  rows: materialized.createdValues,
@@ -32371,6 +33027,17 @@ function variantSwapDeclaredMember(document2, rootValueId) {
32371
33027
  if (placement === void 0) return void 0;
32372
33028
  return document2.members.find((member) => member.id === placement.memberId);
32373
33029
  }
33030
+ function emptyExpansionReads() {
33031
+ return {
33032
+ valueIds: /* @__PURE__ */ new Set(),
33033
+ containerIds: /* @__PURE__ */ new Set(),
33034
+ localizedTextIds: /* @__PURE__ */ new Set(),
33035
+ variantIds: /* @__PURE__ */ new Set(),
33036
+ staticMemberIds: /* @__PURE__ */ new Set(),
33037
+ global: false,
33038
+ merged: /* @__PURE__ */ new WeakSet()
33039
+ };
33040
+ }
32374
33041
  function createHeadlessVirtualInstanceResolver(args) {
32375
33042
  const { document: document2 } = args;
32376
33043
  const membersById = args.membersById ?? new Map(document2.members.map((member) => [member.id, member]));
@@ -32394,16 +33061,22 @@ function createHeadlessVirtualInstanceResolver(args) {
32394
33061
  const emptyRows = [];
32395
33062
  const graphByValueId = /* @__PURE__ */ new Map();
32396
33063
  const failedRootIds = /* @__PURE__ */ new Set();
33064
+ const expandingRootIds = /* @__PURE__ */ new Set();
32397
33065
  const expandedRowById = /* @__PURE__ */ new Map();
32398
33066
  const expandedRowByRecord = /* @__PURE__ */ new WeakMap();
32399
33067
  const readsByRootId = /* @__PURE__ */ new Map();
32400
33068
  const activeReads = [];
32401
33069
  const sharedByReceiverId = /* @__PURE__ */ new Map();
33070
+ const callerReads = /* @__PURE__ */ new WeakMap();
32402
33071
  const mergeReads = (reads) => {
32403
33072
  for (const active of activeReads) {
32404
- if (active === reads) continue;
33073
+ if (active === reads || active.merged.has(reads)) continue;
33074
+ active.merged.add(reads);
32405
33075
  for (const id of reads.valueIds) active.valueIds.add(id);
32406
33076
  for (const id of reads.containerIds) active.containerIds.add(id);
33077
+ for (const id of reads.localizedTextIds) active.localizedTextIds.add(id);
33078
+ for (const id of reads.variantIds) active.variantIds.add(id);
33079
+ for (const id of reads.staticMemberIds) active.staticMemberIds.add(id);
32407
33080
  if (reads.global) active.global = true;
32408
33081
  }
32409
33082
  };
@@ -32412,9 +33085,18 @@ function createHeadlessVirtualInstanceResolver(args) {
32412
33085
  for (const active of activeReads) active.valueIds.add(id);
32413
33086
  args.readRecorder?.recordValueRead(id);
32414
33087
  },
32415
- recordLocalizedTextRead: (id) => args.readRecorder?.recordLocalizedTextRead(id),
32416
- recordVariantRead: (id) => args.readRecorder?.recordVariantRead(id),
32417
- recordStaticMemberRead: (id) => args.readRecorder?.recordStaticMemberRead(id),
33088
+ recordLocalizedTextRead: (id) => {
33089
+ for (const active of activeReads) active.localizedTextIds.add(id);
33090
+ args.readRecorder?.recordLocalizedTextRead(id);
33091
+ },
33092
+ recordVariantRead: (id) => {
33093
+ for (const active of activeReads) active.variantIds.add(id);
33094
+ args.readRecorder?.recordVariantRead(id);
33095
+ },
33096
+ recordStaticMemberRead: (id) => {
33097
+ for (const active of activeReads) active.staticMemberIds.add(id);
33098
+ args.readRecorder?.recordStaticMemberRead(id);
33099
+ },
32418
33100
  recordContainerMembershipRead: (id) => {
32419
33101
  for (const active of activeReads) active.containerIds.add(id);
32420
33102
  args.readRecorder?.recordContainerMembershipRead(id);
@@ -32460,6 +33142,7 @@ function createHeadlessVirtualInstanceResolver(args) {
32460
33142
  if (reads2 !== void 0) mergeReads(reads2);
32461
33143
  return cached;
32462
33144
  }
33145
+ if (expandingRootIds.has(rootId)) return emptyRows;
32463
33146
  if (failedRootIds.has(rootId)) return emptyRows;
32464
33147
  const instanceRoot = rawById.get(rootId);
32465
33148
  if (instanceRoot === void 0 || declaredMember === void 0) {
@@ -32475,12 +33158,9 @@ function createHeadlessVirtualInstanceResolver(args) {
32475
33158
  failedRootIds.add(rootId);
32476
33159
  return emptyRows;
32477
33160
  }
32478
- const reads = {
32479
- valueIds: /* @__PURE__ */ new Set(),
32480
- containerIds: /* @__PURE__ */ new Set(),
32481
- global: false
32482
- };
33161
+ const reads = emptyExpansionReads();
32483
33162
  activeReads.push(reads);
33163
+ expandingRootIds.add(rootId);
32484
33164
  try {
32485
33165
  const resolverDocument = resolverDocumentOnce();
32486
33166
  materializedIndex ??= buildVirtualInstanceMaterializedIndex({
@@ -32504,6 +33184,7 @@ function createHeadlessVirtualInstanceResolver(args) {
32504
33184
  failedRootIds.add(rootId);
32505
33185
  return emptyRows;
32506
33186
  } finally {
33187
+ expandingRootIds.delete(rootId);
32507
33188
  activeReads.pop();
32508
33189
  mergeReads(reads);
32509
33190
  }
@@ -32522,9 +33203,15 @@ function createHeadlessVirtualInstanceResolver(args) {
32522
33203
  share.containerChanged
32523
33204
  );
32524
33205
  if (shared === null) return null;
33206
+ recorder.recordValuePlacementRead();
32525
33207
  for (const id of shared.reads.valueIds) recorder.recordValueRead(id);
32526
33208
  for (const id of shared.reads.containerIds)
32527
33209
  recorder.recordContainerMembershipRead(id);
33210
+ for (const id of shared.reads.localizedTextIds)
33211
+ recorder.recordLocalizedTextRead(id);
33212
+ for (const id of shared.reads.variantIds) recorder.recordVariantRead(id);
33213
+ for (const id of shared.reads.staticMemberIds)
33214
+ recorder.recordStaticMemberRead(id);
32528
33215
  if (graphRowsByRootId.get(shared.graph.instanceRootId) === void 0) {
32529
33216
  readsByRootId.set(shared.graph.instanceRootId, shared.reads);
32530
33217
  remember(shared.graph, shared.rows);
@@ -32568,7 +33255,16 @@ function createHeadlessVirtualInstanceResolver(args) {
32568
33255
  return graph?.instanceRootId === rootId ? graph : null;
32569
33256
  },
32570
33257
  virtualInstanceRowsForValue,
32571
- valueById: (id) => expandedRowById.get(id) ?? null,
33258
+ valueById: (id) => {
33259
+ const row = expandedRowById.get(id);
33260
+ if (row === void 0) return null;
33261
+ if (activeReads.length > 0) {
33262
+ const rootId = graphByValueId.get(id)?.instanceRootId;
33263
+ const reads = rootId === void 0 ? void 0 : readsByRootId.get(rootId);
33264
+ if (reads !== void 0) mergeReads(reads);
33265
+ }
33266
+ return row;
33267
+ },
32572
33268
  rowForValueReference: (value) => expandedRowByRecord.get(value) ?? null,
32573
33269
  virtualInstanceGraphForValue: (valueId) => {
32574
33270
  const known = graphByValueId.get(valueId);
@@ -32580,11 +33276,7 @@ function createHeadlessVirtualInstanceResolver(args) {
32580
33276
  return graphByValueId.get(valueId) ?? null;
32581
33277
  },
32582
33278
  shareExpansion: (receiverValueId, masked, containerChanged) => {
32583
- const reads = {
32584
- valueIds: /* @__PURE__ */ new Set(),
32585
- containerIds: /* @__PURE__ */ new Set(),
32586
- global: false
32587
- };
33279
+ const reads = emptyExpansionReads();
32588
33280
  activeReads.push(reads);
32589
33281
  let rows;
32590
33282
  try {
@@ -32605,6 +33297,29 @@ function createHeadlessVirtualInstanceResolver(args) {
32605
33297
  );
32606
33298
  }
32607
33299
  return { graph, rows, reads };
33300
+ },
33301
+ recordReads: (target, read) => {
33302
+ let reads = callerReads.get(target);
33303
+ if (reads === void 0) {
33304
+ reads = {
33305
+ valueIds: target.valueIds,
33306
+ containerIds: target.containerIds,
33307
+ localizedTextIds: target.localizedTextIds,
33308
+ variantIds: target.variantIds,
33309
+ staticMemberIds: target.staticMemberIds,
33310
+ global: false,
33311
+ merged: /* @__PURE__ */ new WeakSet()
33312
+ };
33313
+ callerReads.set(target, reads);
33314
+ }
33315
+ activeReads.push(reads);
33316
+ try {
33317
+ return read();
33318
+ } finally {
33319
+ activeReads.pop();
33320
+ if (reads.global)
33321
+ target.recordUnattributableValueRead("virtual-instance-expansion");
33322
+ }
32608
33323
  }
32609
33324
  };
32610
33325
  }
@@ -32654,6 +33369,10 @@ function initializerEvaluatorLookups(document2, readTracking) {
32654
33369
  ...databaseVM.changeListenerDefaultsForOwner === void 0 ? {} : {
32655
33370
  changeListenerDefaultsForOwner: (id) => databaseVM.changeListenerDefaultsForOwner(id)
32656
33371
  },
33372
+ // Read live: this wrapper outlives a scalar's nullness change.
33373
+ get valueGeneration() {
33374
+ return databaseVM.valueGeneration;
33375
+ },
32657
33376
  memberById: (id) => databaseVM.memberById(id),
32658
33377
  valueById: (id) => databaseVM.valueById(id),
32659
33378
  defaultValueById: (id) => databaseVM.defaultValueById?.(id) ?? databaseVM.valueById(id),
@@ -32680,6 +33399,7 @@ function initializerEvaluatorLookups(document2, readTracking) {
32680
33399
  return resolved;
32681
33400
  },
32682
33401
  virtualInstanceRowsForValue: (receiverValueId) => databaseVM.virtualInstanceRowsForValue(receiverValueId),
33402
+ ...databaseVM.worldGridQueryIndex === void 0 ? {} : { worldGridQueryIndex: () => databaseVM.worldGridQueryIndex() },
32683
33403
  rowForValueReference: (value) => databaseVM.rowForValueReference?.(value) ?? null,
32684
33404
  resolveVariantInstanceGraph: (args) => {
32685
33405
  const resolver = databaseVM.resolveVariantInstanceGraph;
@@ -32708,88 +33428,45 @@ function initializerEvaluatorLookups(document2, readTracking) {
32708
33428
  indexKey,
32709
33429
  revision
32710
33430
  );
32711
- const shareFrom = document2.databaseVM === void 0 && document2.evaluatorOverlay !== void 0 ? sharedHeadlessResolver(document2.evaluatorOverlay) : void 0;
33431
+ const shareFrom = document2.evaluatorOverlay === void 0 ? void 0 : sharedHeadlessResolver(document2.evaluatorOverlay);
32712
33432
  let hasListenerMetadata;
32713
- const headlessVirtualResolver = document2.databaseVM === void 0 ? createHeadlessVirtualInstanceResolver({
33433
+ const headlessVirtualResolver = createHeadlessVirtualInstanceResolver({
32714
33434
  evaluateInitializer: evaluateMemberInitializer,
32715
33435
  document: document2,
32716
33436
  resolverLookups: () => lookups,
32717
33437
  ...shareFrom === void 0 ? {} : { shareFrom },
32718
33438
  ...readTracking === void 0 ? {} : { readRecorder: virtualReadRecorder(readTracking) }
32719
- }) : null;
33439
+ });
32720
33440
  const lookups = {
32721
33441
  ...indexedLookups,
32722
- ...document2.databaseVM === void 0 && headlessVirtualResolver !== null ? {
32723
- changeListenerDefaultsForOwner: (id) => {
32724
- if (!(hasListenerMetadata ??= hasAuthoredChangeListenerMetadata(document2)))
32725
- return void 0;
32726
- const inherited = headlessVirtualResolver.virtualInstanceGraphForValue(id)?.listenerDefaultsByOwner?.get(id);
32727
- const authored = authoredChangeListenerOwners(document2.values).get(
32728
- id
32729
- );
32730
- return inherited === void 0 ? authored : { ...inherited, ...authored };
32731
- },
32732
- defaultValueById: (id) => declarationDefaultSource(
32733
- id,
32734
- indexedLookups.valueById(id),
32735
- headlessVirtualResolver.virtualInstanceGraphForValue
32736
- ),
32737
- valueById: (id) => indexedLookups.valueById(id) ?? headlessVirtualResolver.valueById(id),
32738
- rowForValueReference: (value) => indexedLookups.rowForValueReference?.(value) ?? headlessVirtualResolver.rowForValueReference(value),
32739
- virtualInstanceRowsForValue: (receiverValueId) => headlessVirtualResolver.virtualInstanceRowsForValue(
32740
- receiverValueId
32741
- ),
32742
- // Headless hosts still evaluate `ToVariant` during
32743
- // stored-construction replay — production's variant-constructed
32744
- // placements collapse through exactly this path. The shared core
32745
- // resolves against the plain document, with these lookups as the
32746
- // nested resolver.
32747
- resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
32748
- evaluateInitializer: evaluateMemberInitializer,
32749
- document: document2,
32750
- resolverLookups: lookups,
32751
- ...readTracking === void 0 ? {} : { readRecorder: virtualReadRecorder(readTracking) },
32752
- ...args
32753
- })
32754
- } : {
32755
- get worldQueryRevision() {
32756
- return document2.databaseVM?.worldQueryRevision;
32757
- },
32758
- memberById: (id) => document2.databaseVM?.memberById(id) ?? null,
32759
- valueById: (id) => document2.databaseVM?.valueById(id) ?? null,
32760
- variantById: (id) => document2.databaseVM?.variantById?.(id) ?? null,
32761
- // The VM's `valueById` answers EXPANDED-first: a collapse-stamped
32762
- // root resolves to a record the VM minted, an object the raw value
32763
- // index has never seen. Reference-identity dispatch (`.Id`, `is`,
32764
- // lookup selection) must reach the VM's reverse map for those
32765
- // records — dropping to the raw index alone made every lookup
32766
- // variant's initializer report "produced a value with no backing
32767
- // row" once P75 expansion started succeeding.
32768
- rowForValueReference: (value) => indexedLookups.rowForValueReference?.(value) ?? document2.databaseVM?.rowForValueReference?.(value) ?? null,
32769
- unorderedListEntryIds: (containerValueId) => {
32770
- const resolved = document2.databaseVM?.unorderedListEntryIds?.(containerValueId) ?? indexedLookups.unorderedListEntryIds?.(containerValueId);
32771
- if (resolved === void 0) {
32772
- throw new Error(
32773
- `Evaluator database resolves no unordered-list membership for container "${containerValueId}".`
32774
- );
32775
- }
32776
- return resolved;
32777
- },
32778
- virtualInstanceRowsForValue: (receiverValueId) => {
32779
- const databaseVM = document2.databaseVM;
32780
- if (databaseVM === void 0) return [];
32781
- return databaseVM.virtualInstanceRowsForValue(receiverValueId);
32782
- },
32783
- resolveVariantInstanceGraph: (args) => {
32784
- const resolver = document2.databaseVM?.resolveVariantInstanceGraph;
32785
- if (resolver === void 0) {
32786
- throw new Error(
32787
- "Evaluator database has no virtual variant resolver."
32788
- );
32789
- }
32790
- return resolver.call(document2.databaseVM, args);
32791
- }
32792
- }
33442
+ changeListenerDefaultsForOwner: (id) => {
33443
+ if (!(hasListenerMetadata ??= hasAuthoredChangeListenerMetadata(document2)))
33444
+ return void 0;
33445
+ const inherited = headlessVirtualResolver.virtualInstanceGraphForValue(id)?.listenerDefaultsByOwner?.get(id);
33446
+ const authored = authoredChangeListenerOwners(document2.values).get(id);
33447
+ return inherited === void 0 ? authored : { ...inherited, ...authored };
33448
+ },
33449
+ defaultValueById: (id) => declarationDefaultSource(
33450
+ id,
33451
+ indexedLookups.valueById(id),
33452
+ headlessVirtualResolver.virtualInstanceGraphForValue
33453
+ ),
33454
+ valueById: (id) => indexedLookups.valueById(id) ?? headlessVirtualResolver.valueById(id),
33455
+ rowForValueReference: (value) => indexedLookups.rowForValueReference?.(value) ?? headlessVirtualResolver.rowForValueReference(value),
33456
+ virtualInstanceRowsForValue: (receiverValueId) => headlessVirtualResolver.virtualInstanceRowsForValue(receiverValueId),
33457
+ recordVirtualInstanceReads: (reads, read) => headlessVirtualResolver.recordReads(reads, read),
33458
+ // Headless hosts still evaluate `ToVariant` during
33459
+ // stored-construction replay — production's variant-constructed
33460
+ // placements collapse through exactly this path. The shared core
33461
+ // resolves against the plain document, with these lookups as the
33462
+ // nested resolver.
33463
+ resolveVariantInstanceGraph: (args) => resolveVariantInstanceGraphForDocument({
33464
+ evaluateInitializer: evaluateMemberInitializer,
33465
+ document: document2,
33466
+ resolverLookups: lookups,
33467
+ ...readTracking === void 0 ? {} : { readRecorder: virtualReadRecorder(readTracking) },
33468
+ ...args
33469
+ })
32793
33470
  };
32794
33471
  if (!trackedHeadless) {
32795
33472
  evaluatorLookupsByDocument.set(lookupKey, {
@@ -32798,8 +33475,7 @@ function initializerEvaluatorLookups(document2, readTracking) {
32798
33475
  revision,
32799
33476
  lookups
32800
33477
  });
32801
- if (headlessVirtualResolver !== null)
32802
- headlessResolversByLookupKey.set(lookupKey, headlessVirtualResolver);
33478
+ headlessResolversByLookupKey.set(lookupKey, headlessVirtualResolver);
32803
33479
  }
32804
33480
  return lookups;
32805
33481
  }
@@ -32976,6 +33652,9 @@ function evaluateMemberInitializer(args) {
32976
33652
  } catch (error) {
32977
33653
  if (error instanceof NSGetterRuntimeError) {
32978
33654
  error.initializerValueId ??= args.sourceValueId ?? void 0;
33655
+ const memberId = Reflect.get(args.member, "id");
33656
+ if (args.sourceValueId == null && typeof memberId === "string")
33657
+ error.sourceOwnerId ??= memberId;
32979
33658
  }
32980
33659
  throw error;
32981
33660
  }
@@ -33116,53 +33795,6 @@ function memoizeFrozenJsonGuard(isValid) {
33116
33795
  };
33117
33796
  }
33118
33797
 
33119
- // ../packages/manifest/src/value-comparison.ts
33120
- function isObjectRecord(value) {
33121
- return typeof value === "object" && value !== null && !Array.isArray(value);
33122
- }
33123
-
33124
- // ../packages/neoscript-runtime/src/values/canonical-json.ts
33125
- function canonicalJsonStringify(value) {
33126
- return JSON.stringify(toCanonicalJsonValue(value));
33127
- }
33128
- function toCanonicalJsonValue(value) {
33129
- if (value === null) return null;
33130
- if (value === void 0) return void 0;
33131
- if (value instanceof Date) return value.toISOString();
33132
- if (typeof value === "string") return value;
33133
- if (typeof value === "boolean") return value;
33134
- if (typeof value === "number") {
33135
- if (!Number.isFinite(value)) {
33136
- throw new Error("Cannot canonicalize a non-finite number.");
33137
- }
33138
- return value;
33139
- }
33140
- if (typeof value === "bigint") {
33141
- throw new Error("Cannot canonicalize bigint values.");
33142
- }
33143
- if (typeof value === "symbol") {
33144
- throw new Error("Cannot canonicalize symbol values.");
33145
- }
33146
- if (typeof value === "function") {
33147
- throw new Error("Cannot canonicalize function values.");
33148
- }
33149
- if (Array.isArray(value)) {
33150
- return value.map((item) => {
33151
- const canonicalItem = toCanonicalJsonValue(item);
33152
- if (canonicalItem === void 0) return null;
33153
- return canonicalItem;
33154
- });
33155
- }
33156
- const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
33157
- const canonicalObject = {};
33158
- for (const [key, entryValue] of entries) {
33159
- const canonicalValue = toCanonicalJsonValue(entryValue);
33160
- if (canonicalValue === void 0) continue;
33161
- canonicalObject[key] = canonicalValue;
33162
- }
33163
- return canonicalObject;
33164
- }
33165
-
33166
33798
  // ../packages/neoscript-language/src/syntax-index.ts
33167
33799
  var OPEN_TO_CLOSE = /* @__PURE__ */ new Map([
33168
33800
  ["(", ")"],
@@ -33240,6 +33872,9 @@ function buildNeoScriptEditorIndex(lexed, kind) {
33240
33872
  const references = [];
33241
33873
  const calls = [];
33242
33874
  const switches = [];
33875
+ const lambdaBodies = [];
33876
+ const contextualKeywordRanges = [];
33877
+ const objectInitializers = [];
33243
33878
  for (const executable of executableRegions) {
33244
33879
  const executablePairs = pairBrackets(executable);
33245
33880
  const regionSwitches = indexSwitchStatements(
@@ -33249,7 +33884,13 @@ function buildNeoScriptEditorIndex(lexed, kind) {
33249
33884
  diagnostics
33250
33885
  );
33251
33886
  const regionLocals = applySwitchSectionScopes(
33252
- indexLocals(executable, executablePairs, lexed, diagnostics),
33887
+ indexLocals(
33888
+ executable,
33889
+ executablePairs,
33890
+ lexed,
33891
+ diagnostics,
33892
+ lambdaBodies
33893
+ ),
33253
33894
  regionSwitches,
33254
33895
  lexed
33255
33896
  );
@@ -33260,24 +33901,36 @@ function buildNeoScriptEditorIndex(lexed, kind) {
33260
33901
  )
33261
33902
  );
33262
33903
  const contextualKeywords = new Set(
33263
- [
33264
- ...regionLocals.flatMap(
33265
- (local) => local.contextualKeywordRange ? [local.contextualKeywordRange] : []
33266
- ),
33267
- ...regionCalls.flatMap(
33268
- (call) => call.contextualKeywordRange ? [call.contextualKeywordRange] : []
33269
- )
33270
- ].map((range2) => `${range2.start.line}:${range2.start.character}`)
33904
+ regionLocals.flatMap(
33905
+ (local) => local.contextualKeywordRange ? [local.contextualKeywordRange] : []
33906
+ ).map((range2) => `${range2.start.line}:${range2.start.character}`)
33271
33907
  );
33272
33908
  locals.push(...regionLocals);
33273
33909
  references.push(
33274
- ...indexReferences(executable, declarations, contextualKeywords)
33910
+ ...indexReferences(
33911
+ executable,
33912
+ executablePairs,
33913
+ declarations,
33914
+ contextualKeywords,
33915
+ contextualKeywordRanges,
33916
+ objectInitializers
33917
+ )
33275
33918
  );
33276
33919
  calls.push(...regionCalls);
33277
33920
  switches.push(...regionSwitches);
33278
33921
  validateTerminatedStatements(executable, diagnostics);
33279
33922
  }
33280
- return { units, locals, references, calls, switches, diagnostics };
33923
+ return {
33924
+ units,
33925
+ locals,
33926
+ references,
33927
+ calls,
33928
+ switches,
33929
+ lambdaBodies,
33930
+ contextualKeywordRanges,
33931
+ objectInitializers,
33932
+ diagnostics
33933
+ };
33281
33934
  }
33282
33935
  function indexUnits(tokens, pairs, kind, lexed) {
33283
33936
  if (kind !== "property") {
@@ -33694,8 +34347,9 @@ function duplicateUnitDiagnostic(label, units, diagnostics) {
33694
34347
  ]
33695
34348
  });
33696
34349
  }
33697
- function indexLocals(tokens, pairs, lexed, diagnostics) {
34350
+ function indexLocals(tokens, pairs, lexed, diagnostics, lambdaBodies) {
33698
34351
  const locals = [];
34352
+ const braceScope = braceScopeIndex(tokens, lexed.end);
33699
34353
  for (let index = 0; index < tokens.length; index++) {
33700
34354
  const caught = tryParseCatchParameter(tokens, index, pairs, lexed);
33701
34355
  if (caught) {
@@ -33703,7 +34357,14 @@ function indexLocals(tokens, pairs, lexed, diagnostics) {
33703
34357
  index = caught.resumeTokenIndex;
33704
34358
  continue;
33705
34359
  }
33706
- const loop = tryParseLoopLocal(tokens, index, pairs, lexed, diagnostics);
34360
+ const loop = tryParseLoopLocal(
34361
+ tokens,
34362
+ index,
34363
+ pairs,
34364
+ lexed,
34365
+ diagnostics,
34366
+ braceScope
34367
+ );
33707
34368
  if (loop) {
33708
34369
  locals.push(...loop.locals);
33709
34370
  index = loop.resumeTokenIndex;
@@ -33712,10 +34373,16 @@ function indexLocals(tokens, pairs, lexed, diagnostics) {
33712
34373
  const lambda = tryParseLambdaParameters(tokens, index, pairs, lexed);
33713
34374
  if (lambda) {
33714
34375
  locals.push(...lambda.locals);
34376
+ lambdaBodies.push(lambda.body);
33715
34377
  index = lambda.endTokenIndex;
33716
34378
  continue;
33717
34379
  }
33718
- const declaration = tryParseVariableDeclaration(tokens, index, lexed);
34380
+ const declaration = tryParseVariableDeclaration(
34381
+ tokens,
34382
+ index,
34383
+ lexed,
34384
+ braceScope
34385
+ );
33719
34386
  if (!declaration) continue;
33720
34387
  locals.push(declaration.local);
33721
34388
  if (declaration.missingInitializer) {
@@ -33731,36 +34398,14 @@ function indexLocals(tokens, pairs, lexed, diagnostics) {
33731
34398
  }
33732
34399
  return locals;
33733
34400
  }
33734
- function tryParseVariableDeclaration(tokens, start, lexed) {
34401
+ function tryParseVariableDeclaration(tokens, start, lexed, braceScope) {
33735
34402
  const first = tokens[start];
33736
34403
  if (!first || first.kind !== "type" && first.kind !== "identifier")
33737
34404
  return null;
33738
34405
  const inferred = first.kind === "identifier" && first.text === NEOSCRIPT_INFERRED_LOCAL_KEYWORD;
33739
- let cursor = start + 1;
33740
- if (!inferred && (first.text === "Dictionary" || first.text === "Set")) {
33741
- const open = tokens[cursor];
33742
- if (!open || open.kind !== "operator" || open.text !== "<") return null;
33743
- let angleDepth = 0;
33744
- while (cursor < tokens.length) {
33745
- const token = tokens[cursor];
33746
- if (!token) return null;
33747
- if (token.kind === "operator" && token.text === "<") angleDepth++;
33748
- if (token.kind === "operator" && token.text === ">") {
33749
- angleDepth--;
33750
- if (angleDepth === 0) {
33751
- cursor++;
33752
- break;
33753
- }
33754
- }
33755
- cursor++;
33756
- }
33757
- }
33758
- while (!inferred && tokens[cursor]?.kind === "punctuation" && tokens[cursor]?.text === "[" && tokens[cursor + 1]?.kind === "punctuation" && tokens[cursor + 1]?.text === "]") {
33759
- cursor += 2;
33760
- }
33761
- if (!inferred && tokens[cursor]?.kind === "operator" && tokens[cursor]?.text === "?") {
33762
- cursor++;
33763
- }
34406
+ if (!inferred && !mayStartTypedLocal(tokens, start)) return null;
34407
+ const cursor = inferred ? start + 1 : new Parser(tokens, start).typeEnd();
34408
+ if (cursor < 0) return null;
33764
34409
  const name = tokens[cursor];
33765
34410
  const equals = tokens[cursor + 1];
33766
34411
  if (!name || name.kind !== "identifier") return null;
@@ -33772,7 +34417,7 @@ function tryParseVariableDeclaration(tokens, start, lexed) {
33772
34417
  const statementEnd = statementEndTokenIndex(tokens, cursor + 2);
33773
34418
  const initializerTokens = hasEquals ? tokens.slice(cursor + 2, statementEnd) : [];
33774
34419
  const terminator = tokens[statementEnd];
33775
- const scope = containingBraceRange(tokens, start, lexed.end);
34420
+ const scope = braceScope(start);
33776
34421
  return {
33777
34422
  local: {
33778
34423
  name: name.text,
@@ -33790,6 +34435,24 @@ function tryParseVariableDeclaration(tokens, start, lexed) {
33790
34435
  missingInitializer: inferred && (!hasEquals || initializerTokens.length === 0)
33791
34436
  };
33792
34437
  }
34438
+ var STATEMENT_BOUNDARY_TOKENS = /* @__PURE__ */ new Set([
34439
+ ";",
34440
+ "{",
34441
+ "}",
34442
+ ")",
34443
+ ":"
34444
+ ]);
34445
+ function mayStartTypedLocal(tokens, start) {
34446
+ const previous = tokens[start - 1];
34447
+ if (previous && !STATEMENT_BOUNDARY_TOKENS.has(previous.text) && previous.text !== "else" && !(previous.text === "(" && tokens[start - 2]?.text === "for")) {
34448
+ return false;
34449
+ }
34450
+ const next = tokens[start + 1];
34451
+ if (!next) return false;
34452
+ if (next.kind === "identifier") return true;
34453
+ if (next.kind === "operator") return next.text === "<" || next.text === "?";
34454
+ return next.kind === "punctuation" && next.text === "[";
34455
+ }
33793
34456
  function statementEndTokenIndex(tokens, start) {
33794
34457
  let depth = 0;
33795
34458
  for (let cursor = start; cursor < tokens.length; cursor++) {
@@ -33816,6 +34479,7 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
33816
34479
  if (!arrow2 || arrow2.kind !== "operator" || arrow2.text !== "=>") {
33817
34480
  return null;
33818
34481
  }
34482
+ const body2 = lambdaBodySpan(tokens, start + 1, pairs, lexed);
33819
34483
  return {
33820
34484
  locals: [
33821
34485
  {
@@ -33824,17 +34488,13 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
33824
34488
  typeTokens: [],
33825
34489
  inferred: false,
33826
34490
  declarationRange: open.range,
33827
- scopeStart: arrow2.end,
33828
- scopeEnd: lambdaExpressionScopeEnd(
33829
- tokens,
33830
- start + 2,
33831
- pairs,
33832
- lexed.end
33833
- ),
34491
+ scopeStart: body2.start,
34492
+ scopeEnd: body2.end,
33834
34493
  lambdaParameter: true,
33835
34494
  lambdaParameterIndex: 0
33836
34495
  }
33837
34496
  ],
34497
+ body: body2,
33838
34498
  endTokenIndex: start + 1
33839
34499
  };
33840
34500
  }
@@ -33842,12 +34502,8 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
33842
34502
  const closeIndex = pairs.get(start);
33843
34503
  if (closeIndex === void 0) return null;
33844
34504
  const arrow = tokens[closeIndex + 1];
33845
- const bodyOpen = tokens[closeIndex + 2];
33846
34505
  if (!arrow || arrow.kind !== "operator" || arrow.text !== "=>") return null;
33847
- const hasBlockBody = bodyOpen?.kind === "punctuation" && bodyOpen.text === "{";
33848
- const bodyCloseIndex = hasBlockBody ? pairs.get(closeIndex + 2) : void 0;
33849
- const bodyClose = bodyCloseIndex === void 0 ? void 0 : tokens[bodyCloseIndex];
33850
- const scopeEnd = hasBlockBody ? bodyClose?.start ?? lexed.end : lambdaExpressionScopeEnd(tokens, closeIndex + 2, pairs, lexed.end);
34506
+ const body = lambdaBodySpan(tokens, closeIndex + 1, pairs, lexed);
33851
34507
  const locals = [];
33852
34508
  let segmentStart = start + 1;
33853
34509
  for (let cursor = start + 1; cursor <= closeIndex; cursor++) {
@@ -33868,15 +34524,28 @@ function tryParseLambdaParameters(tokens, start, pairs, lexed) {
33868
34524
  segment[0]?.start ?? nameToken.start,
33869
34525
  nameToken.end
33870
34526
  ),
33871
- scopeStart: hasBlockBody && bodyOpen ? bodyOpen.end : bodyOpen?.start ?? arrow.end,
33872
- scopeEnd,
34527
+ scopeStart: body.start,
34528
+ scopeEnd: body.end,
33873
34529
  lambdaParameter: true,
33874
34530
  lambdaParameterIndex: locals.length
33875
34531
  });
33876
34532
  }
33877
34533
  segmentStart = cursor + 1;
33878
34534
  }
33879
- return { locals, endTokenIndex: closeIndex };
34535
+ return { locals, body, endTokenIndex: closeIndex };
34536
+ }
34537
+ function lambdaBodySpan(tokens, arrowIndex, pairs, lexed) {
34538
+ const arrow = tokens[arrowIndex];
34539
+ const bodyOpen = tokens[arrowIndex + 1];
34540
+ if (bodyOpen?.kind === "punctuation" && bodyOpen.text === "{") {
34541
+ const closeIndex = pairs.get(arrowIndex + 1);
34542
+ const close = closeIndex === void 0 ? void 0 : tokens[closeIndex];
34543
+ return { start: bodyOpen.end, end: close?.start ?? lexed.end };
34544
+ }
34545
+ return {
34546
+ start: arrow?.end ?? lexed.end,
34547
+ end: lambdaExpressionScopeEnd(tokens, arrowIndex + 1, pairs, lexed.end)
34548
+ };
33880
34549
  }
33881
34550
  function lambdaExpressionScopeEnd(tokens, bodyStart, pairs, sourceEnd) {
33882
34551
  for (let cursor = bodyStart; cursor < tokens.length; cursor++) {
@@ -33893,6 +34562,9 @@ function lambdaExpressionScopeEnd(tokens, bodyStart, pairs, sourceEnd) {
33893
34562
  }
33894
34563
  return sourceEnd;
33895
34564
  }
34565
+ function isCallTypeArgumentToken(token) {
34566
+ return token.kind === "identifier" || token.kind === "type" || [".", ",", "?", "[", "]"].includes(token.text);
34567
+ }
33896
34568
  function callOpenParenIndex(tokens, nameIndex) {
33897
34569
  if (tokens[nameIndex + 1]?.text === "(") return nameIndex + 1;
33898
34570
  if (tokens[nameIndex + 1]?.text !== "<") return -1;
@@ -33901,8 +34573,7 @@ function callOpenParenIndex(tokens, nameIndex) {
33901
34573
  const token = tokens[cursor];
33902
34574
  if (token.text === "<") depth++;
33903
34575
  else if (/^>+$/.test(token.text)) depth -= token.text.length;
33904
- else if (token.kind !== "identifier" && token.kind !== "type" && ![".", ",", "?", "[", "]"].includes(token.text))
33905
- return -1;
34576
+ else if (!isCallTypeArgumentToken(token)) return -1;
33906
34577
  if (depth === 0) return tokens[cursor + 1]?.text === "(" ? cursor + 1 : -1;
33907
34578
  if (depth < 0) return -1;
33908
34579
  }
@@ -33924,15 +34595,84 @@ function callTypeArgumentTokens(tokens, nameIndex, openIndex) {
33924
34595
  }
33925
34596
  return argumentsTokens;
33926
34597
  }
33927
- function indexReferences(tokens, declarations, contextualKeywords) {
34598
+ function enclosingOpenerIndex(tokens) {
34599
+ const enclosing = new Int32Array(tokens.length);
34600
+ const openers = [];
34601
+ for (let index = 0; index < tokens.length; index++) {
34602
+ enclosing[index] = openers.length ? openers[openers.length - 1] : -1;
34603
+ const token = tokens[index];
34604
+ if (token.kind !== "punctuation") continue;
34605
+ if (token.text === "(" || token.text === "[" || token.text === "{") {
34606
+ openers.push(index);
34607
+ } else if (token.text === ")" || token.text === "]" || token.text === "}") {
34608
+ openers.pop();
34609
+ }
34610
+ }
34611
+ return enclosing;
34612
+ }
34613
+ function isContextualNew(token, previous, next) {
34614
+ return token.text === NEOSCRIPT_CONSTRUCTOR_KEYWORD && previous?.text !== "." && previous?.text !== "?." && (next?.kind === "identifier" || next?.kind === "type" || next?.text === "(" || next?.text === "{");
34615
+ }
34616
+ function objectInitializerBraceIndex(tokens, newIndex, pairs) {
34617
+ let cursor = newIndex + 1;
34618
+ const opener = tokens[cursor]?.text;
34619
+ if (opener !== "(" && opener !== "{") {
34620
+ const typeEnd = new Parser(tokens, cursor).typeEnd();
34621
+ if (typeEnd >= 0) cursor = typeEnd;
34622
+ }
34623
+ if (tokens[cursor]?.text === "(") {
34624
+ const close = pairs.get(cursor);
34625
+ if (close === void 0) return -1;
34626
+ cursor = close + 1;
34627
+ }
34628
+ return tokens[cursor]?.text === "{" ? cursor : -1;
34629
+ }
34630
+ function indexReferences(tokens, pairs, declarations, contextualKeywords, negations, initializers) {
33928
34631
  const references = [];
34632
+ const enclosing = enclosingOpenerIndex(tokens);
34633
+ const initializerBraces = /* @__PURE__ */ new Set();
34634
+ const patternBindings = /* @__PURE__ */ new Set();
33929
34635
  for (let index = 0; index < tokens.length; index++) {
33930
34636
  const token = tokens[index];
33931
- if (!token || token.kind !== "identifier" && token.text !== "base")
34637
+ if (!token) continue;
34638
+ if (token.kind === "keyword" && token.text === "is") {
34639
+ const not = tokens[index + 1];
34640
+ let typeStart = index + 1;
34641
+ if (not?.text === "not") {
34642
+ negations.push(not.range);
34643
+ typeStart = index + 2;
34644
+ index++;
34645
+ }
34646
+ const end = new Parser(tokens, typeStart).typeEnd({
34647
+ conditionalQuestion: true
34648
+ });
34649
+ if (end >= 0 && tokens[end]?.kind === "identifier") {
34650
+ patternBindings.add(end);
34651
+ }
33932
34652
  continue;
34653
+ }
34654
+ if (token.kind !== "identifier" && token.text !== "base") continue;
34655
+ const previous = tokens[index - 1];
34656
+ const next = tokens[index + 1];
34657
+ if (isContextualNew(token, previous, next)) {
34658
+ const brace = objectInitializerBraceIndex(tokens, index, pairs);
34659
+ if (brace >= 0) {
34660
+ initializerBraces.add(brace);
34661
+ initializers.push({
34662
+ constructorStart: token.start,
34663
+ braceStart: tokens[brace].start
34664
+ });
34665
+ }
34666
+ continue;
34667
+ }
34668
+ const opener = enclosing[index];
34669
+ if (opener >= 0 && (previous?.text === "," || index - 1 === opener)) {
34670
+ const label = next?.text === ":" && tokens[opener]?.text === "(";
34671
+ const key = next?.kind === "operator" && next.text === "=" && initializerBraces.has(opener);
34672
+ if (label || key) continue;
34673
+ }
33933
34674
  const declarationKey = `${token.range.start.line}:${token.range.start.character}`;
33934
34675
  if (contextualKeywords.has(declarationKey)) continue;
33935
- const previous = tokens[index - 1];
33936
34676
  references.push({
33937
34677
  name: token.text,
33938
34678
  range: token.range,
@@ -33940,7 +34680,7 @@ function indexReferences(tokens, declarations, contextualKeywords) {
33940
34680
  end: token.end,
33941
34681
  member: previous?.kind === "punctuation" && previous.text === "." || previous?.kind === "operator" && previous.text === "?.",
33942
34682
  call: callOpenParenIndex(tokens, index) >= 0,
33943
- declaration: declarations.has(declarationKey)
34683
+ declaration: declarations.has(declarationKey) || patternBindings.has(index)
33944
34684
  });
33945
34685
  }
33946
34686
  return references;
@@ -33953,12 +34693,18 @@ function indexCalls(tokens, pairs, lexed) {
33953
34693
  const open = tokens[openIndex];
33954
34694
  if (!name || name.kind !== "identifier") continue;
33955
34695
  if (!open || open.kind !== "punctuation" || open.text !== "(") continue;
33956
- const contextualKeyword = tokens[index - 1];
33957
- const constructor = contextualKeyword?.kind === "identifier" && contextualKeyword.text === NEOSCRIPT_CONSTRUCTOR_KEYWORD;
34696
+ const previous = tokens[index - 1];
34697
+ const targetTyped = isContextualNew(name, previous, open);
34698
+ let contextualKeyword;
34699
+ if (targetTyped) contextualKeyword = name;
34700
+ else if (previous?.kind === "identifier" && previous.text === NEOSCRIPT_CONSTRUCTOR_KEYWORD)
34701
+ contextualKeyword = previous;
33958
34702
  const closeIndex = pairs.get(openIndex);
33959
34703
  const close = closeIndex === void 0 ? void 0 : tokens[closeIndex];
33960
34704
  const ranges = [];
34705
+ const names = [];
33961
34706
  let segmentStart = open.end;
34707
+ let segmentStartIndex = openIndex + 1;
33962
34708
  let nested = 0;
33963
34709
  const limit = closeIndex ?? tokens.length;
33964
34710
  for (let cursor = openIndex + 1; cursor < limit; cursor++) {
@@ -33970,17 +34716,21 @@ function indexCalls(tokens, pairs, lexed) {
33970
34716
  nested--;
33971
34717
  if (nested === 0 && token.kind === "punctuation" && token.text === ",") {
33972
34718
  ranges.push(lexed.source.range(segmentStart, token.start));
34719
+ names.push(callArgumentLabel(tokens, segmentStartIndex, cursor));
33973
34720
  segmentStart = token.end;
34721
+ segmentStartIndex = cursor + 1;
33974
34722
  }
33975
34723
  }
33976
34724
  if (segmentStart < (close?.start ?? lexed.end)) {
33977
34725
  ranges.push(lexed.source.range(segmentStart, close?.start ?? lexed.end));
34726
+ names.push(callArgumentLabel(tokens, segmentStartIndex, limit));
33978
34727
  }
33979
34728
  calls.push({
33980
- kind: constructor ? "constructor" : "function",
34729
+ kind: contextualKeyword ? "constructor" : "function",
33981
34730
  name: name.text,
33982
34731
  nameRange: name.range,
33983
- ...constructor ? { contextualKeywordRange: contextualKeyword.range } : {},
34732
+ ...contextualKeyword ? { contextualKeywordRange: contextualKeyword.range } : {},
34733
+ ...targetTyped ? { targetTyped: true } : {},
33984
34734
  ...openIndex > index + 1 ? {
33985
34735
  typeArgumentTokens: callTypeArgumentTokens(
33986
34736
  tokens,
@@ -33990,11 +34740,17 @@ function indexCalls(tokens, pairs, lexed) {
33990
34740
  } : {},
33991
34741
  openParenOffset: open.start,
33992
34742
  ...close ? { closeParenOffset: close.end } : {},
33993
- argumentRanges: ranges
34743
+ argumentRanges: ranges,
34744
+ argumentNames: names
33994
34745
  });
33995
34746
  }
33996
34747
  return calls;
33997
34748
  }
34749
+ function callArgumentLabel(tokens, start, end) {
34750
+ const name = tokens[start];
34751
+ const colon = tokens[start + 1];
34752
+ return start + 1 < end && name !== void 0 && isCallArgumentLabelToken(name) && colon?.kind === "punctuation" && colon.text === ":" ? name.text : null;
34753
+ }
33998
34754
  function validateTerminatedStatements(tokens, diagnostics) {
33999
34755
  for (let index = 0; index < tokens.length; index++) {
34000
34756
  const token = tokens[index];
@@ -34039,36 +34795,44 @@ function validateTerminatedStatements(tokens, diagnostics) {
34039
34795
  }
34040
34796
  }
34041
34797
  }
34042
- function containingBraceRange(tokens, tokenIndex, documentEnd) {
34043
- let depth = 0;
34044
- let start = 0;
34045
- for (let index = tokenIndex - 1; index >= 0; index--) {
34798
+ function braceScopeIndex(tokens, documentEnd) {
34799
+ const openBefore = new Int32Array(tokens.length);
34800
+ const closeOf = /* @__PURE__ */ new Map();
34801
+ const unmatchedCloses = [];
34802
+ const stack = [];
34803
+ for (let index = 0; index < tokens.length; index++) {
34804
+ openBefore[index] = stack.at(-1) ?? -1;
34046
34805
  const token = tokens[index];
34047
- if (!token || token.kind !== "punctuation") continue;
34048
- if (token.text === "}") depth++;
34049
- if (token.text === "{") {
34050
- if (depth === 0) {
34051
- start = token.end;
34052
- break;
34053
- }
34054
- depth--;
34806
+ if (token.kind !== "punctuation") continue;
34807
+ if (token.text === "{") stack.push(index);
34808
+ else if (token.text === "}") {
34809
+ const open = stack.pop();
34810
+ if (open === void 0) unmatchedCloses.push(index);
34811
+ else closeOf.set(open, index);
34812
+ }
34813
+ }
34814
+ return (tokenIndex) => {
34815
+ const open = openBefore[tokenIndex] ?? -1;
34816
+ if (open >= 0) {
34817
+ const close2 = closeOf.get(open);
34818
+ return {
34819
+ start: tokens[open].end,
34820
+ end: close2 === void 0 ? documentEnd : tokens[close2].start
34821
+ };
34055
34822
  }
34056
- }
34057
- depth = 0;
34058
- let end = documentEnd;
34059
- for (let index = tokenIndex + 1; index < tokens.length; index++) {
34060
- const token = tokens[index];
34061
- if (!token || token.kind !== "punctuation") continue;
34062
- if (token.text === "{") depth++;
34063
- if (token.text === "}") {
34064
- if (depth === 0) {
34065
- end = token.start;
34066
- break;
34067
- }
34068
- depth--;
34823
+ let low = 0;
34824
+ let high = unmatchedCloses.length;
34825
+ while (low < high) {
34826
+ const mid = low + high >> 1;
34827
+ if (unmatchedCloses[mid] > tokenIndex) high = mid;
34828
+ else low = mid + 1;
34069
34829
  }
34070
- }
34071
- return { start, end };
34830
+ const close = unmatchedCloses[low];
34831
+ return {
34832
+ start: 0,
34833
+ end: close === void 0 ? documentEnd : tokens[close].start
34834
+ };
34835
+ };
34072
34836
  }
34073
34837
  function tryParseCatchParameter(tokens, start, pairs, lexed) {
34074
34838
  const keyword = tokens[start];
@@ -34116,7 +34880,7 @@ function tryParseCatchParameter(tokens, start, pairs, lexed) {
34116
34880
  resumeTokenIndex: closeIndex
34117
34881
  };
34118
34882
  }
34119
- function tryParseLoopLocal(tokens, start, pairs, lexed, diagnostics) {
34883
+ function tryParseLoopLocal(tokens, start, pairs, lexed, diagnostics, braceScope) {
34120
34884
  const keyword = tokens[start];
34121
34885
  if (!keyword || keyword.kind !== "keyword" || keyword.text !== "for" && keyword.text !== "foreach") {
34122
34886
  return null;
@@ -34127,7 +34891,12 @@ function tryParseLoopLocal(tokens, start, pairs, lexed, diagnostics) {
34127
34891
  if (closeIndex === void 0) return null;
34128
34892
  const scopeEnd = loopBodyScopeEnd(tokens, closeIndex + 1, pairs, lexed.end);
34129
34893
  if (keyword.text === "for") {
34130
- const declaration = tryParseVariableDeclaration(tokens, start + 2, lexed);
34894
+ const declaration = tryParseVariableDeclaration(
34895
+ tokens,
34896
+ start + 2,
34897
+ lexed,
34898
+ braceScope
34899
+ );
34131
34900
  if (!declaration || declaration.endTokenIndex >= closeIndex) return null;
34132
34901
  if (declaration.missingInitializer) {
34133
34902
  diagnostics.push({
@@ -34449,6 +35218,23 @@ var COLLECTION_QUERY_METHODS = {
34449
35218
  Reverse: "none",
34450
35219
  Concat: "collection"
34451
35220
  };
35221
+ var COLLECTION_FUNCTION_ARGUMENTS = {
35222
+ Where: "predicate",
35223
+ First: "optionalPredicate",
35224
+ FirstOrDefault: "optionalPredicate",
35225
+ Select: "selector",
35226
+ Count: "optionalPredicate",
35227
+ ...COLLECTION_QUERY_METHODS
35228
+ };
35229
+ function isCollectionFunctionName(name) {
35230
+ return Object.hasOwn(COLLECTION_FUNCTION_ARGUMENTS, name);
35231
+ }
35232
+ var COLLECTION_FUNCTION_ALIASES = { Find: "FirstOrDefault" };
35233
+ function collectionFunctionContract(name) {
35234
+ if (Object.hasOwn(COLLECTION_FUNCTION_ALIASES, name))
35235
+ return COLLECTION_FUNCTION_ALIASES[name];
35236
+ return isCollectionFunctionName(name) ? name : null;
35237
+ }
34452
35238
  function isCollectionQueryName(name) {
34453
35239
  return Object.hasOwn(COLLECTION_QUERY_METHODS, name);
34454
35240
  }
@@ -36339,10 +37125,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
36339
37125
  statement.pos
36340
37126
  );
36341
37127
  }
36342
- if (statement.target.kind === "member" && statement.target.name === "OnChanged") {
37128
+ if (statement.target.kind === "member" && statement.target.name === NEOSCRIPT_ON_CHANGED_MEMBER) {
36343
37129
  const observed = this.resolveExpression(statement.target.receiver, scope);
36344
37130
  const observedType = neoScriptMemberLookupType(observed.type);
36345
- const declared = observedType.kind === "named" && this.project.typeById.get(observedType.typeId)?.members.some((member) => member.name === "OnChanged");
37131
+ const declared = observedType.kind === "named" && this.project.typeById.get(observedType.typeId)?.members.some(
37132
+ (member) => member.name === NEOSCRIPT_ON_CHANGED_MEMBER
37133
+ );
36346
37134
  if (!declared) {
36347
37135
  if (statement.op !== "+=" && statement.op !== "-=")
36348
37136
  throw new CompileError(ON_CHANGED_OPERATIONS_ERROR, statement.pos);
@@ -36561,12 +37349,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
36561
37349
  }
36562
37350
  /** `X.M.OnChanged.Clear()` empties M's listener set on X (P70, P106). */
36563
37351
  resolveChangeListenerClear(expression, scope, pos) {
36564
- if (expression.kind !== "call" || expression.callee.kind !== "member" || expression.callee.name !== "Clear" || expression.callee.receiver.kind !== "member" || expression.callee.receiver.name !== "OnChanged")
37352
+ if (expression.kind !== "call" || expression.callee.kind !== "member" || expression.callee.name !== "Clear" || expression.callee.receiver.kind !== "member" || expression.callee.receiver.name !== NEOSCRIPT_ON_CHANGED_MEMBER)
36565
37353
  return null;
36566
37354
  const onChanged = expression.callee.receiver;
36567
37355
  const observed = this.resolveExpression(onChanged.receiver, scope);
36568
37356
  const observedType = neoScriptMemberLookupType(observed.type);
36569
- if (observedType.kind === "named" && this.project.typeById.get(observedType.typeId)?.members.some((member) => member.name === "OnChanged"))
37357
+ if (observedType.kind === "named" && this.project.typeById.get(observedType.typeId)?.members.some((member) => member.name === NEOSCRIPT_ON_CHANGED_MEMBER))
36570
37358
  return null;
36571
37359
  if (expression.callee.optional)
36572
37360
  throw new CompileError(
@@ -37292,7 +38080,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37292
38080
  );
37293
38081
  }
37294
38082
  case "new": {
37295
- const vector3 = this.targetTypedVectorKind(expression, expected);
38083
+ const constructed = expression.className ?? (expected?.kind === "primitive" ? expected.name : null);
38084
+ if (constructed === "Color") {
38085
+ throw new CompileError(
38086
+ "Color has no NeoScript constructor; write its components as numeric literals.",
38087
+ expression.pos
38088
+ );
38089
+ }
38090
+ const vector3 = this.constructedVectorKind(expression, constructed);
37296
38091
  if (vector3 !== null) {
37297
38092
  return this.resolveVectorConstructor(
37298
38093
  vector3,
@@ -37802,10 +38597,19 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37802
38597
  };
37803
38598
  }
37804
38599
  resolveListLiteral(elements, scope, expected, pos) {
37805
- const expectedEntry = expected?.kind === "list" ? expected.elementType : void 0;
38600
+ const expectedEntry = expected?.kind === "list" || expected?.kind === "set" ? expected.elementType : void 0;
37806
38601
  const resolved = elements.map(
37807
38602
  (element) => this.resolveExpression(element, scope, expectedEntry)
37808
38603
  );
38604
+ if (expectedEntry !== void 0 && this.context.kind === "initializer") {
38605
+ resolved.forEach((item, index) => {
38606
+ if (isNeoScriptTypeAssignable(item.type, expectedEntry, this.project)) return;
38607
+ throw new CompileError(
38608
+ `Expected ${this.describe(expectedEntry)} but received ${this.describe(item.type)}.`,
38609
+ elements[index].pos
38610
+ );
38611
+ });
38612
+ }
37809
38613
  let entryType = expectedEntry ?? resolved[0]?.type;
37810
38614
  if (!entryType) {
37811
38615
  throw new CompileError(
@@ -37827,6 +38631,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
37827
38631
  }
37828
38632
  entryType = common;
37829
38633
  }
38634
+ if (expected?.kind === "set" && this.context.kind === "initializer") {
38635
+ const element = expected.elementType;
38636
+ const spelling = element.kind === "named" && this.project.typeById.get(element.typeId)?.kind === "enum" ? `.Option or ${this.describe({ ...element, nullable: false })}.Option values` : "literal values";
38637
+ throw new CompileError(
38638
+ `${this.describe(expected)} has no NeoScript literal; write its elements as ${spelling}.`,
38639
+ pos
38640
+ );
38641
+ }
37830
38642
  const type = {
37831
38643
  kind: "list",
37832
38644
  elementType: entryType
@@ -38763,7 +39575,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38763
39575
  pos
38764
39576
  );
38765
39577
  }
38766
- if (name === "Id" && type.kind === "class") {
39578
+ if (name === NEOSCRIPT_CLASS_ID_MEMBER && type.kind === "class") {
38767
39579
  return this.keyOf(
38768
39580
  receiver,
38769
39581
  name,
@@ -38852,7 +39664,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38852
39664
  entryUserData
38853
39665
  };
38854
39666
  }
38855
- if (name === "OnChanged")
39667
+ if (name === NEOSCRIPT_ON_CHANGED_MEMBER)
38856
39668
  throw new CompileError(ON_CHANGED_OPERATIONS_ERROR, pos);
38857
39669
  throw new CompileError(
38858
39670
  `Cannot read member '${name}' on ${this.describe(receiver.type)}`,
@@ -39925,7 +40737,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39925
40737
  const resolved = this.resolveIdentifier(callee.name, scope, callee.pos);
39926
40738
  return resolved.type.kind === "delegate" || resolved.type.kind === "action" ? resolved : null;
39927
40739
  }
39928
- if (callee.kind !== "member") return null;
40740
+ if (callee.kind !== "member") {
40741
+ const resolved = this.resolveExpression(callee, scope);
40742
+ return resolved.type.kind === "delegate" ? resolved : null;
40743
+ }
39929
40744
  try {
39930
40745
  const resolved = this.resolveMember(
39931
40746
  callee.receiver,
@@ -40349,23 +41164,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40349
41164
  this.project.typeByName.get(className) ?? { declaredConstructors: [] }
40350
41165
  );
40351
41166
  }
40352
- const inferredTypes = this.inferOverloadArgumentTypes(
41167
+ const resolution = this.declaredConstructorResolution(
40353
41168
  declared,
40354
41169
  named,
40355
- expression,
41170
+ expression.args,
40356
41171
  scope
40357
41172
  );
40358
- const resolution = resolveNeoScriptDeclaredConstructorOverload(
40359
- declared,
40360
- named.map((name, index) => {
40361
- const inferred = inferredTypes?.[index];
40362
- if (!inferred) return { name };
40363
- return {
40364
- name,
40365
- matchesParameter: (parameter3) => isNeoScriptTypeAssignable(inferred, parameter3.type, this.project)
40366
- };
40367
- })
40368
- );
40369
41173
  if (resolution.kind === "resolved") return resolution.constructor;
40370
41174
  if (resolution.kind === "ambiguous") {
40371
41175
  throw new CompileError(
@@ -40378,6 +41182,38 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40378
41182
  pos
40379
41183
  );
40380
41184
  }
41185
+ /**
41186
+ * #1310. The overload a named `new` call in an initializer expression
41187
+ * compiles against, for editor features that hold its argument expressions.
41188
+ */
41189
+ initializerConstructorOverload(declared, named, args) {
41190
+ const resolution = this.declaredConstructorResolution(
41191
+ declared,
41192
+ named,
41193
+ args,
41194
+ this.initialScope()
41195
+ );
41196
+ return resolution.kind === "resolved" ? resolution.constructor : null;
41197
+ }
41198
+ declaredConstructorResolution(declared, named, args, scope) {
41199
+ const inferredTypes = this.inferOverloadArgumentTypes(
41200
+ declared,
41201
+ named,
41202
+ args,
41203
+ scope
41204
+ );
41205
+ return resolveNeoScriptDeclaredConstructorOverload(
41206
+ declared,
41207
+ named.map((name, index) => {
41208
+ const inferred = inferredTypes?.[index];
41209
+ if (!inferred) return { name };
41210
+ return {
41211
+ name,
41212
+ matchesParameter: (parameter3) => isNeoScriptTypeAssignable(inferred, parameter3.type, this.project)
41213
+ };
41214
+ })
41215
+ );
41216
+ }
40381
41217
  /**
40382
41218
  * Types for the §6.1.1 step-2 tie-break, computed only when several
40383
41219
  * overloads share the call's name set. Expected-type inference is
@@ -40385,7 +41221,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40385
41221
  * known — so an argument that needs it (a contextual enum option, a
40386
41222
  * target-typed `new`) simply does not participate in the tie-break.
40387
41223
  */
40388
- inferOverloadArgumentTypes(declared, named, expression, scope) {
41224
+ inferOverloadArgumentTypes(declared, named, args, scope) {
40389
41225
  const nameSetKey = neoScriptArgumentNameSetKey(named);
40390
41226
  const sharing = declared.filter(
40391
41227
  (candidate) => neoScriptArgumentNameSetKey(
@@ -40394,7 +41230,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
40394
41230
  );
40395
41231
  if (sharing.length < 2) return null;
40396
41232
  return named.map((_, index) => {
40397
- const argument2 = expression.args[index];
41233
+ const argument2 = args[index];
40398
41234
  if (!argument2) return null;
40399
41235
  try {
40400
41236
  return this.resolveExpression(argument2, scope).type;
@@ -41078,6 +41914,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41078
41914
  resolveCollectionFunction(receiver, name, args, scope, pos) {
41079
41915
  const collection = collectionPartsFor(receiver);
41080
41916
  if (!collection) return null;
41917
+ const contract = collectionFunctionContract(name);
41918
+ if (contract !== null) {
41919
+ requireCollectionArguments(
41920
+ name,
41921
+ COLLECTION_FUNCTION_ARGUMENTS[contract],
41922
+ args,
41923
+ pos
41924
+ );
41925
+ }
41081
41926
  if (isCollectionQueryName(name)) {
41082
41927
  return this.resolveCollectionQuery(
41083
41928
  receiver,
@@ -41089,12 +41934,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41089
41934
  );
41090
41935
  }
41091
41936
  if (name === "Count") {
41092
- if (args.length > 1) {
41093
- throw new CompileError(
41094
- `Count expects zero or one predicate, got ${args.length}.`,
41095
- pos
41096
- );
41097
- }
41098
41937
  const fn = args[0] ? this.resolveCollectionLambda(
41099
41938
  args[0],
41100
41939
  collection,
@@ -41170,7 +42009,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41170
42009
  );
41171
42010
  }
41172
42011
  if (name === "Where") {
41173
- requireArgCount(name, args, 1, pos);
41174
42012
  const fn = this.resolveCollectionLambda(
41175
42013
  requiredAt(args, 0),
41176
42014
  collection,
@@ -41193,12 +42031,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41193
42031
  };
41194
42032
  }
41195
42033
  if (name === "First" || name === "FirstOrDefault" || name === "Find") {
41196
- if (args.length > 1) {
41197
- throw new CompileError(
41198
- `${name} expects zero or one predicate, got ${args.length}.`,
41199
- pos
41200
- );
41201
- }
41202
42034
  const fn = args[0] ? this.resolveCollectionLambda(
41203
42035
  args[0],
41204
42036
  collection,
@@ -41223,7 +42055,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41223
42055
  };
41224
42056
  }
41225
42057
  if (name === "Select") {
41226
- requireArgCount(name, args, 1, pos);
41227
42058
  const lambda = requiredAt(args, 0);
41228
42059
  if (lambda.kind !== "lambda") {
41229
42060
  throw new CompileError("Select requires a lambda argument.", pos);
@@ -41250,16 +42081,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41250
42081
  return null;
41251
42082
  }
41252
42083
  resolveCollectionQuery(receiver, collection, name, args, scope, pos) {
41253
- const kind = COLLECTION_QUERY_METHODS[name];
41254
- if (kind === "optionalPredicate") {
41255
- if (args.length > 1)
41256
- throw new CompileError(
41257
- `${name} expects zero or one predicate, got ${args.length}.`,
41258
- pos
41259
- );
41260
- } else {
41261
- requireArgCount(name, args, kind === "none" ? 0 : 1, pos);
41262
- }
41263
42084
  const base = { collectionPointer: receiver.pointer };
41264
42085
  let info;
41265
42086
  let resultType = {
@@ -41425,6 +42246,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41425
42246
  };
41426
42247
  }
41427
42248
  resolveScalarFunction(receiver, name, args, scope, pos) {
42249
+ if (receiver.type.kind !== "primitive" || !neoScriptScalarMethod(receiver.type.name, name))
42250
+ return null;
41428
42251
  if (isPrimitive(receiver.type, "string")) {
41429
42252
  if (name === "Contains") {
41430
42253
  requireArgCount("string.Contains", args, 1, pos);
@@ -42576,27 +43399,26 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42576
43399
  };
42577
43400
  }
42578
43401
  /**
42579
- * The vector leaf a target-typed `new(…)` constructs, or null when the
42580
- * expression is not one.
43402
+ * The vector leaf a target-typed `new(…)` or a named `new Vector2(…)`
43403
+ * constructs, or null when the expression is not one.
42581
43404
  *
42582
43405
  * A vector has fields rather than members, so neither of `new`'s two
42583
43406
  * declaration-side spellings applies to it: an argument names a component by
42584
43407
  * position and there is no member for an initializer block to settle.
42585
43408
  */
42586
- targetTypedVectorKind(expression, expected) {
42587
- if (expression.className !== null) return null;
42588
- if (expected?.kind !== "primitive") return null;
42589
- const vector3 = vectorKind(expected.name);
43409
+ constructedVectorKind(expression, constructed) {
43410
+ const vector3 = constructed === null ? null : vectorKind(constructed);
42590
43411
  if (vector3 === null) return null;
43412
+ const spelling = expression.className === null ? "new(\u2026)" : `new ${vector3}(\u2026)`;
42591
43413
  if (expression.argumentNames !== void 0) {
42592
43414
  throw new CompileError(
42593
- `${vector3} components are positional, so \`new(\u2026)\` cannot name them.`,
43415
+ `${vector3} components are positional, so \`${spelling}\` cannot name them.`,
42594
43416
  expression.pos
42595
43417
  );
42596
43418
  }
42597
43419
  if ((expression.initializer?.length ?? 0) > 0) {
42598
43420
  throw new CompileError(
42599
- `${vector3} has fields rather than members, so \`new(\u2026)\` cannot carry an initializer block. Pass every component instead.`,
43421
+ `${vector3} has fields rather than members, so \`${spelling}\` cannot carry an initializer block. Pass every component instead.`,
42600
43422
  expression.pos
42601
43423
  );
42602
43424
  }
@@ -42767,6 +43589,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42767
43589
  }
42768
43590
  requireAssignable(source, target, pos, usage) {
42769
43591
  if (isNeoScriptTypeAssignable(source, target, this.project)) return;
43592
+ if (usage === "return" && this.context.kind === "initializer" && this.lambdaDepth === 0) {
43593
+ throw new CompileError(
43594
+ `Expected ${this.describe(target)} but received ${this.describe(source)}.`,
43595
+ pos
43596
+ );
43597
+ }
42770
43598
  const prefix = usage === "return" ? "Returned" : "Cannot use";
42771
43599
  throw new CompileError(
42772
43600
  `${prefix} ${this.describe(source)} ${usage === "return" ? "is not assignable to declared return type" : `as ${usage} of type`} ${this.describe(target)}`,
@@ -44041,17 +44869,6 @@ function collectionOperationValueType(expression, collection) {
44041
44869
  function isLookupSelectionCollection(expression, collection) {
44042
44870
  return collection.kind === "set" && expression.wireType?.type === 9 /* Lookup */;
44043
44871
  }
44044
- var SPRITE_DERIVED_MEMBERS = {
44045
- FileName: { kind: "primitive", name: "string" },
44046
- Name: { kind: "primitive", name: "string" },
44047
- Size: { kind: "primitive", name: "Vector2" },
44048
- Pivot: { kind: "primitive", name: "Vector2" },
44049
- Slices: {
44050
- kind: "list",
44051
- elementType: { kind: "primitive", name: "SpriteInfo" },
44052
- readOnly: true
44053
- }
44054
- };
44055
44872
  function assignableFieldList(owner) {
44056
44873
  if (!isNeoScriptStructuredLeafTypeName(owner)) return "a stored field";
44057
44874
  const names = neoScriptStructuredLeafFieldNames(owner);
@@ -44065,19 +44882,8 @@ function resolvePrimitiveMember(type, name) {
44065
44882
  );
44066
44883
  if (field) return { type: field.type, key: field.key };
44067
44884
  }
44068
- if (type.name === "SpriteInfo" && Object.prototype.hasOwnProperty.call(SPRITE_DERIVED_MEMBERS, name)) {
44069
- const derived = SPRITE_DERIVED_MEMBERS[name];
44070
- if (derived) return { type: derived, derived: true };
44071
- }
44072
- if (type.name === "AudioClipInfo") {
44073
- if (name === "url" || name === "name")
44074
- return { type: { kind: "primitive", name: "string" } };
44075
- if (name === "length")
44076
- return { type: { kind: "primitive", name: "float" } };
44077
- }
44078
- if (type.name === "NeoDialogueReference" && name === "id")
44079
- return { type: { kind: "primitive", name: "string" } };
44080
- return null;
44885
+ const derived = neoScriptPrimitiveDerivedMember(type.name, name);
44886
+ return derived ? { type: derived.type, derived: true } : null;
44081
44887
  }
44082
44888
  function isActionMemberPointer(pointer) {
44083
44889
  if (pointer.type === "staticMember" /* StaticMember */) return true;
@@ -44326,6 +45132,17 @@ function functionArityMessage(name, minimum, maximum, got) {
44326
45132
  }
44327
45133
  return `Function '${name}' expects between ${minimum} and ${maximum} arguments, got ${got}.`;
44328
45134
  }
45135
+ function requireCollectionArguments(name, shape, args, pos) {
45136
+ if (shape !== "optionalPredicate") {
45137
+ requireArgCount(name, args, shape === "none" ? 0 : 1, pos);
45138
+ return;
45139
+ }
45140
+ if (args.length <= 1) return;
45141
+ throw new CompileError(
45142
+ `${name} expects zero or one predicate, got ${args.length}.`,
45143
+ pos
45144
+ );
45145
+ }
44329
45146
  function requireArgCount(name, args, expected, pos) {
44330
45147
  if (args.length === expected) return;
44331
45148
  throw new CompileError(
@@ -44407,6 +45224,18 @@ function resolveNeoScriptType(type, context, project) {
44407
45224
  resolved = registryReference;
44408
45225
  break;
44409
45226
  }
45227
+ if (type.name === "NeoDelegate") {
45228
+ const [returnType, ...parameterTypes] = (type.typeArguments ?? []).map(
45229
+ (argument2) => resolveNeoScriptType(argument2, context, project)
45230
+ );
45231
+ if (!returnType)
45232
+ throw new CompileError(
45233
+ "NeoDelegate requires a return type argument, for example NeoDelegate<int>.",
45234
+ type.pos
45235
+ );
45236
+ resolved = { kind: "delegate", returnType, parameterTypes };
45237
+ break;
45238
+ }
44410
45239
  const named = project.typeByName.get(type.name);
44411
45240
  if (!named)
44412
45241
  throw new CompileError(
@@ -46031,7 +46860,7 @@ function manifestParameterDefault(argument2, environment, field) {
46031
46860
  const value = constantDefaultValue(declared.value, `${field}.default.value`);
46032
46861
  const type = record2(argument2.type, `${field}.type`);
46033
46862
  const kind = string(type.kind, `${field}.type.kind`);
46034
- const enumOptionName = kind === "enum" && typeof value === "string" ? manifestEnumOptionName(
46863
+ const enumOptionName2 = kind === "enum" && typeof value === "string" ? manifestEnumOptionName(
46035
46864
  string(type.enumId, `${field}.type.enumId`),
46036
46865
  value,
46037
46866
  environment
@@ -46041,7 +46870,7 @@ function manifestParameterDefault(argument2, environment, field) {
46041
46870
  displayText: neoScriptParameterDefaultDisplayText({
46042
46871
  value,
46043
46872
  kind: kind === "enum" || kind === "decimal" ? kind : "other",
46044
- ...enumOptionName === void 0 ? {} : { enumOptionName }
46873
+ ...enumOptionName2 === void 0 ? {} : { enumOptionName: enumOptionName2 }
46045
46874
  }),
46046
46875
  value
46047
46876
  }
@@ -46906,13 +47735,13 @@ function overrideBaseClass(context) {
46906
47735
  function parameterDefaultDescriptor(argument2, context) {
46907
47736
  if (argument2.defaultValue === void 0) return {};
46908
47737
  const value = argument2.defaultValue.value;
46909
- const enumOptionName = argument2.type === 8 /* Enum */ && typeof value === "string" ? analyzerEnumOptionName(argument2.enumId, value, context) : void 0;
47738
+ const enumOptionName2 = argument2.type === 8 /* Enum */ && typeof value === "string" ? analyzerEnumOptionName(argument2.enumId, value, context) : void 0;
46910
47739
  return {
46911
47740
  defaultValue: {
46912
47741
  displayText: neoScriptParameterDefaultDisplayText({
46913
47742
  value,
46914
47743
  kind: parameterDefaultSpellingKind(argument2.type),
46915
- ...enumOptionName === void 0 ? {} : { enumOptionName }
47744
+ ...enumOptionName2 === void 0 ? {} : { enumOptionName: enumOptionName2 }
46916
47745
  }),
46917
47746
  value
46918
47747
  }
@@ -48535,8 +49364,9 @@ function createContext(ctx, options) {
48535
49364
  }
48536
49365
 
48537
49366
  // ../src/database/neoscript/compile-delegate-closure.ts
49367
+ var CLOSURE_GETTER_PREFIX = "return ";
48538
49368
  function compileDelegateClosureValue(code, signature) {
48539
- const compiled = compileNSGetter(`return ${code};`, {
49369
+ const compiled = compileNSGetter(`${CLOSURE_GETTER_PREFIX}${code};`, {
48540
49370
  project: signature.project,
48541
49371
  projectFiles: [...signature.projectFiles ?? []],
48542
49372
  dialogueGroups: signature.dialogueGroups ?? [],
@@ -48548,13 +49378,16 @@ function compileDelegateClosureValue(code, signature) {
48548
49378
  variants: [...signature.variants ?? []],
48549
49379
  variantFolders: [...signature.variantFolders ?? []],
48550
49380
  thisClass: signature.thisClass,
49381
+ implicitMemberAccess: true,
49382
+ staticMember: signature.staticMember,
48551
49383
  returnTypeInfo: {
48552
49384
  type: 25 /* NSDelegate */,
48553
49385
  required: true,
48554
49386
  returnTypeInfo: signature.returnTypeInfo,
48555
49387
  argumentTypes: [...signature.argumentTypes]
48556
49388
  },
48557
- functionName: signature.name
49389
+ functionName: signature.name,
49390
+ compilationProject: signature.compilationProject
48558
49391
  });
48559
49392
  const instruction = compiled.instructions[0];
48560
49393
  if (compiled.instructions.length !== 1 || instruction?.type !== "return" /* return */ || instruction.pointer?.type !== "value" /* value */) {
@@ -48616,7 +49449,11 @@ function compileMemberInitializerBody(args) {
48616
49449
  );
48617
49450
  }
48618
49451
  const members = replaceMember(args.members, args.member);
48619
- const returnTypeInfo = resolveMemberDeclaredTypeInfo(args.member, members) ?? initializerGenericTypeInfo(args.member, args.thisClass);
49452
+ const returnTypeInfo = resolveMemberDeclaredTypeInfo(
49453
+ args.member,
49454
+ members,
49455
+ args.thisClass
49456
+ );
48620
49457
  if (returnTypeInfo === null) {
48621
49458
  throw new Error(
48622
49459
  `Member "${args.member.name}" has an initializer but no resolvable declared type.`
@@ -48644,24 +49481,12 @@ function compileMemberInitializerBody(args) {
48644
49481
  error,
48645
49482
  memberId: args.member.id,
48646
49483
  memberName: args.member.name,
48647
- valueId: null
49484
+ valueId: null,
49485
+ code: defaultValue.init.code
48648
49486
  });
48649
49487
  }
48650
49488
  Object.assign(defaultValue.init, { compiled });
48651
49489
  }
48652
- function initializerGenericTypeInfo(member, ownerClass) {
48653
- if (!isMemberGenericBase(member) || ownerClass === null) return null;
48654
- const declaration = ownerClass.genericParams?.find(
48655
- (parameter3) => parameter3.id === member.genericParamId
48656
- );
48657
- if (declaration === void 0) return null;
48658
- return {
48659
- type: 21 /* Generic */,
48660
- required: isRequiredMember(member),
48661
- ownerClassId: ownerClass.id,
48662
- genericParamId: declaration.id
48663
- };
48664
- }
48665
49490
  function compileValueRowInitializerBody(args) {
48666
49491
  const container = args.valueRow;
48667
49492
  if (!isInitValueContent(container)) return;
@@ -48703,7 +49528,8 @@ function compileValueRowInitializerBody(args) {
48703
49528
  error,
48704
49529
  memberId: args.member.id,
48705
49530
  memberName: args.member.name,
48706
- valueId: args.valueId
49531
+ valueId: args.valueId,
49532
+ code: container.init.code
48707
49533
  });
48708
49534
  }
48709
49535
  Object.assign(container.init, { compiled });
@@ -48732,10 +49558,20 @@ var NeoScriptBodyCompileError = class extends Error {
48732
49558
  memberId;
48733
49559
  memberName;
48734
49560
  valueId;
49561
+ /**
49562
+ * The constructor argument the body is stored inline under, when the value
49563
+ * row carries it as creation data rather than as its own row (#1303).
49564
+ */
49565
+ argument;
49566
+ /** The exact code handed to the compiler; `bodyPosition` is measured in it. */
49567
+ code;
48735
49568
  bodyPosition;
49569
+ /** The compiler's message without its body position. */
49570
+ detail;
48736
49571
  constructor(args) {
48737
- const subject = args.valueId === null ? `Member "${args.memberName}" (${args.memberId})` : `Value row "${args.valueId}" of member "${args.memberName}" (${args.memberId})`;
48738
- const at2 = args.bodyPosition === null ? "" : ` at initializer ${args.bodyPosition}`;
49572
+ const argument2 = args.argument === void 0 ? "" : ` constructor argument "${args.argument.parameterName}"`;
49573
+ const subject = args.valueId === null ? `Member "${args.memberName}" (${args.memberId})` : `Value row "${args.valueId}"${argument2} of member "${args.memberName}" (${args.memberId})`;
49574
+ const at2 = args.bodyPosition === null ? "" : ` at initializer ${args.bodyPosition.line}:${args.bodyPosition.column}`;
48739
49575
  super(
48740
49576
  `${subject} has a NeoScript body that failed to compile${at2}: ${args.detail}`
48741
49577
  );
@@ -48743,18 +49579,24 @@ var NeoScriptBodyCompileError = class extends Error {
48743
49579
  this.memberId = args.memberId;
48744
49580
  this.memberName = args.memberName;
48745
49581
  this.valueId = args.valueId;
49582
+ this.argument = args.argument ?? null;
49583
+ this.code = args.code;
48746
49584
  this.bodyPosition = args.bodyPosition;
49585
+ this.detail = args.detail;
48747
49586
  }
48748
49587
  };
48749
49588
  function throwNamedBodyCompileFailure(args) {
48750
49589
  if (args.error instanceof NeoScriptBodyCompileError) throw args.error;
48751
49590
  const compileError = args.error instanceof CompileError ? args.error : null;
48752
49591
  const detail = args.error instanceof Error ? args.error.message : String(args.error);
49592
+ const position = compileError === null ? null : { line: compileError.line, column: compileError.column };
48753
49593
  throw new NeoScriptBodyCompileError({
48754
49594
  memberId: args.memberId,
48755
49595
  memberName: args.memberName,
48756
49596
  valueId: args.valueId,
48757
- bodyPosition: compileError === null ? null : `${compileError.line}:${compileError.column}`,
49597
+ ...args.argument === void 0 ? {} : { argument: args.argument },
49598
+ code: args.code,
49599
+ bodyPosition: position === null ? null : args.codePosition?.(position) ?? position,
48758
49600
  detail: compileError === null ? detail : detail.replace(
48759
49601
  new RegExp(`^${compileError.line}:${compileError.column}: `),
48760
49602
  ""
@@ -56025,79 +56867,9 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
56025
56867
  "g"
56026
56868
  );
56027
56869
 
56028
- // ../packages/neoscript-language/src/project-schema-contract.generated.ts
56029
- var PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
56030
-
56031
- // src/project-source/lower-configuration.ts
56032
- var wireEnumOptions = () => (options) => options;
56033
- var TEXTURE_TYPE_WIRE_OPTIONS = wireEnumOptions()([
56034
- "default",
56035
- "normal-map",
56036
- "editor-gui-and-legacy-gui",
56037
- "sprite",
56038
- "cursor",
56039
- "cookie",
56040
- "lightmap",
56041
- "single-channel"
56042
- ]);
56043
- var ALPHA_SOURCE_WIRE_OPTIONS = wireEnumOptions()(["none", "input-texture-alpha", "from-gray-scale"]);
56044
- var NON_POWER_OF_TWO_SCALE_WIRE_OPTIONS = wireEnumOptions()(["none", "to-nearest", "to-larger", "to-smaller"]);
56045
- var MIP_MAP_FILTERING_WIRE_OPTIONS = wireEnumOptions()(["box", "kaiser"]);
56046
- var WRAP_MODE_WIRE_OPTIONS = wireEnumOptions()(["repeat", "clamp", "mirror", "mirror-once", "per-axis"]);
56047
- var FILTER_MODE_WIRE_OPTIONS = wireEnumOptions()(["point", "bilinear", "trilinear"]);
56048
- var RESIZE_ALGORITHM_WIRE_OPTIONS = wireEnumOptions()(["mitchell", "bilinear"]);
56049
- var TEXTURE_COMPRESSION_WIRE_OPTIONS = wireEnumOptions()(["none", "low-quality", "normal-quality", "high-quality"]);
56050
- var PLATFORM_FORMAT_WIRE_OPTIONS = wireEnumOptions()([
56051
- "automatic",
56052
- "rgba-compressed-dxt5-bc3",
56053
- "rgb-compressed-dxt1-bc1",
56054
- "rgba-32-bit",
56055
- "rgb-24-bit"
56056
- ]);
56057
- var SPRITE_MODE_WIRE_OPTIONS = wireEnumOptions()(["single", "multiple", "polygon"]);
56058
- var MESH_TYPE_WIRE_OPTIONS = wireEnumOptions()(["full-rect", "tight"]);
56059
- var PIVOT_ALIGNMENT_WIRE_OPTIONS = wireEnumOptions()([
56060
- "center",
56061
- "top-left",
56062
- "top-center",
56063
- "top-right",
56064
- "left-center",
56065
- "right-center",
56066
- "bottom-left",
56067
- "bottom-center",
56068
- "bottom-right",
56069
- "custom"
56070
- ]);
56071
- var SLICE_TYPE_WIRE_OPTIONS = wireEnumOptions()(["grid-by-cell-size"]);
56072
- var SLICE_NAMING_ORDER_WIRE_OPTIONS = wireEnumOptions()(["row-major", "column-major"]);
56073
- var NORMAL_MAP_FILTERING_WIRE_OPTIONS = wireEnumOptions()(["sharp", "smooth"]);
56074
- var COOKIE_LIGHT_TYPE_WIRE_OPTIONS = wireEnumOptions()(["spot", "directional", "point"]);
56075
- var SINGLE_CHANNEL_COMPONENT_WIRE_OPTIONS = wireEnumOptions()(["alpha", "red"]);
56076
- var SWIZZLE_WIRE_OPTIONS = wireEnumOptions()(["red", "green", "blue", "alpha", "zero", "one"]);
56077
- var AUDIO_LOAD_TYPE_WIRE_OPTIONS = wireEnumOptions()(["decompress-on-load", "compressed-in-memory", "streaming"]);
56078
- var AUDIO_COMPRESSION_FORMAT_WIRE_OPTIONS = wireEnumOptions()(["pcm", "adpcm", "vorbis"]);
56079
- var AUDIO_SAMPLE_RATE_WIRE_OPTIONS = wireEnumOptions()(["preserve-sample-rate", "optimize-sample-rate", "override-sample-rate"]);
56080
-
56081
- // src/project-source/lower-relations.ts
56082
- var RELATION_KIND_BY_PROPERTY = /* @__PURE__ */ new Map([
56083
- ["tileImports", "world.grid.tile-import"],
56084
- ["objectImports", "world.grid.object-import"],
56085
- ["tileLayers", "world.grid.tile-layer"],
56086
- ["objectLayers", "world.grid.object-layer"]
56087
- ]);
56088
- var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
56089
- ...RELATION_KIND_BY_PROPERTY.values(),
56090
- "world.tile.compatible-layer",
56091
- "world.tile.default-layer",
56092
- "world.object.compatible-layer",
56093
- "world.object.default-layer",
56094
- "world.tile-layer-link.target",
56095
- "world.object-layer-link.target"
56096
- ]);
56097
-
56098
56870
  // ../packages/manifest/schema-contract/registry.mjs
56099
56871
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
56100
- cliVersion: "0.76.1",
56872
+ cliVersion: "0.76.3",
56101
56873
  projectFileUploadBatchSize: 32,
56102
56874
  documentRecords: {
56103
56875
  member: {
@@ -57531,6 +58303,76 @@ var PROJECT_SCHEMA_CONTRACT = Object.freeze({
57531
58303
  }
57532
58304
  });
57533
58305
 
58306
+ // ../packages/neoscript-language/src/project-schema-contract.generated.ts
58307
+ var PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
58308
+
58309
+ // src/project-source/lower-configuration.ts
58310
+ var wireEnumOptions = () => (options) => options;
58311
+ var TEXTURE_TYPE_WIRE_OPTIONS = wireEnumOptions()([
58312
+ "default",
58313
+ "normal-map",
58314
+ "editor-gui-and-legacy-gui",
58315
+ "sprite",
58316
+ "cursor",
58317
+ "cookie",
58318
+ "lightmap",
58319
+ "single-channel"
58320
+ ]);
58321
+ var ALPHA_SOURCE_WIRE_OPTIONS = wireEnumOptions()(["none", "input-texture-alpha", "from-gray-scale"]);
58322
+ var NON_POWER_OF_TWO_SCALE_WIRE_OPTIONS = wireEnumOptions()(["none", "to-nearest", "to-larger", "to-smaller"]);
58323
+ var MIP_MAP_FILTERING_WIRE_OPTIONS = wireEnumOptions()(["box", "kaiser"]);
58324
+ var WRAP_MODE_WIRE_OPTIONS = wireEnumOptions()(["repeat", "clamp", "mirror", "mirror-once", "per-axis"]);
58325
+ var FILTER_MODE_WIRE_OPTIONS = wireEnumOptions()(["point", "bilinear", "trilinear"]);
58326
+ var RESIZE_ALGORITHM_WIRE_OPTIONS = wireEnumOptions()(["mitchell", "bilinear"]);
58327
+ var TEXTURE_COMPRESSION_WIRE_OPTIONS = wireEnumOptions()(["none", "low-quality", "normal-quality", "high-quality"]);
58328
+ var PLATFORM_FORMAT_WIRE_OPTIONS = wireEnumOptions()([
58329
+ "automatic",
58330
+ "rgba-compressed-dxt5-bc3",
58331
+ "rgb-compressed-dxt1-bc1",
58332
+ "rgba-32-bit",
58333
+ "rgb-24-bit"
58334
+ ]);
58335
+ var SPRITE_MODE_WIRE_OPTIONS = wireEnumOptions()(["single", "multiple", "polygon"]);
58336
+ var MESH_TYPE_WIRE_OPTIONS = wireEnumOptions()(["full-rect", "tight"]);
58337
+ var PIVOT_ALIGNMENT_WIRE_OPTIONS = wireEnumOptions()([
58338
+ "center",
58339
+ "top-left",
58340
+ "top-center",
58341
+ "top-right",
58342
+ "left-center",
58343
+ "right-center",
58344
+ "bottom-left",
58345
+ "bottom-center",
58346
+ "bottom-right",
58347
+ "custom"
58348
+ ]);
58349
+ var SLICE_TYPE_WIRE_OPTIONS = wireEnumOptions()(["grid-by-cell-size"]);
58350
+ var SLICE_NAMING_ORDER_WIRE_OPTIONS = wireEnumOptions()(["row-major", "column-major"]);
58351
+ var NORMAL_MAP_FILTERING_WIRE_OPTIONS = wireEnumOptions()(["sharp", "smooth"]);
58352
+ var COOKIE_LIGHT_TYPE_WIRE_OPTIONS = wireEnumOptions()(["spot", "directional", "point"]);
58353
+ var SINGLE_CHANNEL_COMPONENT_WIRE_OPTIONS = wireEnumOptions()(["alpha", "red"]);
58354
+ var SWIZZLE_WIRE_OPTIONS = wireEnumOptions()(["red", "green", "blue", "alpha", "zero", "one"]);
58355
+ var AUDIO_LOAD_TYPE_WIRE_OPTIONS = wireEnumOptions()(["decompress-on-load", "compressed-in-memory", "streaming"]);
58356
+ var AUDIO_COMPRESSION_FORMAT_WIRE_OPTIONS = wireEnumOptions()(["pcm", "adpcm", "vorbis"]);
58357
+ var AUDIO_SAMPLE_RATE_WIRE_OPTIONS = wireEnumOptions()(["preserve-sample-rate", "optimize-sample-rate", "override-sample-rate"]);
58358
+
58359
+ // src/project-source/lower-relations.ts
58360
+ var RELATION_KIND_BY_PROPERTY = /* @__PURE__ */ new Map([
58361
+ ["tileImports", "world.grid.tile-import"],
58362
+ ["objectImports", "world.grid.object-import"],
58363
+ ["tileLayers", "world.grid.tile-layer"],
58364
+ ["objectLayers", "world.grid.object-layer"]
58365
+ ]);
58366
+ var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
58367
+ ...RELATION_KIND_BY_PROPERTY.values(),
58368
+ "world.tile.compatible-layer",
58369
+ "world.tile.default-layer",
58370
+ "world.object.compatible-layer",
58371
+ "world.object.default-layer",
58372
+ "world.tile-layer-link.target",
58373
+ "world.object-layer-link.target"
58374
+ ]);
58375
+
57534
58376
  // src/project-source/workspace-status-core.ts
57535
58377
  var ANIMATION_DOCUMENT_RECORD_KINDS = [
57536
58378
  ProjectRecordKind.Project,
@@ -58213,6 +59055,7 @@ function validateRegistrationAction(action, allowRegistration) {
58213
59055
  }
58214
59056
  }
58215
59057
  function registerSpec(spec, document2) {
59058
+ document2 = withCompiledConstructionTypes(document2, spec.action);
58216
59059
  validateRegistrationAction(spec.action, true);
58217
59060
  const root = {
58218
59061
  name: "",
@@ -58293,7 +59136,7 @@ function registerSpec(spec, document2) {
58293
59136
  makeEvaluatorContext(document2, interceptor),
58294
59137
  []
58295
59138
  );
58296
- return { spec, root, tests };
59139
+ return { spec, root, tests, document: document2 };
58297
59140
  }
58298
59141
  function mockResponse(environment, mock, selected, call) {
58299
59142
  if (selected === null) {
@@ -58716,13 +59559,13 @@ function prepareTestEvaluator(document2) {
58716
59559
  async function executeTestFile(spec, document2, selected, timeoutMs, interrupted2 = () => false) {
58717
59560
  return executeRegisteredSpec(
58718
59561
  registerSpec(spec, document2),
58719
- document2,
58720
59562
  selected,
58721
59563
  timeoutMs,
58722
59564
  interrupted2
58723
59565
  );
58724
59566
  }
58725
- async function executeRegisteredSpec(registered, document2, selected, timeoutMs, interrupted2) {
59567
+ async function executeRegisteredSpec(registered, selected, timeoutMs, interrupted2) {
59568
+ const document2 = registered.document;
58726
59569
  let restoredRuntimeSources = false;
58727
59570
  const reportFailure = (error, position, member = null) => {
58728
59571
  if (error instanceof NSGetterRuntimeError && error.node !== void 0 && (error.source === void 0 || error.callerNode !== void 0 && runtimeSource(error.callerNode) === void 0)) {