@neocompose/cli 0.79.1 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2966,9 +2966,21 @@ function isNSTypeInfoInterface(value) {
2966
2966
  if (typeof v.interfaceId !== "string") return false;
2967
2967
  return v.interfaceId.length > 0;
2968
2968
  }
2969
+ function isClassGenericParamTypeInfo(value) {
2970
+ return "ownerClassId" in value;
2971
+ }
2969
2972
  function isNSTypeInfoGenericParam(value) {
2970
2973
  if (!isNSTypeInfoBase(value)) return false;
2971
2974
  if (value.type !== 21 /* Generic */) return false;
2975
+ if ("ownerMemberId" in value) {
2976
+ if ("ownerClassId" in value) return false;
2977
+ if ("genericParamId" in value) return false;
2978
+ const v2 = value;
2979
+ if (typeof v2.ownerMemberId !== "string") return false;
2980
+ if (typeof v2.index !== "number") return false;
2981
+ return Number.isInteger(v2.index) && v2.index >= 0;
2982
+ }
2983
+ if ("index" in value) return false;
2972
2984
  const v = value;
2973
2985
  if (typeof v.ownerClassId !== "string") return false;
2974
2986
  if (v.ownerClassId.length === 0) return false;
@@ -3116,6 +3128,86 @@ function hasValidParameterDefault(value) {
3116
3128
  return false;
3117
3129
  }
3118
3130
  }
3131
+ function isFunctionGenericParams(value, isValidName) {
3132
+ if (!Array.isArray(value) || value.length === 0) return false;
3133
+ const names = /* @__PURE__ */ new Set();
3134
+ let defaulted = false;
3135
+ for (const entry of value) {
3136
+ if (!entry || typeof entry !== "object" || Array.isArray(entry))
3137
+ return false;
3138
+ const v = entry;
3139
+ for (const key of Object.keys(v)) {
3140
+ if (key !== "name" && key !== "constraint" && key !== "defaultType")
3141
+ return false;
3142
+ }
3143
+ if (!isValidName(v.name)) return false;
3144
+ const name = v.name;
3145
+ if (names.has(name)) return false;
3146
+ names.add(name);
3147
+ if (v.constraint !== void 0) {
3148
+ const constraint = v.constraint;
3149
+ if (!isNSTypeInfoClass(constraint) && !isNSTypeInfoEnum(constraint))
3150
+ return false;
3151
+ if (constraint.required !== true) return false;
3152
+ if (typeInfoContainsFunctionGeneric(constraint, /* @__PURE__ */ new Set()))
3153
+ return false;
3154
+ }
3155
+ if (v.defaultType === void 0) {
3156
+ if (defaulted) return false;
3157
+ continue;
3158
+ }
3159
+ defaulted = true;
3160
+ if (!isNSTypeInfo(v.defaultType)) return false;
3161
+ if (v.defaultType.required !== true) return false;
3162
+ if (v.defaultType.type === NS_TYPE_UNKNOWN) return false;
3163
+ if (typeInfoContainsGeneric(v.defaultType, /* @__PURE__ */ new Set())) return false;
3164
+ }
3165
+ return true;
3166
+ }
3167
+ function typeInfoContainsFunctionGeneric(value, ancestors) {
3168
+ return typeInfoSome(
3169
+ value,
3170
+ (type) => type.type === 21 /* Generic */ && "ownerMemberId" in type,
3171
+ ancestors
3172
+ );
3173
+ }
3174
+ function typeInfoContainsGeneric(value, ancestors) {
3175
+ return typeInfoSome(
3176
+ value,
3177
+ (type) => type.type === 21 /* Generic */,
3178
+ ancestors
3179
+ );
3180
+ }
3181
+ function typeInfoSome(value, predicate, ancestors) {
3182
+ if (predicate(value)) return true;
3183
+ if (ancestors.has(value)) return true;
3184
+ ancestors.add(value);
3185
+ try {
3186
+ switch (value.type) {
3187
+ case 6 /* List */:
3188
+ case 28 /* Set */:
3189
+ case 5 /* Dictionary */:
3190
+ case 9 /* Lookup */:
3191
+ return typeInfoSome(value.entryTypeInfo, predicate, ancestors);
3192
+ case 25 /* NSDelegate */:
3193
+ return value.returnTypeInfo.type !== NS_TYPE_VOID && typeInfoSome(value.returnTypeInfo, predicate, ancestors) || value.argumentTypes.some(
3194
+ (argument2) => typeInfoSome(argument2, predicate, ancestors)
3195
+ );
3196
+ case 26 /* NSAction */:
3197
+ return value.argumentTypes.some(
3198
+ (argument2) => typeInfoSome(argument2, predicate, ancestors)
3199
+ );
3200
+ case 7 /* Class */:
3201
+ return Object.values(value.typeArguments ?? {}).some(
3202
+ (argument2) => typeInfoSome(argument2, predicate, ancestors)
3203
+ );
3204
+ default:
3205
+ return false;
3206
+ }
3207
+ } finally {
3208
+ ancestors.delete(value);
3209
+ }
3210
+ }
3119
3211
  function typeInfoContainsUnknown(value, ancestors) {
3120
3212
  if (value.type === NS_TYPE_UNKNOWN) return true;
3121
3213
  if (ancestors.has(value)) return true;
@@ -3336,7 +3428,9 @@ function isNSPointerCallFunction(value) {
3336
3428
  if (v.missingMemberFallback === "valueEquality" && (!hasMemberKey || v.receiver?.kind !== "instance" || v.args.length !== 1)) {
3337
3429
  return false;
3338
3430
  }
3339
- return true;
3431
+ if (v.typeArguments === void 0) return true;
3432
+ if (!Array.isArray(v.typeArguments)) return false;
3433
+ return v.typeArguments.every(isNSTypeInfo);
3340
3434
  }
3341
3435
  function isNSPointerObjectInitializer(value) {
3342
3436
  if (typeof value !== "object" || value === null) return false;
@@ -4135,6 +4229,9 @@ function typeInfosInvariantlyEqual(left, right) {
4135
4229
  return left.interfaceId === right.interfaceId;
4136
4230
  }
4137
4231
  if (left.type === 21 /* Generic */ && right.type === 21 /* Generic */) {
4232
+ if ("index" in left || "index" in right) {
4233
+ return "index" in left && "index" in right && left.index === right.index;
4234
+ }
4138
4235
  return left.ownerClassId === right.ownerClassId && left.genericParamId === right.genericParamId;
4139
4236
  }
4140
4237
  if (left.type === 8 /* Enum */ && right.type === 8 /* Enum */) {
@@ -4767,6 +4864,7 @@ function isMemberFunctionBase(value) {
4767
4864
  if (!Array.isArray(v.argumentTypes)) return false;
4768
4865
  if (v.dispatch !== void 0 && v.dispatch !== 0 /* Synchronous */ && v.dispatch !== 1 /* Asynchronous */)
4769
4866
  return false;
4867
+ if (!hasValidFunctionGenericParams(v)) return false;
4770
4868
  const names = /* @__PURE__ */ new Set();
4771
4869
  const argumentTypes = [];
4772
4870
  for (const arg of v.argumentTypes) {
@@ -4782,6 +4880,13 @@ function isMemberFunctionBase(value) {
4782
4880
  v.dispatch === 1 /* Asynchronous */
4783
4881
  );
4784
4882
  }
4883
+ function hasValidFunctionGenericParams(value) {
4884
+ if (value.genericParams === void 0) return true;
4885
+ return isFunctionGenericParams(
4886
+ value.genericParams,
4887
+ isValidSchemaBindingIdentifier
4888
+ );
4889
+ }
4785
4890
  function hasValidParameterDefaults(argumentTypes, deferred) {
4786
4891
  if (deferred && hasAnyParameterDefault(argumentTypes)) return false;
4787
4892
  return validateParameterDefaults(argumentTypes).length === 0;
@@ -4835,6 +4940,7 @@ function isMemberNSFunctionBase(value) {
4835
4940
  if (v.action !== void 0 && v.action !== null) return false;
4836
4941
  if (v.bodyMode !== void 0 && v.bodyMode !== 0 /* Code */ && v.bodyMode !== 1 /* UI */)
4837
4942
  return false;
4943
+ if (!hasValidFunctionGenericParams(v)) return false;
4838
4944
  const names = /* @__PURE__ */ new Set();
4839
4945
  const argumentTypes = [];
4840
4946
  for (const argument2 of v.argumentTypes) {
@@ -5108,6 +5214,13 @@ function hasValidEffectField(v) {
5108
5214
  if (!isFunctionEffectKind(v.effect)) return false;
5109
5215
  return v.kind === 13 /* Function */ || v.kind === 23 /* NSFunction */;
5110
5216
  }
5217
+ function hasValidOverrideGenericParams(v) {
5218
+ if (v.genericParams === void 0) return true;
5219
+ if (v.kind !== 13 /* Function */ && v.kind !== 23 /* NSFunction */) {
5220
+ return false;
5221
+ }
5222
+ return hasValidFunctionGenericParams(v);
5223
+ }
5111
5224
  function hasValidDistributionField(v) {
5112
5225
  if (v.distribution === void 0) return true;
5113
5226
  if (!isNeoSubtreeDistributionKind(v.distribution)) return false;
@@ -5246,6 +5359,7 @@ function isMemberOverrideBase(value) {
5246
5359
  if (!hasValidStorageField(v, false)) return false;
5247
5360
  if (!hasValidDistributionField(v)) return false;
5248
5361
  if (!hasValidEffectField(v)) return false;
5362
+ if (!hasValidOverrideGenericParams(v)) return false;
5249
5363
  if (v.defaultValue !== void 0 && v.defaultValue !== null && !isMemberValueBase(v.defaultValue)) {
5250
5364
  return false;
5251
5365
  }
@@ -7399,14 +7513,15 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7399
7513
  {
7400
7514
  memberId: "system_f5ca386c-990c-54a1-8473-2d49d2cd887d",
7401
7515
  memberKind: "function",
7402
- docsText: "Objects at the cells around this placement, shifted by offset, in pattern order. Use GetObjects<T>(pattern, offset) to filter by class. A repeated footprint can appear more than once.",
7516
+ docsText: "Objects of type T at the cells around this placement, shifted by offset, in pattern order. A repeated footprint can appear more than once.",
7403
7517
  returnTypeInfo: {
7404
7518
  type: 6,
7405
7519
  required: true,
7406
7520
  entryTypeInfo: {
7407
- type: 7,
7521
+ type: 21,
7408
7522
  required: true,
7409
- classId: "system_f671535d-0eb6-4139-9caf-5c5276febd31"
7523
+ ownerMemberId: "system_f5ca386c-990c-54a1-8473-2d49d2cd887d",
7524
+ index: 0
7410
7525
  }
7411
7526
  },
7412
7527
  argumentTypes: [
@@ -7423,17 +7538,33 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7423
7538
  defaultValue: { value: null }
7424
7539
  }
7425
7540
  ],
7541
+ genericParams: [
7542
+ {
7543
+ name: "T",
7544
+ constraint: {
7545
+ type: 7,
7546
+ required: true,
7547
+ classId: "system_f671535d-0eb6-4139-9caf-5c5276febd31"
7548
+ },
7549
+ defaultType: {
7550
+ type: 7,
7551
+ required: true,
7552
+ classId: "system_f671535d-0eb6-4139-9caf-5c5276febd31"
7553
+ }
7554
+ }
7555
+ ],
7426
7556
  dispatch: 0 /* Synchronous */,
7427
7557
  schemaKey: "GetObjects"
7428
7558
  },
7429
7559
  {
7430
7560
  memberId: "system_593e6208-e2ca-505e-9933-04b17102b6d2",
7431
7561
  memberKind: "function",
7432
- docsText: "The first tile found in pattern order around this placement, shifted by offset, or null. Each cell uses the grid layer precedence.",
7562
+ docsText: "The first tile of type T found in pattern order around this placement, shifted by offset, or null. Each cell uses the grid layer precedence.",
7433
7563
  returnTypeInfo: {
7434
- type: 7,
7564
+ type: 21,
7435
7565
  required: false,
7436
- classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7566
+ ownerMemberId: "system_593e6208-e2ca-505e-9933-04b17102b6d2",
7567
+ index: 0
7437
7568
  },
7438
7569
  argumentTypes: [
7439
7570
  {
@@ -7449,20 +7580,36 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7449
7580
  defaultValue: { value: null }
7450
7581
  }
7451
7582
  ],
7583
+ genericParams: [
7584
+ {
7585
+ name: "T",
7586
+ constraint: {
7587
+ type: 7,
7588
+ required: true,
7589
+ classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7590
+ },
7591
+ defaultType: {
7592
+ type: 7,
7593
+ required: true,
7594
+ classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7595
+ }
7596
+ }
7597
+ ],
7452
7598
  dispatch: 0 /* Synchronous */,
7453
7599
  schemaKey: "GetTile"
7454
7600
  },
7455
7601
  {
7456
7602
  memberId: "system_5a41d36a-bcd9-4867-9e46-d743f6e09582",
7457
7603
  memberKind: "function",
7458
- docsText: "The tiles at the cells around this placement, shifted by offset, in pattern order. Each cell uses the grid layer precedence and empty cells are skipped.",
7604
+ docsText: "The tiles of type T at the cells around this placement, shifted by offset, in pattern order. Each cell uses the grid layer precedence and empty cells are skipped.",
7459
7605
  returnTypeInfo: {
7460
7606
  type: 6,
7461
7607
  required: true,
7462
7608
  entryTypeInfo: {
7463
- type: 7,
7609
+ type: 21,
7464
7610
  required: true,
7465
- classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7611
+ ownerMemberId: "system_5a41d36a-bcd9-4867-9e46-d743f6e09582",
7612
+ index: 0
7466
7613
  }
7467
7614
  },
7468
7615
  argumentTypes: [
@@ -7479,6 +7626,21 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
7479
7626
  defaultValue: { value: null }
7480
7627
  }
7481
7628
  ],
7629
+ genericParams: [
7630
+ {
7631
+ name: "T",
7632
+ constraint: {
7633
+ type: 7,
7634
+ required: true,
7635
+ classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7636
+ },
7637
+ defaultType: {
7638
+ type: 7,
7639
+ required: true,
7640
+ classId: "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0"
7641
+ }
7642
+ }
7643
+ ],
7482
7644
  dispatch: 0 /* Synchronous */,
7483
7645
  schemaKey: "GetTiles"
7484
7646
  }
@@ -9111,7 +9273,8 @@ function callableBindingMember(memberId, slotName, members) {
9111
9273
  return binding;
9112
9274
  }
9113
9275
  function mapGenericTypeInfo(typeInfo, close) {
9114
- if (typeInfo.type === 21 /* Generic */) return close(typeInfo);
9276
+ if (typeInfo.type === 21 /* Generic */)
9277
+ return isClassGenericParamTypeInfo(typeInfo) ? close(typeInfo) : typeInfo;
9115
9278
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 28 /* Set */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
9116
9279
  return {
9117
9280
  ...typeInfo,
@@ -12507,6 +12670,14 @@ function validateAudioMemberValue(document2, member, body) {
12507
12670
  }
12508
12671
  }
12509
12672
 
12673
+ // ../packages/models/src/members/list-index-values.ts
12674
+ function normalizeListIndexKey(value, kind) {
12675
+ if (kind === "enum") {
12676
+ return Array.isArray(value) && typeof value[0] === "string" ? value[0] : null;
12677
+ }
12678
+ return typeof value === "string" ? value : null;
12679
+ }
12680
+
12510
12681
  // ../packages/models/src/members/list-indexes.ts
12511
12682
  function validateListIndexDefinitions(ctx, listMember) {
12512
12683
  const errors = [];
@@ -13030,6 +13201,109 @@ function classImplementsInterface(classId, interfaceId, classes, interfaces) {
13030
13201
  );
13031
13202
  }
13032
13203
 
13204
+ // ../packages/models/src/neoscript/function-type-arguments.ts
13205
+ function functionGenericParamsOf(member) {
13206
+ const kind = getField(member, "kind");
13207
+ if (kind !== 13 /* Function */ && kind !== 23 /* NSFunction */) {
13208
+ return void 0;
13209
+ }
13210
+ const params = getField(member, "genericParams");
13211
+ return isFunctionGenericParams(params, isValidSchemaBindingIdentifier) ? params : void 0;
13212
+ }
13213
+ function firstFunctionGenericReference(typeInfo, matches) {
13214
+ switch (typeInfo.type) {
13215
+ case 21 /* Generic */:
13216
+ if (isClassGenericParamTypeInfo(typeInfo)) return null;
13217
+ return matches(typeInfo) ? typeInfo : null;
13218
+ case 6 /* List */:
13219
+ case 28 /* Set */:
13220
+ case 5 /* Dictionary */:
13221
+ case 9 /* Lookup */:
13222
+ return firstFunctionGenericReference(typeInfo.entryTypeInfo, matches);
13223
+ case 25 /* NSDelegate */:
13224
+ return firstInList(
13225
+ [typeInfo.returnTypeInfo, ...typeInfo.argumentTypes],
13226
+ matches
13227
+ );
13228
+ case 26 /* NSAction */:
13229
+ return firstInList(typeInfo.argumentTypes, matches);
13230
+ case 7 /* Class */:
13231
+ return firstInList(Object.values(typeInfo.typeArguments ?? {}), matches);
13232
+ default:
13233
+ return null;
13234
+ }
13235
+ }
13236
+ function firstInList(list, matches) {
13237
+ for (const entry of list) {
13238
+ const found = firstFunctionGenericReference(entry, matches);
13239
+ if (found !== null) return found;
13240
+ }
13241
+ return null;
13242
+ }
13243
+ function typeInfoHasFunctionGeneric(typeInfo) {
13244
+ return firstFunctionGenericReference(typeInfo, () => true) !== null;
13245
+ }
13246
+ function bindFunctionTypeArguments(typeInfo, table) {
13247
+ switch (typeInfo.type) {
13248
+ case 21 /* Generic */: {
13249
+ if (isClassGenericParamTypeInfo(typeInfo)) return typeInfo;
13250
+ const bound = table[typeInfo.index];
13251
+ if (bound === void 0) return typeInfo;
13252
+ return { ...bound, required: bound.required && typeInfo.required };
13253
+ }
13254
+ case 6 /* List */:
13255
+ case 28 /* Set */:
13256
+ case 5 /* Dictionary */:
13257
+ case 9 /* Lookup */: {
13258
+ const entry = bindFunctionTypeArguments(typeInfo.entryTypeInfo, table);
13259
+ return entry === typeInfo.entryTypeInfo ? typeInfo : { ...typeInfo, entryTypeInfo: entry };
13260
+ }
13261
+ case 25 /* NSDelegate */: {
13262
+ const returnTypeInfo = bindFunctionTypeArguments(
13263
+ typeInfo.returnTypeInfo,
13264
+ table
13265
+ );
13266
+ const argumentTypes = bindTypeInfoList(typeInfo.argumentTypes, table);
13267
+ return returnTypeInfo === typeInfo.returnTypeInfo && argumentTypes === typeInfo.argumentTypes ? typeInfo : { ...typeInfo, returnTypeInfo, argumentTypes };
13268
+ }
13269
+ case 26 /* NSAction */: {
13270
+ const argumentTypes = bindTypeInfoList(typeInfo.argumentTypes, table);
13271
+ return argumentTypes === typeInfo.argumentTypes ? typeInfo : { ...typeInfo, argumentTypes };
13272
+ }
13273
+ case 7 /* Class */: {
13274
+ if (!typeInfo.typeArguments) return typeInfo;
13275
+ let typeArguments;
13276
+ for (const [key, argument2] of Object.entries(typeInfo.typeArguments)) {
13277
+ const bound = bindFunctionTypeArguments(argument2, table);
13278
+ if (bound === argument2) continue;
13279
+ typeArguments ??= { ...typeInfo.typeArguments };
13280
+ typeArguments[key] = bound;
13281
+ }
13282
+ return typeArguments === void 0 ? typeInfo : { ...typeInfo, typeArguments };
13283
+ }
13284
+ default:
13285
+ return typeInfo;
13286
+ }
13287
+ }
13288
+ function bindArgumentTypeArguments(argument2, table) {
13289
+ const bound = bindFunctionTypeArguments(argument2, table);
13290
+ if (bound === argument2) return argument2;
13291
+ if (argument2.defaultValue === void 0) {
13292
+ return { ...bound, name: argument2.name };
13293
+ }
13294
+ return { ...bound, name: argument2.name, defaultValue: { value: null } };
13295
+ }
13296
+ function bindTypeInfoList(list, table) {
13297
+ let bound;
13298
+ for (let index = 0; index < list.length; index++) {
13299
+ const entry = bindFunctionTypeArguments(list[index], table);
13300
+ if (entry === list[index]) continue;
13301
+ bound ??= [...list];
13302
+ bound[index] = entry;
13303
+ }
13304
+ return bound ?? list;
13305
+ }
13306
+
13033
13307
  // ../packages/manifest/src/value-comparison.ts
13034
13308
  function isObjectRecord(value) {
13035
13309
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -13326,6 +13600,9 @@ import { createHash as createHash2, randomUUID } from "node:crypto";
13326
13600
  import { isDeepStrictEqual } from "node:util";
13327
13601
 
13328
13602
  // ../packages/neoscript-language/src/project.ts
13603
+ function functionTypeParameterId(memberId, index) {
13604
+ return `${memberId}#${index}`;
13605
+ }
13329
13606
  function neoScriptMemberLookupType(type) {
13330
13607
  if (type.kind !== "typeParameter") return type;
13331
13608
  const visited = /* @__PURE__ */ new Set();
@@ -14102,6 +14379,61 @@ var UncompiledInitializerRuntimeError = class extends NSGetterRuntimeError {
14102
14379
  valueId;
14103
14380
  };
14104
14381
 
14382
+ // ../packages/neoscript-runtime/src/neoscript/runtime-set.ts
14383
+ var RuntimeSet = class {
14384
+ constructor(source, reference, enumEntries) {
14385
+ this.source = source;
14386
+ this.reference = reference;
14387
+ this.enumEntries = enumEntries;
14388
+ }
14389
+ source;
14390
+ reference;
14391
+ enumEntries;
14392
+ entries = /* @__PURE__ */ new Map();
14393
+ validations = /* @__PURE__ */ new Map();
14394
+ snapshot;
14395
+ get size() {
14396
+ return this.entries.size;
14397
+ }
14398
+ has(key) {
14399
+ return this.entries.has(key);
14400
+ }
14401
+ add(key, raw, reference) {
14402
+ if (this.entries.has(key)) return;
14403
+ this.entries.set(key, { raw, reference });
14404
+ for (const check2 of this.validations.values())
14405
+ if (!check2.test(raw)) check2.invalid.add(key);
14406
+ this.snapshot = void 0;
14407
+ }
14408
+ remove(key) {
14409
+ if (this.entries.delete(key)) {
14410
+ this.snapshot = void 0;
14411
+ for (const check2 of this.validations.values()) check2.invalid.delete(key);
14412
+ }
14413
+ }
14414
+ clear() {
14415
+ this.entries.clear();
14416
+ for (const check2 of this.validations.values()) check2.invalid.clear();
14417
+ this.snapshot = void 0;
14418
+ }
14419
+ matches(type, test) {
14420
+ let check2 = this.validations.get(type);
14421
+ if (check2 === void 0) {
14422
+ check2 = { test, invalid: /* @__PURE__ */ new Set() };
14423
+ for (const [key, entry] of this.entries)
14424
+ if (!test(entry.raw)) check2.invalid.add(key);
14425
+ this.validations.set(type, check2);
14426
+ }
14427
+ return check2.invalid.size === 0;
14428
+ }
14429
+ membership() {
14430
+ return this.snapshot ??= [...this.entries.values()];
14431
+ }
14432
+ toArray() {
14433
+ return this.membership().map((entry) => entry.raw);
14434
+ }
14435
+ };
14436
+
14105
14437
  // ../packages/neoscript-runtime/src/listener-write-index.ts
14106
14438
  var indexes = /* @__PURE__ */ new WeakMap();
14107
14439
  var empty = /* @__PURE__ */ new Map();
@@ -14756,6 +15088,10 @@ var NEO_CELL_PATTERN_PURE_NATIVE_MEMBER_IDS = /* @__PURE__ */ new Set([
14756
15088
  ]);
14757
15089
  var NEO_OBJECT_CLASS_ID = "system_f671535d-0eb6-4139-9caf-5c5276febd31";
14758
15090
 
15091
+ // ../packages/neoscript-language/src/tile-conversion.ts
15092
+ var NEO_TILE_CONVERT_MEMBER_ID = "system_54ecc5a7-874d-54ed-92f4-38100a4b7465";
15093
+ var NEO_TILE_CLASS_ID = "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0";
15094
+
14759
15095
  // ../packages/neoscript-runtime/src/neoscript/cell-pattern.ts
14760
15096
  function integer(value, name) {
14761
15097
  if (typeof value !== "number" || !Number.isInteger(value)) {
@@ -15671,8 +16007,11 @@ var WorldGridQueryIndex = class {
15671
16007
  );
15672
16008
  return matches[0];
15673
16009
  }
15674
- /** `shift` moves the whole pattern; null queries around the placement cell. */
15675
- objects(placement, offsets, reads, shift = null) {
16010
+ /**
16011
+ * `shift` moves the whole pattern; null queries around the placement cell.
16012
+ * `accepts` (P110 §6) keeps only objects of a class; every cell is still read.
16013
+ */
16014
+ objects(placement, offsets, reads, shift = null, accepts) {
15676
16015
  reads?.add({ kind: "placement", valueId: placement.valueId });
15677
16016
  const origin = shiftedOrigin(placement, shift);
15678
16017
  const result = [];
@@ -15680,24 +16019,34 @@ var WorldGridQueryIndex = class {
15680
16019
  const cell = translated2(origin, offset);
15681
16020
  reads?.add({ kind: "objects", gridId: placement.gridId, cell });
15682
16021
  for (const item of this.objectsAt(placement.gridId, cell)) {
15683
- result.push(item.valueId);
16022
+ if (accepts === void 0 || accepts(item.classId)) {
16023
+ result.push(item.valueId);
16024
+ }
15684
16025
  }
15685
16026
  }
15686
16027
  return result;
15687
16028
  }
15688
- tile(placement, offsets, reads, shift = null) {
16029
+ /** The first cell's winner that `accepts` keeps, in pattern order. */
16030
+ tile(placement, offsets, reads, shift = null, accepts) {
15689
16031
  reads?.add({ kind: "placement", valueId: placement.valueId });
15690
16032
  const origin = shiftedOrigin(placement, shift);
15691
16033
  let result = null;
15692
16034
  for (const offset of offsets) {
15693
16035
  const cell = translated2(origin, offset);
15694
16036
  reads?.add({ kind: "tile", gridId: placement.gridId, cell });
15695
- result ??= this.tileAt(placement.gridId, cell);
16037
+ if (result !== null) continue;
16038
+ const tile = this.tileAt(placement.gridId, cell);
16039
+ if (tile !== null && (accepts === void 0 || accepts(tile.classId))) {
16040
+ result = tile;
16041
+ }
15696
16042
  }
15697
16043
  return result;
15698
16044
  }
15699
- /** One tile per occupied pattern cell, in pattern order. */
15700
- tiles(placement, offsets, reads, shift = null) {
16045
+ /**
16046
+ * One tile per occupied pattern cell, in pattern order. `accepts` filters
16047
+ * each cell's winner; it never looks under a winner.
16048
+ */
16049
+ tiles(placement, offsets, reads, shift = null, accepts) {
15701
16050
  reads?.add({ kind: "placement", valueId: placement.valueId });
15702
16051
  const origin = shiftedOrigin(placement, shift);
15703
16052
  const result = [];
@@ -15705,7 +16054,9 @@ var WorldGridQueryIndex = class {
15705
16054
  const cell = translated2(origin, offset);
15706
16055
  reads?.add({ kind: "tile", gridId: placement.gridId, cell });
15707
16056
  const tile = this.tileAt(placement.gridId, cell);
15708
- if (tile !== null) result.push(tile.placementValueId);
16057
+ if (tile !== null && (accepts === void 0 || accepts(tile.classId))) {
16058
+ result.push(tile.placementValueId);
16059
+ }
15709
16060
  }
15710
16061
  return result;
15711
16062
  }
@@ -16584,6 +16935,9 @@ var NeoScriptScope = class {
16584
16935
  // ../packages/neoscript-runtime/src/neoscript/evaluateNSGetter.ts
16585
16936
  var DELEGATE_LEXICAL_THIS = /* @__PURE__ */ Symbol("neoDelegateLexicalThis");
16586
16937
  var DELEGATE_LEXICAL_ROOT = /* @__PURE__ */ Symbol("neoDelegateLexicalRoot");
16938
+ var DELEGATE_LEXICAL_TYPE_ARGUMENTS = /* @__PURE__ */ Symbol(
16939
+ "neoDelegateLexicalTypeArguments"
16940
+ );
16587
16941
  var NonCatchableNSGetterRuntimeError = class extends NSGetterRuntimeError {
16588
16942
  };
16589
16943
  var NativeFunctionDelegateUnavailableError = class extends NonCatchableNSGetterRuntimeError {
@@ -17309,6 +17663,7 @@ function forgetLocalListIndexes(ctx, list) {
17309
17663
  ctx.__indexes?.declaredListByArray.delete(list);
17310
17664
  }
17311
17665
  function trackedRowForValueReference(value, ctx) {
17666
+ if (value instanceof RuntimeSet) value = value.source;
17312
17667
  if (typeof value !== "object" || value === null) return null;
17313
17668
  const indexes3 = evaluatorIndexes(ctx);
17314
17669
  const indexed = indexes3.rowByValueReference.get(value) ?? indexes3.baseRowByValueReference?.get(value) ?? ctx.vm.databaseVM?.rowForValueReference?.(value) ?? null;
@@ -17708,6 +18063,10 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options =
17708
18063
  if (getter.typeInfo.type === 20 /* Decimal */ && typeof result.value === "number") {
17709
18064
  result.value = coerceDecimalOperand(result.value, "return");
17710
18065
  }
18066
+ if (ownsInvocationState) {
18067
+ flushRuntimeSets(runtimeCtx);
18068
+ result.value = exportRuntimeSetValue(result.value, runtimeCtx);
18069
+ }
17711
18070
  const initializerResult = options.initializerResult;
17712
18071
  if (initializerResult !== void 0 && result.value !== null && isMemberWithEntries(initializerResult.member) && findKnownRowIdByValueReference(result.value, runtimeCtx) === null) {
17713
18072
  const createdValues = createdSessionValuesSince(runtimeCtx, creationCheckpoint);
@@ -17824,6 +18183,10 @@ function evaluateNSFunction(action, ctx, args) {
17824
18183
  runtimeArgs,
17825
18184
  action.typeInfo.type === 0 /* Null */
17826
18185
  );
18186
+ if (ownsInvocationState) {
18187
+ flushRuntimeSets(runtimeCtx);
18188
+ value = exportRuntimeSetValue(value, runtimeCtx);
18189
+ }
17827
18190
  exported = prepareSessionValueExport(
17828
18191
  runtimeCtx,
17829
18192
  creationCheckpoint,
@@ -17860,10 +18223,18 @@ function evaluateNSFunction(action, ctx, args) {
17860
18223
  }
17861
18224
  function evaluateNSDelegate(value, ctx, args = []) {
17862
18225
  const runtimeCtx = withEvaluationRuntime(ctx, []);
17863
- return preserveReadOnlyReturnIdentity(
17864
- invokeDelegateValue(value, args, runtimeCtx),
17865
- runtimeCtx
17866
- );
18226
+ try {
18227
+ const result = preserveReadOnlyReturnIdentity(
18228
+ invokeDelegateValue(value, args, runtimeCtx),
18229
+ runtimeCtx
18230
+ );
18231
+ if (ctx.__executionState !== void 0) return result;
18232
+ flushRuntimeSets(runtimeCtx);
18233
+ return exportRuntimeSetValue(result, runtimeCtx);
18234
+ } finally {
18235
+ if (ctx.__executionState === void 0)
18236
+ runtimeCtx.__dirtyRuntimeSets?.clear();
18237
+ }
17867
18238
  }
17868
18239
  function bindNeoScriptDelegateToContext(value, ctx) {
17869
18240
  if (!isNSDelegateClosureValue(value)) return value;
@@ -17891,6 +18262,8 @@ function withEvaluationRuntime(ctx, writes) {
17891
18262
  if (ctx.__runtimeSessionValues !== void 0 && ctx.__executionState !== void 0 && ctx.__valueOverlay !== void 0) {
17892
18263
  ctx.__unorderedListProjections ??= createUnorderedListProjectionCache();
17893
18264
  ctx.__setEntryIndexes ??= /* @__PURE__ */ new WeakMap();
18265
+ ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
18266
+ ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
17894
18267
  ctx.__runtimeClassOverrides ??= /* @__PURE__ */ new Map();
17895
18268
  ctx.__getterSubscriptions ??= getterSubscriptionsFor(ctx);
17896
18269
  return ctx;
@@ -17925,6 +18298,8 @@ function withEvaluationRuntime(ctx, writes) {
17925
18298
  __valueOverlay: overlay,
17926
18299
  __unorderedListProjections: ctx.__unorderedListProjections ?? createUnorderedListProjectionCache(),
17927
18300
  __setEntryIndexes: ctx.__setEntryIndexes ?? /* @__PURE__ */ new WeakMap(),
18301
+ __runtimeSets: ctx.__runtimeSets ?? /* @__PURE__ */ new WeakMap(),
18302
+ __dirtyRuntimeSets: ctx.__dirtyRuntimeSets ?? /* @__PURE__ */ new Set(),
17928
18303
  __runtimeReferenceRemap: referenceRemap,
17929
18304
  __executionState: ctx.__executionState ?? {
17930
18305
  writes,
@@ -18023,6 +18398,7 @@ function cleanupRowDatabase(ctx, session, groupByRowId) {
18023
18398
  }
18024
18399
  function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, returnTypeInfo, retainListenerReceivers = true) {
18025
18400
  if (!ownsInvocationState) return;
18401
+ ctx.__dirtyRuntimeSets?.clear();
18026
18402
  const state = ctx.__executionState;
18027
18403
  const session = ctx.__runtimeSessionValues;
18028
18404
  if (state === void 0 || session === void 0) return;
@@ -18555,7 +18931,7 @@ function executeCompiledFunction(action, ctx, args, allowFallthroughReturn, runt
18555
18931
  for (let index = 0; index < filledArgs.length; index += 1) {
18556
18932
  const parameter3 = action.parameters[index + 2];
18557
18933
  const runtimeTypeInfo = runtimeArgumentTypes[index];
18558
- const value2 = filledArgs[index];
18934
+ const value2 = asDeclaredRuntimeSet(filledArgs[index], runtimeTypeInfo, ctx);
18559
18935
  if (!runtimeValueMatchesType(value2, runtimeTypeInfo, ctx)) {
18560
18936
  throw new NSGetterRuntimeError(
18561
18937
  `NSFunction argument ${index + 1} does not match its declared runtime type.`
@@ -18933,6 +19309,7 @@ function evalInstructions(instructions, scope, ctx, options) {
18933
19309
  if (ins.variable.typeInfo.type === 20 /* Decimal */ && typeof value === "number") {
18934
19310
  value = coerceDecimalOperand(value, "variable initialization");
18935
19311
  }
19312
+ value = asDeclaredRuntimeSet(value, ins.variable.typeInfo, ctx);
18936
19313
  scope.setLocal(ins.variable.id, value);
18937
19314
  break;
18938
19315
  }
@@ -20134,7 +20511,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20134
20511
  }
20135
20512
  writableStaticBindingMap(member, ctx);
20136
20513
  }
20137
- const targetValue = evalPointer(ins.target.pointer, scope, ctx);
20514
+ let targetValue = evalPointer(ins.target.pointer, scope, ctx);
20138
20515
  const variablePointer = ins.target.pointer.type === "variable" /* variable */ ? ins.target.pointer : null;
20139
20516
  const unorderedContainerValueId = unorderedListProjectionContainerId(
20140
20517
  targetValue,
@@ -20157,6 +20534,14 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20157
20534
  const args = ins.args.map((arg) => evalPointer(arg, scope, ctx));
20158
20535
  const setEntryMember = mutatesLocalVariable ? null : storedSetEntryMember(targetValue, ctx);
20159
20536
  const isLookupSet = setEntryMember === null && ins.target.typeInfo.type === 9 /* Lookup */;
20537
+ if (isLookupSet && Array.isArray(targetValue)) {
20538
+ targetValue = runtimeSet(
20539
+ targetValue,
20540
+ ins.reference === true,
20541
+ ins.target.typeInfo.type === 9 /* Lookup */ && (ins.target.typeInfo.entryTypeInfo.type === 8 /* Enum */ || ins.target.typeInfo.entryTypeInfo.type === 18 /* DialogueLookup */),
20542
+ ctx
20543
+ );
20544
+ }
20160
20545
  const setMatch = setEntryMember !== null && Array.isArray(targetValue) && (ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) ? findStoredSetEntry(targetValue, args[0], setEntryMember, ctx) : null;
20161
20546
  if (ins.mutation === "Add" /* Add */ && setMatch !== null) return;
20162
20547
  if (ins.mutation === "Remove" /* Remove */ && setEntryMember !== null && setMatch === null) {
@@ -20187,7 +20572,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20187
20572
  }
20188
20573
  validateCollectionMutation(targetValue, ins.mutation, args);
20189
20574
  const overlayArgs = [...args];
20190
- if ((ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) && Array.isArray(targetValue)) {
20575
+ if ((ins.mutation === "Add" /* Add */ || ins.mutation === "Remove" /* Remove */) && isArrayCollection(targetValue)) {
20191
20576
  if (setMatch !== null) overlayArgs[0] = setMatch.entry;
20192
20577
  else if (isLookupSet)
20193
20578
  overlayArgs[0] = lookupSetSelectionValue(
@@ -20199,10 +20584,10 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20199
20584
  overlayArgs[0] = findKnownRowIdByValueReference(args[0], ctx) ?? args[0];
20200
20585
  } else if (ins.mutation === "Insert" /* Insert */) {
20201
20586
  overlayArgs[1] = findKnownRowIdByValueReference(args[1], ctx) ?? args[1];
20202
- } else if (ins.mutation === "Add" /* Add */ && !Array.isArray(targetValue)) {
20587
+ } else if (ins.mutation === "Add" /* Add */ && !isArrayCollection(targetValue)) {
20203
20588
  overlayArgs[1] = findKnownRowIdByValueReference(args[1], ctx) ?? args[1];
20204
20589
  }
20205
- if (ins.mutation === "Add" /* Add */ && Array.isArray(targetValue) && unorderedContainerValueId !== null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null) {
20590
+ if (ins.mutation === "Add" /* Add */ && isArrayCollection(targetValue) && unorderedContainerValueId !== null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null) {
20206
20591
  overlayArgs[0] = createUnorderedScalarProjectionEntry(
20207
20592
  unorderedContainerValueId,
20208
20593
  args[0],
@@ -20211,7 +20596,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20211
20596
  }
20212
20597
  const unorderedEntriesBeforeMutation = unorderedContainerValueId === null || !Array.isArray(targetValue) || ins.mutation === "Add" /* Add */ ? null : [...targetValue];
20213
20598
  if ((ins.mutation === "Add" /* Add */ || ins.mutation === "Insert" /* Insert */) && !isLookupSet) {
20214
- const attachedValue = Array.isArray(targetValue) && ins.mutation !== "Insert" /* Insert */ ? args[0] : args[1];
20599
+ const attachedValue = isArrayCollection(targetValue) && ins.mutation !== "Insert" /* Insert */ ? args[0] : args[1];
20215
20600
  const attachedValueId = findKnownRowIdByValueReference(attachedValue, ctx);
20216
20601
  const parentId = findKnownRowIdByValueReference(targetValue, ctx);
20217
20602
  if (attachedValueId !== null && parentId !== null) {
@@ -20220,8 +20605,8 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20220
20605
  unorderedContainerValueId ?? void 0
20221
20606
  );
20222
20607
  let slot = `slot:${String(args[0])}`;
20223
- if (Array.isArray(targetValue)) {
20224
- const insertionIndex = ins.mutation === "Insert" /* Insert */ ? args[0] : targetValue.length;
20608
+ if (isArrayCollection(targetValue)) {
20609
+ const insertionIndex = ins.mutation === "Insert" /* Insert */ ? args[0] : collectionLength(targetValue);
20225
20610
  slot = `index:${insertionIndex}`;
20226
20611
  }
20227
20612
  assertOwnedValueAttachable(
@@ -20240,7 +20625,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20240
20625
  overlayArgs,
20241
20626
  ctx,
20242
20627
  isLookupSet,
20243
- ins.reference !== true && ins.mutation === "Remove" /* Remove */ && Array.isArray(targetValue) && unorderedContainerValueId !== null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
20628
+ ins.reference !== true && ins.mutation === "Remove" /* Remove */ && isArrayCollection(targetValue) && setEntryMember === null && !isLookupSet && findKnownRowIdByValueReference(args[0], ctx) === null,
20244
20629
  ins.reference === true
20245
20630
  );
20246
20631
  updateCollectionReferenceProvenance(
@@ -20278,7 +20663,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20278
20663
  });
20279
20664
  return;
20280
20665
  case "Add" /* Add */:
20281
- if (Array.isArray(targetValue)) {
20666
+ if (isArrayCollection(targetValue)) {
20282
20667
  options.writes.push({
20283
20668
  kind: "add",
20284
20669
  target: ins.target,
@@ -20300,7 +20685,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
20300
20685
  });
20301
20686
  return;
20302
20687
  case "Remove" /* Remove */:
20303
- if (Array.isArray(targetValue)) {
20688
+ if (isArrayCollection(targetValue)) {
20304
20689
  options.writes.push({
20305
20690
  kind: "remove",
20306
20691
  target: ins.target,
@@ -20366,6 +20751,101 @@ function storedSetEntryMember(collection, ctx) {
20366
20751
  ctx.vm.members
20367
20752
  );
20368
20753
  }
20754
+ function flushRuntimeSets(ctx) {
20755
+ for (const set of ctx.__dirtyRuntimeSets ?? [])
20756
+ exportRuntimeSetValue(set, ctx);
20757
+ ctx.__dirtyRuntimeSets?.clear();
20758
+ for (const write of ctx.__executionState?.writes ?? []) {
20759
+ if ("value" in write) write.value = exportRuntimeSetValue(write.value, ctx);
20760
+ }
20761
+ }
20762
+ function exportRuntimeSetValue(value, ctx, seen = /* @__PURE__ */ new Map()) {
20763
+ if (typeof value !== "object" || value === null) return value;
20764
+ if (seen.has(value)) return seen.get(value);
20765
+ if (value instanceof RuntimeSet) {
20766
+ seen.set(value, value.source);
20767
+ const entries = value.membership();
20768
+ value.source.length = entries.length;
20769
+ const references = /* @__PURE__ */ new Set();
20770
+ for (let index = 0; index < entries.length; index++) {
20771
+ value.source[index] = exportRuntimeSetValue(
20772
+ entries[index].raw,
20773
+ ctx,
20774
+ seen
20775
+ );
20776
+ if (entries[index].reference) references.add(index);
20777
+ }
20778
+ unorderedListProjectionCache(ctx).referenceEntryIndexesByArray.set(
20779
+ value.source,
20780
+ references
20781
+ );
20782
+ ctx.__dirtyRuntimeSets?.delete(value);
20783
+ return value.source;
20784
+ }
20785
+ if (Array.isArray(value)) {
20786
+ const copy = [];
20787
+ seen.set(value, copy);
20788
+ let changed = false;
20789
+ for (const entry of value) {
20790
+ const exported = exportRuntimeSetValue(entry, ctx, seen);
20791
+ copy.push(exported);
20792
+ changed ||= exported !== entry;
20793
+ }
20794
+ const result = changed ? copy : value;
20795
+ seen.set(value, result);
20796
+ return result;
20797
+ }
20798
+ if (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null) {
20799
+ const copy = {};
20800
+ seen.set(value, copy);
20801
+ let changed = false;
20802
+ for (const [key, entry] of Object.entries(value)) {
20803
+ const exported = exportRuntimeSetValue(entry, ctx, seen);
20804
+ setOwnField(copy, key, exported);
20805
+ changed ||= exported !== entry;
20806
+ }
20807
+ const result = changed ? copy : value;
20808
+ seen.set(value, result);
20809
+ return result;
20810
+ }
20811
+ return value;
20812
+ }
20813
+ function isArrayCollection(value) {
20814
+ return Array.isArray(value) || value instanceof RuntimeSet;
20815
+ }
20816
+ function asDeclaredRuntimeSet(value, type, ctx) {
20817
+ if (type.type !== 9 /* Lookup */ || !Array.isArray(value) || storedSetEntryMember(value, ctx) !== null)
20818
+ return value;
20819
+ const entry = type.entryTypeInfo.type;
20820
+ return runtimeSet(
20821
+ value,
20822
+ entry === 7 /* Class */ || entry === 22 /* Interface */ || entry === 6 /* List */ || entry === 5 /* Dictionary */ || entry === 9 /* Lookup */,
20823
+ entry === 8 /* Enum */ || entry === 18 /* DialogueLookup */,
20824
+ ctx
20825
+ );
20826
+ }
20827
+ function runtimeSetKey(value, set, ctx) {
20828
+ if (set.enumEntries && Array.isArray(value) && value.length === 1)
20829
+ value = value[0];
20830
+ return toSetEntryKey(value, null, set.reference, ctx);
20831
+ }
20832
+ function runtimeSet(array2, reference, enumEntries, ctx) {
20833
+ const sets = ctx.__runtimeSets ??= /* @__PURE__ */ new WeakMap();
20834
+ ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set();
20835
+ const existing = sets.get(array2);
20836
+ if (existing !== void 0) return existing;
20837
+ const set = new RuntimeSet(array2, reference, enumEntries);
20838
+ for (let index = 0; index < array2.length; index++) {
20839
+ const raw = array2[index];
20840
+ const resolves = collectionEntryUsesReferenceResolution(array2, index, ctx);
20841
+ const value = resolves ? resolveValueIfId(raw, ctx) : raw;
20842
+ const key = runtimeSetKey(value, set, ctx);
20843
+ set.add(key, enumEntries ? key : raw, !enumEntries && resolves);
20844
+ }
20845
+ sets.set(array2, set);
20846
+ (ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(set);
20847
+ return set;
20848
+ }
20369
20849
  function storedSetEntryMatch(raw, entryMember, ctx) {
20370
20850
  const byIdentity = entryMember.kind === 7 /* Class */;
20371
20851
  const row = byIdentity || typeof raw !== "string" ? null : evalValueById(ctx, raw, ctx.__runtimeSessionValues, ctx.__valueOverlay);
@@ -20407,7 +20887,29 @@ function findStoredSetEntry(set, value, entryMember, ctx) {
20407
20887
  if (key === null) return null;
20408
20888
  return storedSetEntries(set, entryMember, ctx).get(key) ?? null;
20409
20889
  }
20410
- function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveJoinedRemovalEntries = false, reference = false) {
20890
+ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false, resolveRemovalEntries = false, reference = false) {
20891
+ if (targetValue instanceof RuntimeSet) {
20892
+ (ctx.__dirtyRuntimeSets ??= /* @__PURE__ */ new Set()).add(targetValue);
20893
+ switch (mutation) {
20894
+ case "Add" /* Add */:
20895
+ targetValue.add(
20896
+ runtimeSetKey(args[0], targetValue, ctx),
20897
+ args[0],
20898
+ targetValue.reference
20899
+ );
20900
+ return null;
20901
+ case "Remove" /* Remove */:
20902
+ targetValue.remove(runtimeSetKey(args[0], targetValue, ctx));
20903
+ return null;
20904
+ case "Clear" /* Clear */:
20905
+ targetValue.clear();
20906
+ return null;
20907
+ default:
20908
+ throw new NSGetterRuntimeError(
20909
+ "Set only supports Add, Remove, and Clear."
20910
+ );
20911
+ }
20912
+ }
20411
20913
  validateCollectionMutation(targetValue, mutation, args);
20412
20914
  switch (mutation) {
20413
20915
  case "Insert" /* Insert */: {
@@ -20448,7 +20950,7 @@ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique =
20448
20950
  }
20449
20951
  const referenceEntry = ctx.__unorderedListProjections?.referenceEntryIndexesByArray.get(targetValue)?.has(candidate) === true;
20450
20952
  if (jsEqual(
20451
- resolveJoinedRemovalEntries || referenceEntry ? resolveValueIfId(entry, ctx) : entry,
20953
+ resolveRemovalEntries || referenceEntry ? resolveCollectionEntry(targetValue, entry, candidate, ctx) : entry,
20452
20954
  args[0]
20453
20955
  )) {
20454
20956
  index = candidate;
@@ -20518,6 +21020,7 @@ function lookupSetSelectionValue(value, typeInfo, ctx) {
20518
21020
  return findKnownRowIdByValueReference(value, ctx) ?? value;
20519
21021
  }
20520
21022
  function validateCollectionMutation(targetValue, mutation, args) {
21023
+ if (targetValue instanceof RuntimeSet) return;
20521
21024
  if (mutation === "Insert" /* Insert */) {
20522
21025
  const list = listArg(targetValue, "Insert target");
20523
21026
  const index = numberArg(args[0], "Insert index");
@@ -20566,6 +21069,7 @@ function listIndexError(index, length) {
20566
21069
  return `List index out of bounds: ${String(index)}; list length is ${length}. Use an index from 0 to ${length - 1}.`;
20567
21070
  }
20568
21071
  function listArg(value, name) {
21072
+ if (value instanceof RuntimeSet) return value.toArray();
20569
21073
  if (Array.isArray(value)) return value;
20570
21074
  throw new NSGetterRuntimeError(`${name} must be a list`);
20571
21075
  }
@@ -20667,7 +21171,8 @@ function evalStaticMember(memberId, ctx) {
20667
21171
  }
20668
21172
  function evalPointer(pointer, scope, ctx, resultUsage = "value") {
20669
21173
  try {
20670
- return pointer.source ? evalPointerAtSource(pointer, scope, ctx, resultUsage) : evalPointerCore(pointer, scope, ctx, resultUsage);
21174
+ const value = pointer.source ? evalPointerAtSource(pointer, scope, ctx, resultUsage) : evalPointerCore(pointer, scope, ctx, resultUsage);
21175
+ return Array.isArray(value) ? ctx.__runtimeSets?.get(value) ?? value : value;
20671
21176
  } catch (error) {
20672
21177
  if (error instanceof NSGetterRuntimeError) {
20673
21178
  error.at(pointer);
@@ -20702,7 +21207,10 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20702
21207
  return {
20703
21208
  ...value,
20704
21209
  ...ctx.thisValue === null || ctx.thisValue === void 0 ? {} : { [DELEGATE_LEXICAL_THIS]: ctx.thisValue },
20705
- [DELEGATE_LEXICAL_ROOT]: ctx.rootValue
21210
+ [DELEGATE_LEXICAL_ROOT]: ctx.rootValue,
21211
+ ...ctx.__functionTypeArguments === void 0 ? {} : {
21212
+ [DELEGATE_LEXICAL_TYPE_ARGUMENTS]: ctx.__functionTypeArguments
21213
+ }
20706
21214
  };
20707
21215
  }
20708
21216
  if (isMemberDelegateTarget(value) && value.valueId === null) {
@@ -20828,15 +21336,27 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20828
21336
  }
20829
21337
  const args = fillCallableCallSiteArguments(suppliedArgs, member, ctx);
20830
21338
  const interceptedMemberId = member?.id ?? pointer.memberId ?? pointer.memberKey ?? pointer.callSiteId;
21339
+ const typeArguments = member === null ? void 0 : calleeTypeArguments(pointer.typeArguments, member, ctx);
20831
21340
  checkDeadline(ctx);
20832
21341
  const intercepted = ctx.callInterceptor?.({
20833
21342
  resultUsage,
20834
21343
  memberId: interceptedMemberId,
20835
21344
  member,
20836
21345
  receiver: innerThis,
20837
- args,
21346
+ get args() {
21347
+ return args.map((value) => exportRuntimeSetValue(value, ctx));
21348
+ },
20838
21349
  callSiteId: pointer.callSiteId,
20839
- invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, pointer.callSiteId)
21350
+ typeArguments,
21351
+ invokeDelegate: (delegate, delegateArgs = []) => exportRuntimeSetValue(
21352
+ invokeDelegateValue(
21353
+ delegate,
21354
+ delegateArgs,
21355
+ ctx,
21356
+ pointer.callSiteId
21357
+ ),
21358
+ ctx
21359
+ )
20840
21360
  });
20841
21361
  if (intercepted?.handled === true)
20842
21362
  return hostCallResult(member, intercepted.value, ctx);
@@ -20858,7 +21378,8 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20858
21378
  member.id,
20859
21379
  innerThis,
20860
21380
  args,
20861
- ctx
21381
+ ctx,
21382
+ typeArguments
20862
21383
  );
20863
21384
  if (systemResult.handled) return systemResult.value;
20864
21385
  const hosted = ctx.unavailableNativeHandler?.({
@@ -20866,13 +21387,18 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20866
21387
  memberId: member.id,
20867
21388
  member,
20868
21389
  receiver: innerThis,
20869
- args,
21390
+ get args() {
21391
+ return args.map((value) => exportRuntimeSetValue(value, ctx));
21392
+ },
20870
21393
  callSiteId: pointer.callSiteId,
20871
- invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(
20872
- delegate,
20873
- delegateArgs,
20874
- ctx,
20875
- pointer.callSiteId
21394
+ invokeDelegate: (delegate, delegateArgs = []) => exportRuntimeSetValue(
21395
+ invokeDelegateValue(
21396
+ delegate,
21397
+ delegateArgs,
21398
+ ctx,
21399
+ pointer.callSiteId
21400
+ ),
21401
+ ctx
20876
21402
  )
20877
21403
  });
20878
21404
  if (hosted?.handled === true)
@@ -20917,7 +21443,12 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20917
21443
  `NSFunction call stack exceeded 64 frames: ${chain.join(" -> ")}.`
20918
21444
  );
20919
21445
  }
20920
- const runtimeSignature = pointer.receiver.kind === "static" ? signature : substituteCallableSignatureForReceiver(signature, innerThis, ctx);
21446
+ const boundSignature = typeArguments === void 0 ? signature : bindSignatureTypeArguments(signature, typeArguments);
21447
+ const runtimeSignature = pointer.receiver.kind === "static" ? boundSignature : substituteCallableSignatureForReceiver(
21448
+ boundSignature,
21449
+ innerThis,
21450
+ ctx
21451
+ );
20921
21452
  state.functionStack.push({
20922
21453
  name: member.name,
20923
21454
  deferred: signature.deferred
@@ -20925,7 +21456,7 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
20925
21456
  try {
20926
21457
  return executeCompiledFunction(
20927
21458
  action,
20928
- bindThisValue(ctx, innerThis),
21459
+ withFrameTypeArguments(bindThisValue(ctx, innerThis), typeArguments),
20929
21460
  args,
20930
21461
  runtimeSignature.returnTypeInfo.type === NS_TYPE_VOID,
20931
21462
  runtimeSignature
@@ -21020,7 +21551,8 @@ function evalPointerCore(pointer, scope, ctx, resultUsage = "value") {
21020
21551
  (capture) => evalPointer(capture, scope, ctx)
21021
21552
  ),
21022
21553
  ...ctx.thisValue === null || ctx.thisValue === void 0 ? {} : { [DELEGATE_LEXICAL_THIS]: ctx.thisValue },
21023
- [DELEGATE_LEXICAL_ROOT]: ctx.rootValue
21554
+ [DELEGATE_LEXICAL_ROOT]: ctx.rootValue,
21555
+ ...ctx.__functionTypeArguments === void 0 ? {} : { [DELEGATE_LEXICAL_TYPE_ARGUMENTS]: ctx.__functionTypeArguments }
21024
21556
  };
21025
21557
  case "toBool" /* toBool */: {
21026
21558
  const v = evalPointer(pointer.pointer, scope, ctx);
@@ -21088,7 +21620,8 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
21088
21620
  {
21089
21621
  ...ctx,
21090
21622
  thisValue,
21091
- rootValue: closure[DELEGATE_LEXICAL_ROOT] ?? ctx.rootValue
21623
+ rootValue: closure[DELEGATE_LEXICAL_ROOT] ?? ctx.rootValue,
21624
+ __functionTypeArguments: closure[DELEGATE_LEXICAL_TYPE_ARGUMENTS]
21092
21625
  },
21093
21626
  [...args, ...captures],
21094
21627
  value.action.typeInfo.type === 0 /* Null */
@@ -21162,9 +21695,15 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
21162
21695
  memberId: member.id,
21163
21696
  member,
21164
21697
  receiver,
21165
- args,
21698
+ get args() {
21699
+ return args.map((value2) => exportRuntimeSetValue(value2, ctx));
21700
+ },
21166
21701
  callSiteId,
21167
- invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId)
21702
+ typeArguments: calleeTypeArguments(void 0, member, ctx),
21703
+ invokeDelegate: (delegate, delegateArgs = []) => exportRuntimeSetValue(
21704
+ invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId),
21705
+ ctx
21706
+ )
21168
21707
  });
21169
21708
  if (onCompleted === void 0) {
21170
21709
  const intercepted = intercept();
@@ -21192,9 +21731,14 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
21192
21731
  memberId: member.id,
21193
21732
  member,
21194
21733
  receiver,
21195
- args,
21734
+ get args() {
21735
+ return args.map((value2) => exportRuntimeSetValue(value2, ctx));
21736
+ },
21196
21737
  callSiteId,
21197
- invokeDelegate: (delegate, delegateArgs = []) => invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId)
21738
+ invokeDelegate: (delegate, delegateArgs = []) => exportRuntimeSetValue(
21739
+ invokeDelegateValue(delegate, delegateArgs, ctx, callSiteId),
21740
+ ctx
21741
+ )
21198
21742
  });
21199
21743
  if (hosted?.handled === true)
21200
21744
  return hostCallResult(member, hosted.value, ctx);
@@ -21213,11 +21757,17 @@ function invokeDelegateValue(value, args, ctx, callSiteId, ownerReceiver, result
21213
21757
  `NeoDelegate target NSFunction '${member.name}' has no valid compiled body.`
21214
21758
  );
21215
21759
  }
21216
- const runtimeSignature = receiver === null ? signature : substituteCallableSignatureForReceiver(signature, receiver, ctx);
21760
+ const typeArguments = calleeTypeArguments(void 0, member, ctx);
21761
+ const boundSignature = typeArguments === void 0 ? signature : bindSignatureTypeArguments(signature, typeArguments);
21762
+ const runtimeSignature = receiver === null ? boundSignature : substituteCallableSignatureForReceiver(
21763
+ boundSignature,
21764
+ receiver,
21765
+ ctx
21766
+ );
21217
21767
  try {
21218
21768
  return executeCompiledFunction(
21219
21769
  action,
21220
- bindThisValue(ctx, receiver),
21770
+ withFrameTypeArguments(bindThisValue(ctx, receiver), typeArguments),
21221
21771
  args,
21222
21772
  runtimeSignature.returnTypeInfo.type === NS_TYPE_VOID,
21223
21773
  runtimeSignature
@@ -21479,8 +22029,8 @@ function resolveCallableSignature(memberId, memberKind, ctx) {
21479
22029
  return resolved;
21480
22030
  }
21481
22031
  function substituteCallableSignatureForReceiver(signature, receiver, ctx) {
21482
- if (!typeInfoContainsGeneric(signature.returnTypeInfo) && !signature.argumentTypes.some(
21483
- (typeInfo) => typeInfoContainsGeneric(typeInfo)
22032
+ if (!typeInfoContainsGeneric2(signature.returnTypeInfo) && !signature.argumentTypes.some(
22033
+ (typeInfo) => typeInfoContainsGeneric2(typeInfo)
21484
22034
  )) {
21485
22035
  return signature;
21486
22036
  }
@@ -21500,7 +22050,7 @@ function substituteCallableSignatureForReceiver(signature, receiver, ctx) {
21500
22050
  ctx
21501
22051
  ),
21502
22052
  argumentTypes: signature.argumentTypes.map((argument2) => {
21503
- if (!typeInfoContainsGeneric(argument2)) return argument2;
22053
+ if (!typeInfoContainsGeneric2(argument2)) return argument2;
21504
22054
  const substituted = substituteRuntimeTypeInfo(argument2, env, ctx);
21505
22055
  if (substituted.type === NS_TYPE_VOID) {
21506
22056
  throw new NSGetterRuntimeError(
@@ -21524,7 +22074,66 @@ function substituteCallableSignatureForReceiver(signature, receiver, ctx) {
21524
22074
  );
21525
22075
  }
21526
22076
  }
21527
- function typeInfoContainsGeneric(typeInfo, visited = /* @__PURE__ */ new Set()) {
22077
+ function calleeTypeArguments(written, member, ctx) {
22078
+ const parameters = member.genericParams;
22079
+ if (parameters === void 0) return void 0;
22080
+ if (written !== void 0 && written.length === parameters.length && !typeArgumentsForward(written)) {
22081
+ return written;
22082
+ }
22083
+ return parameters.map((parameter3, index) => {
22084
+ const argument2 = written?.[index];
22085
+ if (argument2 !== void 0) {
22086
+ return ctx.__functionTypeArguments === void 0 ? argument2 : bindFunctionTypeArguments(argument2, ctx.__functionTypeArguments);
22087
+ }
22088
+ if (parameter3.defaultType !== void 0) return parameter3.defaultType;
22089
+ throw new NSGetterRuntimeError(
22090
+ `Call to '${member.name}' supplies no type argument for '${parameter3.name}', and it has no default.`
22091
+ );
22092
+ });
22093
+ }
22094
+ var FORWARDING_TYPE_ARGUMENTS = /* @__PURE__ */ new WeakMap();
22095
+ function typeArgumentsForward(written) {
22096
+ let forwards = FORWARDING_TYPE_ARGUMENTS.get(written);
22097
+ if (forwards === void 0) {
22098
+ forwards = written.some(typeInfoHasFunctionGeneric);
22099
+ FORWARDING_TYPE_ARGUMENTS.set(written, forwards);
22100
+ }
22101
+ return forwards;
22102
+ }
22103
+ function withFrameTypeArguments(ctx, table) {
22104
+ if (ctx.__functionTypeArguments === table) return ctx;
22105
+ return { ...ctx, __functionTypeArguments: table };
22106
+ }
22107
+ function functionTypeArgument(typeInfo, ctx) {
22108
+ const bound = ctx.__functionTypeArguments?.[typeInfo.index];
22109
+ if (bound !== void 0) return bound;
22110
+ const owner = evalMemberById(ctx.vm, typeInfo.ownerMemberId);
22111
+ const parameter3 = functionGenericParamsOf(owner)?.[typeInfo.index];
22112
+ if (parameter3?.defaultType !== void 0) return parameter3.defaultType;
22113
+ throw new NSGetterRuntimeError(
22114
+ `Type parameter ${typeInfo.index} of function '${owner?.name ?? typeInfo.ownerMemberId}' has no type argument in this frame and no default.`
22115
+ );
22116
+ }
22117
+ function bindSignatureTypeArguments(signature, table) {
22118
+ const returnTypeInfo = bindFunctionTypeArguments(
22119
+ signature.returnTypeInfo,
22120
+ table
22121
+ );
22122
+ let argumentTypes;
22123
+ for (let index = 0; index < signature.argumentTypes.length; index++) {
22124
+ const argument2 = signature.argumentTypes[index];
22125
+ const bound = bindArgumentTypeArguments(argument2, table);
22126
+ if (bound === argument2) continue;
22127
+ argumentTypes ??= [...signature.argumentTypes];
22128
+ argumentTypes[index] = bound;
22129
+ }
22130
+ return returnTypeInfo === signature.returnTypeInfo && argumentTypes === void 0 ? signature : {
22131
+ ...signature,
22132
+ returnTypeInfo,
22133
+ argumentTypes: argumentTypes ?? signature.argumentTypes
22134
+ };
22135
+ }
22136
+ function typeInfoContainsGeneric2(typeInfo, visited = /* @__PURE__ */ new Set()) {
21528
22137
  if (visited.has(typeInfo)) {
21529
22138
  throw new NSGetterRuntimeError(
21530
22139
  "Corrupt NSFunction signature contains a cyclic type-info graph."
@@ -21534,11 +22143,11 @@ function typeInfoContainsGeneric(typeInfo, visited = /* @__PURE__ */ new Set())
21534
22143
  nextVisited.add(typeInfo);
21535
22144
  if (typeInfo.type === 21 /* Generic */) return true;
21536
22145
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 28 /* Set */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
21537
- return typeInfoContainsGeneric(typeInfo.entryTypeInfo, nextVisited);
22146
+ return typeInfoContainsGeneric2(typeInfo.entryTypeInfo, nextVisited);
21538
22147
  }
21539
22148
  if (typeInfo.type !== 7 /* Class */) return false;
21540
22149
  return Object.values(typeInfo.typeArguments ?? {}).some(
21541
- (argument2) => typeInfoContainsGeneric(argument2, nextVisited)
22150
+ (argument2) => typeInfoContainsGeneric2(argument2, nextVisited)
21542
22151
  );
21543
22152
  }
21544
22153
  function runtimeGenericEnvForValueRow(row, ctx, visited = /* @__PURE__ */ new Set(), readRow) {
@@ -21602,7 +22211,7 @@ function overlayConcreteGenericEntries(target, source) {
21602
22211
  }
21603
22212
  function genericParametersConcretelyBound(typeInfo, env) {
21604
22213
  if (typeInfo.type === 21 /* Generic */) {
21605
- return env.get(typeInfo.genericParamId)?.kind === "member";
22214
+ return isClassGenericParamTypeInfo(typeInfo) && env.get(typeInfo.genericParamId)?.kind === "member";
21606
22215
  }
21607
22216
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 28 /* Set */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
21608
22217
  return genericParametersConcretelyBound(typeInfo.entryTypeInfo, env);
@@ -21619,6 +22228,10 @@ function genericParametersConcretelyBound(typeInfo, env) {
21619
22228
  return true;
21620
22229
  }
21621
22230
  function substituteRuntimeTypeInfo(typeInfo, env, ctx) {
22231
+ if (typeInfo.type === 21 /* Generic */ && !isClassGenericParamTypeInfo(typeInfo)) {
22232
+ const bound = functionTypeArgument(typeInfo, ctx);
22233
+ return { ...bound, required: bound.required && typeInfo.required };
22234
+ }
21622
22235
  if (typeInfo.type === 21 /* Generic */) {
21623
22236
  const binding = env.get(typeInfo.genericParamId);
21624
22237
  if (binding?.kind !== "member") {
@@ -22074,6 +22687,20 @@ function runtimeTypeCheck(value, checkType, ctx, seenCollections = /* @__PURE__
22074
22687
  case 6 /* List */:
22075
22688
  case 28 /* Set */:
22076
22689
  case 9 /* Lookup */: {
22690
+ if (value instanceof RuntimeSet) {
22691
+ if (seenCollections.has(value)) return false;
22692
+ const seen2 = new Set(seenCollections);
22693
+ seen2.add(value);
22694
+ return value.matches(
22695
+ checkType,
22696
+ (entry) => runtimeCollectionEntryMatchesType(
22697
+ value.enumEntries && typeof entry === "string" ? [entry] : entry,
22698
+ checkType.entryTypeInfo,
22699
+ ctx,
22700
+ seen2
22701
+ )
22702
+ );
22703
+ }
22077
22704
  if (!Array.isArray(value)) return false;
22078
22705
  if (seenCollections.has(value)) return false;
22079
22706
  if (checkType.type === 9 /* Lookup */ && (checkType.entryTypeInfo.type === 8 /* Enum */ || checkType.entryTypeInfo.type === 18 /* DialogueLookup */)) {
@@ -22130,6 +22757,14 @@ function runtimeTypeCheck(value, checkType, ctx, seenCollections = /* @__PURE__
22130
22757
  );
22131
22758
  }
22132
22759
  case 21 /* Generic */:
22760
+ if (!isClassGenericParamTypeInfo(checkType)) {
22761
+ return runtimeTypeCheck(
22762
+ value,
22763
+ functionTypeArgument(checkType, ctx),
22764
+ ctx,
22765
+ seenCollections
22766
+ );
22767
+ }
22133
22768
  return true;
22134
22769
  default:
22135
22770
  return false;
@@ -22138,7 +22773,7 @@ function runtimeTypeCheck(value, checkType, ctx, seenCollections = /* @__PURE__
22138
22773
  function runtimeValueMatchesType(value, typeInfo, ctx, seenCollections = /* @__PURE__ */ new Set()) {
22139
22774
  if (typeInfo.type === NS_TYPE_UNKNOWN) return true;
22140
22775
  if (value === null || value === void 0) {
22141
- return typeInfo.type === 0 /* Null */ || typeInfo.type === 21 /* Generic */ || !typeInfo.required;
22776
+ return typeInfo.type === 0 /* Null */ || typeInfo.type === 21 /* Generic */ && isClassGenericParamTypeInfo(typeInfo) || !typeInfo.required;
22142
22777
  }
22143
22778
  return runtimeTypeCheck(value, typeInfo, ctx, seenCollections);
22144
22779
  }
@@ -22957,7 +23592,21 @@ function readGridQueryOffset(value) {
22957
23592
  }
22958
23593
  return value;
22959
23594
  }
22960
- function evaluateSystemNative(memberId, receiver, args, ctx) {
23595
+ function gridQueryClassFilter(typeArgument, ctx) {
23596
+ if (typeArgument === void 0) return void 0;
23597
+ if (typeArgument.type !== 7 /* Class */) {
23598
+ throw new NSGetterRuntimeError(
23599
+ `Grid query type argument must be a class, not member kind ${typeArgument.type}.`
23600
+ );
23601
+ }
23602
+ const classId = typeArgument.classId;
23603
+ if (classId === NEO_OBJECT_CLASS_ID || classId === NEO_TILE_CLASS_ID) {
23604
+ return void 0;
23605
+ }
23606
+ const schema = evaluatorSchemaIndex(ctx);
23607
+ return (candidate) => schema.classIsOrExtends(candidate, classId);
23608
+ }
23609
+ function evaluateSystemNative(memberId, receiver, args, ctx, typeArguments) {
22961
23610
  try {
22962
23611
  if (memberId === NEO_OBJECT_GRID_MEMBER_IDS.GetCell || memberId === NEO_OBJECT_GRID_MEMBER_IDS.GetObjects || memberId === NEO_OBJECT_GRID_MEMBER_IDS.GetTile || memberId === NEO_OBJECT_GRID_MEMBER_IDS.GetTiles) {
22963
23612
  const receiverRow = trackedRowForValueReference(receiver, ctx);
@@ -22975,12 +23624,14 @@ function evaluateSystemNative(memberId, receiver, args, ctx) {
22975
23624
  return { handled: true, value: { ...placement.cell } };
22976
23625
  const offsets = readCellPattern(args[0], ctx);
22977
23626
  const shift = readGridQueryOffset(args[1]);
23627
+ const accepts = gridQueryClassFilter(typeArguments?.[0], ctx);
22978
23628
  if (memberId === NEO_OBJECT_GRID_MEMBER_IDS.GetObjects) {
22979
23629
  const value = index.objects(
22980
23630
  placement,
22981
23631
  offsets,
22982
23632
  ctx.worldQueryDependencies,
22983
- shift
23633
+ shift,
23634
+ accepts
22984
23635
  );
22985
23636
  return { handled: true, value };
22986
23637
  }
@@ -22989,7 +23640,8 @@ function evaluateSystemNative(memberId, receiver, args, ctx) {
22989
23640
  placement,
22990
23641
  offsets,
22991
23642
  ctx.worldQueryDependencies,
22992
- shift
23643
+ shift,
23644
+ accepts
22993
23645
  );
22994
23646
  return { handled: true, value };
22995
23647
  }
@@ -22997,7 +23649,8 @@ function evaluateSystemNative(memberId, receiver, args, ctx) {
22997
23649
  placement,
22998
23650
  offsets,
22999
23651
  ctx.worldQueryDependencies,
23000
- shift
23652
+ shift,
23653
+ accepts
23001
23654
  );
23002
23655
  if (tile === null) return { handled: true, value: null };
23003
23656
  const row = evalValueById(
@@ -23153,12 +23806,41 @@ function applyArithmetic(op, operands, decimal, ctx, numeric) {
23153
23806
  }
23154
23807
  }
23155
23808
  function hostCallResult(member, value, ctx) {
23156
- if (typeof value !== "number" || member === null) return value;
23809
+ if (member === null || typeof value !== "number" && !Array.isArray(value))
23810
+ return value;
23157
23811
  if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
23158
23812
  return value;
23159
23813
  }
23160
23814
  const signature = resolveCallableSignature(member.id, member.kind, ctx);
23161
- return signature?.returnTypeInfo.type === 4 /* Float */ ? Math.fround(value) : value;
23815
+ if (signature?.returnTypeInfo.type === 9 /* Lookup */)
23816
+ return asDeclaredRuntimeSet(value, signature.returnTypeInfo, ctx);
23817
+ return signature?.returnTypeInfo.type === 4 /* Float */ && typeof value === "number" ? Math.fround(value) : value;
23818
+ }
23819
+ function narrowGenericCallResult(value, member, typeArguments, ctx) {
23820
+ if (member.kind !== 13 /* Function */ && member.kind !== 23 /* NSFunction */) {
23821
+ return { value };
23822
+ }
23823
+ const signature = resolveCallableSignature(member.id, member.kind, ctx);
23824
+ if (signature === null) return { value };
23825
+ const returnType = bindFunctionTypeArguments(
23826
+ signature.returnTypeInfo,
23827
+ typeArguments
23828
+ );
23829
+ if (returnType === signature.returnTypeInfo) return { value };
23830
+ if (returnType.type === NS_TYPE_VOID) return { value };
23831
+ if (value === null || value === void 0) {
23832
+ return returnType.required ? { mismatch: returnType } : { value: null };
23833
+ }
23834
+ if (returnType.type === 6 /* List */ && Array.isArray(value)) {
23835
+ const entryType = returnType.entryTypeInfo;
23836
+ return {
23837
+ value: value.filter(
23838
+ (entry) => runtimeCollectionEntryMatchesType(entry, entryType, ctx, /* @__PURE__ */ new Set())
23839
+ )
23840
+ };
23841
+ }
23842
+ if (runtimeTypeCheck(value, returnType, ctx)) return { value };
23843
+ return returnType.required ? { mismatch: returnType } : { value: null };
23162
23844
  }
23163
23845
  function coerceAssignmentValue(value, targetTypeInfo, context) {
23164
23846
  if (targetTypeInfo.type === 8 /* Enum */ && typeof value === "string") {
@@ -23564,7 +24246,7 @@ function evalDeclaredListIndex(info, scope, ctx) {
23564
24246
  }
23565
24247
  const childId = row.value[info.schemaKey];
23566
24248
  const rawKey = resolveValueIfId(childId, ctx);
23567
- const normalizedKey = info.keyKind === "enum" ? Array.isArray(rawKey) && typeof rawKey[0] === "string" ? rawKey[0] : null : typeof rawKey === "string" ? rawKey : null;
24249
+ const normalizedKey = normalizeListIndexKey(rawKey, info.keyKind);
23568
24250
  if (normalizedKey === null) continue;
23569
24251
  if (info.unique) {
23570
24252
  const existing = index.get(normalizedKey);
@@ -23814,7 +24496,7 @@ function callbackBodyMayAddInvocationLocals(instructions, parameterIds) {
23814
24496
  });
23815
24497
  }
23816
24498
  function isListCollection(collection) {
23817
- if (Array.isArray(collection)) return true;
24499
+ if (isArrayCollection(collection)) return true;
23818
24500
  if (typeof collection === "object" && collection !== null) return false;
23819
24501
  throw new NSGetterRuntimeError(
23820
24502
  "Collection callback receiver must be a present List or Dictionary value."
@@ -23891,7 +24573,12 @@ function evalCollectionQuery(info, scope, ctx) {
23891
24573
  output,
23892
24574
  references
23893
24575
  );
23894
- return output;
24576
+ return info.op === "ToSet" ? runtimeSet(
24577
+ output,
24578
+ info.reference === true,
24579
+ info.enumEntries === true,
24580
+ ctx
24581
+ ) : output;
23895
24582
  };
23896
24583
  if (info.op === "OrderBy" || info.op === "OrderByDescending") {
23897
24584
  let entries = [];
@@ -24121,7 +24808,7 @@ function evalFunction(fn, scope, ctx) {
24121
24808
  return count;
24122
24809
  }
24123
24810
  case "contains" /* contains */: {
24124
- const c = evalPointer(fn.info.collectionPointer, scope, ctx);
24811
+ let c = evalPointer(fn.info.collectionPointer, scope, ctx);
24125
24812
  const target = evalPointer(fn.info.valuePointer, scope, ctx);
24126
24813
  if (typeof c === "string") {
24127
24814
  if (typeof target !== "string") {
@@ -24131,6 +24818,17 @@ function evalFunction(fn, scope, ctx) {
24131
24818
  }
24132
24819
  return c.includes(target);
24133
24820
  }
24821
+ if (Array.isArray(c)) {
24822
+ const row = trackedRowForValueReference(c, ctx);
24823
+ const member = row === null ? null : memberForValueRow(row, ctx);
24824
+ if (member !== null && (member.kind === 9 /* Lookup */ || member.kind === 8 /* Enum */ || member.kind === 18 /* DialogueLookup */))
24825
+ c = asDeclaredRuntimeSet(
24826
+ c,
24827
+ runtimeTypeInfoForMember(member, /* @__PURE__ */ new Map(), ctx, /* @__PURE__ */ new Set()),
24828
+ ctx
24829
+ );
24830
+ }
24831
+ if (c instanceof RuntimeSet) return c.has(runtimeSetKey(target, c, ctx));
24134
24832
  const setEntryMember = storedSetEntryMember(c, ctx);
24135
24833
  if (setEntryMember !== null) {
24136
24834
  return findStoredSetEntry(
@@ -24560,7 +25258,7 @@ function receiverClosedTypeArguments(typeArguments, ctx) {
24560
25258
  let env = null;
24561
25259
  let closed = null;
24562
25260
  for (const [parameterId, typeInfo] of Object.entries(typeArguments)) {
24563
- if (!typeInfoContainsGeneric(typeInfo)) continue;
25261
+ if (!typeInfoContainsGeneric2(typeInfo)) continue;
24564
25262
  if (env === null) {
24565
25263
  const row = ctx.thisValueRowId ? readNeoScriptRuntimeRow(ctx, ctx.thisValueRowId) : trackedRowForValueReference(ctx.thisValue, ctx);
24566
25264
  if (row) {
@@ -25861,6 +26559,7 @@ function encodeLookupInitializerResult(member, value, created, ctx) {
25861
26559
  function encodeLookupInitializerSelection(member, value, created, ctx) {
25862
26560
  if (value === null) return null;
25863
26561
  if (value === void 0) return null;
26562
+ if (value instanceof RuntimeSet) value = value.toArray();
25864
26563
  if (Array.isArray(value)) {
25865
26564
  if (isMultiSelectionMember(member) !== true && value.length > 1) {
25866
26565
  throw new NSGetterRuntimeError(
@@ -27466,6 +28165,8 @@ function cloneConstructorLiteralValue(value) {
27466
28165
  );
27467
28166
  }
27468
28167
  function materializeConstructorArgumentValue(args) {
28168
+ if (args.value instanceof RuntimeSet)
28169
+ args = { ...args, value: args.value.toArray() };
27469
28170
  const trackedValueId = findKnownRowIdByValueReference(args.value, args.ctx);
27470
28171
  if (args.value === null && !isRequiredMember(args.member) && isMemberWithEntries(args.member)) {
27471
28172
  return registerConstructorArgumentRow(args, null);
@@ -28176,6 +28877,7 @@ function collectionEntriesOrEmpty(value, ctx) {
28176
28877
  }
28177
28878
  }
28178
28879
  function collectionLength(c) {
28880
+ if (c instanceof RuntimeSet) return c.size;
28179
28881
  if (Array.isArray(c)) return c.length;
28180
28882
  if (typeof c === "object" && c !== null) {
28181
28883
  return Object.keys(c).length;
@@ -28204,6 +28906,17 @@ function snapshotCollectionMembership(collection, ctx) {
28204
28906
  );
28205
28907
  }
28206
28908
  function forEachRawCollectionEntry(c, callback) {
28909
+ if (c instanceof RuntimeSet) {
28910
+ for (const [key, entry] of c.membership().entries()) {
28911
+ if (callback({
28912
+ raw: entry.raw,
28913
+ key,
28914
+ valueId: entry.reference && typeof entry.raw === "string" ? entry.raw : null
28915
+ }) === 1 /* Break */)
28916
+ break;
28917
+ }
28918
+ return true;
28919
+ }
28207
28920
  if (Array.isArray(c)) {
28208
28921
  for (let key = 0; key < c.length; key += 1) {
28209
28922
  const raw = c[key];
@@ -28263,6 +28976,8 @@ function resolveCollectionEntry(collection, raw, key, ctx) {
28263
28976
  return collectionEntryUsesReferenceResolution(collection, key, ctx) ? resolveValueIfId(raw, ctx) : raw;
28264
28977
  }
28265
28978
  function collectionEntryUsesReferenceResolution(collection, key, ctx) {
28979
+ if (collection instanceof RuntimeSet && typeof key === "number")
28980
+ return collection.membership()[key]?.reference === true;
28266
28981
  if (!Array.isArray(collection) || typeof key !== "number") return true;
28267
28982
  const referenceIndexes = ctx.__unorderedListProjections?.referenceEntryIndexesByArray.get(
28268
28983
  collection
@@ -29044,6 +29759,7 @@ var MaterializedValueGraphContext = class {
29044
29759
  }
29045
29760
  resolveTypeInfo(rawTypeInfo, env) {
29046
29761
  if (rawTypeInfo.type === 21 /* Generic */) {
29762
+ if (!isClassGenericParamTypeInfo(rawTypeInfo)) return null;
29047
29763
  const binding = env.get(rawTypeInfo.genericParamId);
29048
29764
  if (binding === void 0 || binding.kind !== "member") return null;
29049
29765
  const member = this.membersById.get(binding.memberId);
@@ -29197,6 +29913,7 @@ function rowGenericEnvironment(document2, row, contextualRootMember) {
29197
29913
  }
29198
29914
  function tryResolveTypeInfo(document2, rawTypeInfo, env) {
29199
29915
  if (rawTypeInfo.type === 21 /* Generic */) {
29916
+ if (!isClassGenericParamTypeInfo(rawTypeInfo)) return null;
29200
29917
  const binding = env.get(rawTypeInfo.genericParamId);
29201
29918
  if (binding === void 0 || binding.kind !== "member") return null;
29202
29919
  const member = document2.members.find(
@@ -35605,18 +36322,42 @@ function sourcePositionMapper(source) {
35605
36322
  };
35606
36323
  }
35607
36324
 
36325
+ // ../packages/neoscript-language/src/system-record-id.ts
36326
+ var SYSTEM_RECORD_ID_PREFIX2 = "system_";
36327
+
35608
36328
  // ../packages/neoscript-language/src/type-substitution.ts
35609
36329
  function substituteTypeParameters(member, receiver, declaring) {
35610
- const parameters = declaring.typeParameters ?? [];
35611
- const argumentsList2 = receiver.typeArguments ?? [];
36330
+ const bindings = classTypeBindings({ type: receiver, declaring });
36331
+ return substituteBindings(
36332
+ member,
36333
+ (type) => type.ownerMemberId === void 0 ? bindings.get(type.id) : void 0
36334
+ );
36335
+ }
36336
+ function substituteCallTypeArguments(member, functionArguments, typeParameters, receiver) {
36337
+ const classBindings = receiver && classTypeBindings(receiver);
36338
+ const declared = typeParameters?.[0]?.type;
36339
+ const owner = declared?.kind === "typeParameter" ? declared.ownerMemberId : void 0;
36340
+ return substituteBindings(member, (type) => {
36341
+ if (type.ownerMemberId === void 0) return classBindings?.get(type.id);
36342
+ if (type.ownerMemberId !== owner) return void 0;
36343
+ if (type.index === void 0) return void 0;
36344
+ return functionArguments[type.index];
36345
+ });
36346
+ }
36347
+ function classTypeBindings(receiver) {
36348
+ const parameters = receiver.declaring.typeParameters ?? [];
36349
+ const argumentsList2 = receiver.type.typeArguments ?? [];
35612
36350
  const bindings = /* @__PURE__ */ new Map();
35613
36351
  parameters.forEach((parameter3, index) => {
35614
36352
  const value = argumentsList2[index];
35615
36353
  if (value) bindings.set(parameter3.id ?? parameter3.name, value);
35616
36354
  });
36355
+ return bindings;
36356
+ }
36357
+ function substituteBindings(member, bindingOf) {
35617
36358
  const visit = (type) => {
35618
36359
  if (type.kind === "typeParameter") {
35619
- const binding = bindings.get(type.id);
36360
+ const binding = bindingOf(type);
35620
36361
  return binding && type.nullable ? { ...binding, nullable: true } : binding ?? type;
35621
36362
  }
35622
36363
  if (type.kind === "named" && type.typeArguments) {
@@ -35983,10 +36724,6 @@ var UserSafeTypeCheck = class {
35983
36724
  }
35984
36725
  };
35985
36726
 
35986
- // ../packages/neoscript-language/src/tile-conversion.ts
35987
- var NEO_TILE_CONVERT_MEMBER_ID = "system_54ecc5a7-874d-54ed-92f4-38100a4b7465";
35988
- var NEO_TILE_CLASS_ID = "system_d7fa161b-b269-4bf1-9ec9-3aebec67e6e0";
35989
-
35990
36727
  // ../packages/neoscript-language/src/strict-resolver.ts
35991
36728
  var CONSTRUCTING_FUNCTION_KINDS = /* @__PURE__ */ new Set(
35992
36729
  [
@@ -38416,13 +39153,17 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38416
39153
  type
38417
39154
  };
38418
39155
  }
38419
- return this.resolveExpression(expression, scope);
39156
+ return this.resolveMemberTargetReceiver(expression, scope);
38420
39157
  }
38421
39158
  requireActionListenerSignature(symbol, owner, receiverType, expected, pos) {
38422
- const substitute = (type) => {
38423
- if (receiverType?.kind !== "named" || owner === void 0) return type;
38424
- return substituteTypeParameters(type, receiverType, owner);
38425
- };
39159
+ const listenerArguments = methodGroupTypeArguments(symbol, false, pos);
39160
+ const receiver = callReceiver(receiverType, owner);
39161
+ const substitute = (type) => substituteCallTypeArguments(
39162
+ type,
39163
+ listenerArguments,
39164
+ symbol.typeParameters,
39165
+ receiver
39166
+ );
38426
39167
  const signature = actionListenerSignature(symbol);
38427
39168
  if (signature === null) {
38428
39169
  throw new CompileError(
@@ -38644,15 +39385,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38644
39385
  );
38645
39386
  if (conversion !== null) return conversion;
38646
39387
  }
38647
- if (expression.typeArguments && expression.callee.kind === "member" && expression.callee.name === "GetObjects") {
38648
- return this.resolveGridObjectQuery(
38649
- expression.callee,
38650
- expression.args,
38651
- expression.typeArguments,
38652
- scope,
38653
- expression.pos
38654
- );
38655
- }
38656
39388
  if (expression.typeArguments && expression.callee.kind === "member" && expression.callee.receiver.kind === "ident" && expression.callee.receiver.name === NEOSCRIPT_LIST_TYPE_NAME) {
38657
39389
  if (expression.callee.name !== NEOSCRIPT_LIST_REPEAT_NAME) {
38658
39390
  throw new CompileError(
@@ -38684,12 +39416,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38684
39416
  expression.pos
38685
39417
  );
38686
39418
  }
38687
- if (expression.typeArguments) {
38688
- throw new CompileError(
38689
- "Type arguments are not supported for this call. Remove the explicit type arguments.",
38690
- expression.pos
38691
- );
38692
- }
38693
39419
  if (expression.argumentNames) {
38694
39420
  throw new CompileError(
38695
39421
  "Named arguments are not supported for this call. Pass arguments in declaration order, without names.",
@@ -38702,7 +39428,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
38702
39428
  scope,
38703
39429
  expression.pos,
38704
39430
  expected,
38705
- receiverValue
39431
+ receiverValue,
39432
+ expression.typeArguments
38706
39433
  );
38707
39434
  }
38708
39435
  case "new": {
@@ -39066,6 +39793,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39066
39793
  }
39067
39794
  return void 0;
39068
39795
  }
39796
+ resolveMemberTargetReceiver(expression, scope) {
39797
+ return expression.kind === "ident" && expression.name === "this" ? this.resolveIdentifier("this", scope, expression.pos, "member-target") : this.resolveExpression(expression, scope);
39798
+ }
39069
39799
  resolveDelegateMethodGroup(expression, expected, scope, options = {}) {
39070
39800
  let symbol;
39071
39801
  let receiver = null;
@@ -39079,7 +39809,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39079
39809
  owner = implicit.owner;
39080
39810
  receiver = symbol.static === true ? { kind: "static", memberId: symbol.id } : {
39081
39811
  kind: "instance",
39082
- expression: this.resolveIdentifier("this", scope, expression.pos)
39812
+ expression: this.resolveIdentifier(
39813
+ "this",
39814
+ scope,
39815
+ expression.pos,
39816
+ "member-target"
39817
+ )
39083
39818
  };
39084
39819
  } else if (expression.kind === "member") {
39085
39820
  if (expression.receiver.kind === "ident" && !this.hasValueReceiver(expression.receiver.name, scope)) {
@@ -39096,7 +39831,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39096
39831
  }
39097
39832
  receiver = { kind: "static", memberId: symbol.id };
39098
39833
  } else {
39099
- const receiverExpression = this.resolveExpression(
39834
+ const receiverExpression = this.resolveMemberTargetReceiver(
39100
39835
  expression.receiver,
39101
39836
  scope
39102
39837
  );
@@ -39119,17 +39854,29 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39119
39854
  }
39120
39855
  if (owner !== void 0)
39121
39856
  this.assertMemberAccessible(owner, symbol, expression.pos);
39122
- let returnType = symbol.returnType ?? symbol.type;
39123
- let parameterTypes = (symbol.parameters ?? []).map(
39124
- (parameter3) => parameter3.type
39857
+ const methodGroupArguments = methodGroupTypeArguments(
39858
+ symbol,
39859
+ options.mockTarget === true,
39860
+ expression.pos
39861
+ );
39862
+ const bound = callReceiver(
39863
+ receiver?.kind === "instance" ? receiver.expression.type : void 0,
39864
+ owner
39865
+ );
39866
+ const returnType = substituteCallTypeArguments(
39867
+ symbol.returnType ?? symbol.type,
39868
+ methodGroupArguments,
39869
+ symbol.typeParameters,
39870
+ bound
39871
+ );
39872
+ const parameterTypes = (symbol.parameters ?? []).map(
39873
+ (parameter3) => substituteCallTypeArguments(
39874
+ parameter3.type,
39875
+ methodGroupArguments,
39876
+ symbol.typeParameters,
39877
+ bound
39878
+ )
39125
39879
  );
39126
- if (receiver?.kind === "instance" && receiver.expression.type.kind === "named" && owner !== void 0) {
39127
- const receiverType = receiver.expression.type;
39128
- returnType = substituteTypeParameters(returnType, receiverType, owner);
39129
- parameterTypes = parameterTypes.map(
39130
- (parameter3) => substituteTypeParameters(parameter3, receiverType, owner)
39131
- );
39132
- }
39133
39880
  const expectedVoid = isVoid(expected.returnType);
39134
39881
  const actualVoid = isVoid(returnType);
39135
39882
  if (expectedVoid !== actualVoid || !expectedVoid && !isNeoScriptTypeAssignable(returnType, expected.returnType, this.project) || parameterTypes.length !== expected.parameterTypes.length || !parameterTypes.every((parameter3, index) => {
@@ -39141,7 +39888,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39141
39888
  expression.pos
39142
39889
  );
39143
39890
  }
39144
- if (receiver?.kind === "instance" && options.allowUnboundInstanceTarget !== true && (receiver.expression.pointer.type !== "variable" /* Variable */ || receiver.expression.pointer.variableId !== this.thisVariable.id)) {
39891
+ if (receiver?.kind === "instance" && options.mockTarget !== true && (receiver.expression.pointer.type !== "variable" /* Variable */ || receiver.expression.pointer.variableId !== this.thisVariable.id)) {
39145
39892
  throw new CompileError(
39146
39893
  "NeoDelegate method groups currently require the current 'this' receiver.",
39147
39894
  expression.pos
@@ -39174,10 +39921,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39174
39921
  );
39175
39922
  if (symbol === void 0 || symbol.static !== true) return null;
39176
39923
  } else {
39177
- const receiver = this.resolveExpression(expression.receiver, scope);
39178
- if (receiver.type.kind !== "named") return null;
39179
- receiverType = receiver.type;
39180
- owner = this.project.typeById.get(receiver.type.typeId);
39924
+ const receiver2 = this.resolveExpression(expression.receiver, scope);
39925
+ if (receiver2.type.kind !== "named") return null;
39926
+ receiverType = receiver2.type;
39927
+ owner = this.project.typeById.get(receiver2.type.typeId);
39181
39928
  symbol = owner?.members.find(
39182
39929
  (candidate) => candidate.name === expression.name && (candidate.kind === "function" || candidate.kind === "method")
39183
39930
  );
@@ -39186,16 +39933,26 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39186
39933
  } else {
39187
39934
  return null;
39188
39935
  }
39189
- let returnType = symbol.returnType ?? symbol.type;
39190
- let parameterTypes = (symbol.parameters ?? []).map(
39191
- (parameter3) => parameter3.type
39936
+ const mockArguments = methodGroupTypeArguments(
39937
+ symbol,
39938
+ true,
39939
+ expression.pos
39940
+ );
39941
+ const receiver = callReceiver(receiverType, owner);
39942
+ const returnType = substituteCallTypeArguments(
39943
+ symbol.returnType ?? symbol.type,
39944
+ mockArguments,
39945
+ symbol.typeParameters,
39946
+ receiver
39947
+ );
39948
+ const parameterTypes = (symbol.parameters ?? []).map(
39949
+ (parameter3) => substituteCallTypeArguments(
39950
+ parameter3.type,
39951
+ mockArguments,
39952
+ symbol.typeParameters,
39953
+ receiver
39954
+ )
39192
39955
  );
39193
- if (receiverType?.kind === "named" && owner !== void 0) {
39194
- returnType = substituteTypeParameters(returnType, receiverType, owner);
39195
- parameterTypes = parameterTypes.map(
39196
- (parameter3) => substituteTypeParameters(parameter3, receiverType, owner)
39197
- );
39198
- }
39199
39956
  return { kind: "delegate", returnType, parameterTypes };
39200
39957
  }
39201
39958
  resolveInterpolatedString(parts, scope) {
@@ -39378,7 +40135,13 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
39378
40135
  type
39379
40136
  };
39380
40137
  }
39381
- resolveIdentifier(name, scope, pos) {
40138
+ resolveIdentifier(name, scope, pos, usage = "value") {
40139
+ if (name === "this" && this.context.kind === "initializer" && this.delegateCaptureContexts.length === 0 && usage === "value") {
40140
+ throw new CompileError(
40141
+ "'this' is unavailable while an initializer runs. Defer instance access with a lambda or method group.",
40142
+ pos
40143
+ );
40144
+ }
39382
40145
  if (name === "base") {
39383
40146
  throw new CompileError(
39384
40147
  "'base' can only qualify a function call or getter read inside an override body.",
@@ -41038,7 +41801,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41038
41801
  return result.value;
41039
41802
  };
41040
41803
  }
41041
- resolveCall(callee, argumentsList2, scope, pos, expected, receiverValue = this.callReceiver(callee, scope)) {
41804
+ resolveCall(callee, argumentsList2, scope, pos, expected, receiverValue = this.callReceiver(callee, scope), typeArguments) {
41805
+ const rejectTypeArguments = () => {
41806
+ if (typeArguments === void 0) return;
41807
+ throw new CompileError(
41808
+ "Type arguments are not supported for this call. Remove the explicit type arguments.",
41809
+ pos
41810
+ );
41811
+ };
41042
41812
  if (callee.kind === "member" && callee.receiver.kind === "ident" && callee.receiver.name === "Debug" && this.resolveDebugStatement(
41043
41813
  { kind: "call", callee, args: [...argumentsList2], pos },
41044
41814
  scope
@@ -41049,7 +41819,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41049
41819
  );
41050
41820
  }
41051
41821
  if (callee.kind === "member" && callee.receiver.kind === "ident" && callee.receiver.name === "base") {
41052
- return this.resolveBaseCall(callee, argumentsList2, scope, pos);
41822
+ return this.resolveBaseCall(
41823
+ callee,
41824
+ argumentsList2,
41825
+ scope,
41826
+ pos,
41827
+ false,
41828
+ typeArguments
41829
+ );
41053
41830
  }
41054
41831
  const variantCall = this.resolveVariantCall(
41055
41832
  callee,
@@ -41058,12 +41835,16 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41058
41835
  pos,
41059
41836
  receiverValue
41060
41837
  );
41061
- if (variantCall !== null) return variantCall;
41838
+ if (variantCall !== null) {
41839
+ rejectTypeArguments();
41840
+ return variantCall;
41841
+ }
41062
41842
  const callable2 = this.resolveCallableValueCallee(
41063
41843
  callee,
41064
41844
  scope,
41065
41845
  receiverValue
41066
41846
  );
41847
+ if (callable2 !== null) rejectTypeArguments();
41067
41848
  if (callable2?.type.kind === "delegate") {
41068
41849
  return this.resolveDelegateCall(
41069
41850
  callable2,
@@ -41081,9 +41862,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41081
41862
  }
41082
41863
  if (callee.kind === "ident") {
41083
41864
  const vector3 = vectorKind(callee.name);
41084
- if (vector3)
41865
+ if (vector3) {
41866
+ rejectTypeArguments();
41085
41867
  return this.resolveVectorConstructor(vector3, argumentsList2, scope, pos);
41868
+ }
41086
41869
  if (callee.name === "VisitCount" || callee.name === "HasVisited") {
41870
+ rejectTypeArguments();
41087
41871
  return this.resolveDialogueMemoryRead(
41088
41872
  callee.name,
41089
41873
  argumentsList2,
@@ -41101,7 +41885,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41101
41885
  argumentsList2,
41102
41886
  scope,
41103
41887
  pos,
41104
- false
41888
+ false,
41889
+ false,
41890
+ typeArguments
41105
41891
  );
41106
41892
  const target = this.resolveImplicitCallTarget(callee.name, scope, pos);
41107
41893
  if (target)
@@ -41111,7 +41897,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41111
41897
  argumentsList2,
41112
41898
  scope,
41113
41899
  pos,
41114
- false
41900
+ false,
41901
+ false,
41902
+ typeArguments
41115
41903
  );
41116
41904
  throw new CompileError(`Unknown function '${callee.name}'`, pos);
41117
41905
  }
@@ -41123,6 +41911,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41123
41911
  }
41124
41912
  if (callee.receiver.kind === "ident" && !this.hasValueReceiver(callee.receiver.name, scope)) {
41125
41913
  if (callee.receiver.name === MATH_NAMESPACE_NAME) {
41914
+ rejectTypeArguments();
41126
41915
  if (callee.optional) {
41127
41916
  throw new CompileError(
41128
41917
  `Optional chaining is not valid on builtin namespace '${MATH_NAMESPACE_NAME}'.`,
@@ -41159,41 +41948,44 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41159
41948
  pos
41160
41949
  );
41161
41950
  }
41162
- const member = staticType.members.find(
41951
+ const member2 = staticType.members.find(
41163
41952
  (candidate) => candidate.name === callee.name
41164
41953
  );
41165
- if (!member) {
41954
+ if (!member2) {
41166
41955
  throw new CompileError(
41167
41956
  `Class '${staticType.name}' has no static callable member '${callee.name}'.`,
41168
41957
  pos
41169
41958
  );
41170
41959
  }
41171
- this.assertMemberAccessible(staticType, member, pos);
41172
- if (member.static !== true) {
41960
+ this.assertMemberAccessible(staticType, member2, pos);
41961
+ if (member2.static !== true) {
41173
41962
  throw new CompileError(
41174
41963
  `Member '${staticType.name}.${callee.name}' requires an instance receiver.`,
41175
41964
  pos
41176
41965
  );
41177
41966
  }
41178
- if (member.kind !== "function" && member.kind !== "method") {
41967
+ if (member2.kind !== "function" && member2.kind !== "method") {
41179
41968
  throw new CompileError(
41180
41969
  `Static member '${staticType.name}.${callee.name}' is not callable.`,
41181
41970
  pos
41182
41971
  );
41183
41972
  }
41184
41973
  return this.resolveSymbolCall(
41185
- member,
41186
- { kind: "static", memberId: member.id },
41974
+ member2,
41975
+ { kind: "static", memberId: member2.id },
41187
41976
  argumentsList2,
41188
41977
  scope,
41189
41978
  pos,
41190
- false
41979
+ false,
41980
+ false,
41981
+ typeArguments
41191
41982
  );
41192
41983
  }
41193
41984
  }
41194
41985
  const receiver = receiverValue();
41195
41986
  const optional2 = callee.optional === true;
41196
41987
  if (receiver.dialogues !== void 0) {
41988
+ rejectTypeArguments();
41197
41989
  if (optional2) {
41198
41990
  throw new CompileError(
41199
41991
  `\`?.\` is not valid on ${receiver.dialogues.path}; it is never null.`,
@@ -41214,6 +42006,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41214
42006
  pos
41215
42007
  );
41216
42008
  }
42009
+ const memberReceiverType = neoScriptMemberLookupType(receiver.type);
42010
+ const namedType2 = memberReceiverType.kind === "named" ? this.project.typeById.get(memberReceiverType.typeId) : void 0;
42011
+ const member = namedType2?.members.find(
42012
+ (candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
42013
+ );
42014
+ if (member === void 0) rejectTypeArguments();
41217
42015
  if (isPrimitive(receiver.type, "NeoDialogueReference") && isDialogueRequestName(callee.name)) {
41218
42016
  return this.resolveDialogueReferenceCall(
41219
42017
  receiver,
@@ -41233,7 +42031,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41233
42031
  pos
41234
42032
  );
41235
42033
  }
41236
- const memberReceiverType = neoScriptMemberLookupType(receiver.type);
41237
42034
  if (callee.name === "Equals" && memberReceiverType.kind === "typeParameter") {
41238
42035
  if (optional2) {
41239
42036
  throw new CompileError(
@@ -41266,10 +42063,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41266
42063
  };
41267
42064
  }
41268
42065
  if (memberReceiverType.kind === "named") {
41269
- const type = this.project.typeById.get(memberReceiverType.typeId);
41270
- const member = type?.members.find(
41271
- (candidate) => (candidate.kind === "function" || candidate.kind === "method") && candidate.name === callee.name
41272
- );
42066
+ const type = namedType2;
41273
42067
  if (member) {
41274
42068
  this.validateFunctionReceiver(receiver, callee.name, optional2, pos);
41275
42069
  if (type !== void 0) this.assertMemberAccessible(type, member, pos);
@@ -41288,7 +42082,9 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
41288
42082
  argumentsList2,
41289
42083
  scope,
41290
42084
  pos,
41291
- optional2
42085
+ optional2,
42086
+ false,
42087
+ typeArguments
41292
42088
  );
41293
42089
  }
41294
42090
  if (callee.name === "Clone" && type?.kind === "class") {
@@ -42089,81 +42885,6 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42089
42885
  type: { kind: "primitive", name: "bool" }
42090
42886
  };
42091
42887
  }
42092
- resolveGridObjectQuery(callee, args, typeArguments, scope, pos) {
42093
- const receiver = this.resolveExpression(callee.receiver, scope);
42094
- const owner = receiver.type.kind === "named" ? this.project.typeById.get(receiver.type.typeId) : void 0;
42095
- const symbol = owner?.members.find((member) => member.name === callee.name);
42096
- if (symbol?.id !== NEO_OBJECT_GRID_MEMBER_IDS.GetObjects)
42097
- throw new CompileError(
42098
- "Only NeoObject.GetObjects accepts a class filter type argument.",
42099
- pos
42100
- );
42101
- if (callee.optional || isNullable(receiver.type))
42102
- throw new CompileError(
42103
- "GetObjects<T> requires a non-null placed object receiver.",
42104
- pos
42105
- );
42106
- if (typeArguments.length !== 1)
42107
- throw new CompileError(
42108
- "GetObjects<T> requires exactly one object class type argument.",
42109
- pos
42110
- );
42111
- const target = this.resolveType(requiredAt(typeArguments, 0));
42112
- if (target.kind !== "named" || this.project.typeById.get(target.typeId)?.kind !== "class" || target.nullable || !isNeoScriptTypeAssignable(
42113
- target,
42114
- { kind: "named", typeId: NEO_OBJECT_CLASS_ID },
42115
- this.project
42116
- ))
42117
- throw new CompileError(
42118
- "GetObjects<T> requires a non-null NeoObject class or a derived class.",
42119
- pos
42120
- );
42121
- this.assertMemberAccessible(owner, symbol, pos);
42122
- const queried = this.resolveSymbolCall(
42123
- symbol,
42124
- { kind: "instance", expression: receiver },
42125
- args,
42126
- scope,
42127
- pos,
42128
- false
42129
- );
42130
- if (queried.type.kind !== "list")
42131
- throw new CompileError("NeoObject.GetObjects must return a list.", pos);
42132
- const item = variable(
42133
- "__grid_query_item__",
42134
- queried.type.elementType,
42135
- void 0,
42136
- this.project
42137
- );
42138
- const predicate = {
42139
- compilerRevision: NEOSCRIPT_COMPILER_REVISION,
42140
- source: {
42141
- name: this.debugSource.name,
42142
- uri: this.debugSource.uri,
42143
- coordinateSpace: this.debugSource.coordinateSpace
42144
- },
42145
- parameters: [item],
42146
- instructions: [
42147
- {
42148
- type: "return" /* Return */,
42149
- pointer: {
42150
- type: "isCheck" /* IsCheck */,
42151
- pointer: {
42152
- type: "variable" /* Variable */,
42153
- variableId: item.id
42154
- },
42155
- checkType: toWireType(target, this.project)
42156
- }
42157
- }
42158
- ],
42159
- typeInfo: toWireType({ kind: "primitive", name: "bool" }, this.project)
42160
- };
42161
- return intrinsic(
42162
- "where" /* Where */,
42163
- { collectionPointer: queried.pointer, function: predicate },
42164
- { kind: "list", elementType: target, readOnly: true }
42165
- );
42166
- }
42167
42888
  resolveBaseMember(name, scope, pos, optional2) {
42168
42889
  const baseClass = this.context.baseClass;
42169
42890
  if (baseClass?.kind !== "named" || this.context.staticMember === true || this.context.thisClass === void 0) {
@@ -42207,7 +42928,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42207
42928
  }
42208
42929
  };
42209
42930
  }
42210
- resolveBaseCall(callee, args, scope, pos, allowVoid = false) {
42931
+ resolveBaseCall(callee, args, scope, pos, allowVoid = false, typeArguments) {
42211
42932
  const { symbol, receiver } = this.resolveBaseMember(
42212
42933
  callee.name,
42213
42934
  scope,
@@ -42227,17 +42948,19 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42227
42948
  scope,
42228
42949
  pos,
42229
42950
  false,
42230
- allowVoid
42951
+ allowVoid,
42952
+ typeArguments
42231
42953
  );
42232
42954
  }
42233
- resolveSymbolCall(symbol, receiver, argumentsList2, scope, pos, optional2, allowVoid = false) {
42955
+ resolveSymbolCall(symbol, receiver, argumentsList2, scope, pos, optional2, allowVoid = false, typeArguments) {
42234
42956
  this.validateCallableInContext(symbol, pos);
42235
42957
  const resolvedCall = this.resolveCallableArguments(
42236
42958
  symbol,
42237
42959
  receiver,
42238
42960
  argumentsList2,
42239
42961
  scope,
42240
- pos
42962
+ pos,
42963
+ typeArguments
42241
42964
  );
42242
42965
  const call = {
42243
42966
  type: "callFunction" /* CallFunction */,
@@ -42247,6 +42970,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42247
42970
  pointer: receiver?.expression.pointer ?? this.thisVariable.pointer
42248
42971
  },
42249
42972
  args: resolvedCall.args,
42973
+ ...resolvedCall.typeArguments ? { typeArguments: resolvedCall.typeArguments } : {},
42250
42974
  ...receiver?.kind === "instance" && receiver.dispatch === "base" ? { dispatch: "base" } : {},
42251
42975
  ...optional2 ? { optional: true } : {},
42252
42976
  callSiteId: this.nextCallSite(pos)
@@ -42269,8 +42993,18 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42269
42993
  * whose type depends on the supplied value or method group. The special
42270
42994
  * cases are unreachable unless the host injected the test prelude.
42271
42995
  */
42272
- resolveCallableArguments(symbol, receiver, argumentsList2, scope, pos) {
42273
- const signature = this.callableSignatureForReceiver(symbol, receiver);
42996
+ resolveCallableArguments(symbol, receiver, argumentsList2, scope, pos, typeArguments) {
42997
+ const signature = this.callableSignatureForReceiver(
42998
+ symbol,
42999
+ receiver,
43000
+ typeArguments,
43001
+ pos
43002
+ );
43003
+ const wireTypeArguments = signature.typeArguments.length ? {
43004
+ typeArguments: signature.typeArguments.map(
43005
+ (argument2) => toWireType(argument2, this.project)
43006
+ )
43007
+ } : {};
42274
43008
  if (symbol.id === NEO_TEST_IDS.expect) {
42275
43009
  requireArgCount(symbol.name, argumentsList2, 1, pos);
42276
43010
  const argument2 = requiredAt(argumentsList2, 0);
@@ -42304,7 +43038,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42304
43038
  scope,
42305
43039
  // Mock targets are member-identity metadata. They are never invoked as
42306
43040
  // delegates, and mockHandle.on(receiver) owns receiver scoping.
42307
- { allowUnboundInstanceTarget: true }
43041
+ { mockTarget: true }
42308
43042
  );
42309
43043
  if (target === null) {
42310
43044
  throw new CompileError(
@@ -42493,23 +43227,100 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
42493
43227
  );
42494
43228
  }
42495
43229
  }
42496
- return { args, returnType: signature.returnType };
43230
+ return { args, returnType: signature.returnType, ...wireTypeArguments };
43231
+ }
43232
+ callableSignatureForReceiver(symbol, receiver, typeArguments, pos) {
43233
+ const bound = this.genericCallReceiver(receiver);
43234
+ const functionArguments = this.resolveFunctionTypeArguments(
43235
+ symbol,
43236
+ typeArguments,
43237
+ (type) => substituteCallTypeArguments(type, [], void 0, bound),
43238
+ pos
43239
+ );
43240
+ const bind = (type) => substituteCallTypeArguments(
43241
+ type,
43242
+ functionArguments,
43243
+ symbol.typeParameters,
43244
+ bound
43245
+ );
43246
+ return {
43247
+ parameters: (symbol.parameters ?? []).map((parameter3) => ({
43248
+ ...parameter3,
43249
+ type: bind(parameter3.type)
43250
+ })),
43251
+ returnType: bind(symbol.returnType ?? symbol.type),
43252
+ typeArguments: functionArguments
43253
+ };
42497
43254
  }
42498
- callableSignatureForReceiver(symbol, receiver) {
42499
- let parameters = symbol.parameters ?? [];
42500
- let returnType = symbol.returnType ?? symbol.type;
42501
- if (receiver?.kind !== "instance") return { parameters, returnType };
43255
+ /** The instance receiver whose class type arguments a call binds, if any. */
43256
+ genericCallReceiver(receiver) {
43257
+ if (receiver?.kind !== "instance") return void 0;
42502
43258
  const receiverType = receiver.expression.type;
42503
- if (receiverType.kind !== "named") return { parameters, returnType };
42504
- if (!receiverType.typeArguments?.length) return { parameters, returnType };
42505
- const declaring = this.project.typeById.get(receiverType.typeId);
42506
- if (declaring === void 0) return { parameters, returnType };
42507
- parameters = parameters.map((parameter3) => ({
42508
- ...parameter3,
42509
- type: substituteTypeParameters(parameter3.type, receiverType, declaring)
42510
- }));
42511
- returnType = substituteTypeParameters(returnType, receiverType, declaring);
42512
- return { parameters, returnType };
43259
+ if (receiverType.kind !== "named") return void 0;
43260
+ if (!receiverType.typeArguments?.length) return void 0;
43261
+ return callReceiver(
43262
+ receiverType,
43263
+ this.project.typeById.get(receiverType.typeId)
43264
+ );
43265
+ }
43266
+ /**
43267
+ * P110 §2. The callee's full positional type-argument list: written
43268
+ * arguments, then defaults. Each written argument is non-nullable and
43269
+ * satisfies its param's constraint.
43270
+ */
43271
+ resolveFunctionTypeArguments(symbol, typeArguments, substitute, pos) {
43272
+ const parameters = symbol.typeParameters ?? [];
43273
+ if (parameters.length === 0) {
43274
+ if (typeArguments === void 0) return [];
43275
+ throw new CompileError(
43276
+ `Function '${symbol.name}' is not generic; remove the type arguments.`,
43277
+ pos
43278
+ );
43279
+ }
43280
+ const written = typeArguments ?? [];
43281
+ if (written.length > parameters.length) {
43282
+ throw new CompileError(
43283
+ `Function '${symbol.name}' takes ${parameters.length} type argument${parameters.length === 1 ? "" : "s"} but got ${written.length}.`,
43284
+ pos
43285
+ );
43286
+ }
43287
+ return parameters.map((parameter3, index) => {
43288
+ const declared = parameter3.type;
43289
+ if (declared.kind !== "typeParameter") {
43290
+ throw new Error(
43291
+ `Function '${symbol.name}' type parameter '${parameter3.name}' has no type parameter type.`
43292
+ );
43293
+ }
43294
+ const authored = written[index];
43295
+ if (authored === void 0) {
43296
+ if (declared.defaultType !== void 0) return declared.defaultType;
43297
+ throw new CompileError(
43298
+ `'${symbol.name}' needs a type argument for '${parameter3.name}'.`,
43299
+ pos
43300
+ );
43301
+ }
43302
+ const argument2 = this.resolveType(authored);
43303
+ if (argument2.nullable === true) {
43304
+ throw new CompileError(
43305
+ `Type argument '${this.describe(argument2)}' cannot be nullable; declare '${parameter3.name}?' in the signature instead.`,
43306
+ authored.pos
43307
+ );
43308
+ }
43309
+ if (symbol.native === true && !symbol.id.startsWith(SYSTEM_RECORD_ID_PREFIX2) && argument2.kind === "named" && (argument2.typeArguments?.length ?? 0) > 0) {
43310
+ throw new CompileError(
43311
+ `Native function '${symbol.name}' takes a non-generic class type argument; '${this.describe(argument2)}' is generic.`,
43312
+ authored.pos
43313
+ );
43314
+ }
43315
+ const constraint = declared.constraint === void 0 ? void 0 : substitute(declared.constraint);
43316
+ if (constraint !== void 0 && !isNeoScriptTypeAssignable(argument2, constraint, this.project)) {
43317
+ throw new CompileError(
43318
+ `Type argument '${this.describe(argument2)}' does not satisfy '${parameter3.name} extends ${this.describe(constraint)}' on '${symbol.name}'.`,
43319
+ authored.pos
43320
+ );
43321
+ }
43322
+ return argument2;
43323
+ });
42513
43324
  }
42514
43325
  delegateTypeFromMockHandle(type) {
42515
43326
  if (type.kind !== "named" || type.typeId !== NEO_TEST_IDS.mockHandleType || type.typeArguments?.[0]?.kind !== "delegate") {
@@ -43437,8 +44248,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43437
44248
  resolveFunctionStatement(expression, scope) {
43438
44249
  if (expression.kind !== "call") return null;
43439
44250
  const receiverValue = this.callReceiver(expression.callee, scope);
43440
- if (expression.typeArguments) return null;
43441
44251
  if (expression.argumentNames) return null;
44252
+ const typeArguments = expression.typeArguments;
44253
+ if (typeArguments !== void 0 && expression.callee.kind === "member" && expression.callee.receiver.kind === "ident" && expression.callee.receiver.name === NEOSCRIPT_LIST_TYPE_NAME)
44254
+ return null;
43442
44255
  if (expression.callee.kind === "member" && expression.callee.name === "TryConvert") {
43443
44256
  const conversion = this.resolveTileConversion(
43444
44257
  expression.callee,
@@ -43458,7 +44271,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43458
44271
  expression.args,
43459
44272
  scope,
43460
44273
  expression.pos,
43461
- true
44274
+ true,
44275
+ typeArguments
43462
44276
  );
43463
44277
  if (result.pointer.type !== "callFunction" /* CallFunction */)
43464
44278
  throw new Error("Base call did not produce a function call.");
@@ -43469,6 +44283,12 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43469
44283
  scope,
43470
44284
  receiverValue
43471
44285
  );
44286
+ if (callable2 !== null && typeArguments !== void 0) {
44287
+ throw new CompileError(
44288
+ "Type arguments are not supported for this call. Remove the explicit type arguments.",
44289
+ expression.pos
44290
+ );
44291
+ }
43472
44292
  if (callable2?.type.kind === "action") {
43473
44293
  return this.resolveActionCall(callable2, callable2.type, expression, scope);
43474
44294
  }
@@ -43521,13 +44341,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43521
44341
  null,
43522
44342
  expression.args,
43523
44343
  scope,
43524
- expression.pos
44344
+ expression.pos,
44345
+ typeArguments
43525
44346
  );
43526
44347
  return {
43527
44348
  type: "callFunction" /* CallFunction */,
43528
44349
  memberId: global.id,
43529
44350
  receiver: { kind: "static", memberId: global.id },
43530
44351
  args: resolved2.args,
44352
+ ...resolved2.typeArguments ? { typeArguments: resolved2.typeArguments } : {},
43531
44353
  callSiteId: this.nextCallSite(expression.pos)
43532
44354
  };
43533
44355
  }
@@ -43544,7 +44366,8 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43544
44366
  scope,
43545
44367
  expression.pos,
43546
44368
  false,
43547
- true
44369
+ true,
44370
+ typeArguments
43548
44371
  );
43549
44372
  if (result.pointer.type !== "callFunction" /* CallFunction */)
43550
44373
  throw new Error("Bare call did not produce a function call.");
@@ -43585,13 +44408,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43585
44408
  { kind: "static", memberId: symbol2.id },
43586
44409
  expression.args,
43587
44410
  scope,
43588
- expression.pos
44411
+ expression.pos,
44412
+ typeArguments
43589
44413
  );
43590
44414
  return {
43591
44415
  type: "callFunction" /* CallFunction */,
43592
44416
  memberId: symbol2.id,
43593
44417
  receiver: { kind: "static", memberId: symbol2.id },
43594
44418
  args: resolved2.args,
44419
+ ...resolved2.typeArguments ? { typeArguments: resolved2.typeArguments } : {},
43595
44420
  callSiteId: this.nextCallSite(expression.pos)
43596
44421
  };
43597
44422
  }
@@ -43629,13 +44454,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
43629
44454
  },
43630
44455
  expression.args,
43631
44456
  scope,
43632
- expression.pos
44457
+ expression.pos,
44458
+ typeArguments
43633
44459
  );
43634
44460
  return {
43635
44461
  type: "callFunction" /* CallFunction */,
43636
44462
  ...type?.kind === "interface" ? { memberKey: symbol.schemaKey ?? symbol.name } : { memberId: symbol.id },
43637
44463
  receiver: { kind: "instance", pointer: receiver.pointer },
43638
44464
  args: resolved.args,
44465
+ ...resolved.typeArguments ? { typeArguments: resolved.typeArguments } : {},
43639
44466
  ...expression.callee.optional ? { optional: true } : {},
43640
44467
  callSiteId: this.nextCallSite(expression.pos)
43641
44468
  };
@@ -45264,6 +46091,14 @@ function toWireType(type, project) {
45264
46091
  };
45265
46092
  }
45266
46093
  case "typeParameter":
46094
+ if (type.ownerMemberId !== void 0 && type.index !== void 0) {
46095
+ return {
46096
+ type: 21 /* Generic */,
46097
+ required,
46098
+ ownerMemberId: type.ownerMemberId,
46099
+ index: type.index
46100
+ };
46101
+ }
45267
46102
  return {
45268
46103
  type: 21 /* Generic */,
45269
46104
  required,
@@ -45300,6 +46135,16 @@ function fromWireType(type) {
45300
46135
  if (type.type === 8 /* Enum */)
45301
46136
  return { kind: "named", typeId: type.enumId, nullable: nullable2 };
45302
46137
  if (type.type === 21 /* Generic */) {
46138
+ if ("ownerMemberId" in type) {
46139
+ return {
46140
+ kind: "typeParameter",
46141
+ id: functionTypeParameterId(type.ownerMemberId, type.index),
46142
+ name: `T${type.index}`,
46143
+ ownerMemberId: type.ownerMemberId,
46144
+ index: type.index,
46145
+ nullable: nullable2
46146
+ };
46147
+ }
45303
46148
  return {
45304
46149
  kind: "typeParameter",
45305
46150
  id: type.genericParamId,
@@ -45938,9 +46783,8 @@ function resolveNeoScriptType(type, context, project) {
45938
46783
  }
45939
46784
  const declaringTypeRef = context.declaringType === void 0 ? context.thisClass : context.declaringType;
45940
46785
  const declaringType = declaringTypeRef?.kind === "named" ? project.typeById.get(declaringTypeRef.typeId) : void 0;
45941
- const typeParameter2 = declaringType?.typeParameters?.find(
45942
- (candidate) => candidate.name === type.name
45943
- );
46786
+ const byName = (candidate) => candidate.name === type.name;
46787
+ const typeParameter2 = context.typeParameters?.find(byName) ?? declaringType?.typeParameters?.find(byName);
45944
46788
  if (typeParameter2?.type.kind === "typeParameter") {
45945
46789
  resolved = typeParameter2.type;
45946
46790
  break;
@@ -46015,6 +46859,20 @@ function resolveNeoScriptType(type, context, project) {
46015
46859
  }
46016
46860
  return { ...resolved, nullable: !type.required };
46017
46861
  }
46862
+ function methodGroupTypeArguments(symbol, mockTarget, pos) {
46863
+ return (symbol.typeParameters ?? []).map((parameter3) => {
46864
+ const declared = parameter3.type;
46865
+ const fallback = declared.kind === "typeParameter" ? declared.defaultType : void 0;
46866
+ if (fallback !== void 0) return fallback;
46867
+ if (!mockTarget) {
46868
+ throw new CompileError(
46869
+ `Function '${symbol.name}' can be a delegate target only when every type parameter has a default; '${parameter3.name}' has none.`,
46870
+ pos
46871
+ );
46872
+ }
46873
+ return declared.kind === "typeParameter" && declared.constraint ? declared.constraint : { kind: "primitive", name: "unknown" };
46874
+ });
46875
+ }
46018
46876
  function wrappedTypeParameterMessage(target, project) {
46019
46877
  for (const argument2 of target.typeArguments ?? []) {
46020
46878
  if (argument2.kind === "typeParameter") continue;
@@ -46045,6 +46903,11 @@ function intersectCollectionWritability(left, right) {
46045
46903
  const writable = (value) => value === "local" /* Local */ || value === "save" /* Save */ || value === "session" /* Session */ || value === "runtime" /* Runtime */;
46046
46904
  return writable(left) && writable(right) ? "runtime" /* Runtime */ : "readOnly" /* ReadOnly */;
46047
46905
  }
46906
+ function callReceiver(receiverType, declaring) {
46907
+ if (receiverType?.kind !== "named") return void 0;
46908
+ if (declaring === void 0) return void 0;
46909
+ return { type: receiverType, declaring };
46910
+ }
46048
46911
 
46049
46912
  // ../packages/neoscript-language/src/compiler.ts
46050
46913
  function compileNeoScriptStrict(document2, context, options = {}) {
@@ -47957,15 +48820,30 @@ function isInterfaceFunctionMember(member) {
47957
48820
  function interfacePropertyIsSettable(member) {
47958
48821
  return member.accessors === 1 /* GetSet */;
47959
48822
  }
47960
- function containsForbiddenMemberTypeInfo(typeInfo) {
48823
+ function containsForbiddenMemberTypeInfo(typeInfo, own) {
47961
48824
  if (typeInfo.type === NS_TYPE_UNKNOWN) return true;
47962
- if (typeInfo.type === 21 /* Generic */) return true;
48825
+ if (typeInfo.type === 21 /* Generic */) {
48826
+ if (isClassGenericParamTypeInfo(typeInfo)) return true;
48827
+ if (own === null) return true;
48828
+ if (typeInfo.ownerMemberId !== own.ownerMemberId) return true;
48829
+ return typeInfo.index >= own.count;
48830
+ }
47963
48831
  if (typeInfo.type === 6 /* List */ || typeInfo.type === 28 /* Set */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
47964
- return containsForbiddenMemberTypeInfo(typeInfo.entryTypeInfo);
48832
+ return containsForbiddenMemberTypeInfo(typeInfo.entryTypeInfo, own);
48833
+ }
48834
+ if (typeInfo.type === 25 /* NSDelegate */) {
48835
+ return containsForbiddenMemberTypeInfo(typeInfo.returnTypeInfo, own) || typeInfo.argumentTypes.some(
48836
+ (argument2) => containsForbiddenMemberTypeInfo(argument2, own)
48837
+ );
48838
+ }
48839
+ if (typeInfo.type === 26 /* NSAction */) {
48840
+ return typeInfo.argumentTypes.some(
48841
+ (argument2) => containsForbiddenMemberTypeInfo(argument2, own)
48842
+ );
47965
48843
  }
47966
48844
  if (typeInfo.type === 7 /* Class */ && typeInfo.typeArguments) {
47967
48845
  return Object.values(typeInfo.typeArguments).some(
47968
- containsForbiddenMemberTypeInfo
48846
+ (argument2) => containsForbiddenMemberTypeInfo(argument2, own)
47969
48847
  );
47970
48848
  }
47971
48849
  return false;
@@ -47981,17 +48859,23 @@ function isNeoInterfaceMember(value) {
47981
48859
  if (member.kind === void 0 || member.kind === 0 /* Property */) {
47982
48860
  const property2 = value;
47983
48861
  if (!isNSTypeInfo(property2.typeInfo)) return false;
47984
- if (containsForbiddenMemberTypeInfo(property2.typeInfo)) return false;
48862
+ if (containsForbiddenMemberTypeInfo(property2.typeInfo, null)) return false;
47985
48863
  return property2.accessors === void 0 || property2.accessors === 0 /* Get */ || property2.accessors === 1 /* GetSet */;
47986
48864
  }
47987
48865
  if (member.kind !== 1 /* Function */) return false;
47988
48866
  const fn = value;
47989
48867
  if (!isNSFunctionReturnTypeInfo(fn.returnTypeInfo)) return false;
47990
- if (containsForbiddenMemberTypeInfo(fn.returnTypeInfo)) return false;
48868
+ if (fn.genericParams !== void 0 && !isFunctionGenericParams(fn.genericParams, isValidSchemaBindingIdentifier))
48869
+ return false;
48870
+ const own = {
48871
+ ownerMemberId: member.id,
48872
+ count: fn.genericParams?.length ?? 0
48873
+ };
48874
+ if (containsForbiddenMemberTypeInfo(fn.returnTypeInfo, own)) return false;
47991
48875
  if (!Array.isArray(fn.argumentTypes)) return false;
47992
48876
  for (const argumentType of fn.argumentTypes) {
47993
48877
  if (!isNSFunctionArgumentTypeInfo(argumentType)) return false;
47994
- if (containsForbiddenMemberTypeInfo(argumentType)) return false;
48878
+ if (containsForbiddenMemberTypeInfo(argumentType, own)) return false;
47995
48879
  }
47996
48880
  if (fn.dispatch !== void 0 && fn.dispatch !== 0 /* Synchronous */ && fn.dispatch !== 1 /* Asynchronous */)
47997
48881
  return false;
@@ -48461,6 +49345,11 @@ function createNeoScriptDocumentContextInScope(context, projectOverride) {
48461
49345
  ...baseClass ? { baseClass } : {},
48462
49346
  ...returnType ? { returnType } : {},
48463
49347
  ...parameters ? { parameters } : {},
49348
+ ...context.memberId === void 0 || documentKind !== "function" ? {} : functionTypeParameterSymbols(
49349
+ context.memberId,
49350
+ declaredFunctionGenericParams(context, context.memberId),
49351
+ context
49352
+ ),
48464
49353
  ...context.functionDeferred !== void 0 ? { deferred: context.functionDeferred } : {},
48465
49354
  ...functionName ? { functionName } : {},
48466
49355
  ...context.dialogueContext ? {
@@ -48880,6 +49769,11 @@ function memberToSymbol(record4, schemaKey, containingClass, ownerClassId, index
48880
49769
  kind: authoredCallable.kind === 23 /* NSFunction */ ? "function" : "method",
48881
49770
  type: returnType,
48882
49771
  returnType,
49772
+ ...functionTypeParameterSymbols(
49773
+ record4.id,
49774
+ authoredCallable.genericParams,
49775
+ context
49776
+ ),
48883
49777
  parameters: authoredCallable.argumentTypes.map(
48884
49778
  (argument2, argumentIndex) => ({
48885
49779
  id: `${record4.id}:argument:${argumentIndex}`,
@@ -49069,6 +49963,7 @@ function interfaceMemberToSymbol(neoInterface, key, member, context, inherited)
49069
49963
  kind: "function",
49070
49964
  type: returnType,
49071
49965
  returnType,
49966
+ ...functionTypeParameterSymbols(member.id, member.genericParams, context),
49072
49967
  parameters: member.argumentTypes.map((argument2, index) => ({
49073
49968
  id: `${neoInterface.id}:member:${key}:argument:${index}`,
49074
49969
  name: argument2.name,
@@ -49591,6 +50486,9 @@ function toLanguageType(type, context, genericEnvironment) {
49591
50486
  nullable: false
49592
50487
  };
49593
50488
  case 21 /* Generic */:
50489
+ if (!isClassGenericParamTypeInfo(type)) {
50490
+ return functionGenericLanguageType(type, required, context);
50491
+ }
49594
50492
  return genericParameterLanguageType(
49595
50493
  type.genericParamId,
49596
50494
  required,
@@ -49599,6 +50497,64 @@ function toLanguageType(type, context, genericEnvironment) {
49599
50497
  );
49600
50498
  }
49601
50499
  }
50500
+ var INTERFACE_FUNCTION_GENERICS = /* @__PURE__ */ new WeakMap();
50501
+ function declaredFunctionGenericParams(context, ownerMemberId) {
50502
+ const member = analyzerMemberById(context, ownerMemberId);
50503
+ if (member !== null) return functionGenericParamsOf(member);
50504
+ const interfaces = context.vm.interfaces ?? [];
50505
+ let byMember = INTERFACE_FUNCTION_GENERICS.get(interfaces);
50506
+ if (byMember === void 0) {
50507
+ const index = /* @__PURE__ */ new Map();
50508
+ for (const neoInterface of interfaces) {
50509
+ for (const interfaceMember of Object.values(neoInterface.members)) {
50510
+ if (!isInterfaceFunctionMember(interfaceMember)) continue;
50511
+ if (interfaceMember.genericParams === void 0) continue;
50512
+ index.set(interfaceMember.id, interfaceMember.genericParams);
50513
+ }
50514
+ }
50515
+ byMember = index;
50516
+ INTERFACE_FUNCTION_GENERICS.set(interfaces, byMember);
50517
+ }
50518
+ return byMember.get(ownerMemberId);
50519
+ }
50520
+ function functionGenericLanguageType(type, required, context) {
50521
+ return functionTypeParameterRef(
50522
+ type.ownerMemberId,
50523
+ type.index,
50524
+ declaredFunctionGenericParams(context, type.ownerMemberId)?.[type.index],
50525
+ required,
50526
+ context
50527
+ );
50528
+ }
50529
+ function functionTypeParameterRef(ownerMemberId, index, parameter3, required, context) {
50530
+ const id = functionTypeParameterId(ownerMemberId, index);
50531
+ return {
50532
+ kind: "typeParameter",
50533
+ id,
50534
+ name: parameter3?.name ?? id,
50535
+ ownerMemberId,
50536
+ index,
50537
+ ...parameter3?.constraint ? { constraint: toLanguageType(parameter3.constraint, context) } : {},
50538
+ ...parameter3?.defaultType ? { defaultType: toLanguageType(parameter3.defaultType, context) } : {},
50539
+ nullable: !required
50540
+ };
50541
+ }
50542
+ function functionTypeParameterSymbols(ownerMemberId, parameters, context) {
50543
+ if (parameters === void 0) return {};
50544
+ return {
50545
+ typeParameters: parameters.map((parameter3, index) => ({
50546
+ id: functionTypeParameterId(ownerMemberId, index),
50547
+ name: parameter3.name,
50548
+ type: functionTypeParameterRef(
50549
+ ownerMemberId,
50550
+ index,
50551
+ parameter3,
50552
+ true,
50553
+ context
50554
+ )
50555
+ }))
50556
+ };
50557
+ }
49602
50558
  function genericParameterLanguageType(genericParamId, required, context, genericEnvironment, visiting = /* @__PURE__ */ new Set()) {
49603
50559
  const environmentEntry = genericEnvironment?.get(genericParamId);
49604
50560
  if (environmentEntry?.kind === "member") {
@@ -52986,6 +53942,7 @@ var SCHEMA_DOCUMENT_FIELD_CONTRACTS = {
52986
53942
  "setterCode",
52987
53943
  "returnTypeInfo",
52988
53944
  "argumentTypes",
53945
+ "genericParams",
52989
53946
  "dispatch",
52990
53947
  "bodyMode",
52991
53948
  "effect",
@@ -53060,6 +54017,7 @@ var SCHEMA_DOCUMENT_FIELD_CONTRACTS = {
53060
54017
  code: "nullIsAbsentOnFullMember",
53061
54018
  templateId: "nullIsAbsentOnFullMember",
53062
54019
  setterCode: "nullIsAbsentOnFullMember",
54020
+ genericParams: "nullOrEmptyArrayIsAbsent",
53063
54021
  dispatch: {
53064
54022
  kind: "absentMeansDefault",
53065
54023
  defaultValue: 0
@@ -53457,6 +54415,13 @@ function normalizeDocumentFields(recordKind, value) {
53457
54415
  normalizeTypeInfoBindings(argument2);
53458
54416
  }
53459
54417
  }
54418
+ if (Array.isArray(normalized.genericParams)) {
54419
+ for (const parameter3 of normalized.genericParams) {
54420
+ if (!isRecord2(parameter3)) continue;
54421
+ normalizeTypeInfoBindings(parameter3.constraint);
54422
+ normalizeTypeInfoBindings(parameter3.defaultType);
54423
+ }
54424
+ }
53460
54425
  stripCompiledInitializer(normalized.defaultValue);
53461
54426
  }
53462
54427
  if (recordKind === "constructor") {
@@ -54690,6 +55655,10 @@ function schemaTypeOptionsAtDepth(depth) {
54690
55655
  ownerClassId: nonEmptyString,
54691
55656
  genericParamId: nonEmptyString
54692
55657
  }),
55658
+ nullableTypeSchema("functionGeneric", {
55659
+ ownerMemberId: nonEmptyString,
55660
+ index: pipe(number(), integer2(), minValue(0))
55661
+ }),
54693
55662
  nullableTypeSchema("enum", {
54694
55663
  enumId: nonEmptyString
54695
55664
  }),
@@ -54935,10 +55904,21 @@ var schemaListColumnSchema = strictObject({
54935
55904
  frozen: boolean2(),
54936
55905
  wrapContent: boolean2()
54937
55906
  });
55907
+ var schemaFunctionGenericParameterSchema = strictObject({
55908
+ name: nonEmptyString,
55909
+ constraint: nullable(schemaTypeSchema),
55910
+ default: nullable(schemaTypeSchema)
55911
+ });
54938
55912
  var callableEntries = {
54939
55913
  returnType: schemaFunctionReturnTypeSchema,
54940
55914
  arguments: array(schemaFunctionArgumentSchema)
54941
55915
  };
55916
+ var genericCallableEntries = {
55917
+ ...callableEntries,
55918
+ genericParams: optional(
55919
+ pipe(array(schemaFunctionGenericParameterSchema), minLength(1))
55920
+ )
55921
+ };
54942
55922
  var functionEffectSchema = optional(picklist(["none", "auto"]));
54943
55923
  var schemaMemberSchema = variant("kind", [
54944
55924
  ...simpleMemberSchemas,
@@ -55018,12 +55998,12 @@ var schemaMemberSchema = variant("kind", [
55018
55998
  templateId: nullableId
55019
55999
  }),
55020
56000
  memberSchema("function", {
55021
- ...callableEntries,
56001
+ ...genericCallableEntries,
55022
56002
  deferred: boolean2(),
55023
56003
  effect: functionEffectSchema
55024
56004
  }),
55025
56005
  memberSchema("scriptFunction", {
55026
- ...callableEntries,
56006
+ ...genericCallableEntries,
55027
56007
  deferred: boolean2(),
55028
56008
  effect: functionEffectSchema,
55029
56009
  bodyMode: optional(literal2("ui")),
@@ -55486,6 +56466,10 @@ function memberFromDocument(record4, members, owners, classNames, context) {
55486
56466
  record4,
55487
56467
  source.span
55488
56468
  ),
56469
+ ...documentGenericParamsToManifest(
56470
+ field("genericParams", void 0),
56471
+ record4
56472
+ ),
55489
56473
  deferred: ordinalValue(
55490
56474
  field("dispatch", 0),
55491
56475
  FUNCTION_DISPATCH,
@@ -55776,6 +56760,11 @@ function memberToDocumentFields(member, baseData) {
55776
56760
  fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
55777
56761
  fields.argumentTypes = member.arguments.map(manifestArgumentToDocument);
55778
56762
  }
56763
+ if (member.genericParams !== void 0) {
56764
+ fields.genericParams = manifestGenericParamsToDocument(
56765
+ member.genericParams
56766
+ );
56767
+ }
55779
56768
  if (member.deferred || isOverride) {
55780
56769
  fields.dispatch = member.deferred ? 1 : 0;
55781
56770
  }
@@ -55923,6 +56912,32 @@ function optionalDocumentType(value, record4, path) {
55923
56912
  if (value === null || value === void 0) return null;
55924
56913
  return documentTypeToManifest(value, record4, path);
55925
56914
  }
56915
+ function documentGenericParamsToManifest(value, record4) {
56916
+ if (value === void 0) return {};
56917
+ if (!Array.isArray(value)) {
56918
+ throw invalidDocument(record4, "genericParams", "must be an array");
56919
+ }
56920
+ return {
56921
+ genericParams: value.map((entry, index) => {
56922
+ const path = `genericParams[${index}]`;
56923
+ if (!isRecord3(entry))
56924
+ throw invalidDocument(record4, path, "must be an object");
56925
+ return {
56926
+ name: requiredStringValue(entry.name, record4, `${path}.name`),
56927
+ constraint: optionalDocumentType(
56928
+ entry.constraint,
56929
+ record4,
56930
+ `${path}.constraint`
56931
+ ),
56932
+ default: optionalDocumentType(
56933
+ entry.defaultType,
56934
+ record4,
56935
+ `${path}.defaultType`
56936
+ )
56937
+ };
56938
+ })
56939
+ };
56940
+ }
55926
56941
  function documentReturnTypeToManifest(value, record4, path) {
55927
56942
  if (isRecord3(value) && value.type === "Void") {
55928
56943
  return { kind: "void", nullable: false };
@@ -55965,6 +56980,18 @@ function documentTypeToManifest(value, record4, path) {
55965
56980
  )
55966
56981
  };
55967
56982
  }
56983
+ if (kind === MEMBER_KIND.Generic && "ownerMemberId" in typeInfo) {
56984
+ return {
56985
+ kind: "functionGeneric",
56986
+ nullable: nullable2,
56987
+ ownerMemberId: requiredStringValue(
56988
+ typeInfo.ownerMemberId,
56989
+ record4,
56990
+ `${path}.ownerMemberId`
56991
+ ),
56992
+ index: requiredNumberValue(typeInfo.index, record4, `${path}.index`)
56993
+ };
56994
+ }
55968
56995
  if (kind === MEMBER_KIND.Generic) {
55969
56996
  return {
55970
56997
  kind: "generic",
@@ -56098,6 +57125,15 @@ function documentTypeToManifest(value, record4, path) {
56098
57125
  `unsupported type-info discriminator ${kind}`
56099
57126
  );
56100
57127
  }
57128
+ function manifestGenericParamsToDocument(params) {
57129
+ return params.map(
57130
+ (parameter3) => omitUndefined({
57131
+ name: parameter3.name,
57132
+ constraint: parameter3.constraint ? manifestTypeToDocument(parameter3.constraint) : void 0,
57133
+ defaultType: parameter3.default ? manifestTypeToDocument(parameter3.default) : void 0
57134
+ })
57135
+ );
57136
+ }
56101
57137
  function manifestArgumentToDocument(argument2) {
56102
57138
  return {
56103
57139
  name: argument2.name,
@@ -56141,6 +57177,14 @@ function manifestTypeToDocument(type) {
56141
57177
  genericParamId: type.genericParamId
56142
57178
  };
56143
57179
  }
57180
+ if (type.kind === "functionGeneric") {
57181
+ return {
57182
+ type: MEMBER_KIND.Generic,
57183
+ required,
57184
+ ownerMemberId: type.ownerMemberId,
57185
+ index: type.index
57186
+ };
57187
+ }
56144
57188
  if (type.kind === "enum") {
56145
57189
  return { type: MEMBER_KIND.Enum, required, enumId: type.enumId };
56146
57190
  }
@@ -56812,6 +57856,7 @@ function interfaceFromDocument(record4, context) {
56812
57856
  record4,
56813
57857
  source.span
56814
57858
  ),
57859
+ ...documentGenericParamsToManifest(member.genericParams, record4),
56815
57860
  deferred: ordinalValue(
56816
57861
  member.dispatch ?? 0,
56817
57862
  ["synchronous", "asynchronous"],
@@ -56848,6 +57893,11 @@ function interfaceToDocument(neoInterface) {
56848
57893
  ...member.docsText === void 0 ? {} : { docsText: member.docsText },
56849
57894
  returnTypeInfo: manifestReturnTypeToDocument(member.returnType),
56850
57895
  argumentTypes: member.arguments.map(manifestArgumentToDocument),
57896
+ ...member.genericParams === void 0 ? {} : {
57897
+ genericParams: manifestGenericParamsToDocument(
57898
+ member.genericParams
57899
+ )
57900
+ },
56851
57901
  ...member.deferred ? { dispatch: 1 } : {},
56852
57902
  ...accessToDocument(member.accessModifier)
56853
57903
  };
@@ -57756,7 +58806,7 @@ var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
57756
58806
 
57757
58807
  // ../packages/manifest/schema-contract/registry.mjs
57758
58808
  var PROJECT_SCHEMA_CONTRACT = Object.freeze({
57759
- cliVersion: "0.79.1",
58809
+ cliVersion: "0.80.0",
57760
58810
  projectFileUploadBatchSize: 32,
57761
58811
  documentRecords: {
57762
58812
  member: {
@@ -57806,6 +58856,7 @@ var PROJECT_SCHEMA_CONTRACT = Object.freeze({
57806
58856
  "setterCode",
57807
58857
  "returnTypeInfo",
57808
58858
  "argumentTypes",
58859
+ "genericParams",
57809
58860
  "dispatch",
57810
58861
  "bodyMode",
57811
58862
  // P97 §1.1. No normalization rule, like `distribution`: absence means
@@ -57850,6 +58901,7 @@ var PROJECT_SCHEMA_CONTRACT = Object.freeze({
57850
58901
  code: "nullIsAbsentOnFullMember",
57851
58902
  templateId: "nullIsAbsentOnFullMember",
57852
58903
  setterCode: "nullIsAbsentOnFullMember",
58904
+ genericParams: "nullOrEmptyArrayIsAbsent",
57853
58905
  dispatch: { kind: "absentMeansDefault", defaultValue: 0 },
57854
58906
  bodyMode: { kind: "absentMeansDefault", defaultValue: 0 },
57855
58907
  uiAction: "nullIsAbsentOnFullMember"
@@ -59595,7 +60647,7 @@ var SCRIPT_COLLECTION_READERS = {
59595
60647
  };
59596
60648
 
59597
60649
  // ../src/models/exports/unity-codegen-revision.ts
59598
- var UNITY_CODEGEN_REVISION = "49b24ee52b3e40b147f73d6d58f5c01eacc9f304463b8689d3d92ae57b14aef0";
60650
+ var UNITY_CODEGEN_REVISION = "edfd4061dffcd1a747b234cd135b99beca6f4cf1958cb69715029c5935dd7f1b";
59599
60651
 
59600
60652
  // src/export-cache.ts
59601
60653
  var CACHE_BUILD = JSON.stringify([
@@ -60042,23 +61094,53 @@ function mockResponse(environment, mock, selected, call) {
60042
61094
  if (selected.kind === "throw") {
60043
61095
  throw new NSGetterRuntimeError(selected.message);
60044
61096
  }
60045
- if (selected.kind === "implementation") {
60046
- return {
60047
- handled: true,
60048
- value: call.invokeDelegate(
60049
- bindNeoScriptDelegateToContext(
60050
- selected.delegate,
60051
- environment.context
60052
- ),
60053
- mock.isStatic ? call.args : [call.receiver, ...call.args]
60054
- )
60055
- };
60056
- }
60057
61097
  return {
60058
61098
  handled: true,
60059
- value: selected.kind === "return" ? selected.value : null
61099
+ value: narrowMockResult(
61100
+ environment,
61101
+ mock,
61102
+ call,
61103
+ mockValue(environment, mock, selected, call)
61104
+ )
60060
61105
  };
60061
61106
  }
61107
+ function mockValue(environment, mock, selected, call) {
61108
+ if (selected.kind === "implementation") {
61109
+ return call.invokeDelegate(
61110
+ bindNeoScriptDelegateToContext(
61111
+ selected.delegate,
61112
+ environment.context
61113
+ ),
61114
+ mock.isStatic ? call.args : [call.receiver, ...call.args]
61115
+ );
61116
+ }
61117
+ return selected.kind === "return" ? selected.value : null;
61118
+ }
61119
+ function narrowMockResult(environment, mock, call, value) {
61120
+ if (call.typeArguments === void 0 || call.member === null) return value;
61121
+ const narrowed = narrowGenericCallResult(
61122
+ value,
61123
+ call.member,
61124
+ call.typeArguments,
61125
+ environment.context
61126
+ );
61127
+ if ("value" in narrowed) return narrowed.value;
61128
+ const typeArguments = call.typeArguments.map((typeInfo) => typeArgumentLabel(environment, typeInfo)).join(", ");
61129
+ throw new NeoTestAssertionError(
61130
+ `Mock for Function '${mock.memberId}' returned a value that isn't the return type of '${call.member.name}<${typeArguments}>'.`
61131
+ );
61132
+ }
61133
+ function typeArgumentLabel(environment, typeInfo) {
61134
+ const vm = environment.context.vm;
61135
+ if (typeInfo.type === 7 /* Class */) {
61136
+ return vm.classes.find((schemaClass2) => schemaClass2.id === typeInfo.classId)?.name ?? typeInfo.classId;
61137
+ }
61138
+ if (typeInfo.type === 8 /* Enum */) {
61139
+ return vm.enums.find((e) => e.id === typeInfo.enumId)?.name ?? typeInfo.enumId;
61140
+ }
61141
+ if (typeInfo.type === NS_TYPE_UNKNOWN) return NS_TYPE_UNKNOWN;
61142
+ return MemberKind[typeInfo.type];
61143
+ }
60062
61144
  function partialObjectMatch(actual, expected) {
60063
61145
  if (!isRecord4(expected)) return isDeepStrictEqual(actual, expected);
60064
61146
  if (!isRecord4(actual)) return false;