@neocompose/cli 0.19.5 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/neo.mjs CHANGED
@@ -898,6 +898,7 @@ var init_language_spec = __esm({
898
898
  "Reference",
899
899
  "Partial",
900
900
  "FunctionRef",
901
+ "NeoDelegate",
901
902
  "Dialogue",
902
903
  "Trigger",
903
904
  "Node",
@@ -1534,6 +1535,16 @@ function isNeoScriptTypeAssignable(source, target, project) {
1534
1535
  if (source.kind === "dictionary" && target.kind === "dictionary") {
1535
1536
  return isNeoScriptTypeAssignable(source.keyType, target.keyType, project) && isNeoScriptTypeAssignable(source.valueType, target.valueType, project);
1536
1537
  }
1538
+ if (source.kind === "delegate" && target.kind === "delegate") {
1539
+ return source.parameterTypes.length === target.parameterTypes.length && isNeoScriptTypeAssignable(
1540
+ source.returnType,
1541
+ target.returnType,
1542
+ project
1543
+ ) && source.parameterTypes.every((parameter3, index) => {
1544
+ const expected = target.parameterTypes[index];
1545
+ return expected !== void 0 && isNeoScriptTypeAssignable(parameter3, expected, project) && isNeoScriptTypeAssignable(expected, parameter3, project);
1546
+ });
1547
+ }
1537
1548
  return false;
1538
1549
  }
1539
1550
  function commonNeoScriptAssignableType(left, right, project) {
@@ -1588,6 +1599,13 @@ function formatType(type, project) {
1588
1599
  return `Dictionary<${formatType(type.keyType, project)}, ${formatType(type.valueType, project)}>${suffix}`;
1589
1600
  case "typeParameter":
1590
1601
  return `${type.name}${suffix}`;
1602
+ case "delegate":
1603
+ return `NeoDelegate<${[
1604
+ formatType(type.returnType, project),
1605
+ ...type.parameterTypes.map(
1606
+ (parameter3) => formatType(parameter3, project)
1607
+ )
1608
+ ].join(", ")}>${suffix}`;
1591
1609
  }
1592
1610
  }
1593
1611
  var UNKNOWN_TYPE;
@@ -6476,6 +6494,8 @@ function neoScriptPositionalTypeKey(type) {
6476
6494
  return `dictionary:${neoScriptPositionalTypeKey(type.keyType)}:${neoScriptPositionalTypeKey(type.valueType)}`;
6477
6495
  case "typeParameter":
6478
6496
  return `typeParameter:${type.id}`;
6497
+ case "delegate":
6498
+ return `delegate:${neoScriptPositionalTypeKey(type.returnType)}(${type.parameterTypes.map(neoScriptPositionalTypeKey).join(",")})`;
6479
6499
  }
6480
6500
  }
6481
6501
  function validateNeoScriptOverloadSignatures(className, signatures) {
@@ -6575,7 +6595,7 @@ var NEOSCRIPT_COMPILER_REVISION;
6575
6595
  var init_strict_ir = __esm({
6576
6596
  "../packages/neoscript-language/src/strict-ir.ts"() {
6577
6597
  "use strict";
6578
- NEOSCRIPT_COMPILER_REVISION = 6;
6598
+ NEOSCRIPT_COMPILER_REVISION = 7;
6579
6599
  }
6580
6600
  });
6581
6601
 
@@ -6731,6 +6751,12 @@ function typeRefsEqual(left, right) {
6731
6751
  if (left.kind === "set" && right.kind === "set") {
6732
6752
  return typeRefsEqual(left.elementType, right.elementType);
6733
6753
  }
6754
+ if (left.kind === "delegate" && right.kind === "delegate") {
6755
+ return typeRefsEqual(left.returnType, right.returnType) && left.parameterTypes.length === right.parameterTypes.length && left.parameterTypes.every((parameter3, index) => {
6756
+ const other = right.parameterTypes[index];
6757
+ return other !== void 0 && typeRefsEqual(parameter3, other);
6758
+ });
6759
+ }
6734
6760
  return left.kind === "dictionary" && right.kind === "dictionary" ? typeRefsEqual(left.keyType, right.keyType) && typeRefsEqual(left.valueType, right.valueType) : false;
6735
6761
  }
6736
6762
  function variable(id2, type, pointer, project) {
@@ -7104,6 +7130,15 @@ function toWireType(type, project) {
7104
7130
  ownerClassId: type.ownerClassId ?? findGenericParameterOwner(type.id, project) ?? "",
7105
7131
  genericParamId: type.id
7106
7132
  };
7133
+ case "delegate":
7134
+ return {
7135
+ type: 25 /* Delegate */,
7136
+ required: required2,
7137
+ returnTypeInfo: type.returnType.kind === "primitive" && type.returnType.name === "void" ? { type: "Void", required: true } : toWireType(type.returnType, project),
7138
+ argumentTypes: type.parameterTypes.map(
7139
+ (parameter3) => toWireType(parameter3, project)
7140
+ )
7141
+ };
7107
7142
  }
7108
7143
  }
7109
7144
  function fromWireType(type) {
@@ -7150,6 +7185,14 @@ function fromWireType(type) {
7150
7185
  nullable
7151
7186
  };
7152
7187
  }
7188
+ if (type.type === 25 /* Delegate */) {
7189
+ return {
7190
+ kind: "delegate",
7191
+ returnType: type.returnTypeInfo.type === "Void" ? { kind: "primitive", name: "void" } : fromWireType(type.returnTypeInfo),
7192
+ parameterTypes: type.argumentTypes.map(fromWireType),
7193
+ nullable
7194
+ };
7195
+ }
7153
7196
  return { kind: "primitive", name: valueKindPrimitive(type.type), nullable };
7154
7197
  }
7155
7198
  function findGenericParameterOwner(parameterId, project) {
@@ -7371,6 +7414,13 @@ function substituteTypeParameters(member, receiver, declaring) {
7371
7414
  valueType: visit(type.valueType)
7372
7415
  };
7373
7416
  }
7417
+ if (type.kind === "delegate") {
7418
+ return {
7419
+ ...type,
7420
+ returnType: visit(type.returnType),
7421
+ parameterTypes: type.parameterTypes.map(visit)
7422
+ };
7423
+ }
7374
7424
  return type;
7375
7425
  };
7376
7426
  return visit(member);
@@ -8882,6 +8932,17 @@ var init_strict_resolver = __esm({
8882
8932
  );
8883
8933
  }
8884
8934
  resolveExpression(expression, scope, expected) {
8935
+ if (expected?.kind === "delegate") {
8936
+ if (expression.kind === "lambda") {
8937
+ return this.resolveDelegateLambda(expression, expected, scope);
8938
+ }
8939
+ const methodGroup = this.resolveDelegateMethodGroup(
8940
+ expression,
8941
+ expected,
8942
+ scope
8943
+ );
8944
+ if (methodGroup !== null) return methodGroup;
8945
+ }
8885
8946
  switch (expression.kind) {
8886
8947
  case "litNull":
8887
8948
  return literal(
@@ -9123,11 +9184,174 @@ var init_strict_resolver = __esm({
9123
9184
  }
9124
9185
  case "lambda":
9125
9186
  throw new CompileError(
9126
- "A lambda is valid only as an argument to a collection function.",
9187
+ "A lambda requires a NeoDelegate expected type.",
9127
9188
  expression.pos
9128
9189
  );
9129
9190
  }
9130
9191
  }
9192
+ resolveDelegateLambda(ast, expected, outerScope) {
9193
+ if (ast.params.length !== expected.parameterTypes.length) {
9194
+ throw new CompileError(
9195
+ `Delegate lambda expects ${expected.parameterTypes.length} parameter${expected.parameterTypes.length === 1 ? "" : "s"}, got ${ast.params.length}.`,
9196
+ ast.pos
9197
+ );
9198
+ }
9199
+ const scope = new Scope(outerScope);
9200
+ const parameters = ast.params.map((parameter3, index) => {
9201
+ this.assertLocalNameAvailable(parameter3.name, scope, parameter3.pos);
9202
+ const expectedType = requiredAt(expected.parameterTypes, index);
9203
+ const declared = parameter3.type ? this.resolveType(parameter3.type) : expectedType;
9204
+ if (!isNeoScriptTypeAssignable(declared, expectedType, this.project) || !isNeoScriptTypeAssignable(expectedType, declared, this.project)) {
9205
+ throw new CompileError(
9206
+ `Delegate lambda parameter ${index + 1} must be ${this.describe(expectedType)}, got ${this.describe(declared)}.`,
9207
+ parameter3.pos
9208
+ );
9209
+ }
9210
+ const item = variable(
9211
+ `__arg_${index}__`,
9212
+ declared,
9213
+ void 0,
9214
+ this.project
9215
+ );
9216
+ scope.define(
9217
+ scopeVariable(
9218
+ parameter3.name,
9219
+ item,
9220
+ declared,
9221
+ void 0,
9222
+ "runtime" /* Runtime */
9223
+ )
9224
+ );
9225
+ return item;
9226
+ });
9227
+ this.functionControlBoundaries.push({
9228
+ controlDepth: this.controlContexts.length,
9229
+ loopFlowDepth: this.loopFlowContexts.length,
9230
+ catchDepth: this.catchContexts.length
9231
+ });
9232
+ this.lambdaDepth++;
9233
+ this.expectedReturnStack.push(expected.returnType);
9234
+ try {
9235
+ const instructions = this.resolveStatements(ast.body, scope);
9236
+ const returnsVoid = isVoid(expected.returnType);
9237
+ if (!returnsVoid && !instructionsTerminate(instructions)) {
9238
+ throw new CompileError(
9239
+ "Not every reachable delegate path returns a value or throws.",
9240
+ ast.pos
9241
+ );
9242
+ }
9243
+ const action = {
9244
+ compilerRevision: NEOSCRIPT_COMPILER_REVISION,
9245
+ parameters: [this.thisVariable, this.rootVariable, ...parameters],
9246
+ instructions,
9247
+ typeInfo: returnsVoid ? toWireType({ kind: "primitive", name: "null" }, this.project) : toWireType(expected.returnType, this.project)
9248
+ };
9249
+ return literal(expected, { action }, this.project);
9250
+ } finally {
9251
+ this.expectedReturnStack.pop();
9252
+ this.lambdaDepth--;
9253
+ this.functionControlBoundaries.pop();
9254
+ }
9255
+ }
9256
+ resolveDelegateMethodGroup(expression, expected, scope) {
9257
+ let symbol;
9258
+ let receiver = null;
9259
+ let owner;
9260
+ if (expression.kind === "ident") {
9261
+ const implicit = this.implicitMember(expression.name);
9262
+ if (implicit === null || implicit.symbol.kind !== "function" && implicit.symbol.kind !== "method") {
9263
+ return null;
9264
+ }
9265
+ symbol = implicit.symbol;
9266
+ owner = implicit.owner;
9267
+ receiver = symbol.static === true ? { kind: "static", memberId: symbol.id } : {
9268
+ kind: "instance",
9269
+ expression: this.resolveIdentifier("this", scope, expression.pos)
9270
+ };
9271
+ } else if (expression.kind === "member") {
9272
+ if (expression.receiver.kind === "ident" && !scope.lookup(expression.receiver.name)) {
9273
+ owner = this.project.typeByName.get(expression.receiver.name);
9274
+ symbol = owner?.members.find(
9275
+ (candidate) => candidate.name === expression.name && (candidate.kind === "function" || candidate.kind === "method")
9276
+ );
9277
+ if (symbol === void 0) return null;
9278
+ if (symbol.static !== true) {
9279
+ throw new CompileError(
9280
+ `Member '${owner?.name}.${symbol.name}' requires an instance receiver.`,
9281
+ expression.pos
9282
+ );
9283
+ }
9284
+ receiver = { kind: "static", memberId: symbol.id };
9285
+ } else {
9286
+ const receiverExpression = this.resolveExpression(
9287
+ expression.receiver,
9288
+ scope
9289
+ );
9290
+ if (receiverExpression.type.kind !== "named") return null;
9291
+ owner = this.project.typeById.get(receiverExpression.type.typeId);
9292
+ symbol = owner?.members.find(
9293
+ (candidate) => candidate.name === expression.name && (candidate.kind === "function" || candidate.kind === "method")
9294
+ );
9295
+ if (symbol === void 0) return null;
9296
+ if (symbol.static === true) {
9297
+ throw new CompileError(
9298
+ `Static member '${owner?.name}.${symbol.name}' must be accessed through the type name, not an instance.`,
9299
+ expression.pos
9300
+ );
9301
+ }
9302
+ receiver = { kind: "instance", expression: receiverExpression };
9303
+ }
9304
+ } else {
9305
+ return null;
9306
+ }
9307
+ if (owner !== void 0)
9308
+ this.assertMemberAccessible(owner, symbol, expression.pos);
9309
+ let returnType = symbol.returnType ?? symbol.type;
9310
+ let parameterTypes = (symbol.parameters ?? []).map(
9311
+ (parameter3) => parameter3.type
9312
+ );
9313
+ if (receiver?.kind === "instance" && receiver.expression.type.kind === "named" && owner !== void 0) {
9314
+ const receiverType = receiver.expression.type;
9315
+ returnType = substituteTypeParameters(returnType, receiverType, owner);
9316
+ parameterTypes = parameterTypes.map(
9317
+ (parameter3) => substituteTypeParameters(parameter3, receiverType, owner)
9318
+ );
9319
+ }
9320
+ const expectedVoid = isVoid(expected.returnType);
9321
+ const actualVoid = isVoid(returnType);
9322
+ if (expectedVoid !== actualVoid || !expectedVoid && !isNeoScriptTypeAssignable(returnType, expected.returnType, this.project) || parameterTypes.length !== expected.parameterTypes.length || !parameterTypes.every((parameter3, index) => {
9323
+ const target = expected.parameterTypes[index];
9324
+ return target !== void 0 && isNeoScriptTypeAssignable(parameter3, target, this.project) && isNeoScriptTypeAssignable(target, parameter3, this.project);
9325
+ })) {
9326
+ throw new CompileError(
9327
+ `Function '${symbol.name}' is not assignable to ${this.describe(expected)}.`,
9328
+ expression.pos
9329
+ );
9330
+ }
9331
+ const parameters = expected.parameterTypes.map(
9332
+ (type, index) => variable(`__arg_${index}__`, type, void 0, this.project)
9333
+ );
9334
+ const call = {
9335
+ type: "callFunction" /* CallFunction */,
9336
+ memberId: symbol.id,
9337
+ receiver: receiver?.kind === "static" ? { kind: "static", memberId: receiver.memberId } : {
9338
+ kind: "instance",
9339
+ pointer: receiver?.expression.pointer ?? this.thisVariable.pointer
9340
+ },
9341
+ args: parameters.map((parameter3) => ({
9342
+ type: "variable" /* Variable */,
9343
+ variableId: parameter3.id
9344
+ })),
9345
+ callSiteId: this.nextCallSite(expression.pos)
9346
+ };
9347
+ const action = {
9348
+ compilerRevision: NEOSCRIPT_COMPILER_REVISION,
9349
+ parameters: [this.thisVariable, this.rootVariable, ...parameters],
9350
+ instructions: expectedVoid ? [{ type: "functionCall" /* FunctionCall */, call }] : [{ type: "return" /* Return */, pointer: call }],
9351
+ typeInfo: expectedVoid ? toWireType({ kind: "primitive", name: "null" }, this.project) : toWireType(expected.returnType, this.project)
9352
+ };
9353
+ return literal(expected, { action }, this.project);
9354
+ }
9131
9355
  resolveInterpolatedString(parts, scope) {
9132
9356
  const stringType = { kind: "primitive", name: "string" };
9133
9357
  const pointers = parts.map((part) => {
@@ -9949,6 +10173,16 @@ var init_strict_resolver = __esm({
9949
10173
  }
9950
10174
  }
9951
10175
  resolveCall(callee, argumentsList2, scope, pos) {
10176
+ const delegate = this.resolveDelegateCallee(callee, scope);
10177
+ if (delegate !== null) {
10178
+ return this.resolveDelegateCall(
10179
+ delegate,
10180
+ argumentsList2,
10181
+ scope,
10182
+ pos,
10183
+ callee.kind === "member" && callee.optional === true
10184
+ );
10185
+ }
9952
10186
  if (callee.kind === "ident") {
9953
10187
  const vector = vectorKind(callee.name);
9954
10188
  if (vector)
@@ -10146,6 +10380,71 @@ var init_strict_resolver = __esm({
10146
10380
  pos
10147
10381
  );
10148
10382
  }
10383
+ resolveDelegateCallee(callee, scope) {
10384
+ if (callee.kind === "ident") {
10385
+ const scoped = scope.lookup(callee.name);
10386
+ const implicit = this.implicitMember(callee.name);
10387
+ if (scoped === null && (implicit === null || implicit.symbol.kind === "function" || implicit.symbol.kind === "method")) {
10388
+ return null;
10389
+ }
10390
+ const resolved = this.resolveIdentifier(callee.name, scope, callee.pos);
10391
+ return resolved.type.kind === "delegate" ? resolved : null;
10392
+ }
10393
+ if (callee.kind !== "member") return null;
10394
+ try {
10395
+ const resolved = this.resolveMember(
10396
+ callee.receiver,
10397
+ callee.name,
10398
+ scope,
10399
+ callee.pos,
10400
+ callee.optional === true
10401
+ );
10402
+ return resolved.type.kind === "delegate" ? resolved : null;
10403
+ } catch (error) {
10404
+ if (error instanceof CompileError) return null;
10405
+ throw error;
10406
+ }
10407
+ }
10408
+ resolveDelegateCall(delegate, args, scope, pos, optional) {
10409
+ if (delegate.type.kind !== "delegate") {
10410
+ throw new Error("Delegate call received a non-delegate type.");
10411
+ }
10412
+ const delegateType = delegate.type;
10413
+ if (isNullable(delegateType) && !optional) {
10414
+ throw new CompileError(
10415
+ `Cannot call optional ${this.describe(delegate.type)} without optional chaining or force-unwrapping it.`,
10416
+ pos
10417
+ );
10418
+ }
10419
+ requireArgCount("Delegate", args, delegateType.parameterTypes.length, pos);
10420
+ const pointers = args.map((argument2, index) => {
10421
+ const expected = requiredAt(delegateType.parameterTypes, index);
10422
+ const resolved = this.resolveExpression(argument2, scope, expected);
10423
+ this.requireAssignable(
10424
+ resolved.type,
10425
+ expected,
10426
+ argument2.pos,
10427
+ `delegate argument ${index + 1}`
10428
+ );
10429
+ return resolved.pointer;
10430
+ });
10431
+ if (isVoid(delegateType.returnType)) {
10432
+ throw new CompileError(
10433
+ "A void delegate cannot be used as a value; call it as a statement instead.",
10434
+ pos
10435
+ );
10436
+ }
10437
+ return {
10438
+ pointer: {
10439
+ type: "callDelegate" /* CallDelegate */,
10440
+ delegate: delegate.pointer,
10441
+ args: pointers,
10442
+ ...optional ? { optional: true } : {},
10443
+ callSiteId: this.nextCallSite(pos)
10444
+ },
10445
+ type: optional ? { ...delegateType.returnType, nullable: true } : delegateType.returnType
10446
+ };
10447
+ }
10149
10448
  resolveClassConstructor(className, argumentsList2, scope, pos) {
10150
10449
  const schemaClass2 = this.project.typeByName.get(className);
10151
10450
  if (!schemaClass2 || schemaClass2.kind !== "class") {
@@ -10917,8 +11216,42 @@ var init_strict_resolver = __esm({
10917
11216
  };
10918
11217
  }
10919
11218
  resolveFunctionStatement(expression, scope) {
10920
- if (expression.kind !== "call" || expression.callee.kind !== "member")
10921
- return null;
11219
+ if (expression.kind !== "call") return null;
11220
+ const delegate = this.resolveDelegateCallee(expression.callee, scope);
11221
+ if (delegate?.type.kind === "delegate") {
11222
+ const delegateType = delegate.type;
11223
+ requireArgCount(
11224
+ "Delegate",
11225
+ expression.args,
11226
+ delegateType.parameterTypes.length,
11227
+ expression.pos
11228
+ );
11229
+ if (isNullable(delegateType) && !(expression.callee.kind === "member" && expression.callee.optional)) {
11230
+ throw new CompileError(
11231
+ `Cannot call optional ${this.describe(delegate.type)} without optional chaining or force-unwrapping it.`,
11232
+ expression.pos
11233
+ );
11234
+ }
11235
+ const args2 = expression.args.map((argument2, index) => {
11236
+ const expected = requiredAt(delegateType.parameterTypes, index);
11237
+ const resolved = this.resolveExpression(argument2, scope, expected);
11238
+ this.requireAssignable(
11239
+ resolved.type,
11240
+ expected,
11241
+ argument2.pos,
11242
+ `delegate argument ${index + 1}`
11243
+ );
11244
+ return resolved.pointer;
11245
+ });
11246
+ return {
11247
+ type: "callDelegate" /* CallDelegate */,
11248
+ delegate: delegate.pointer,
11249
+ args: args2,
11250
+ ...expression.callee.kind === "member" && expression.callee.optional ? { optional: true } : {},
11251
+ callSiteId: this.nextCallSite(expression.pos)
11252
+ };
11253
+ }
11254
+ if (expression.callee.kind !== "member") return null;
10922
11255
  const memberName = expression.callee.name;
10923
11256
  if (expression.callee.receiver.kind === "ident" && !scope.lookup(expression.callee.receiver.name)) {
10924
11257
  const staticType = this.project.typeByName.get(
@@ -20118,6 +20451,13 @@ function substituteInheritedSourceMember(member, baseInfo, resolvedBaseType) {
20118
20451
  valueType: substitute2(type.valueType)
20119
20452
  };
20120
20453
  }
20454
+ if (type.kind === "delegate") {
20455
+ return {
20456
+ ...type,
20457
+ returnType: substitute2(type.returnType),
20458
+ parameterTypes: type.parameterTypes.map(substitute2)
20459
+ };
20460
+ }
20121
20461
  return type;
20122
20462
  };
20123
20463
  return {
@@ -20188,6 +20528,15 @@ function sourceTypeRef(type, owner, typeIds) {
20188
20528
  ...nullable ? { nullable } : {}
20189
20529
  };
20190
20530
  }
20531
+ if (type.name === "NeoDelegate") {
20532
+ const returnType = type.typeArguments[0] ? sourceTypeRef(type.typeArguments[0], owner, typeIds) : { kind: "primitive", name: "unknown" };
20533
+ return {
20534
+ kind: "delegate",
20535
+ returnType,
20536
+ parameterTypes: type.typeArguments.slice(1).map((argument2) => sourceTypeRef(argument2, owner, typeIds)),
20537
+ ...nullable ? { nullable } : {}
20538
+ };
20539
+ }
20191
20540
  if (type.name === "Reference" && type.typeArguments[0]) {
20192
20541
  return {
20193
20542
  ...sourceTypeRef(type.typeArguments[0], owner, typeIds),
@@ -20906,6 +21255,18 @@ function validateTypeApplication(uri, type, genericParameters, environment, diag
20906
21255
  return;
20907
21256
  }
20908
21257
  const target = environment.declarations.get(type.name);
21258
+ if (type.name === "NeoDelegate") {
21259
+ if (type.typeArguments.length < 1 || type.typeArguments.length > 17) {
21260
+ diagnose(
21261
+ diagnostics,
21262
+ uri,
21263
+ type.range,
21264
+ "generic-argument-arity",
21265
+ `Type 'NeoDelegate' expects a return type followed by up to 16 parameter types, but ${type.typeArguments.length} type arguments were provided.`
21266
+ );
21267
+ }
21268
+ return;
21269
+ }
20909
21270
  const expected = target?.declaration.kind === "class" ? target.declaration.genericParameters.length : BUILTIN_ARITY.get(type.name) ?? 0;
20910
21271
  if (!target && !BUILTIN_TYPES.has(type.name)) return;
20911
21272
  if (type.typeArguments.length !== expected) {
@@ -21557,9 +21918,15 @@ function memberCompatibility(implementation, implementationSubstitution, target,
21557
21918
  environment,
21558
21919
  implementationGenericParameters
21559
21920
  ) && isClassTypedShape(targetType, environment, implementationGenericParameters);
21921
+ const permitsDelegateReturnCovariance = isClassOverride && implementationFamily === "value" && delegateShapeAssignable(
21922
+ implementationType,
21923
+ targetType,
21924
+ environment,
21925
+ implementationGenericParameters
21926
+ );
21560
21927
  const permitsStoredOverrideNullability = isClassOverride && implementation.kind === "field" && (target.member.kind === "field" || isAbstractPropertyContract(target.member, targetAccessors));
21561
21928
  const comparableImplementationType = permitsStoredOverrideNullability ? { ...implementationType, nullable: targetType.nullable } : implementationType;
21562
- if (!typesEqual(comparableImplementationType, targetType) && !((permitsCovariantGetter || permitsClassCovariance) && isTypeAssignable(
21929
+ if (!typesEqual(comparableImplementationType, targetType) && !(permitsDelegateReturnCovariance || (permitsCovariantGetter || permitsClassCovariance) && isTypeAssignable(
21563
21930
  comparableImplementationType,
21564
21931
  targetType,
21565
21932
  environment,
@@ -21600,6 +21967,28 @@ function memberCompatibility(implementation, implementationSubstitution, target,
21600
21967
  }
21601
21968
  return null;
21602
21969
  }
21970
+ function delegateShapeAssignable(actual, expected, environment, genericParameters) {
21971
+ if (actual.name !== "NeoDelegate" || expected.name !== "NeoDelegate") {
21972
+ return false;
21973
+ }
21974
+ if (actual.nullable !== expected.nullable) return false;
21975
+ if (actual.arguments.length !== expected.arguments.length) return false;
21976
+ const actualReturn = actual.arguments[0];
21977
+ const expectedReturn = expected.arguments[0];
21978
+ if (actualReturn === void 0 || expectedReturn === void 0) return false;
21979
+ if (!isTypeAssignable(
21980
+ actualReturn,
21981
+ expectedReturn,
21982
+ environment,
21983
+ genericParameters
21984
+ )) {
21985
+ return false;
21986
+ }
21987
+ return actual.arguments.slice(1).every((argument2, index) => {
21988
+ const expectedArgument = expected.arguments[index + 1];
21989
+ return expectedArgument !== void 0 && typesEqual(argument2, expectedArgument);
21990
+ });
21991
+ }
21603
21992
  function valueAccessors(member, environment) {
21604
21993
  if (member.kind === "field") {
21605
21994
  const owner = environment.memberOwners.get(member);
@@ -28009,6 +28398,12 @@ function normalizeTypeInfoBindings(value) {
28009
28398
  }
28010
28399
  }
28011
28400
  normalizeTypeInfoBindings(value.entryTypeInfo);
28401
+ normalizeTypeInfoBindings(value.returnTypeInfo);
28402
+ if (Array.isArray(value.argumentTypes)) {
28403
+ for (const argument2 of value.argumentTypes) {
28404
+ normalizeTypeInfoBindings(argument2);
28405
+ }
28406
+ }
28012
28407
  }
28013
28408
  function stripCompiledInitializer(value) {
28014
28409
  if (!isRecord(value)) return;
@@ -28573,6 +28968,22 @@ function memberFromDocument(record3, members, owners, classNames, context) {
28573
28968
  if (kind === MEMBER_KIND.FunctionRef) {
28574
28969
  return { ...common, kind: "functionRef" };
28575
28970
  }
28971
+ if (kind === MEMBER_KIND.NSDelegate) {
28972
+ return {
28973
+ ...common,
28974
+ kind: "delegate",
28975
+ returnType: documentReturnTypeToManifest(
28976
+ field("returnTypeInfo", void 0),
28977
+ record3,
28978
+ "returnTypeInfo"
28979
+ ),
28980
+ arguments: documentArgumentsToManifest(
28981
+ field("argumentTypes", []),
28982
+ record3,
28983
+ source.span
28984
+ )
28985
+ };
28986
+ }
28576
28987
  if (kind === MEMBER_KIND.Generic) {
28577
28988
  return {
28578
28989
  ...common,
@@ -28711,6 +29122,13 @@ function memberToDocumentFields(member, baseData3) {
28711
29122
  if (member.uiAction !== void 0) fields.uiAction = member.uiAction;
28712
29123
  }
28713
29124
  }
29125
+ if (member.kind === "delegate") {
29126
+ fields.returnTypeInfo = manifestReturnTypeToDocument(member.returnType);
29127
+ fields.argumentTypes = member.arguments.map((argument2) => ({
29128
+ name: argument2.name,
29129
+ ...manifestTypeToDocument(argument2.type)
29130
+ }));
29131
+ }
28714
29132
  if (member.kind === "generic") {
28715
29133
  fields.genericParamId = member.genericParamId;
28716
29134
  if (member.partial) fields.partial = true;
@@ -28908,6 +29326,24 @@ function documentTypeToManifest(value, record3, path) {
28908
29326
  collectionValueId: optionalStringOrNull(typeInfo.collectionValueId)
28909
29327
  };
28910
29328
  }
29329
+ if (kind === MEMBER_KIND.NSDelegate) {
29330
+ return {
29331
+ kind: "delegate",
29332
+ nullable,
29333
+ returnType: documentReturnTypeToManifest(
29334
+ typeInfo.returnTypeInfo,
29335
+ record3,
29336
+ `${path}.returnTypeInfo`
29337
+ ),
29338
+ argumentTypes: optionalArray(typeInfo.argumentTypes).map(
29339
+ (argument2, index) => documentTypeToManifest(
29340
+ argument2,
29341
+ record3,
29342
+ `${path}.argumentTypes.${index}`
29343
+ )
29344
+ )
29345
+ };
29346
+ }
28911
29347
  throw invalidDocument(
28912
29348
  record3,
28913
29349
  path,
@@ -28971,6 +29407,14 @@ function manifestTypeToDocument(type) {
28971
29407
  readOnly: type.readOnly || void 0
28972
29408
  });
28973
29409
  }
29410
+ if (type.kind === "delegate") {
29411
+ return {
29412
+ type: MEMBER_KIND.NSDelegate,
29413
+ required: required2,
29414
+ returnTypeInfo: manifestReturnTypeToDocument(type.returnType),
29415
+ argumentTypes: type.argumentTypes.map(manifestTypeToDocument)
29416
+ };
29417
+ }
28974
29418
  if (type.kind !== "lookup") {
28975
29419
  throw new Error(`No document type-info mapping for ${type.kind}.`);
28976
29420
  }
@@ -29362,7 +29806,8 @@ var init_codecs = __esm({
29362
29806
  Generic: 21,
29363
29807
  Interface: 22,
29364
29808
  NSFunction: 23,
29365
- FunctionRef: 24
29809
+ FunctionRef: 24,
29810
+ NSDelegate: 25
29366
29811
  };
29367
29812
  TYPE_KIND_BY_MEMBER_KIND = /* @__PURE__ */ new Map([
29368
29813
  [MEMBER_KIND.Null, "null"],
@@ -29413,7 +29858,8 @@ var init_codecs = __esm({
29413
29858
  ["decimal", MEMBER_KIND.Decimal],
29414
29859
  ["generic", MEMBER_KIND.Generic],
29415
29860
  ["scriptFunction", MEMBER_KIND.NSFunction],
29416
- ["functionRef", MEMBER_KIND.FunctionRef]
29861
+ ["functionRef", MEMBER_KIND.FunctionRef],
29862
+ ["delegate", MEMBER_KIND.NSDelegate]
29417
29863
  ]);
29418
29864
  TYPE_MEMBER_KIND_BY_KIND = /* @__PURE__ */ new Map([
29419
29865
  ["null", MEMBER_KIND.Null],
@@ -31428,10 +31874,18 @@ function assertMember2(value, path) {
31428
31874
  assertMemberOwner(member.owner, `${path}.owner`);
31429
31875
  assertOptionalDocsText2(member.docsText, `${path}.docsText`);
31430
31876
  const owner = requireRecord(member.owner, `${path}.owner`);
31431
- if (member.docsText !== void 0 && owner.kind !== "classMember" && owner.kind !== "sharedClassMember") {
31877
+ if (member.docsText !== void 0 && owner.kind !== "classMember" && owner.kind !== "sharedClassMember" && // A loose member is not a kind of member — it is a member no class schema
31878
+ // in *this* view claims. A workspace merging its own pending records over
31879
+ // newer server ones sees exactly that: the local class still names the
31880
+ // pending member id the push replaced, so the committed member it now
31881
+ // holds is claimed by nothing. Doc text belongs to the member record, not
31882
+ // to where a schema happens to place it, so rejecting it here fails a pull
31883
+ // for a workspace whose only problem is being mid-sync — the one operation
31884
+ // that would fix it.
31885
+ owner.kind !== "loose") {
31432
31886
  invalid(
31433
31887
  `${path}.docsText`,
31434
- "is allowed only on source-declarable class members."
31888
+ `is allowed only on source-declarable class members; ${JSON.stringify(String(member.name))} is owned by ${JSON.stringify(String(owner.kind))}.`
31435
31889
  );
31436
31890
  }
31437
31891
  nonEmptyString(member.name, `${path}.name`);
@@ -31601,6 +32055,14 @@ function assertMember2(value, path) {
31601
32055
  assertAbstractScriptInvariant(member, path);
31602
32056
  return;
31603
32057
  }
32058
+ if (kind === "delegate") {
32059
+ assertReturnType(member.returnType, `${path}.returnType`);
32060
+ arrayOf(member.arguments, `${path}.arguments`, assertFunctionArgument);
32061
+ if (Array.isArray(member.arguments) && member.arguments.length > 16) {
32062
+ invalid(`${path}.arguments`, "delegate arity cannot exceed 16.");
32063
+ }
32064
+ return;
32065
+ }
31604
32066
  if (kind === "generic") {
31605
32067
  nonEmptyString(member.genericParamId, `${path}.genericParamId`);
31606
32068
  if (member.partial !== void 0) {
@@ -31909,6 +32371,20 @@ function assertType2(value, path, depth = 0) {
31909
32371
  nullableNonEmptyString(type.collectionValueId, `${path}.collectionValueId`);
31910
32372
  return;
31911
32373
  }
32374
+ if (kind === "delegate") {
32375
+ knownKeys(type, path, ["kind", "nullable", "returnType", "argumentTypes"]);
32376
+ booleanAt(type.nullable, `${path}.nullable`);
32377
+ assertReturnType(type.returnType, `${path}.returnType`);
32378
+ arrayOf(
32379
+ type.argumentTypes,
32380
+ `${path}.argumentTypes`,
32381
+ (entry, entryPath) => assertType2(entry, entryPath, depth + 1)
32382
+ );
32383
+ if (Array.isArray(type.argumentTypes) && type.argumentTypes.length > 16) {
32384
+ invalid(`${path}.argumentTypes`, "delegate arity cannot exceed 16.");
32385
+ }
32386
+ return;
32387
+ }
31912
32388
  invalid(`${path}.kind`, `unsupported schema type ${JSON.stringify(kind)}.`);
31913
32389
  }
31914
32390
  function assertInterface(value, path) {
@@ -32810,7 +33286,8 @@ var init_validate = __esm({
32810
33286
  function: ["returnType", "arguments", "deferred"],
32811
33287
  scriptFunction: ["returnType", "arguments", "deferred", "script"],
32812
33288
  generic: ["genericParamId"],
32813
- functionRef: []
33289
+ functionRef: [],
33290
+ delegate: ["returnType", "arguments"]
32814
33291
  };
32815
33292
  PRIMITIVE_TYPE_KINDS = /* @__PURE__ */ new Set([
32816
33293
  "null",
@@ -35875,6 +36352,27 @@ function isNSTypeInfoGenericParam(value) {
35875
36352
  if (typeof v.genericParamId !== "string") return false;
35876
36353
  return v.genericParamId.length > 0;
35877
36354
  }
36355
+ function isNSTypeInfoDelegateInternal(value, ancestors) {
36356
+ if (!isNSTypeInfoBase(value) || value.type !== 25 /* NSDelegate */) {
36357
+ return false;
36358
+ }
36359
+ const delegate = value;
36360
+ if (ancestors.has(delegate)) return false;
36361
+ ancestors.add(delegate);
36362
+ try {
36363
+ if (!isNSTypeInfoVoid(delegate.returnTypeInfo) && !isNSTypeInfoInternal(delegate.returnTypeInfo, ancestors)) {
36364
+ return false;
36365
+ }
36366
+ if (!Array.isArray(delegate.argumentTypes) || delegate.argumentTypes.length > 16) {
36367
+ return false;
36368
+ }
36369
+ return delegate.argumentTypes.every(
36370
+ (argument2) => isNSTypeInfoInternal(argument2, ancestors)
36371
+ );
36372
+ } finally {
36373
+ ancestors.delete(delegate);
36374
+ }
36375
+ }
35878
36376
  function isNSTypeInfoCollection(value) {
35879
36377
  return isNSTypeInfoCollectionInternal(value, /* @__PURE__ */ new Set());
35880
36378
  }
@@ -35931,7 +36429,7 @@ function isNSTypeInfo(value) {
35931
36429
  return isNSTypeInfoInternal(value, /* @__PURE__ */ new Set());
35932
36430
  }
35933
36431
  function isNSTypeInfoInternal(value, ancestors) {
35934
- return isNSTypeInfoUnknown(value) || isNSTypeInfoPrimitive(value) || isNSTypeInfoAsset(value) || isNSTypeInfoVector(value) || isNSTypeInfoColor(value) || isNSTypeInfoDialogueLookup(value) || isNSTypeInfoClassInternal(value, ancestors) || isNSTypeInfoInterface(value) || isNSTypeInfoGenericParam(value) || isNSTypeInfoCollectionInternal(value, ancestors) || isNSTypeInfoLookupInternal(value, ancestors) || isNSTypeInfoEnum(value);
36432
+ return isNSTypeInfoUnknown(value) || isNSTypeInfoPrimitive(value) || isNSTypeInfoAsset(value) || isNSTypeInfoVector(value) || isNSTypeInfoColor(value) || isNSTypeInfoDialogueLookup(value) || isNSTypeInfoClassInternal(value, ancestors) || isNSTypeInfoInterface(value) || isNSTypeInfoGenericParam(value) || isNSTypeInfoDelegateInternal(value, ancestors) || isNSTypeInfoCollectionInternal(value, ancestors) || isNSTypeInfoLookupInternal(value, ancestors) || isNSTypeInfoEnum(value);
35935
36433
  }
35936
36434
  function isNSArgumentTypeInfo(value) {
35937
36435
  return isRequiredType(value, isNSArgumentTypeInfoUnsafe);
@@ -35953,6 +36451,11 @@ function typeInfoContainsUnknown(value, ancestors) {
35953
36451
  if (value.type === 6 /* List */ || value.type === 5 /* Dictionary */ || value.type === 9 /* Lookup */) {
35954
36452
  return typeInfoContainsUnknown(value.entryTypeInfo, ancestors);
35955
36453
  }
36454
+ if (value.type === 25 /* NSDelegate */) {
36455
+ return value.returnTypeInfo.type !== NS_TYPE_VOID && typeInfoContainsUnknown(value.returnTypeInfo, ancestors) || value.argumentTypes.some(
36456
+ (argument2) => typeInfoContainsUnknown(argument2, ancestors)
36457
+ );
36458
+ }
35956
36459
  if (value.type !== 7 /* Class */) return false;
35957
36460
  return Object.values(value.typeArguments ?? {}).some(
35958
36461
  (argument2) => typeInfoContainsUnknown(argument2, ancestors)
@@ -36087,6 +36590,16 @@ function isNSPointerCallFunction(value) {
36087
36590
  }
36088
36591
  return true;
36089
36592
  }
36593
+ function isNSPointerCallDelegate(value) {
36594
+ const v = value;
36595
+ if (v?.type !== "callDelegate" /* callDelegate */) return false;
36596
+ if (!isNSPointer(v.delegate)) return false;
36597
+ if (!Array.isArray(v.args) || !v.args.every(isNSPointer)) return false;
36598
+ if (typeof v.callSiteId !== "string" || v.callSiteId.length === 0) {
36599
+ return false;
36600
+ }
36601
+ return v.optional === void 0 || typeof v.optional === "boolean";
36602
+ }
36090
36603
  function isNSCallReceiver(value) {
36091
36604
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
36092
36605
  return false;
@@ -36105,7 +36618,7 @@ function isNSPointerFunctionErrorCheck(value) {
36105
36618
  return isNSFunctionErrorCheckMode(v.mode);
36106
36619
  }
36107
36620
  function isNSPointer(value) {
36108
- return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerCallFunction(value) || isNSPointerFunctionErrorCheck(value);
36621
+ return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerCallFunction(value) || isNSPointerCallDelegate(value) || isNSPointerFunctionErrorCheck(value);
36109
36622
  }
36110
36623
  function isNSPointers(value) {
36111
36624
  return Array.isArray(value) && value.every(isNSPointer);
@@ -36443,7 +36956,7 @@ function isNSInstructionCollectionCall(value) {
36443
36956
  function isNSInstructionFunctionCall(value) {
36444
36957
  const v = value;
36445
36958
  if (v?.type !== "functionCall" /* functionCall */) return false;
36446
- return isNSPointerCallFunction(v.call);
36959
+ return isNSPointerCallFunction(v.call) || isNSPointerCallDelegate(v.call);
36447
36960
  }
36448
36961
  function isNSLoopBinding(value) {
36449
36962
  const binding = value;
@@ -36975,6 +37488,7 @@ var init_member_kind_enum = __esm({
36975
37488
  MemberKind13[MemberKind13["Interface"] = 22] = "Interface";
36976
37489
  MemberKind13[MemberKind13["NSFunction"] = 23] = "NSFunction";
36977
37490
  MemberKind13[MemberKind13["FunctionRef"] = 24] = "FunctionRef";
37491
+ MemberKind13[MemberKind13["NSDelegate"] = 25] = "NSDelegate";
36978
37492
  return MemberKind13;
36979
37493
  })(MemberKind || {});
36980
37494
  }
@@ -37546,6 +38060,61 @@ function isMemberNSFunction(value) {
37546
38060
  if (typeof v.code !== "string" || v.code.length === 0) return false;
37547
38061
  return hasValidNSFunctionAction(v, base.returnTypeInfo, base.argumentTypes);
37548
38062
  }
38063
+ function isMemberDelegateTarget(value) {
38064
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
38065
+ const record3 = value;
38066
+ if (!hasExactKeys(record3, ["memberId", "valueId"])) return false;
38067
+ return typeof record3.memberId === "string" && record3.memberId.length > 0 && (record3.valueId === null || typeof record3.valueId === "string" && record3.valueId.length > 0);
38068
+ }
38069
+ function isNSDelegateClosureValueDraft(value) {
38070
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
38071
+ const record3 = value;
38072
+ return hasExactKeys(record3, ["code"]) && typeof record3.code === "string" && record3.code.length > 0;
38073
+ }
38074
+ function isNSDelegateClosureValue(value) {
38075
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
38076
+ const record3 = value;
38077
+ const keys = record3.code === void 0 ? ["action"] : ["code", "action"];
38078
+ if (!hasExactKeys(record3, keys)) return false;
38079
+ if (record3.code !== void 0 && (typeof record3.code !== "string" || record3.code.length === 0)) {
38080
+ return false;
38081
+ }
38082
+ return isNSFunctionWithReturnType(record3.action);
38083
+ }
38084
+ function isNSDelegateValue(value) {
38085
+ return isMemberDelegateTarget(value) || isNSDelegateClosureValueDraft(value) || isNSDelegateClosureValue(value);
38086
+ }
38087
+ function nsDelegateDirectReferenceValueId(value) {
38088
+ if (!isNSDelegateClosureValue(value)) return null;
38089
+ const instructions = value.action.instructions;
38090
+ if (instructions.length !== 1) return null;
38091
+ const instruction = instructions[0];
38092
+ if (instruction?.type !== "return" /* return */ || instruction.pointer?.type !== "reference" /* reference */) {
38093
+ return null;
38094
+ }
38095
+ return instruction.pointer.valueId;
38096
+ }
38097
+ function isMemberDelegateBase(value) {
38098
+ const v = asMemberBaseForKind(value, 25 /* NSDelegate */);
38099
+ if (v === null) return false;
38100
+ if (!isNSFunctionReturnTypeInfo(v.returnTypeInfo)) return false;
38101
+ if (!Array.isArray(v.argumentTypes) || v.argumentTypes.length > 16) {
38102
+ return false;
38103
+ }
38104
+ const names = /* @__PURE__ */ new Set();
38105
+ for (const argument2 of v.argumentTypes) {
38106
+ if (!isNSFunctionArgumentTypeInfo(argument2)) return false;
38107
+ if (!isValidCallableIdentifier(argument2.name)) return false;
38108
+ if (argument2.type === NS_TYPE_UNKNOWN) return false;
38109
+ if (names.has(argument2.name)) return false;
38110
+ names.add(argument2.name);
38111
+ }
38112
+ const defaultValue = v.defaultValue;
38113
+ if (defaultValue === void 0 || defaultValue === null) return true;
38114
+ if (!isMemberValueBase(defaultValue)) return false;
38115
+ if (isInitValueContent(defaultValue)) return true;
38116
+ return isNSDelegateValue(defaultValue.value);
38117
+ }
37549
38118
  function isFunctionRefValue(value) {
37550
38119
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
37551
38120
  const record3 = value;
@@ -37608,7 +38177,7 @@ function isMemberBase(value) {
37608
38177
  if (partial !== void 0 && v?.kind !== 7 /* Class */ && v?.kind !== 21 /* Generic */) {
37609
38178
  return false;
37610
38179
  }
37611
- const matchesConcreteType = isMemberNullBase(value) || isMemberBoolBase(value) || isMemberIntBase(value) || isMemberStringBase(value) || isMemberFloatBase(value) || isMemberDictionaryBase(value) || isMemberListBase(value) || isMemberClassBase(value) || isMemberEnumBase(value) || isMemberLookupBase(value) || isMemberDialogueLookupBase(value) || isMemberNSPropertyBase(value) || isMemberNSPropertyContractBase(value) || isMemberSpriteBase(value) || isMemberAudioBase(value) || isMemberFunctionBase(value) || isMemberNSFunctionBase(value) || isMemberNSFunction(value) || isMemberFunctionRefBase(value) || isMemberVector2Base(value) || isMemberVector2IntBase(value) || isMemberVector3Base(value) || isMemberVector3IntBase(value) || isMemberColorBase(value) || isMemberDecimalBase(value) || isMemberGenericBase(value);
38180
+ const matchesConcreteType = isMemberNullBase(value) || isMemberBoolBase(value) || isMemberIntBase(value) || isMemberStringBase(value) || isMemberFloatBase(value) || isMemberDictionaryBase(value) || isMemberListBase(value) || isMemberClassBase(value) || isMemberEnumBase(value) || isMemberLookupBase(value) || isMemberDialogueLookupBase(value) || isMemberNSPropertyBase(value) || isMemberNSPropertyContractBase(value) || isMemberSpriteBase(value) || isMemberAudioBase(value) || isMemberFunctionBase(value) || isMemberNSFunctionBase(value) || isMemberNSFunction(value) || isMemberDelegateBase(value) || isMemberFunctionRefBase(value) || isMemberVector2Base(value) || isMemberVector2IntBase(value) || isMemberVector3Base(value) || isMemberVector3IntBase(value) || isMemberColorBase(value) || isMemberDecimalBase(value) || isMemberGenericBase(value);
37612
38181
  if (!matchesConcreteType) return false;
37613
38182
  if (!isValidDocsText(v?.docsText)) return false;
37614
38183
  if (typeof v?.name !== "string") return false;
@@ -38069,7 +38638,7 @@ var init_inheritance = __esm({
38069
38638
  });
38070
38639
 
38071
38640
  // ../src/models/classes/world-system-classes.generated.ts
38072
- var WORLD_GRID_CHILDREN_MEMBER_ID, WORLD_GRID_CHILDREN_ENTRY_MEMBER_ID, WORLD_OBJECT_CHILDREN_MEMBER_ID, WORLD_OBJECT_CHILDREN_ENTRY_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILES_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILES_ENTRY_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILE_CELL_MEMBER_ID, WORLD_TILE_INSTANCE_CELL_MEMBER_ID, WORLD_TILE_LAYER_LINK_TILES_MEMBER_ID, WORLD_TILE_LAYER_LINK_TILE_ENTRY_MEMBER_ID, WORLD_OBJECT_LAYER_LINK_OBJECTS_MEMBER_ID, WORLD_OBJECT_LAYER_LINK_OBJECT_ENTRY_MEMBER_ID, WORLD_ANIMATION_CLIP_TARGET_PARAM_ID, WORLD_ANIMATION_CHILD_OVERRIDE_ENTRY_PARAM_ID, WORLD_ANIMATION_CLIP_FPS_MEMBER_ID, WORLD_ANIMATION_CLIP_DURATION_MEMBER_ID, WORLD_ANIMATION_CLIP_FRAMES_MEMBER_ID, WORLD_ANIMATION_CLIP_TRACKS_MEMBER_ID, WORLD_ANIMATION_FRAME_BASE_INDEX_MEMBER_ID, WORLD_ANIMATION_FRAME_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_ENTRY_MEMBER_ID, WORLD_ANIMATION_FRAME_ACTIONS_MEMBER_ID, WORLD_ANIMATION_CHILD_OVERRIDE_CHILD_MEMBER_ID, WORLD_ANIMATION_CHILD_OVERRIDE_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_TRACK_CHILD_MEMBER_ID, WORLD_ANIMATION_TRACK_START_FRAME_MEMBER_ID, WORLD_ANIMATION_TRACK_DIRECTION_MEMBER_ID, WORLD_ANIMATION_TRACK_OFFSET_START_INDEX_MEMBER_ID, WORLD_ANIMATION_TRACK_OFFSET_END_INDEX_MEMBER_ID, WORLD_ANIMATION_CHILD_TRACK_CLIP_KEY_MEMBER_ID, WORLD_ANIMATION_SEGMENT_DURATION_MEMBER_ID, WORLD_ANIMATION_SEGMENT_FRAMES_MEMBER_ID, WORLD_ANIMATION_SEGMENT_TRACK_CHILD_PARAM_ID, WORLD_ANIMATION_SEGMENT_TRACK_VALUE_PARAM_ID, WORLD_PLAY_DIRECTION_FORWARD_OPTION_ID, WORLD_PLAY_DIRECTION_REVERSE_OPTION_ID, WORLD_SYSTEM_CLASS_DEFINITIONS;
38641
+ var WORLD_GRID_CHILDREN_MEMBER_ID, WORLD_GRID_CHILDREN_ENTRY_MEMBER_ID, WORLD_OBJECT_CHILDREN_MEMBER_ID, WORLD_OBJECT_CHILDREN_ENTRY_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILES_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILES_ENTRY_MEMBER_ID, WORLD_OBJECT_PLACEMENT_TILE_CELL_MEMBER_ID, WORLD_TILE_INSTANCE_CELL_MEMBER_ID, WORLD_TILE_LAYER_LINK_TILES_MEMBER_ID, WORLD_TILE_LAYER_LINK_TILE_ENTRY_MEMBER_ID, WORLD_OBJECT_LAYER_LINK_OBJECTS_MEMBER_ID, WORLD_OBJECT_LAYER_LINK_OBJECT_ENTRY_MEMBER_ID, WORLD_ANIMATION_CLIP_TARGET_PARAM_ID, WORLD_ANIMATION_CHILD_OVERRIDE_ENTRY_PARAM_ID, WORLD_ANIMATION_CLIP_FPS_MEMBER_ID, WORLD_ANIMATION_CLIP_DURATION_MEMBER_ID, WORLD_ANIMATION_CLIP_FRAMES_MEMBER_ID, WORLD_ANIMATION_CLIP_TRACKS_MEMBER_ID, WORLD_ANIMATION_FRAME_BASE_INDEX_MEMBER_ID, WORLD_ANIMATION_FRAME_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_ENTRY_MEMBER_ID, WORLD_ANIMATION_FRAME_ACTIONS_MEMBER_ID, WORLD_ANIMATION_CHILD_OVERRIDE_SELECTOR_MEMBER_ID, WORLD_ANIMATION_CHILD_OVERRIDE_REFRESH_MEMBER_ID, WORLD_ANIMATION_CHILD_OVERRIDE_OVERRIDES_MEMBER_ID, WORLD_ANIMATION_TRACK_SELECTOR_MEMBER_ID, WORLD_ANIMATION_TRACK_REFRESH_MEMBER_ID, WORLD_ANIMATION_TRACK_START_FRAME_MEMBER_ID, WORLD_ANIMATION_TRACK_DIRECTION_MEMBER_ID, WORLD_ANIMATION_TRACK_OFFSET_START_INDEX_MEMBER_ID, WORLD_ANIMATION_TRACK_OFFSET_END_INDEX_MEMBER_ID, WORLD_ANIMATION_CHILD_TRACK_CLIP_KEY_MEMBER_ID, WORLD_ANIMATION_SEGMENT_DURATION_MEMBER_ID, WORLD_ANIMATION_SEGMENT_FRAMES_MEMBER_ID, WORLD_ANIMATION_SEGMENT_TRACK_CHILD_PARAM_ID, WORLD_ANIMATION_SEGMENT_TRACK_VALUE_PARAM_ID, WORLD_SELECTOR_REFRESH_ON_LOAD_OPTION_ID, WORLD_SELECTOR_REFRESH_PER_FRAME_OPTION_ID, WORLD_PLAY_DIRECTION_FORWARD_OPTION_ID, WORLD_PLAY_DIRECTION_REVERSE_OPTION_ID, WORLD_SYSTEM_CLASS_DEFINITIONS;
38073
38642
  var init_world_system_classes_generated = __esm({
38074
38643
  "../src/models/classes/world-system-classes.generated.ts"() {
38075
38644
  "use strict";
@@ -38096,9 +38665,11 @@ var init_world_system_classes_generated = __esm({
38096
38665
  WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_MEMBER_ID = "system_a5905750-c472-46a8-89e9-f04f0bf66696";
38097
38666
  WORLD_ANIMATION_FRAME_CHILD_OVERRIDES_ENTRY_MEMBER_ID = "system_86688965-6b26-529e-95f3-a4070f022582";
38098
38667
  WORLD_ANIMATION_FRAME_ACTIONS_MEMBER_ID = "system_23e05410-6428-4bd1-b085-c0390ed7fcb7";
38099
- WORLD_ANIMATION_CHILD_OVERRIDE_CHILD_MEMBER_ID = "system_6e15db41-a6f2-43fd-9793-c52fe4f3d0f8";
38668
+ WORLD_ANIMATION_CHILD_OVERRIDE_SELECTOR_MEMBER_ID = "system_48e66117-43fe-4429-97a8-964165f063ea";
38669
+ WORLD_ANIMATION_CHILD_OVERRIDE_REFRESH_MEMBER_ID = "system_ba319c4b-3419-4301-a0d6-8bc5a89e20d1";
38100
38670
  WORLD_ANIMATION_CHILD_OVERRIDE_OVERRIDES_MEMBER_ID = "system_819b3743-0c3d-4896-b679-9aeeb73255f4";
38101
- WORLD_ANIMATION_TRACK_CHILD_MEMBER_ID = "system_29abc85e-2d38-4cef-a200-88915d176d06";
38671
+ WORLD_ANIMATION_TRACK_SELECTOR_MEMBER_ID = "system_1e877396-1802-474a-9e4d-1df478d4c888";
38672
+ WORLD_ANIMATION_TRACK_REFRESH_MEMBER_ID = "system_330602f7-bbc0-4be4-9dc3-d33e9dbdbab9";
38102
38673
  WORLD_ANIMATION_TRACK_START_FRAME_MEMBER_ID = "system_5af60692-74a0-45ea-a9ba-747854989b2a";
38103
38674
  WORLD_ANIMATION_TRACK_DIRECTION_MEMBER_ID = "system_75a314b5-c799-4af6-9e64-4cde6eae1b30";
38104
38675
  WORLD_ANIMATION_TRACK_OFFSET_START_INDEX_MEMBER_ID = "system_c71caaab-df72-48c6-a291-2772288351eb";
@@ -38108,6 +38679,8 @@ var init_world_system_classes_generated = __esm({
38108
38679
  WORLD_ANIMATION_SEGMENT_FRAMES_MEMBER_ID = "system_40658ad2-b4a5-4404-bb6d-ed778088a772";
38109
38680
  WORLD_ANIMATION_SEGMENT_TRACK_CHILD_PARAM_ID = "system_d4fe9f71-d9d9-4baf-bc52-8de16933b655";
38110
38681
  WORLD_ANIMATION_SEGMENT_TRACK_VALUE_PARAM_ID = "system_03497842-3381-45a2-b2fa-b2dee36c2759";
38682
+ WORLD_SELECTOR_REFRESH_ON_LOAD_OPTION_ID = "system_88c5d17a-b73e-47a1-a96e-4ebe16e6d200";
38683
+ WORLD_SELECTOR_REFRESH_PER_FRAME_OPTION_ID = "system_dc350ac4-de4b-4d1c-9b46-097dc5b4180f";
38111
38684
  WORLD_PLAY_DIRECTION_FORWARD_OPTION_ID = "system_2e4ca40e-f305-49c6-a91b-b99d56239ba0";
38112
38685
  WORLD_PLAY_DIRECTION_REVERSE_OPTION_ID = "system_6478d195-3905-48db-befe-d276eb5478f0";
38113
38686
  WORLD_SYSTEM_CLASS_DEFINITIONS = [
@@ -38944,8 +39517,12 @@ var init_world_system_classes_generated = __esm({
38944
39517
  isAbstract: false,
38945
39518
  constructorProjections: [
38946
39519
  {
38947
- memberId: "system_6e15db41-a6f2-43fd-9793-c52fe4f3d0f8",
38948
- parameterName: "id"
39520
+ memberId: "system_48e66117-43fe-4429-97a8-964165f063ea",
39521
+ parameterName: "selector"
39522
+ },
39523
+ {
39524
+ memberId: "system_819b3743-0c3d-4896-b679-9aeeb73255f4",
39525
+ parameterName: "overrides"
38949
39526
  }
38950
39527
  ],
38951
39528
  genericParams: [
@@ -38957,13 +39534,26 @@ var init_world_system_classes_generated = __esm({
38957
39534
  ],
38958
39535
  schemaFields: [
38959
39536
  {
38960
- memberId: "system_6e15db41-a6f2-43fd-9793-c52fe4f3d0f8",
38961
- memberKind: "lookup",
38962
- collectionMemberId: "system_bb5d2cf1-a0dd-4eba-a62e-0e1bf0177071",
38963
- collectionValueId: null,
39537
+ memberId: "system_48e66117-43fe-4429-97a8-964165f063ea",
39538
+ memberKind: "delegate",
39539
+ returnTypeInfo: {
39540
+ type: 21,
39541
+ required: true,
39542
+ ownerClassId: "system_e2e88eba-5335-4a16-9dcf-2c0e1951e8bd",
39543
+ genericParamId: "system_de23448a-45be-4e3f-8965-072a545e08f0"
39544
+ },
39545
+ argumentTypes: [],
39546
+ required: true,
39547
+ schemaKey: "Selector"
39548
+ },
39549
+ {
39550
+ memberId: "system_ba319c4b-3419-4301-a0d6-8bc5a89e20d1",
39551
+ memberKind: "enum",
39552
+ defaultValue: ["system_88c5d17a-b73e-47a1-a96e-4ebe16e6d200"],
39553
+ enumId: "system_fb8a4243-fa52-4142-8097-765d9e86ff25",
38964
39554
  multiselect: false,
38965
39555
  required: true,
38966
- schemaKey: "Child"
39556
+ schemaKey: "Refresh"
38967
39557
  },
38968
39558
  {
38969
39559
  memberId: "system_819b3743-0c3d-4896-b679-9aeeb73255f4",
@@ -38981,15 +39571,33 @@ var init_world_system_classes_generated = __esm({
38981
39571
  name: "NeoAnimationTrackBase",
38982
39572
  docsText: "A lane on a clip's timeline: which child it plays against, when it starts,\nwhich way it runs, and which slice of the content to use. Both kinds of\ntrack derive from this, so playing a child clip reversed or cropped is\nsomething you author on the lane rather than pass in when you play it.",
38983
39573
  isAbstract: true,
39574
+ constructorProjections: [
39575
+ {
39576
+ memberId: "system_1e877396-1802-474a-9e4d-1df478d4c888",
39577
+ parameterName: "selector"
39578
+ }
39579
+ ],
38984
39580
  schemaFields: [
38985
39581
  {
38986
- memberId: "system_29abc85e-2d38-4cef-a200-88915d176d06",
38987
- memberKind: "lookup",
38988
- collectionMemberId: "system_bb5d2cf1-a0dd-4eba-a62e-0e1bf0177071",
38989
- collectionValueId: null,
39582
+ memberId: "system_1e877396-1802-474a-9e4d-1df478d4c888",
39583
+ memberKind: "delegate",
39584
+ returnTypeInfo: {
39585
+ type: 7,
39586
+ required: true,
39587
+ classId: "system_61b30a92-90dc-4bf8-8503-ee4f6414effc"
39588
+ },
39589
+ argumentTypes: [],
39590
+ required: true,
39591
+ schemaKey: "Selector"
39592
+ },
39593
+ {
39594
+ memberId: "system_330602f7-bbc0-4be4-9dc3-d33e9dbdbab9",
39595
+ memberKind: "enum",
39596
+ defaultValue: ["system_88c5d17a-b73e-47a1-a96e-4ebe16e6d200"],
39597
+ enumId: "system_fb8a4243-fa52-4142-8097-765d9e86ff25",
38990
39598
  multiselect: false,
38991
39599
  required: true,
38992
- schemaKey: "Child"
39600
+ schemaKey: "Refresh"
38993
39601
  },
38994
39602
  {
38995
39603
  memberId: "system_5af60692-74a0-45ea-a9ba-747854989b2a",
@@ -39048,8 +39656,12 @@ var init_world_system_classes_generated = __esm({
39048
39656
  isAbstract: false,
39049
39657
  constructorProjections: [
39050
39658
  {
39051
- memberId: "system_29abc85e-2d38-4cef-a200-88915d176d06",
39052
- parameterName: "id"
39659
+ memberId: "system_1e877396-1802-474a-9e4d-1df478d4c888",
39660
+ parameterName: "selector"
39661
+ },
39662
+ {
39663
+ memberId: "system_2c816624-0281-46d3-9ed5-d20bd43519f4",
39664
+ parameterName: "clipKey"
39053
39665
  }
39054
39666
  ],
39055
39667
  schemaFields: [
@@ -39071,8 +39683,8 @@ var init_world_system_classes_generated = __esm({
39071
39683
  isAbstract: true,
39072
39684
  constructorProjections: [
39073
39685
  {
39074
- memberId: "system_87900a74-0d7c-4dfc-a6f6-3bd204ebb8f6",
39075
- parameterName: "id"
39686
+ memberId: "system_b29e7ab9-0b8e-4399-84c1-1203070b75dd",
39687
+ parameterName: "selector"
39076
39688
  }
39077
39689
  ],
39078
39690
  genericParams: [
@@ -39085,21 +39697,19 @@ var init_world_system_classes_generated = __esm({
39085
39697
  ],
39086
39698
  schemaFields: [
39087
39699
  {
39088
- memberId: "system_87900a74-0d7c-4dfc-a6f6-3bd204ebb8f6",
39089
- memberKind: "lookup",
39090
- extendsMemberId: "system_29abc85e-2d38-4cef-a200-88915d176d06",
39700
+ memberId: "system_b29e7ab9-0b8e-4399-84c1-1203070b75dd",
39701
+ memberKind: "delegate",
39702
+ extendsMemberId: "system_1e877396-1802-474a-9e4d-1df478d4c888",
39091
39703
  docsText: "The child this lane plays against, typed as the child class you derived with, so a Segment getter can read that child's own members.",
39092
- collectionMemberId: "system_bb5d2cf1-a0dd-4eba-a62e-0e1bf0177071",
39093
- collectionValueId: null,
39094
- multiselect: false,
39095
- declaredTypeInfo: {
39704
+ returnTypeInfo: {
39096
39705
  type: 21,
39097
39706
  required: true,
39098
39707
  ownerClassId: "system_fd551dd8-6e6b-4044-9f32-7445ab344200",
39099
39708
  genericParamId: "system_d4fe9f71-d9d9-4baf-bc52-8de16933b655"
39100
39709
  },
39710
+ argumentTypes: [],
39101
39711
  required: true,
39102
- schemaKey: "Child"
39712
+ schemaKey: "Selector"
39103
39713
  },
39104
39714
  {
39105
39715
  memberId: "system_d2d0bf9b-211f-4b2f-bff3-3d6da5766abd",
@@ -39748,6 +40358,7 @@ var init_generics = __esm({
39748
40358
  13 /* Function */,
39749
40359
  23 /* NSFunction */,
39750
40360
  24 /* FunctionRef */,
40361
+ 25 /* NSDelegate */,
39751
40362
  21 /* Generic */
39752
40363
  ]);
39753
40364
  }
@@ -41950,6 +42561,13 @@ function primitiveFallbackValue(document, member) {
41950
42561
  if (isMemberAudioBase(member)) {
41951
42562
  return { value: pendingAudioValue() };
41952
42563
  }
42564
+ if (member.kind === 25 /* NSDelegate */) {
42565
+ return {
42566
+ value: {
42567
+ code: '() => { throw "Not implemented exception"; }'
42568
+ }
42569
+ };
42570
+ }
41953
42571
  if (member.kind === 21 /* Generic */) {
41954
42572
  throw new Error(
41955
42573
  `Unreachable: Generic member "${member.name}" must be substituted through its binding environment before default value construction \u2014 a substitution site was skipped upstream (https://github.com/ryanbliss/neo-compose-specs/tree/main/new-features/complete/class-generics.md \xA74.1).`
@@ -43532,6 +44150,23 @@ function lowerFieldMember(context, ownerClass, declaration, id2, commonInput, ba
43532
44150
  }
43533
44151
  return { ...common, kind: "functionRef" };
43534
44152
  }
44153
+ if (name === "NeoDelegate") {
44154
+ if (partial) {
44155
+ throw new Error("Partial<T> requires a Class or Class generic target.");
44156
+ }
44157
+ const returnType = requiredTypeArgument(fieldType, 0);
44158
+ return {
44159
+ ...common,
44160
+ kind: "delegate",
44161
+ returnType: returnType.name === "void" ? { kind: "void", nullable: false } : lowerType(context, returnType, ownerClass),
44162
+ arguments: fieldType.arguments.slice(1).map((argumentType, index) => ({
44163
+ name: `p${index + 1}`,
44164
+ type: lowerType(context, argumentType, ownerClass),
44165
+ source: span(declaration),
44166
+ selectionSpan: span(declaration)
44167
+ }))
44168
+ };
44169
+ }
43535
44170
  if (name === "bool" || name === "null") {
43536
44171
  return { ...common, kind: name };
43537
44172
  }
@@ -44103,6 +44738,18 @@ function lowerType(context, type, ownerClass) {
44103
44738
  readOnly: false
44104
44739
  };
44105
44740
  }
44741
+ if (type.name === "Partial") {
44742
+ return lowerType(context, requiredTypeArgument(type, 0), ownerClass);
44743
+ }
44744
+ if (type.name === "NeoDelegate") {
44745
+ const returnType = requiredTypeArgument(type, 0);
44746
+ return {
44747
+ kind: "delegate",
44748
+ nullable,
44749
+ returnType: returnType.name === "void" ? { kind: "void", nullable: false } : lowerType(context, returnType, ownerClass),
44750
+ argumentTypes: type.arguments.slice(1).map((argument2) => lowerType(context, argument2, ownerClass))
44751
+ };
44752
+ }
44106
44753
  const classId = context.classIdsByName.get(type.name);
44107
44754
  if (classId) {
44108
44755
  const parameters = context.genericParametersByClass.get(classId);
@@ -44146,7 +44793,7 @@ function lowerDefault(context, initializer, type, ownerClass, base, memberId, st
44146
44793
  return base?.defaultValue && "serverValueId" in base.defaultValue ? base.defaultValue : null;
44147
44794
  }
44148
44795
  const expression = parseExpression(initializer);
44149
- if (initializerRequiresEvaluation(
44796
+ if (!isStoredDelegateLiteral(type, expression) && initializerRequiresEvaluation(
44150
44797
  context.declaredConstructors,
44151
44798
  expression,
44152
44799
  type.name,
@@ -44160,7 +44807,15 @@ function lowerDefault(context, initializer, type, ownerClass, base, memberId, st
44160
44807
  if (context.rowBackedDefaultMemberIds.has(memberId) && base?.defaultValue && !("serverValueId" in base.defaultValue)) {
44161
44808
  return base.defaultValue;
44162
44809
  }
44163
- let value = lowerExpressionValue(context, expression, type, ownerClass, path);
44810
+ let value = lowerExpressionValue(
44811
+ context,
44812
+ expression,
44813
+ type,
44814
+ ownerClass,
44815
+ path,
44816
+ EMPTY_GENERIC_TYPE_ENVIRONMENT,
44817
+ initializer
44818
+ );
44164
44819
  if (value !== null && storesSelectionArray && !Array.isArray(value)) {
44165
44820
  value = [value];
44166
44821
  }
@@ -44207,12 +44862,12 @@ function manifestTypeFromAstType(type) {
44207
44862
  arguments: (type.typeArguments ?? []).map(manifestTypeFromAstType)
44208
44863
  };
44209
44864
  }
44210
- function lowerExpressionValue(context, expression, declaredExpected, ownerClass, path, genericEnvironment = EMPTY_GENERIC_TYPE_ENVIRONMENT) {
44865
+ function lowerExpressionValue(context, expression, declaredExpected, ownerClass, path, genericEnvironment = EMPTY_GENERIC_TYPE_ENVIRONMENT, sourceText) {
44211
44866
  const expected = substituteGenericTypeNames(
44212
44867
  declaredExpected,
44213
44868
  genericEnvironment
44214
44869
  );
44215
- if (initializerRequiresEvaluation(
44870
+ if (!isStoredDelegateLiteral(expected, expression) && initializerRequiresEvaluation(
44216
44871
  context.declaredConstructors,
44217
44872
  expression,
44218
44873
  expected.name,
@@ -44230,7 +44885,8 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44230
44885
  expected,
44231
44886
  ownerClass,
44232
44887
  path,
44233
- genericEnvironment
44888
+ genericEnvironment,
44889
+ sourceText
44234
44890
  );
44235
44891
  }
44236
44892
  switch (expression.kind) {
@@ -44255,7 +44911,8 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44255
44911
  expected,
44256
44912
  ownerClass,
44257
44913
  path,
44258
- genericEnvironment
44914
+ genericEnvironment,
44915
+ sourceText
44259
44916
  );
44260
44917
  if (typeof operand === "number") return -operand;
44261
44918
  if (expected.name === "decimal" && typeof operand === "string") {
@@ -44285,7 +44942,8 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44285
44942
  entry,
44286
44943
  ownerClass,
44287
44944
  `${path}[${index}]`,
44288
- genericEnvironment
44945
+ genericEnvironment,
44946
+ sourceText
44289
44947
  )
44290
44948
  );
44291
44949
  }
@@ -44299,7 +44957,8 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44299
44957
  { name: "string", nullable: false, arguments: [] },
44300
44958
  ownerClass,
44301
44959
  path,
44302
- genericEnvironment
44960
+ genericEnvironment,
44961
+ sourceText
44303
44962
  );
44304
44963
  if (typeof key !== "string")
44305
44964
  throw new Error("Dictionary keys must be strings.");
@@ -44309,7 +44968,8 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44309
44968
  valueType,
44310
44969
  ownerClass,
44311
44970
  `${path}[${JSON.stringify(key)}]`,
44312
- genericEnvironment
44971
+ genericEnvironment,
44972
+ sourceText
44313
44973
  );
44314
44974
  }
44315
44975
  return value;
@@ -44378,11 +45038,24 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44378
45038
  structuredLeafAssignmentType(partialExpected, declaredType),
44379
45039
  ownerClass,
44380
45040
  `${path}.${assignment.name}`,
44381
- innerEnvironment
45041
+ innerEnvironment,
45042
+ sourceText
44382
45043
  );
44383
45044
  }
44384
45045
  return result;
44385
45046
  }
45047
+ case "lambda": {
45048
+ if (expected.name !== "NeoDelegate") {
45049
+ throw new Error(
45050
+ `A lambda at ${path} requires a NeoDelegate expected type.`
45051
+ );
45052
+ }
45053
+ const code = sourceText === void 0 ? null : lambdaExpressionSource(sourceText, expression.pos);
45054
+ if (code === null || code.length === 0) {
45055
+ throw new Error(`Delegate value ${path} has no recoverable source.`);
45056
+ }
45057
+ return { code: normalizeInitializerSource(code) };
45058
+ }
44386
45059
  case "call": {
44387
45060
  if (expression.callee.kind === "ident" && expression.callee.name === "Reference") {
44388
45061
  const index = expression.argumentNames?.findIndex((name) => name === "id") ?? -1;
@@ -44452,6 +45125,56 @@ function lowerExpressionValue(context, expression, declaredExpected, ownerClass,
44452
45125
  );
44453
45126
  }
44454
45127
  }
45128
+ function isStoredDelegateLiteral(type, expression) {
45129
+ if (type.name !== "NeoDelegate") return false;
45130
+ let current = expression;
45131
+ while (current.kind === "annotated") current = current.expression;
45132
+ return current.kind === "lambda";
45133
+ }
45134
+ function lambdaExpressionSource(source, pos) {
45135
+ let start = 0;
45136
+ for (let line = 1; line < pos.line; line += 1) {
45137
+ const next = source.indexOf("\n", start);
45138
+ if (next < 0) return null;
45139
+ start = next + 1;
45140
+ }
45141
+ start = Math.min(start + pos.column - 1, source.length);
45142
+ const arrow = source.indexOf("=>", start);
45143
+ if (arrow < 0) return null;
45144
+ const bodyStart = source.indexOf("{", arrow + 2);
45145
+ if (bodyStart < 0) return null;
45146
+ let depth = 0;
45147
+ let quote6 = null;
45148
+ let escaped = false;
45149
+ for (let index = bodyStart; index < source.length; index += 1) {
45150
+ const character = source[index];
45151
+ if (quote6 !== null) {
45152
+ if (escaped) escaped = false;
45153
+ else if (character === "\\") escaped = true;
45154
+ else if (character === quote6) quote6 = null;
45155
+ continue;
45156
+ }
45157
+ if (character === '"' || character === "'") {
45158
+ quote6 = character;
45159
+ continue;
45160
+ }
45161
+ if (character === "/" && source[index + 1] === "/") {
45162
+ const newline = source.indexOf("\n", index + 2);
45163
+ index = newline < 0 ? source.length : newline;
45164
+ continue;
45165
+ }
45166
+ if (character === "/" && source[index + 1] === "*") {
45167
+ const close = source.indexOf("*/", index + 2);
45168
+ index = close < 0 ? source.length : close + 1;
45169
+ continue;
45170
+ }
45171
+ if (character === "{") depth += 1;
45172
+ if (character !== "}") continue;
45173
+ depth -= 1;
45174
+ if (depth === 0) return source.slice(start, index + 1).trim();
45175
+ }
45176
+ return null;
45177
+ }
44455
45178
  function lowerStructuredLeafDefault(context, kind, expression, expectedType, ownerClass, partialExpected, path) {
44456
45179
  const label = `${structuredLeafLabel(kind, path)} default`;
44457
45180
  const partial = structuredLeafPartialLiteral(expression);
@@ -44578,6 +45301,18 @@ function manifestTypeForMember(context, member) {
44578
45301
  if (member.kind === "functionRef") {
44579
45302
  return { name: "FunctionRef", nullable, arguments: [] };
44580
45303
  }
45304
+ if (member.kind === "delegate") {
45305
+ return {
45306
+ name: "NeoDelegate",
45307
+ nullable,
45308
+ arguments: [
45309
+ member.returnType.kind === "void" ? { name: "void", nullable: false, arguments: [] } : manifestTypeForSchemaType(context, member.returnType),
45310
+ ...member.arguments.map(
45311
+ (argument2) => manifestTypeForSchemaType(context, argument2.type)
45312
+ )
45313
+ ]
45314
+ };
45315
+ }
44581
45316
  if (member.kind === "enum") {
44582
45317
  return {
44583
45318
  name: context.baseEnums.get(member.enumId)?.name ?? "object",
@@ -44587,6 +45322,99 @@ function manifestTypeForMember(context, member) {
44587
45322
  }
44588
45323
  return { name: "object", nullable, arguments: [] };
44589
45324
  }
45325
+ function manifestTypeForSchemaType(context, type) {
45326
+ const nullable = type.nullable;
45327
+ switch (type.kind) {
45328
+ case "unknown":
45329
+ return { name: "object", nullable, arguments: [] };
45330
+ case "null":
45331
+ case "bool":
45332
+ case "int":
45333
+ case "string":
45334
+ case "float":
45335
+ case "decimal":
45336
+ return { name: type.kind, nullable, arguments: [] };
45337
+ case "sprite":
45338
+ return { name: "SpriteInfo", nullable, arguments: [] };
45339
+ case "audio":
45340
+ return { name: "AudioClipInfo", nullable, arguments: [] };
45341
+ case "vector2":
45342
+ return { name: "Vector2", nullable, arguments: [] };
45343
+ case "vector2Int":
45344
+ return { name: "Vector2Int", nullable, arguments: [] };
45345
+ case "vector3":
45346
+ return { name: "Vector3", nullable, arguments: [] };
45347
+ case "vector3Int":
45348
+ return { name: "Vector3Int", nullable, arguments: [] };
45349
+ case "dialogueLookup":
45350
+ return { name: "Dialogue", nullable, arguments: [] };
45351
+ case "color":
45352
+ return { name: "Color", nullable, arguments: [] };
45353
+ case "class": {
45354
+ const schemaClass2 = context.baseClasses.get(type.classId);
45355
+ return {
45356
+ name: schemaClass2?.name ?? "object",
45357
+ nullable,
45358
+ arguments: schemaClass2?.genericParameters.map((parameter3) => type.classArguments[parameter3.id]).filter(
45359
+ (argument2) => argument2 !== void 0
45360
+ ).map((argument2) => manifestTypeForSchemaType(context, argument2)) ?? []
45361
+ };
45362
+ }
45363
+ case "interface":
45364
+ return {
45365
+ name: context.baseInterfaces.get(type.interfaceId)?.name ?? "object",
45366
+ nullable,
45367
+ arguments: []
45368
+ };
45369
+ case "generic":
45370
+ return {
45371
+ name: genericParameterName(context, type.genericParamId),
45372
+ nullable,
45373
+ arguments: []
45374
+ };
45375
+ case "enum":
45376
+ return {
45377
+ name: context.baseEnums.get(type.enumId)?.name ?? "object",
45378
+ nullable,
45379
+ arguments: []
45380
+ };
45381
+ case "list":
45382
+ return {
45383
+ name: "List",
45384
+ nullable,
45385
+ arguments: [manifestTypeForSchemaType(context, type.entryType)]
45386
+ };
45387
+ case "dictionary":
45388
+ return {
45389
+ name: "Dictionary",
45390
+ nullable,
45391
+ arguments: [
45392
+ type.keyEnumId === null ? { name: "string", nullable: false, arguments: [] } : {
45393
+ name: context.baseEnums.get(type.keyEnumId)?.name ?? "object",
45394
+ nullable: false,
45395
+ arguments: []
45396
+ },
45397
+ manifestTypeForSchemaType(context, type.entryType)
45398
+ ]
45399
+ };
45400
+ case "lookup":
45401
+ return manifestTypeForSchemaType(context, {
45402
+ ...type.entryType,
45403
+ nullable
45404
+ });
45405
+ case "delegate":
45406
+ return {
45407
+ name: "NeoDelegate",
45408
+ nullable,
45409
+ arguments: [
45410
+ type.returnType.kind === "void" ? { name: "void", nullable: false, arguments: [] } : manifestTypeForSchemaType(context, type.returnType),
45411
+ ...type.argumentTypes.map(
45412
+ (argument2) => manifestTypeForSchemaType(context, argument2)
45413
+ )
45414
+ ]
45415
+ };
45416
+ }
45417
+ }
44590
45418
  function genericParameterName(context, genericParamId) {
44591
45419
  for (const parameters of context.genericParametersByClass.values()) {
44592
45420
  for (const [name, id2] of parameters) {
@@ -46458,6 +47286,14 @@ function renderMemberType(context, member, enclosingClassId) {
46458
47286
  case "functionRef":
46459
47287
  value = "FunctionRef";
46460
47288
  break;
47289
+ case "delegate":
47290
+ value = `NeoDelegate<${[
47291
+ renderReturnType(context, member.returnType),
47292
+ ...member.arguments.map(
47293
+ (argument2) => renderType(context, argument2.type)
47294
+ )
47295
+ ].join(", ")}>`;
47296
+ break;
46461
47297
  }
46462
47298
  if ((member.kind === "class" || member.kind === "generic") && member.partial === true) {
46463
47299
  value = `Partial<${value}>`;
@@ -46545,6 +47381,12 @@ function renderType(context, type) {
46545
47381
  case "lookup":
46546
47382
  value = renderType(context, type.entryType);
46547
47383
  break;
47384
+ case "delegate":
47385
+ value = `NeoDelegate<${[
47386
+ renderReturnType(context, type.returnType),
47387
+ ...type.argumentTypes.map((argument2) => renderType(context, argument2))
47388
+ ].join(", ")}>`;
47389
+ break;
46548
47390
  }
46549
47391
  return type.nullable && value !== "null" ? `${value}?` : value;
46550
47392
  }
@@ -52238,6 +53080,16 @@ function objectInitializerSlices(authoredSlice) {
52238
53080
  }
52239
53081
  return assignments;
52240
53082
  }
53083
+ function constructorArgumentValueSlices(authoredSlice) {
53084
+ const expression = initializerExpressionSlice(authoredSlice);
53085
+ if (expression === void 0) return [];
53086
+ return topLevelEntrySlices(expression, "(", ")").map((entry) => {
53087
+ const separator = entry.indexOf(":");
53088
+ return normalizeInitializerSource(
53089
+ separator < 0 ? entry : entry.slice(separator + 1)
53090
+ );
53091
+ });
53092
+ }
52241
53093
  function initializerExpressionSlice(authoredSlice) {
52242
53094
  if (authoredSlice === void 0) return void 0;
52243
53095
  let text = normalizeInitializerSource(authoredSlice);
@@ -52327,7 +53179,8 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
52327
53179
  baseBody,
52328
53180
  body,
52329
53181
  binding,
52330
- environment
53182
+ environment,
53183
+ binding.initializer
52331
53184
  );
52332
53185
  for (const assignment of expression.initializer ?? []) {
52333
53186
  const childMember = classMemberByName(context, classId, assignment.name);
@@ -52601,7 +53454,7 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
52601
53454
  member,
52602
53455
  inheritedEnvironment
52603
53456
  );
52604
- if (initializerRequiresEvaluation(
53457
+ if (resolvedMember.kind !== "delegate" && initializerRequiresEvaluation(
52605
53458
  context.declaredConstructors,
52606
53459
  expression,
52607
53460
  memberClassName(context, resolvedMember),
@@ -52675,10 +53528,12 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
52675
53528
  path
52676
53529
  );
52677
53530
  const body = {};
53531
+ const argumentSlices = constructorArgumentValueSlices(authoredSlice);
52678
53532
  for (const {
52679
53533
  projectedMember,
52680
53534
  schemaKey,
52681
- target
53535
+ argument: argument2,
53536
+ argumentIndex
52682
53537
  } of resolveConstructorProjectionArguments(
52683
53538
  context,
52684
53539
  effectiveClass,
@@ -52692,18 +53547,39 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
52692
53547
  if (rows.has(childValueId)) {
52693
53548
  throw new Error(`Value construction reuses identity ${childValueId}.`);
52694
53549
  }
52695
- const projectionStamp = materializedRowStamp(
53550
+ if (projectedMember.kind === "lookup") {
53551
+ if (argument2.kind !== "litString") {
53552
+ throw new Error(
53553
+ `Class value ${path}.${schemaKey} requires a value-row id string literal.`
53554
+ );
53555
+ }
53556
+ const projectionStamp = materializedRowStamp(
53557
+ context,
53558
+ materializedChild(context, materialization, schemaKey)
53559
+ );
53560
+ rows.set(childValueId, {
53561
+ id: childValueId,
53562
+ memberId: projectedMember.id,
53563
+ value: [argument2.value],
53564
+ classId: null,
53565
+ ...projectionStamp === null ? {} : { sourceValueId: projectionStamp }
53566
+ });
53567
+ body[schemaKey] = childValueId;
53568
+ continue;
53569
+ }
53570
+ body[schemaKey] = lowerSeedChild(
52696
53571
  context,
52697
- materializedChild(context, materialization, schemaKey)
53572
+ projectedMember,
53573
+ argument2,
53574
+ source,
53575
+ childPath,
53576
+ rows,
53577
+ localizedTexts,
53578
+ void 0,
53579
+ environment,
53580
+ materializedChild(context, materialization, schemaKey),
53581
+ argumentSlices[argumentIndex]
52698
53582
  );
52699
- rows.set(childValueId, {
52700
- id: childValueId,
52701
- memberId: projectedMember.id,
52702
- value: [target.id],
52703
- classId: null,
52704
- ...projectionStamp === null ? {} : { sourceValueId: projectionStamp }
52705
- });
52706
- body[schemaKey] = childValueId;
52707
53583
  }
52708
53584
  for (const assignment of expression.initializer ?? []) {
52709
53585
  const childMember = classMemberByName(
@@ -52828,7 +53704,8 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
52828
53704
  expression,
52829
53705
  { id: valueId, value: null },
52830
53706
  source,
52831
- inheritedEnvironment
53707
+ inheritedEnvironment,
53708
+ authoredSlice
52832
53709
  );
52833
53710
  value = lowered.value;
52834
53711
  classId = typeof lowered.classId === "string" ? lowered.classId : null;
@@ -52985,7 +53862,7 @@ function lowerValueRow(context, member, sourceExpression, expectedValueId, sourc
52985
53862
  member,
52986
53863
  environment
52987
53864
  );
52988
- if (initializerRequiresEvaluation(
53865
+ if (resolvedMember.kind !== "delegate" && initializerRequiresEvaluation(
52989
53866
  context.declaredConstructors,
52990
53867
  expression,
52991
53868
  memberClassName(context, resolvedMember),
@@ -53075,6 +53952,16 @@ function lowerValueBody(context, member, expression, base, source, environment,
53075
53952
  ...next,
53076
53953
  value: lowerFunctionReference(context, expression, source.ownerClassId)
53077
53954
  };
53955
+ case "delegate":
53956
+ return {
53957
+ ...next,
53958
+ value: lowerDelegateValue(
53959
+ context,
53960
+ expression,
53961
+ source.ownerClassId,
53962
+ authoredSlice
53963
+ )
53964
+ };
53078
53965
  case "class":
53079
53966
  return lowerClassValue(
53080
53967
  context,
@@ -53156,7 +54043,8 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
53156
54043
  baseBody,
53157
54044
  body,
53158
54045
  source,
53159
- environment
54046
+ environment,
54047
+ authoredSlice
53160
54048
  );
53161
54049
  for (const assignment of expression.initializer ?? []) {
53162
54050
  const childMember = classMemberByName(context, classId, assignment.name);
@@ -53216,7 +54104,7 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
53216
54104
  ...classId === currentClassId ? {} : { classId }
53217
54105
  };
53218
54106
  }
53219
- function lowerConstructorProjections(context, schemaClass2, expression, base, baseBody, body, source, environment) {
54107
+ function lowerConstructorProjections(context, schemaClass2, expression, base, baseBody, body, source, environment, authoredSlice) {
53220
54108
  const resolved = resolveConstructorProjectionArguments(
53221
54109
  context,
53222
54110
  schemaClass2,
@@ -53225,20 +54113,44 @@ function lowerConstructorProjections(context, schemaClass2, expression, base, ba
53225
54113
  environment,
53226
54114
  source
53227
54115
  );
53228
- for (const { schemaKey, target } of resolved) {
54116
+ const argumentSlices = constructorArgumentValueSlices(authoredSlice);
54117
+ for (const {
54118
+ schemaKey,
54119
+ projectedMember,
54120
+ argument: argument2,
54121
+ argumentIndex
54122
+ } of resolved) {
53229
54123
  const childValueId = baseBody[schemaKey];
53230
54124
  if (typeof childValueId !== "string") {
53231
54125
  throw new Error(
53232
54126
  `Class value ${String(base.id)}.${schemaKey} has no existing structural row.`
53233
54127
  );
53234
54128
  }
53235
- const projectedBase = valueBase(context, childValueId);
53236
- addReconstructed(
54129
+ if (projectedMember.kind === "lookup") {
54130
+ if (argument2.kind !== "litString") {
54131
+ throw new Error(
54132
+ `Class value ${String(base.id)}.${schemaKey} requires a value-row id string literal.`
54133
+ );
54134
+ }
54135
+ const projectedBase = valueBase(context, childValueId);
54136
+ addReconstructed(
54137
+ context,
54138
+ "value",
54139
+ childValueId,
54140
+ { ...valueFileFields(projectedBase), value: [argument2.value] },
54141
+ source.source
54142
+ );
54143
+ body[schemaKey] = childValueId;
54144
+ continue;
54145
+ }
54146
+ lowerValueRow(
53237
54147
  context,
53238
- "value",
54148
+ projectedMember,
54149
+ argument2,
53239
54150
  childValueId,
53240
- { ...valueFileFields(projectedBase), value: [target.id] },
53241
- source.source
54151
+ source,
54152
+ environment,
54153
+ argumentSlices[argumentIndex]
53242
54154
  );
53243
54155
  body[schemaKey] = childValueId;
53244
54156
  }
@@ -53342,14 +54254,6 @@ function resolveConstructorProjectionArguments(context, schemaClass2, expression
53342
54254
  });
53343
54255
  continue;
53344
54256
  }
53345
- if (argument2.kind !== "litString") {
53346
- context.loweringFailures.push({
53347
- message: `Constructor '${signature}' parameter '${parameterName}' projects a row identity, so its argument must be a value-row id string literal.`,
53348
- code: "non-literal-constructor-argument",
53349
- site: referenceSite(source, argument2)
53350
- });
53351
- continue;
53352
- }
53353
54257
  const schemaKey = inheritedProjectionSchemaKey(
53354
54258
  context.classes,
53355
54259
  schemaClass2.id,
@@ -53364,29 +54268,40 @@ function resolveConstructorProjectionArguments(context, schemaClass2, expression
53364
54268
  continue;
53365
54269
  }
53366
54270
  const projectedMember = context.members.get(projection.memberId);
53367
- if (projectedMember?.kind !== "lookup") {
54271
+ if (projectedMember === void 0) {
53368
54272
  context.loweringFailures.push({
53369
- message: `Constructor '${signature}' parameter '${parameterName}' projects member ${projection.memberId}, which is ${projectedMember === void 0 ? "in no member of this project" : `a ${projectedMember.kind} member`} and not the Lookup field a projection writes.`,
54273
+ message: `Constructor '${signature}' parameter '${parameterName}' projects member ${projection.memberId}, which is not present in this project.`,
53370
54274
  code: "unprojectable-constructor-argument",
53371
54275
  site: referenceSite(source, argument2)
53372
54276
  });
53373
54277
  continue;
53374
54278
  }
53375
- context.referenceObligations.push({
53376
- kind: "constructorProjection",
53377
- site: referenceSite(source, argument2),
53378
- schemaClassId: schemaClass2.id,
53379
- parameterName,
53380
- projectedMemberId: projectedMember.id,
53381
- targetId: argument2.value,
53382
- ownerValueId,
53383
- environment
53384
- });
54279
+ if (projectedMember.kind === "lookup") {
54280
+ if (argument2.kind !== "litString") {
54281
+ context.loweringFailures.push({
54282
+ message: `Constructor '${signature}' parameter '${parameterName}' projects a row identity, so its argument must be a value-row id string literal.`,
54283
+ code: "non-literal-constructor-argument",
54284
+ site: referenceSite(source, argument2)
54285
+ });
54286
+ continue;
54287
+ }
54288
+ context.referenceObligations.push({
54289
+ kind: "constructorProjection",
54290
+ site: referenceSite(source, argument2),
54291
+ schemaClassId: schemaClass2.id,
54292
+ parameterName,
54293
+ projectedMemberId: projectedMember.id,
54294
+ targetId: argument2.value,
54295
+ ownerValueId,
54296
+ environment
54297
+ });
54298
+ }
53385
54299
  resolved.push({
53386
54300
  parameterName,
53387
54301
  projectedMember,
53388
54302
  schemaKey,
53389
- target: { id: argument2.value, kind: "value" }
54303
+ argument: argument2,
54304
+ argumentIndex: index
53390
54305
  });
53391
54306
  }
53392
54307
  return resolved;
@@ -53439,13 +54354,24 @@ function inferAnimationChildOverrideLowerEnvironment(context, schemaClass2, expr
53439
54354
  );
53440
54355
  const argument2 = argumentIndex === void 0 || argumentIndex < 0 ? void 0 : expression.args[argumentIndex];
53441
54356
  const target = argument2?.kind === "litString" ? valueData(context, argument2.value) : null;
53442
- const targetClassId = target && typeof target.classId === "string" ? target.classId : null;
54357
+ const targetClassId = target && typeof target.classId === "string" ? target.classId : selectorReferenceReturnClassId(context, argument2);
53443
54358
  if (targetClassId === null) return inherited;
53444
54359
  return new Map(inherited).set(
53445
54360
  parameter3.id,
53446
54361
  inferredGenericClassBinding(targetClassId)
53447
54362
  );
53448
54363
  }
54364
+ function selectorReferenceReturnClassId(context, expression) {
54365
+ if (expression?.kind !== "lambda") return null;
54366
+ const returned = expression.body.find(
54367
+ (statement) => statement.kind === "return" && statement.expr !== null
54368
+ )?.expr;
54369
+ if (returned?.kind !== "call" || returned.callee.kind !== "ident" || returned.callee.name !== "Reference" || returned.typeArguments?.length !== 1) {
54370
+ return null;
54371
+ }
54372
+ const className = astTypeNameV4(returned.typeArguments[0]);
54373
+ return className === null ? null : context.classesByName.get(className)?.id ?? null;
54374
+ }
53449
54375
  function animationChildOverrideSeedBindings(context, schemaClass2, environment, source, path) {
53450
54376
  if (schemaClass2.system?.worldKind !== "animationChildOverride") {
53451
54377
  return void 0;
@@ -54653,6 +55579,36 @@ function lowerFunctionReference(context, expression, ownerClassId) {
54653
55579
  }
54654
55580
  return { functionMemberId: target.id };
54655
55581
  }
55582
+ function lowerDelegateValue(context, expression, ownerClassId, authoredSlice) {
55583
+ if (expression.kind === "lambda") {
55584
+ const code = initializerExpressionSlice(authoredSlice);
55585
+ if (code === void 0) {
55586
+ throw new Error(
55587
+ "Delegate lambdas require recoverable authored source so the server can compile their closure."
55588
+ );
55589
+ }
55590
+ return { code };
55591
+ }
55592
+ const path = memberPath(expression);
55593
+ const symbol = path?.startsWith("this.") ? path.slice("this.".length) : path;
55594
+ if (symbol === null || symbol === void 0 || symbol.includes(".")) {
55595
+ throw new Error(
55596
+ "Delegate method groups require a function, NSFunction, or NSDelegate member on the current Class."
55597
+ );
55598
+ }
55599
+ if (ownerClassId === void 0) {
55600
+ throw new Error(
55601
+ `Delegate ${symbol} cannot be resolved without its owning Class.`
55602
+ );
55603
+ }
55604
+ const target = classMemberByName(context, ownerClassId, symbol);
55605
+ if (target.kind !== "function" && target.kind !== "scriptFunction" && target.kind !== "delegate") {
55606
+ throw new Error(
55607
+ `Delegate ${symbol} does not resolve to a function, NSFunction, or NSDelegate member.`
55608
+ );
55609
+ }
55610
+ return { memberId: target.id, valueId: null };
55611
+ }
54656
55612
  function fileTargetId(context, expression, registry) {
54657
55613
  const path = memberPath(expression);
54658
55614
  if (path !== null) {
@@ -54832,6 +55788,7 @@ function emitValueBody(context, member, value, visited, targetTyped, environment
54832
55788
  if (kind === 9) return referenceValue(context, member, body, false);
54833
55789
  if (kind === 18) return referenceValue(context, member, body, true);
54834
55790
  if (kind === 24) return functionReferenceValue(context, body);
55791
+ if (kind === 25) return delegateValue(context, body);
54835
55792
  if (kind === 12) {
54836
55793
  return fileValue(
54837
55794
  context,
@@ -54874,7 +55831,8 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
54874
55831
  context,
54875
55832
  classId,
54876
55833
  value.value,
54877
- visited
55834
+ visited,
55835
+ storedEnvironment
54878
55836
  );
54879
55837
  const environment = inferAnimationChildOverrideEmitEnvironment(
54880
55838
  context,
@@ -54975,7 +55933,7 @@ function manifestMemberTypeName(context, member) {
54975
55933
  }
54976
55934
  return fixedSourceTypeNameForKind(member.kind) ?? member.kind;
54977
55935
  }
54978
- function constructorProjectionSource(context, classId, body, visited) {
55936
+ function constructorProjectionSource(context, classId, body, visited, environment) {
54979
55937
  const projections = inheritedConstructorProjections(
54980
55938
  context.manifestClasses,
54981
55939
  classId
@@ -54991,18 +55949,42 @@ function constructorProjectionSource(context, classId, body, visited) {
54991
55949
  );
54992
55950
  const childValueId = schemaKey === null ? void 0 : body[schemaKey];
54993
55951
  const childValue = typeof childValueId === "string" ? context.values.get(childValueId) : void 0;
54994
- const targetIds = Array.isArray(childValue?.value) ? childValue.value.filter(
54995
- (entry) => typeof entry === "string"
54996
- ) : [];
54997
- if (schemaKey === null || typeof childValueId !== "string" || targetIds.length !== 1) {
55952
+ const projectedMember = context.members.get(projection.memberId);
55953
+ if (schemaKey === null || typeof childValueId !== "string" || childValue === void 0 || projectedMember === void 0) {
54998
55954
  throw new Error(
54999
- `Class ${context.manifestClasses.get(classId)?.name ?? classId} constructor projection ${projection.parameterName} requires exactly one referenced value.`
55955
+ `Class ${context.manifestClasses.get(classId)?.name ?? classId} constructor projection ${projection.parameterName} has no stored projected value.`
55000
55956
  );
55001
55957
  }
55002
- visited.add(childValueId);
55003
55958
  memberIds.add(projection.memberId);
55004
- targetValueIds.push(targetIds[0]);
55005
- argumentsValue.push(`${projection.parameterName}: ${quote4(targetIds[0])}`);
55959
+ if (numberField(projectedMember, "kind") === 9) {
55960
+ const targetIds = Array.isArray(childValue.value) ? childValue.value.filter(
55961
+ (entry) => typeof entry === "string"
55962
+ ) : [];
55963
+ if (targetIds.length !== 1) {
55964
+ throw new Error(
55965
+ `Class ${context.manifestClasses.get(classId)?.name ?? classId} constructor projection ${projection.parameterName} requires exactly one referenced value.`
55966
+ );
55967
+ }
55968
+ visited.add(childValueId);
55969
+ targetValueIds.push(targetIds[0]);
55970
+ argumentsValue.push(
55971
+ `${projection.parameterName}: ${quote4(targetIds[0])}`
55972
+ );
55973
+ continue;
55974
+ }
55975
+ argumentsValue.push(
55976
+ `${projection.parameterName}: ${emitValue(
55977
+ context,
55978
+ projectedMember,
55979
+ childValueId,
55980
+ {
55981
+ definitionSite: true,
55982
+ writeIdentity: false,
55983
+ environment,
55984
+ visited
55985
+ }
55986
+ )}`
55987
+ );
55006
55988
  }
55007
55989
  return { arguments: argumentsValue, memberIds, targetValueIds };
55008
55990
  }
@@ -55317,6 +56299,29 @@ function functionReferenceValue(context, body) {
55317
56299
  }
55318
56300
  return target.name;
55319
56301
  }
56302
+ function delegateValue(context, body) {
56303
+ if (!isObjectRecord2(body)) {
56304
+ throw new Error("NSDelegate value is not a closure or bound target.");
56305
+ }
56306
+ if (typeof body.code === "string") return body.code;
56307
+ if (typeof body.memberId !== "string") {
56308
+ throw new Error("NSDelegate bound target is missing memberId.");
56309
+ }
56310
+ if (body.valueId !== null && body.valueId !== void 0) {
56311
+ throw new Error(
56312
+ "NSDelegate instance-bound target cannot be represented by current project source."
56313
+ );
56314
+ }
56315
+ const target = context.members.get(body.memberId);
56316
+ if (target === void 0 || typeof target.name !== "string") {
56317
+ throw new Error(`NSDelegate target ${body.memberId} was not pulled.`);
56318
+ }
56319
+ const kind = numberField(target, "kind");
56320
+ if (kind !== 10 && kind !== 23 && kind !== 25) {
56321
+ throw new Error(`NSDelegate target ${body.memberId} is not callable.`);
56322
+ }
56323
+ return target.name;
56324
+ }
55320
56325
  function fileValue(context, kind, label, body) {
55321
56326
  if (body === null || body === void 0) return "null";
55322
56327
  if (!isObjectRecord2(body)) {
@@ -58318,7 +59323,8 @@ var init_animation_clips = __esm({
58318
59323
  frameNode,
58319
59324
  frameClassId,
58320
59325
  childIds: authoredChildren.ids,
58321
- childStoragePath: authoredChildren.storagePath
59326
+ childStoragePath: authoredChildren.storagePath,
59327
+ selectorOwnerNode: targetDefinition
58322
59328
  });
58323
59329
  this.validateActions({
58324
59330
  clipName: clipMember.name,
@@ -58334,6 +59340,7 @@ var init_animation_clips = __esm({
58334
59340
  clipClassId: clipMember.classId,
58335
59341
  childIds: authoredChildren.ids,
58336
59342
  childStoragePath: authoredChildren.storagePath,
59343
+ selectorOwnerNode: targetDefinition,
58337
59344
  duration
58338
59345
  });
58339
59346
  }
@@ -58347,12 +59354,16 @@ var init_animation_clips = __esm({
58347
59354
  const seenChildren = /* @__PURE__ */ new Set();
58348
59355
  for (const row of rows) {
58349
59356
  const rowClassId = this.requireNodeClassId(row, "animationChildOverride");
58350
- const childId = this.requireSingleLookupField(
59357
+ const selected2 = this.resolveSelector(
58351
59358
  row,
58352
59359
  rowClassId,
58353
- WORLD_ANIMATION_CHILD_OVERRIDE_CHILD_MEMBER_ID,
59360
+ WORLD_ANIMATION_CHILD_OVERRIDE_SELECTOR_MEMBER_ID,
59361
+ WORLD_ANIMATION_CHILD_OVERRIDE_REFRESH_MEMBER_ID,
59362
+ args.selectorOwnerNode,
58354
59363
  `Animation clip "${args.clipName}" frame ${args.frameIndex} child override`
58355
59364
  );
59365
+ if (selected2 === null) continue;
59366
+ const { childId, childClassId, childNode: child } = selected2;
58356
59367
  if (!args.childIds.has(childId)) {
58357
59368
  throw new Error(
58358
59369
  `Animation clip "${args.clipName}" frame ${args.frameIndex} references child "${childId}" outside the owner's authored Children graph.`
@@ -58364,13 +59375,6 @@ var init_animation_clips = __esm({
58364
59375
  );
58365
59376
  }
58366
59377
  seenChildren.add(childId);
58367
- const child = this.valueById.get(childId);
58368
- const childClassId = child === void 0 ? null : this.rowClassId(child);
58369
- if (child === void 0 || childClassId === null) {
58370
- throw new Error(
58371
- `Animation clip "${args.clipName}" frame ${args.frameIndex} references missing class-backed child "${childId}".`
58372
- );
58373
- }
58374
59378
  const bindingMemberId = row.genericBindings?.[WORLD_ANIMATION_CHILD_OVERRIDE_ENTRY_PARAM_ID];
58375
59379
  const bindingMember = typeof bindingMemberId === "string" ? this.memberById.get(bindingMemberId) : void 0;
58376
59380
  const bindingClassId = isMemberClass(bindingMember) ? bindingMember.classId : null;
@@ -58467,10 +59471,12 @@ var init_animation_clips = __esm({
58467
59471
  track,
58468
59472
  trackClassId: row.classId,
58469
59473
  childIds: args.childIds,
59474
+ selectorOwnerNode: args.selectorOwnerNode,
58470
59475
  duration: args.duration,
58471
59476
  label
58472
59477
  });
58473
59478
  if (row.kind === "childClip") {
59479
+ if (child === null) continue;
58474
59480
  this.validateChildClipTrack({
58475
59481
  track,
58476
59482
  trackClassId: row.classId,
@@ -58483,8 +59489,6 @@ var init_animation_clips = __esm({
58483
59489
  }
58484
59490
  this.validateSegmentTrack({
58485
59491
  trackClassId: row.classId,
58486
- childClassId: child.childClassId,
58487
- childId: child.childId,
58488
59492
  childStoragePath: args.childStoragePath,
58489
59493
  label
58490
59494
  });
@@ -58525,22 +59529,17 @@ var init_animation_clips = __esm({
58525
59529
  * segment's length is instance data this document does not have.
58526
59530
  */
58527
59531
  validateTrackBase(args) {
58528
- const childId = this.requireSingleLookupField(
59532
+ const selected2 = this.resolveSelector(
58529
59533
  args.track,
58530
59534
  args.trackClassId,
58531
- WORLD_ANIMATION_TRACK_CHILD_MEMBER_ID,
59535
+ WORLD_ANIMATION_TRACK_SELECTOR_MEMBER_ID,
59536
+ WORLD_ANIMATION_TRACK_REFRESH_MEMBER_ID,
59537
+ args.selectorOwnerNode,
58532
59538
  args.label
58533
59539
  );
58534
- if (!args.childIds.has(childId)) {
59540
+ if (selected2 !== null && !args.childIds.has(selected2.childId)) {
58535
59541
  throw new Error(
58536
- `${args.label} references child "${childId}" outside the owner's authored Children graph.`
58537
- );
58538
- }
58539
- const childNode = this.valueById.get(childId);
58540
- const childClassId = childNode === void 0 ? null : this.rowClassId(childNode);
58541
- if (childNode === void 0 || childClassId === null) {
58542
- throw new Error(
58543
- `${args.label} references missing class-backed child "${childId}".`
59542
+ `${args.label} references child "${selected2.childId}" outside the owner's authored Children graph.`
58544
59543
  );
58545
59544
  }
58546
59545
  const startFrame = this.requireIntegerField(
@@ -58559,7 +59558,36 @@ var init_animation_clips = __esm({
58559
59558
  }
58560
59559
  this.validateTrackDirection(args.track, args.trackClassId, args.label);
58561
59560
  this.validateTrackCropWindow(args.track, args.trackClassId, args.label);
58562
- return { childId, childClassId, childNode };
59561
+ return selected2;
59562
+ }
59563
+ resolveSelector(parent, classId, selectorMemberId, refreshMemberId, _selectorOwnerNode, label) {
59564
+ this.validateSelectorRefresh(parent, classId, refreshMemberId, label);
59565
+ const selector = this.scalarField(parent, classId, selectorMemberId);
59566
+ if (!isNSDelegateValue(selector)) {
59567
+ throw new Error(`${label} must carry a valid NeoDelegate selector.`);
59568
+ }
59569
+ const directReferenceId = nsDelegateDirectReferenceValueId(selector);
59570
+ if (directReferenceId === null) return null;
59571
+ const childNode = this.valueById.get(directReferenceId);
59572
+ if (childNode === void 0) {
59573
+ throw new Error(`${label} selector did not resolve a stored child row.`);
59574
+ }
59575
+ const childClassId = this.rowClassId(childNode);
59576
+ if (childClassId === null) {
59577
+ throw new Error(
59578
+ `${label} selector resolved child "${childNode.id}" without a class.`
59579
+ );
59580
+ }
59581
+ return { childId: childNode.id, childClassId, childNode };
59582
+ }
59583
+ validateSelectorRefresh(parent, classId, memberId, label) {
59584
+ const value = this.scalarField(parent, classId, memberId);
59585
+ if (value === void 0 || value === null) return;
59586
+ if (!Array.isArray(value) || value.length !== 1 || value[0] !== WORLD_SELECTOR_REFRESH_ON_LOAD_OPTION_ID && value[0] !== WORLD_SELECTOR_REFRESH_PER_FRAME_OPTION_ID) {
59587
+ throw new Error(
59588
+ `${label} Refresh must be exactly one NeoSelectorRefreshKind option.`
59589
+ );
59590
+ }
58563
59591
  }
58564
59592
  validateTrackDirection(track, trackClassId, label) {
58565
59593
  const authored = this.scalarField(
@@ -58684,13 +59712,6 @@ var init_animation_clips = __esm({
58684
59712
  `${args.label} class "${trackClassName}" does not bind its TChild generic to a Class member.`
58685
59713
  );
58686
59714
  }
58687
- if (!this.classDescendsFrom(args.childClassId, boundChildClassId)) {
58688
- const boundName = this.classById.get(boundChildClassId)?.name ?? boundChildClassId;
58689
- const childName = this.classById.get(args.childClassId)?.name ?? args.childClassId;
58690
- throw new Error(
58691
- `${args.label} plays against child "${args.childId}" of class "${childName}", which does not descend from the track's bound TChild "${boundName}".`
58692
- );
58693
- }
58694
59715
  const targetEntry = mergeStoredInstanceSchema(
58695
59716
  boundChildClassId,
58696
59717
  this.document.classes,
@@ -60117,7 +61138,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60117
61138
  parseErrors,
60118
61139
  parseWarnings,
60119
61140
  reconstructed: /* @__PURE__ */ new Map(),
60120
- staticValueSeeds: /* @__PURE__ */ new Map(),
61141
+ authoredValueSeeds: /* @__PURE__ */ new Map(),
60121
61142
  binaryChanges: [],
60122
61143
  binaryFiles: []
60123
61144
  };
@@ -60125,7 +61146,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60125
61146
  const baseDocuments = schemaBaseDocuments(workspace);
60126
61147
  const baseManifest = baseDocuments.length === 0 ? void 0 : documentsToProjectSchemaManifest(baseDocuments);
60127
61148
  let manifest;
60128
- let staticValueSeeds = /* @__PURE__ */ new Map();
61149
+ let authoredValueSeeds = /* @__PURE__ */ new Map();
60129
61150
  let staticMemberValueIds = /* @__PURE__ */ new Map();
60130
61151
  let memberDefaults = {
60131
61152
  records: [],
@@ -60167,7 +61188,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60167
61188
  parseErrors,
60168
61189
  parseWarnings,
60169
61190
  reconstructed: /* @__PURE__ */ new Map(),
60170
- staticValueSeeds,
61191
+ authoredValueSeeds,
60171
61192
  binaryChanges: [],
60172
61193
  binaryFiles: []
60173
61194
  };
@@ -60192,7 +61213,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60192
61213
  parseErrors,
60193
61214
  parseWarnings,
60194
61215
  reconstructed: /* @__PURE__ */ new Map(),
60195
- staticValueSeeds,
61216
+ authoredValueSeeds,
60196
61217
  binaryChanges: [],
60197
61218
  binaryFiles: []
60198
61219
  };
@@ -60241,7 +61262,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60241
61262
  parseErrors,
60242
61263
  parseWarnings,
60243
61264
  reconstructed: /* @__PURE__ */ new Map(),
60244
- staticValueSeeds: /* @__PURE__ */ new Map(),
61265
+ authoredValueSeeds: /* @__PURE__ */ new Map(),
60245
61266
  binaryChanges: [],
60246
61267
  binaryFiles: []
60247
61268
  };
@@ -60289,7 +61310,10 @@ function computeWorkspaceStatus(workspace, options = {}) {
60289
61310
  manifest,
60290
61311
  { registry: valueLowerRegistry }
60291
61312
  );
60292
- staticValueSeeds = new Map([...staticValues.seeds, ...memberDefaults.seeds]);
61313
+ authoredValueSeeds = new Map([
61314
+ ...staticValues.seeds,
61315
+ ...memberDefaults.seeds
61316
+ ]);
60293
61317
  staticMemberValueIds = staticValues.memberValueIds;
60294
61318
  const rootValues = lowerProjectRootSourceV4(
60295
61319
  workspace.state.records,
@@ -60297,7 +61321,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60297
61321
  manifest,
60298
61322
  { registry: valueLowerRegistry }
60299
61323
  );
60300
- staticValueSeeds = new Map([...staticValueSeeds, ...rootValues.seeds]);
61324
+ authoredValueSeeds = new Map([...authoredValueSeeds, ...rootValues.seeds]);
60301
61325
  const rootPathResolutionState = overlayProspectiveSourceRecords(
60302
61326
  workspace.state.records,
60303
61327
  documents,
@@ -60533,7 +61557,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60533
61557
  parseErrors,
60534
61558
  parseWarnings,
60535
61559
  reconstructed: /* @__PURE__ */ new Map(),
60536
- staticValueSeeds: /* @__PURE__ */ new Map(),
61560
+ authoredValueSeeds: /* @__PURE__ */ new Map(),
60537
61561
  binaryChanges: [],
60538
61562
  binaryFiles: []
60539
61563
  };
@@ -60607,7 +61631,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60607
61631
  workspace.state.records,
60608
61632
  reconstructed3,
60609
61633
  changes,
60610
- staticValueSeeds
61634
+ authoredValueSeeds
60611
61635
  )
60612
61636
  );
60613
61637
  } catch (error) {
@@ -60637,7 +61661,7 @@ function computeWorkspaceStatus(workspace, options = {}) {
60637
61661
  parseErrors,
60638
61662
  parseWarnings,
60639
61663
  reconstructed: reconstructed3,
60640
- staticValueSeeds,
61664
+ authoredValueSeeds,
60641
61665
  binaryChanges,
60642
61666
  binaryFiles,
60643
61667
  initConversions: collectInitDefaultConversions(
@@ -63586,7 +64610,7 @@ var init_project_file_pull = __esm({
63586
64610
  function staticValueSeedEmitRecords(status, present) {
63587
64611
  const records2 = /* @__PURE__ */ new Map();
63588
64612
  if (status === null) return records2;
63589
- for (const [memberId, seed] of status.staticValueSeeds) {
64613
+ for (const [memberId, seed] of status.authoredValueSeeds) {
63590
64614
  const rootId = seed.valueId ?? memberValueIdFromRecord(status, memberId);
63591
64615
  if (rootId !== null) {
63592
64616
  addSeedRecord(records2, present, {
@@ -66778,6 +67802,20 @@ function memberRuntimeType(record3, context, seen = /* @__PURE__ */ new Set(), g
66778
67802
  return primitive2("void", true);
66779
67803
  case 24 /* FunctionRef */:
66780
67804
  return UNKNOWN_TYPE2;
67805
+ case 25 /* NSDelegate */:
67806
+ if (!isMemberDelegateBase(member)) return UNKNOWN_TYPE2;
67807
+ return {
67808
+ kind: "delegate",
67809
+ returnType: functionReturnType(
67810
+ member.returnTypeInfo,
67811
+ context,
67812
+ genericEnvironment
67813
+ ),
67814
+ parameterTypes: member.argumentTypes.map(
67815
+ (argument2) => toLanguageType(argument2, context, genericEnvironment)
67816
+ ),
67817
+ nullable: !required2
67818
+ };
66781
67819
  case 21 /* Generic */: {
66782
67820
  const genericParamId = getOptionalString(member, "genericParamId");
66783
67821
  if (!genericParamId) return UNKNOWN_TYPE2;
@@ -66972,6 +68010,19 @@ function toLanguageType(type, context, genericEnvironment) {
66972
68010
  ),
66973
68011
  nullable: !required2
66974
68012
  };
68013
+ case 25 /* NSDelegate */:
68014
+ return {
68015
+ kind: "delegate",
68016
+ returnType: functionReturnType(
68017
+ type.returnTypeInfo,
68018
+ context,
68019
+ genericEnvironment
68020
+ ),
68021
+ parameterTypes: type.argumentTypes.map(
68022
+ (argument2) => toLanguageType(argument2, context, genericEnvironment)
68023
+ ),
68024
+ nullable: !required2
68025
+ };
66975
68026
  case 21 /* Generic */: {
66976
68027
  const environmentEntry = genericEnvironment?.get(type.genericParamId);
66977
68028
  if (environmentEntry?.kind === "member") {
@@ -67940,6 +68991,7 @@ function pushConstructionFrame(ctx, label) {
67940
68991
  "Class construction requires an effect-capable evaluator Session scope."
67941
68992
  );
67942
68993
  }
68994
+ consumeBudget(ctx, "workUnits", 1, "work unit");
67943
68995
  if (state.constructionStack.length >= MAX_CONSTRUCTION_DEPTH) {
67944
68996
  const chain = [...state.constructionStack, label].join(" -> ");
67945
68997
  throw new NSGetterRuntimeError(
@@ -67983,6 +69035,7 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = []) {
67983
69035
  const ownsInvocationState = ctx.__executionState === void 0;
67984
69036
  const requestedWrites = [];
67985
69037
  const runtimeCtx = withEvaluationRuntime(ctx, requestedWrites);
69038
+ consumeBudget(runtimeCtx, "workUnits", 1, "work unit");
67986
69039
  const writes = runtimeCtx.__executionState?.writes ?? requestedWrites;
67987
69040
  const existingIds = new Set(runtimeCtx.__runtimeSessionValues.keys());
67988
69041
  const scope = createTopLevelScope(runtimeCtx);
@@ -68033,6 +69086,7 @@ function evaluateNSAction(action, ctx) {
68033
69086
  const ownsInvocationState = ctx.__executionState === void 0;
68034
69087
  const writes = [];
68035
69088
  const runtimeCtx = withEvaluationRuntime(ctx, writes);
69089
+ consumeBudget(runtimeCtx, "workUnits", 1, "work unit");
68036
69090
  const existingIds = new Set(runtimeCtx.__runtimeSessionValues.keys());
68037
69091
  const scope = createTopLevelScope(runtimeCtx);
68038
69092
  try {
@@ -68063,6 +69117,7 @@ function evaluateNSFunction(action, ctx, args) {
68063
69117
  const ownsInvocationState = ctx.__executionState === void 0;
68064
69118
  const writes = [];
68065
69119
  const runtimeCtx = withEvaluationRuntime(ctx, writes);
69120
+ consumeBudget(runtimeCtx, "workUnits", 1, "work unit");
68066
69121
  const existingIds = new Set(runtimeCtx.__runtimeSessionValues.keys());
68067
69122
  const runtimeArgs = remapRuntimeArguments(args, runtimeCtx);
68068
69123
  let value;
@@ -68115,14 +69170,62 @@ function withEvaluationRuntime(ctx, writes) {
68115
69170
  __executionState: ctx.__executionState ?? {
68116
69171
  writes,
68117
69172
  functionStack: [],
69173
+ delegateStack: [],
68118
69174
  constructorGroups: /* @__PURE__ */ new Map(),
68119
69175
  ownedValueAttachments: /* @__PURE__ */ new Map(),
68120
69176
  constructionStack: [],
68121
- loopIterations: 0
69177
+ loopIterations: 0,
69178
+ budget: createExecutionBudget(ctx.executionBudgetLimits)
68122
69179
  },
68123
69180
  __indexes: ctx.__executionState === void 0 || ctx.__valueOverlay === void 0 ? void 0 : ctx.__indexes
68124
69181
  };
68125
69182
  }
69183
+ function createExecutionBudget(requested) {
69184
+ const limits = { ...DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS };
69185
+ for (const key of Object.keys(limits)) {
69186
+ const value = requested?.[key];
69187
+ if (value === void 0) continue;
69188
+ if (!Number.isSafeInteger(value)) {
69189
+ throw new NeoScriptResourceLimitError(
69190
+ `NeoScript ${key} limit must be a safe integer.`
69191
+ );
69192
+ }
69193
+ if (value < 0) {
69194
+ throw new NeoScriptResourceLimitError(
69195
+ `NeoScript ${key} limit must not be negative.`
69196
+ );
69197
+ }
69198
+ if (value > DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS[key]) {
69199
+ throw new NeoScriptResourceLimitError(
69200
+ `NeoScript ${key} limit cannot exceed the safety ceiling of ${DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS[key]}.`
69201
+ );
69202
+ }
69203
+ limits[key] = value;
69204
+ }
69205
+ return {
69206
+ limits,
69207
+ workUnits: 0,
69208
+ collectionVisits: 0,
69209
+ producedCollectionEntries: 0,
69210
+ constructedSessionRows: 0,
69211
+ producedStringCharacters: 0
69212
+ };
69213
+ }
69214
+ function consumeBudget(ctx, counter, amount, label) {
69215
+ const budget = ctx.__executionState?.budget;
69216
+ if (budget === void 0) {
69217
+ throw new NSGetterRuntimeError(
69218
+ "NeoScript work executed without a shared execution budget."
69219
+ );
69220
+ }
69221
+ const limit = budget.limits[counter];
69222
+ if (amount > limit - budget[counter]) {
69223
+ throw new NeoScriptResourceLimitError(
69224
+ `NeoScript ${label} limit of ${limit} exceeded.`
69225
+ );
69226
+ }
69227
+ budget[counter] += amount;
69228
+ }
68126
69229
  function staticBindingMap(bindings) {
68127
69230
  if (bindings === void 0) return /* @__PURE__ */ new Map();
68128
69231
  if (bindings instanceof Map) return new Map(bindings);
@@ -68497,11 +69600,12 @@ function consumeLoopIteration(ctx) {
68497
69600
  );
68498
69601
  }
68499
69602
  if (state.loopIterations >= MAX_LOOP_ITERATIONS) {
68500
- throw new NSGetterRuntimeError(
69603
+ throw new NeoScriptResourceLimitError(
68501
69604
  `NeoScript loop iteration limit of ${MAX_LOOP_ITERATIONS} exceeded.`
68502
69605
  );
68503
69606
  }
68504
69607
  state.loopIterations += 1;
69608
+ consumeBudget(ctx, "workUnits", 1, "work unit");
68505
69609
  }
68506
69610
  function synchronizeExistingBindings(parent, child, bindingIds) {
68507
69611
  for (const bindingId of bindingIds) {
@@ -68671,6 +69775,7 @@ function validateTryInstruction(instruction) {
68671
69775
  }
68672
69776
  function evalInstructions(instructions, scope, ctx, options) {
68673
69777
  for (const ins of instructions) {
69778
+ consumeBudget(ctx, "workUnits", 1, "work unit");
68674
69779
  switch (ins.type) {
68675
69780
  case "variable" /* variable */: {
68676
69781
  let value = evalPointer(ins.variable.pointer, scope, ctx);
@@ -68785,7 +69890,7 @@ function evalInstructions(instructions, scope, ctx, options) {
68785
69890
  }
68786
69891
  case "forEach" /* forEach */: {
68787
69892
  const collection = evalPointer(ins.collectionPointer, scope, ctx);
68788
- const membership = snapshotCollectionMembership(collection);
69893
+ const membership = snapshotCollectionMembership(collection, ctx);
68789
69894
  const parentBindingIds = [...scope.keys()];
68790
69895
  const loopScope = createChildScope(scope);
68791
69896
  markReadonlyBinding(
@@ -69155,6 +70260,7 @@ function resolvedDestinationFieldsForContainer(targetValue, ctx) {
69155
70260
  return containerValueId === null ? {} : { resolvedDestination: { containerValueId } };
69156
70261
  }
69157
70262
  function dispatchNSSetter(target, value, scope, ctx, writes) {
70263
+ consumeBudget(ctx, "workUnits", 1, "work unit");
69158
70264
  if (target.type !== "callGetter" /* callGetter */) {
69159
70265
  throw new NSGetterRuntimeError(
69160
70266
  "Setter write target must be a callGetter pointer."
@@ -69258,8 +70364,22 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
69258
70364
  const targetValue = evalPointer(ins.target.pointer, scope, ctx);
69259
70365
  const args = ins.args.map((arg) => evalPointer(arg, scope, ctx));
69260
70366
  const isLookupSet = ins.target.typeInfo.type === 9 /* Lookup */;
70367
+ if (ins.mutation === "Add" /* Add */) {
70368
+ consumeBudget(
70369
+ ctx,
70370
+ "producedCollectionEntries",
70371
+ 1,
70372
+ "produced collection entry"
70373
+ );
70374
+ }
69261
70375
  if (ins.target.pointer.type === "variable" /* variable */) {
69262
- applyLocalCollectionMutation(targetValue, ins.mutation, args, isLookupSet);
70376
+ applyLocalCollectionMutation(
70377
+ targetValue,
70378
+ ins.mutation,
70379
+ args,
70380
+ ctx,
70381
+ isLookupSet
70382
+ );
69263
70383
  invalidateEvaluatorIndexes(ctx);
69264
70384
  scope.set(ins.target.pointer.variableId, targetValue);
69265
70385
  return;
@@ -69289,6 +70409,7 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
69289
70409
  targetValue,
69290
70410
  ins.mutation,
69291
70411
  overlayArgs,
70412
+ ctx,
69292
70413
  isLookupSet
69293
70414
  );
69294
70415
  invalidateEvaluatorIndexes(ctx);
@@ -69349,12 +70470,22 @@ function evalCollectionMutationInstruction(ins, scope, ctx, options) {
69349
70470
  return;
69350
70471
  }
69351
70472
  }
69352
- function applyLocalCollectionMutation(targetValue, mutation, args, unique = false) {
70473
+ function applyLocalCollectionMutation(targetValue, mutation, args, ctx, unique = false) {
69353
70474
  validateCollectionMutation(targetValue, mutation, args);
69354
70475
  switch (mutation) {
69355
70476
  case "Add" /* Add */:
69356
70477
  if (Array.isArray(targetValue)) {
69357
- if (!unique || !targetValue.some((entry) => jsEqual(entry, args[0]))) {
70478
+ let alreadyPresent = false;
70479
+ if (unique) {
70480
+ for (const entry of targetValue) {
70481
+ consumeBudget(ctx, "collectionVisits", 1, "collection visit");
70482
+ if (jsEqual(entry, args[0])) {
70483
+ alreadyPresent = true;
70484
+ break;
70485
+ }
70486
+ }
70487
+ }
70488
+ if (!alreadyPresent) {
69358
70489
  targetValue.push(args[0]);
69359
70490
  }
69360
70491
  return;
@@ -69363,7 +70494,14 @@ function applyLocalCollectionMutation(targetValue, mutation, args, unique = fals
69363
70494
  return;
69364
70495
  case "Remove" /* Remove */:
69365
70496
  if (Array.isArray(targetValue)) {
69366
- const index = targetValue.findIndex((entry) => jsEqual(entry, args[0]));
70497
+ let index = -1;
70498
+ for (let candidate = 0; candidate < targetValue.length; candidate += 1) {
70499
+ consumeBudget(ctx, "collectionVisits", 1, "collection visit");
70500
+ if (jsEqual(targetValue[candidate], args[0])) {
70501
+ index = candidate;
70502
+ break;
70503
+ }
70504
+ }
69367
70505
  if (index >= 0) targetValue.splice(index, 1);
69368
70506
  return;
69369
70507
  }
@@ -69380,10 +70518,18 @@ function applyLocalCollectionMutation(targetValue, mutation, args, unique = fals
69380
70518
  }
69381
70519
  case "Clear" /* Clear */:
69382
70520
  if (Array.isArray(targetValue)) {
70521
+ consumeBudget(
70522
+ ctx,
70523
+ "collectionVisits",
70524
+ targetValue.length,
70525
+ "collection visit"
70526
+ );
69383
70527
  targetValue.length = 0;
69384
70528
  return;
69385
70529
  }
69386
- for (const key of Object.keys(objectArg(targetValue, "Clear target"))) {
70530
+ const keys = Object.keys(objectArg(targetValue, "Clear target"));
70531
+ consumeBudget(ctx, "collectionVisits", keys.length, "collection visit");
70532
+ for (const key of keys) {
69387
70533
  delete objectArg(targetValue, "Clear target")[key];
69388
70534
  }
69389
70535
  return;
@@ -69518,8 +70664,17 @@ function evalStaticMember(memberId, ctx) {
69518
70664
  }
69519
70665
  function evalPointer(pointer, scope, ctx) {
69520
70666
  switch (pointer.type) {
69521
- case "value" /* value */:
69522
- return pointer.value.value;
70667
+ case "value" /* value */: {
70668
+ const value = pointer.value.value;
70669
+ if (isNSDelegateClosureValue(value)) {
70670
+ return {
70671
+ ...value,
70672
+ [DELEGATE_LEXICAL_THIS]: ctx.thisValue,
70673
+ [DELEGATE_LEXICAL_ROOT]: ctx.rootValue
70674
+ };
70675
+ }
70676
+ return value;
70677
+ }
69523
70678
  case "variable" /* variable */: {
69524
70679
  if (!scope.has(pointer.variableId)) {
69525
70680
  throw new NSGetterRuntimeError(
@@ -69557,8 +70712,20 @@ function evalPointer(pointer, scope, ctx) {
69557
70712
  case "function" /* function */:
69558
70713
  return evalFunction(pointer.function, scope, ctx);
69559
70714
  case "listLiteral" /* listLiteral */:
70715
+ consumeBudget(
70716
+ ctx,
70717
+ "producedCollectionEntries",
70718
+ pointer.entries.length,
70719
+ "produced collection entry"
70720
+ );
69560
70721
  return pointer.entries.map((e) => evalPointer(e, scope, ctx));
69561
70722
  case "dictLiteral" /* dictLiteral */: {
70723
+ consumeBudget(
70724
+ ctx,
70725
+ "producedCollectionEntries",
70726
+ pointer.entries.length,
70727
+ "produced collection entry"
70728
+ );
69562
70729
  const out = {};
69563
70730
  for (const e of pointer.entries) {
69564
70731
  const k = evalPointer(e.key, scope, ctx);
@@ -69611,6 +70778,7 @@ function evalPointer(pointer, scope, ctx) {
69611
70778
  `Function call '${member.name}' resolves to non-callable member kind ${MemberKind[member.kind]}.`
69612
70779
  );
69613
70780
  }
70781
+ consumeBudget(ctx, "workUnits", 1, "work unit");
69614
70782
  if (member.kind === 13 /* Function */) {
69615
70783
  throw new NativeFunctionDelegateUnavailableError(
69616
70784
  `Cannot evaluate native Function '${member.name}' in web preview because no native delegate is available.`
@@ -69666,6 +70834,17 @@ function evalPointer(pointer, scope, ctx) {
69666
70834
  state.functionStack.pop();
69667
70835
  }
69668
70836
  }
70837
+ case "callDelegate" /* callDelegate */: {
70838
+ const delegate = evalPointer(pointer.delegate, scope, ctx);
70839
+ if (delegate === null || delegate === void 0) {
70840
+ if (pointer.optional === true) return null;
70841
+ throw new NSGetterRuntimeError(
70842
+ "Cannot invoke a null NeoDelegate value."
70843
+ );
70844
+ }
70845
+ const args = pointer.args.map((arg) => evalPointer(arg, scope, ctx));
70846
+ return invokeDelegateValue(delegate, args, ctx);
70847
+ }
69669
70848
  case "functionErrorCheck" /* functionErrorCheck */: {
69670
70849
  try {
69671
70850
  evalPointer(pointer.call, scope, ctx);
@@ -69674,7 +70853,7 @@ function evalPointer(pointer, scope, ctx) {
69674
70853
  if (err instanceof NativeFunctionDelegateUnavailableError) {
69675
70854
  return pointer.mode === "doesNotThrow" /* DoesNotThrow */;
69676
70855
  }
69677
- if (err instanceof NSGetterRuntimeError) {
70856
+ if (isCatchableNSRuntimeError(err)) {
69678
70857
  return pointer.mode === "throws" /* Throws */;
69679
70858
  }
69680
70859
  throw err;
@@ -69691,7 +70870,14 @@ function evalPointer(pointer, scope, ctx) {
69691
70870
  }
69692
70871
  case "stringify" /* stringify */: {
69693
70872
  const v = evalPointer(pointer.pointer, scope, ctx);
69694
- return formatForInterp(v, pointer.sourceType, ctx);
70873
+ const formatted = formatForInterp(v, pointer.sourceType, ctx);
70874
+ consumeBudget(
70875
+ ctx,
70876
+ "producedStringCharacters",
70877
+ formatted.length,
70878
+ "produced string character"
70879
+ );
70880
+ return formatted;
69695
70881
  }
69696
70882
  }
69697
70883
  }
@@ -69706,6 +70892,174 @@ function resolveEffectiveCallableMember(pointer, receiver, ctx) {
69706
70892
  const runtimeMember = resolveRuntimeSchemaMember(receiver, schemaKey, ctx);
69707
70893
  return runtimeMember ?? staticMember;
69708
70894
  }
70895
+ function invokeDelegateValue(value, args, ctx) {
70896
+ if (isNSDelegateClosureValueDraft(value)) {
70897
+ throw new NSGetterRuntimeError(
70898
+ "NeoDelegate closure has source code but no compiled action."
70899
+ );
70900
+ }
70901
+ if (isNSDelegateClosureValue(value)) {
70902
+ const closure = value;
70903
+ const thisValue = delegateClosureLexicalThis(closure, ctx);
70904
+ return executeCompiledFunction(
70905
+ value.action,
70906
+ {
70907
+ ...ctx,
70908
+ thisValue,
70909
+ rootValue: closure[DELEGATE_LEXICAL_ROOT] ?? ctx.rootValue
70910
+ },
70911
+ args,
70912
+ value.action.typeInfo.type === 0 /* Null */
70913
+ );
70914
+ }
70915
+ if (!isMemberDelegateTarget(value)) {
70916
+ throw new NSGetterRuntimeError(
70917
+ "NeoDelegate value is neither a closure nor a bound member target."
70918
+ );
70919
+ }
70920
+ const member = evalMemberById(ctx.vm, value.memberId);
70921
+ if (member === null) {
70922
+ throw new NSGetterRuntimeError(
70923
+ `NeoDelegate target member '${value.memberId}' does not exist.`
70924
+ );
70925
+ }
70926
+ const state = ctx.__executionState;
70927
+ if (state === void 0) {
70928
+ throw new NSGetterRuntimeError(
70929
+ "NeoDelegate invocation reached an evaluator without execution state."
70930
+ );
70931
+ }
70932
+ const frame = `${member.name}[${value.valueId ?? "default"}]`;
70933
+ if (state.delegateStack.includes(frame)) {
70934
+ throw new NSGetterRuntimeError(
70935
+ `NeoDelegate target cycle: ${[...state.delegateStack, frame].join(" -> ")}.`
70936
+ );
70937
+ }
70938
+ if (state.delegateStack.length >= 64) {
70939
+ throw new NSGetterRuntimeError(
70940
+ `NeoDelegate call stack exceeded 64 frames: ${[
70941
+ ...state.delegateStack,
70942
+ frame
70943
+ ].join(" -> ")}.`
70944
+ );
70945
+ }
70946
+ let receiver = null;
70947
+ if (value.valueId !== null) {
70948
+ const row = evalValueById(
70949
+ ctx.vm,
70950
+ value.valueId,
70951
+ ctx.__runtimeSessionValues,
70952
+ ctx.__valueOverlay
70953
+ );
70954
+ if (row === null) {
70955
+ throw new NSGetterRuntimeError(
70956
+ `NeoDelegate target '${member.name}' has missing receiver value '${value.valueId}'.`
70957
+ );
70958
+ }
70959
+ receiver = row.value;
70960
+ }
70961
+ state.delegateStack.push(frame);
70962
+ try {
70963
+ if (member.kind === 13 /* Function */) {
70964
+ throw new NativeFunctionDelegateUnavailableError(
70965
+ `Cannot evaluate native Function '${member.name}' in web preview because no native delegate is available.`
70966
+ );
70967
+ }
70968
+ if (member.kind === 23 /* NSFunction */) {
70969
+ const signature = resolveCallableSignature(member.id, member.kind, ctx);
70970
+ const action = resolveCompiledNSFunction(member.id, ctx);
70971
+ if (signature === null || action === null) {
70972
+ throw new NSGetterRuntimeError(
70973
+ `NeoDelegate target NSFunction '${member.name}' has no valid compiled body.`
70974
+ );
70975
+ }
70976
+ const runtimeSignature = receiver === null ? signature : substituteCallableSignatureForReceiver(signature, receiver, ctx);
70977
+ return executeCompiledFunction(
70978
+ action,
70979
+ { ...ctx, thisValue: receiver },
70980
+ args,
70981
+ runtimeSignature.returnTypeInfo.type === NS_TYPE_VOID,
70982
+ runtimeSignature
70983
+ );
70984
+ }
70985
+ if (member.kind === 25 /* NSDelegate */) {
70986
+ let nested;
70987
+ if (receiver !== null) {
70988
+ const schemaKey = cachedSchemaKeyForMember(member.id, ctx);
70989
+ if (schemaKey === null || typeof receiver !== "object" || !Object.prototype.hasOwnProperty.call(receiver, schemaKey)) {
70990
+ throw new NSGetterRuntimeError(
70991
+ `NeoDelegate target '${member.name}' is missing from its receiver.`
70992
+ );
70993
+ }
70994
+ nested = resolveValueIfIdForMember(
70995
+ receiver[schemaKey],
70996
+ member,
70997
+ ctx
70998
+ );
70999
+ } else if (member.defaultValue !== void 0 && member.defaultValue !== null && isLiteralValueContent(member.defaultValue)) {
71000
+ nested = member.defaultValue.value;
71001
+ } else {
71002
+ throw new NSGetterRuntimeError(
71003
+ `NeoDelegate target '${member.name}' has no declaration default.`
71004
+ );
71005
+ }
71006
+ return invokeDelegateValue(nested, args, ctx);
71007
+ }
71008
+ throw new NSGetterRuntimeError(
71009
+ `NeoDelegate target '${member.name}' resolves to non-callable member kind ${MemberKind[member.kind]}.`
71010
+ );
71011
+ } finally {
71012
+ state.delegateStack.pop();
71013
+ }
71014
+ }
71015
+ function delegateClosureLexicalThis(closure, ctx) {
71016
+ if (Object.prototype.hasOwnProperty.call(closure, DELEGATE_LEXICAL_THIS)) {
71017
+ return closure[DELEGATE_LEXICAL_THIS];
71018
+ }
71019
+ const closureRow = trackedRowForValueReference(closure, ctx);
71020
+ if (closureRow === null) {
71021
+ throw new NSGetterRuntimeError(
71022
+ "Stored NeoDelegate closure has no resolvable value row; lexical this cannot be reconstructed from ownership."
71023
+ );
71024
+ }
71025
+ const owners = /* @__PURE__ */ new Map();
71026
+ for (const link of evaluatorIndexes(ctx).parentLinksByChildId.get(
71027
+ closureRow.id
71028
+ ) ?? []) {
71029
+ const parent = evalValueById(
71030
+ ctx.vm,
71031
+ link.parentId,
71032
+ ctx.__runtimeSessionValues,
71033
+ ctx.__valueOverlay
71034
+ );
71035
+ if (parent === null) continue;
71036
+ if (typeof parent.value !== "object") continue;
71037
+ if (parent.value === null) continue;
71038
+ if (Array.isArray(parent.value)) continue;
71039
+ const classId = classIdForValueRow(parent, ctx);
71040
+ if (classId === void 0) continue;
71041
+ const owningMember = memberForCustomSchemaValue(classId, link.key, ctx);
71042
+ if (owningMember?.kind !== 25 /* NSDelegate */) continue;
71043
+ owners.set(parent.id, parent.value);
71044
+ }
71045
+ if (owners.size === 0) {
71046
+ throw new NSGetterRuntimeError(
71047
+ `Stored NeoDelegate closure value '${closureRow.id}' has no owning class instance; lexical this cannot be reconstructed from ownership.`
71048
+ );
71049
+ }
71050
+ if (owners.size > 1) {
71051
+ throw new NSGetterRuntimeError(
71052
+ `Stored NeoDelegate closure value '${closureRow.id}' has multiple owning class instances (${[...owners.keys()].join(", ")}); lexical this is ambiguous.`
71053
+ );
71054
+ }
71055
+ const owner = owners.values().next();
71056
+ if (owner.done) {
71057
+ throw new NSGetterRuntimeError(
71058
+ `Stored NeoDelegate closure value '${closureRow.id}' lost its owning class instance during lexical-this resolution.`
71059
+ );
71060
+ }
71061
+ return owner.value;
71062
+ }
69709
71063
  function resolveCallableSignature(memberId, memberKind, ctx) {
69710
71064
  const cacheKey = `${memberKind}:${memberId}`;
69711
71065
  const cache = evaluatorResolutionCache(ctx).callableSignatureByKey;
@@ -70633,11 +71987,11 @@ function evalOperation(operation, scope, ctx) {
70633
71987
  if (operation.type === "arithmetic" /* arithmetic */) {
70634
71988
  const op = operation.arithmetic;
70635
71989
  const operands = op.pointers.map((p) => evalPointer(p, scope, ctx));
70636
- return applyArithmetic(op.type, operands, op.decimal === true);
71990
+ return applyArithmetic(op.type, operands, op.decimal === true, ctx);
70637
71991
  }
70638
71992
  return evalBooleanExpression(operation.expression, scope, ctx);
70639
71993
  }
70640
- function applyArithmetic(op, operands, decimal2) {
71994
+ function applyArithmetic(op, operands, decimal2, ctx) {
70641
71995
  if (operands.length === 0) {
70642
71996
  throw new NSGetterRuntimeError("Arithmetic operation with no operands");
70643
71997
  }
@@ -70645,10 +71999,24 @@ function applyArithmetic(op, operands, decimal2) {
70645
71999
  return applyDecimalArithmetic(op, operands);
70646
72000
  }
70647
72001
  if (op === "+" /* addition */ && operands.every((o) => typeof o === "string")) {
70648
- return operands.join("");
72002
+ const result = operands.join("");
72003
+ consumeBudget(
72004
+ ctx,
72005
+ "producedStringCharacters",
72006
+ result.length,
72007
+ "produced string character"
72008
+ );
72009
+ return result;
70649
72010
  }
70650
72011
  if (op === "+" /* addition */ && operands.some((o) => typeof o === "string")) {
70651
- return operands.map((o) => stringifyForInterp(o)).join("");
72012
+ const result = operands.map((o) => stringifyForInterp(o)).join("");
72013
+ consumeBudget(
72014
+ ctx,
72015
+ "producedStringCharacters",
72016
+ result.length,
72017
+ "produced string character"
72018
+ );
72019
+ return result;
70652
72020
  }
70653
72021
  const numbers = operands.map((o) => {
70654
72022
  if (typeof o === "number") return o;
@@ -71043,12 +72411,36 @@ function evalFunction(fn, scope, ctx) {
71043
72411
  );
71044
72412
  }
71045
72413
  switch (fn.info.op) {
71046
- case "toLower":
71047
- return receiver.toLowerCase();
71048
- case "toUpper":
71049
- return receiver.toUpperCase();
71050
- case "trim":
71051
- return receiver.trim();
72414
+ case "toLower": {
72415
+ const result = receiver.toLowerCase();
72416
+ consumeBudget(
72417
+ ctx,
72418
+ "producedStringCharacters",
72419
+ result.length,
72420
+ "produced string character"
72421
+ );
72422
+ return result;
72423
+ }
72424
+ case "toUpper": {
72425
+ const result = receiver.toUpperCase();
72426
+ consumeBudget(
72427
+ ctx,
72428
+ "producedStringCharacters",
72429
+ result.length,
72430
+ "produced string character"
72431
+ );
72432
+ return result;
72433
+ }
72434
+ case "trim": {
72435
+ const result = receiver.trim();
72436
+ consumeBudget(
72437
+ ctx,
72438
+ "producedStringCharacters",
72439
+ result.length,
72440
+ "produced string character"
72441
+ );
72442
+ return result;
72443
+ }
71052
72444
  case "startsWith":
71053
72445
  case "endsWith": {
71054
72446
  if (fn.info.argPointer === void 0) {
@@ -71073,6 +72465,7 @@ function evalFunction(fn, scope, ctx) {
71073
72465
  const isList = Array.isArray(c);
71074
72466
  const out = isList ? [] : {};
71075
72467
  iterateCollection(c, ctx, (entry, key, valueId) => {
72468
+ consumeBudget(ctx, "workUnits", 1, "work unit");
71076
72469
  const innerScope = pushParams(
71077
72470
  scope,
71078
72471
  innerFn.parameters,
@@ -71090,6 +72483,12 @@ function evalFunction(fn, scope, ctx) {
71090
72483
  evaluationOptions(ctx, false)
71091
72484
  );
71092
72485
  if (result.kind === "return" && result.value === true) {
72486
+ consumeBudget(
72487
+ ctx,
72488
+ "producedCollectionEntries",
72489
+ 1,
72490
+ "produced collection entry"
72491
+ );
71093
72492
  if (isList) {
71094
72493
  out.push(valueId ?? entry);
71095
72494
  } else {
@@ -71112,6 +72511,7 @@ function evalFunction(fn, scope, ctx) {
71112
72511
  found = entry;
71113
72512
  return;
71114
72513
  }
72514
+ consumeBudget(ctx, "workUnits", 1, "work unit");
71115
72515
  const innerScope = pushParams(
71116
72516
  scope,
71117
72517
  innerFn.parameters,
@@ -71142,6 +72542,7 @@ function evalFunction(fn, scope, ctx) {
71142
72542
  const isList = Array.isArray(c);
71143
72543
  const out = [];
71144
72544
  iterateCollection(c, ctx, (entry, key) => {
72545
+ consumeBudget(ctx, "workUnits", 1, "work unit");
71145
72546
  const innerScope = pushParams(
71146
72547
  scope,
71147
72548
  innerFn.parameters,
@@ -71155,6 +72556,12 @@ function evalFunction(fn, scope, ctx) {
71155
72556
  evaluationOptions(ctx, false)
71156
72557
  );
71157
72558
  if (result.kind === "return") {
72559
+ consumeBudget(
72560
+ ctx,
72561
+ "producedCollectionEntries",
72562
+ 1,
72563
+ "produced collection entry"
72564
+ );
71158
72565
  out.push(result.value);
71159
72566
  }
71160
72567
  });
@@ -71530,6 +72937,25 @@ function publishConstructedRows(args) {
71530
72937
  "Class construction requires an effect-capable evaluator Session scope."
71531
72938
  );
71532
72939
  }
72940
+ consumeBudget(
72941
+ ctx,
72942
+ "constructedSessionRows",
72943
+ createdValues.length,
72944
+ "constructed Session row"
72945
+ );
72946
+ let producedEntries = 0;
72947
+ for (const row of createdValues) {
72948
+ if (Array.isArray(row.value)) producedEntries += row.value.length;
72949
+ else if (typeof row.value === "object" && row.value !== null) {
72950
+ producedEntries += Object.keys(row.value).length;
72951
+ }
72952
+ }
72953
+ consumeBudget(
72954
+ ctx,
72955
+ "producedCollectionEntries",
72956
+ producedEntries,
72957
+ "produced collection entry"
72958
+ );
71533
72959
  const retained = new Set(createdValues.map((row) => row.id));
71534
72960
  for (const rowId of beforeRetain) {
71535
72961
  if (retained.has(rowId)) continue;
@@ -72942,9 +74368,10 @@ function collectionLength(c) {
72942
74368
  `Cannot Count() ${typeof c}; expected list, dictionary, or string`
72943
74369
  );
72944
74370
  }
72945
- function snapshotCollectionMembership(collection) {
74371
+ function snapshotCollectionMembership(collection, ctx) {
72946
74372
  const membership = [];
72947
74373
  const valid = forEachRawCollectionEntry(collection, ({ raw }) => {
74374
+ consumeBudget(ctx, "collectionVisits", 1, "collection visit");
72948
74375
  membership.push(raw);
72949
74376
  });
72950
74377
  if (valid) return membership;
@@ -72979,12 +74406,14 @@ function forEachRawCollectionEntry(c, callback) {
72979
74406
  function collectionEntries(c, ctx) {
72980
74407
  const entries = [];
72981
74408
  forEachRawCollectionEntry(c, ({ raw }) => {
74409
+ consumeBudget(ctx, "collectionVisits", 1, "collection visit");
72982
74410
  entries.push(resolveValueIfId(raw, ctx));
72983
74411
  });
72984
74412
  return entries;
72985
74413
  }
72986
74414
  function iterateCollection(c, ctx, callback) {
72987
74415
  forEachRawCollectionEntry(c, ({ raw, key, valueId }) => {
74416
+ consumeBudget(ctx, "collectionVisits", 1, "collection visit");
72988
74417
  const entry = resolveValueIfId(raw, ctx);
72989
74418
  callback(entry, key, valueId);
72990
74419
  });
@@ -73000,7 +74429,7 @@ function pushParams(parent, parameters, positional, isList) {
73000
74429
  }
73001
74430
  return child;
73002
74431
  }
73003
- var NonCatchableNSGetterRuntimeError, NativeFunctionDelegateUnavailableError, CorruptNeoScriptIRError, liveListIndexesByProject, MAX_CONSTRUCTION_DEPTH, MAX_LOOP_ITERATIONS, LazyValueOverlay, readonlyBindingErrorsByScope, READONLY_FOREACH_BINDING_ERROR, READONLY_CATCH_BINDING_ERROR;
74432
+ var DELEGATE_LEXICAL_THIS, DELEGATE_LEXICAL_ROOT, NonCatchableNSGetterRuntimeError, NativeFunctionDelegateUnavailableError, CorruptNeoScriptIRError, NeoScriptResourceLimitError, DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS, liveListIndexesByProject, MAX_CONSTRUCTION_DEPTH, MAX_LOOP_ITERATIONS, LazyValueOverlay, readonlyBindingErrorsByScope, READONLY_FOREACH_BINDING_ERROR, READONLY_CATCH_BINDING_ERROR;
73004
74433
  var init_evaluateNSGetter = __esm({
73005
74434
  "../src/view-models/neoscript-evaluator/evaluateNSGetter.ts"() {
73006
74435
  "use strict";
@@ -73016,12 +74445,27 @@ var init_evaluateNSGetter = __esm({
73016
74445
  init_core();
73017
74446
  init_member_storage_key();
73018
74447
  init_project2();
74448
+ DELEGATE_LEXICAL_THIS = /* @__PURE__ */ Symbol("neoDelegateLexicalThis");
74449
+ DELEGATE_LEXICAL_ROOT = /* @__PURE__ */ Symbol("neoDelegateLexicalRoot");
73019
74450
  NonCatchableNSGetterRuntimeError = class extends NSGetterRuntimeError {
73020
74451
  };
73021
74452
  NativeFunctionDelegateUnavailableError = class extends NonCatchableNSGetterRuntimeError {
73022
74453
  };
73023
74454
  CorruptNeoScriptIRError = class extends NonCatchableNSGetterRuntimeError {
73024
74455
  };
74456
+ NeoScriptResourceLimitError = class extends NonCatchableNSGetterRuntimeError {
74457
+ constructor(message) {
74458
+ super(message);
74459
+ this.name = "NeoScriptResourceLimitError";
74460
+ }
74461
+ };
74462
+ DEFAULT_NEO_SCRIPT_EXECUTION_BUDGET_LIMITS = Object.freeze({
74463
+ workUnits: 1e5,
74464
+ collectionVisits: 1e5,
74465
+ producedCollectionEntries: 1e4,
74466
+ constructedSessionRows: 1e3,
74467
+ producedStringCharacters: 1024 * 1024
74468
+ });
73025
74469
  liveListIndexesByProject = /* @__PURE__ */ new WeakMap();
73026
74470
  MAX_CONSTRUCTION_DEPTH = 64;
73027
74471
  MAX_LOOP_ITERATIONS = 1e4;
@@ -74281,6 +75725,58 @@ function compileAuthoredMemberBodies(args) {
74281
75725
  compileNSPropertyBodies(args);
74282
75726
  compileNSFunctionBody(args);
74283
75727
  compileMemberInitializerBody(args);
75728
+ compileMemberDelegateDefault(args);
75729
+ }
75730
+ function compileDelegateClosureValue(code, signature) {
75731
+ const compiled = compileNSGetter(`return ${code};`, {
75732
+ project: signature.project,
75733
+ projectFiles: signature.projectFiles ?? [],
75734
+ members: [...signature.members],
75735
+ classes: [...signature.classes],
75736
+ enums: [...signature.enums],
75737
+ interfaces: [...signature.interfaces ?? []],
75738
+ constructors: [...signature.constructors ?? []],
75739
+ thisClass: signature.thisClass,
75740
+ returnTypeInfo: {
75741
+ type: 25 /* NSDelegate */,
75742
+ required: true,
75743
+ returnTypeInfo: signature.returnTypeInfo,
75744
+ argumentTypes: [...signature.argumentTypes]
75745
+ },
75746
+ functionName: signature.name
75747
+ });
75748
+ const instruction = compiled.instructions[0];
75749
+ if (compiled.instructions.length !== 1 || instruction?.type !== "return" /* return */ || instruction.pointer?.type !== "value" /* value */) {
75750
+ throw new Error(
75751
+ `NeoDelegate closure "${signature.name}" did not compile to one closure literal.`
75752
+ );
75753
+ }
75754
+ const value = instruction.pointer.value.value;
75755
+ if (!value || typeof value !== "object" || !("action" in value)) {
75756
+ throw new Error(
75757
+ `NeoDelegate closure "${signature.name}" compiled without an action.`
75758
+ );
75759
+ }
75760
+ const action = value.action;
75761
+ if (!isNSFunctionWithReturnType(action)) {
75762
+ throw new Error(
75763
+ `NeoDelegate closure "${signature.name}" compiled an invalid action.`
75764
+ );
75765
+ }
75766
+ return { code, action };
75767
+ }
75768
+ function compileMemberDelegateDefault(args) {
75769
+ if (!isMemberDelegateBase(args.member)) return;
75770
+ const defaultValue = args.member.defaultValue;
75771
+ if (defaultValue === void 0 || !isLiteralValueContent(defaultValue) || !isNSDelegateClosureValueDraft(defaultValue.value)) {
75772
+ return;
75773
+ }
75774
+ defaultValue.value = compileDelegateClosureValue(defaultValue.value.code, {
75775
+ ...args,
75776
+ returnTypeInfo: args.member.returnTypeInfo,
75777
+ argumentTypes: args.member.argumentTypes,
75778
+ name: args.member.name
75779
+ });
74284
75780
  }
74285
75781
  function compileConstructorRecord(args) {
74286
75782
  const owner = args.classes.find(
@@ -74523,6 +76019,18 @@ function resolveMemberDeclaredTypeInfo(member, members) {
74523
76019
  enumId: resolved.enumId
74524
76020
  };
74525
76021
  }
76022
+ if (isMemberDelegateBase(resolved)) {
76023
+ return {
76024
+ type: 25 /* NSDelegate */,
76025
+ required: resolved.required,
76026
+ returnTypeInfo: resolved.returnTypeInfo,
76027
+ argumentTypes: resolved.argumentTypes.map((argument2) => {
76028
+ const { name, ...typeInfo } = argument2;
76029
+ void name;
76030
+ return typeInfo;
76031
+ })
76032
+ };
76033
+ }
74526
76034
  if (isMemberListBase(resolved) || isMemberDictionaryBase(resolved)) {
74527
76035
  const entry = members.find(
74528
76036
  (candidate) => candidate.id === resolved.entryMemberId
@@ -81029,7 +82537,7 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
81029
82537
  );
81030
82538
  }
81031
82539
  auditAuthoredSeedRowIdentities(
81032
- status.staticValueSeeds,
82540
+ status.authoredValueSeeds,
81033
82541
  args.stateRecords,
81034
82542
  assignments
81035
82543
  );
@@ -81048,7 +82556,7 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
81048
82556
  expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
81049
82557
  };
81050
82558
  });
81051
- const expectedSeeds = [...status.staticValueSeeds].map(
82559
+ const expectedSeeds = [...status.authoredValueSeeds].map(
81052
82560
  ([memberId, seed]) => ({
81053
82561
  memberId: rewritePending(memberId, assignments, usedAssignments),
81054
82562
  value: rewritePending(seed.value, assignments, usedAssignments),
@@ -81092,7 +82600,7 @@ function verifyProjectSourceCommitAgainstStateV4(args) {
81092
82600
  return !isDerivedOnlyRefresh(change, args.stateRecords);
81093
82601
  });
81094
82602
  compareChanges(expectedChanges, verifiableChanges);
81095
- compareSeeds(expectedSeeds, args.staticValueSeeds);
82603
+ compareSeeds(expectedSeeds, args.authoredValueSeeds);
81096
82604
  }
81097
82605
  function isDerivedOnlyRefresh(change, stateRecords) {
81098
82606
  if (change.operation !== "update") return false;
@@ -82325,7 +83833,7 @@ var init_general_function_call_ir_source_recompile = __esm({
82325
83833
  });
82326
83834
 
82327
83835
  // ../src/database/project-version-transaction-types.ts
82328
- function isStaticMemberValueSeedInitContent(content) {
83836
+ function isAuthoredValueSeedInitContent(content) {
82329
83837
  return content.init !== void 0;
82330
83838
  }
82331
83839
  var init_project_version_transaction_types = __esm({
@@ -83932,10 +85440,10 @@ function prepareServerOwnedSchemaCommit(args) {
83932
85440
  requiresCompleteSweep,
83933
85441
  contentHashHeads: args.contentHashHeads
83934
85442
  });
83935
- materializeStaticValueSeeds({
85443
+ materializeAuthoredValueSeeds({
83936
85444
  document: applyProjectVersionWriteChanges(postDocument, prepared),
83937
85445
  prepared,
83938
- staticValueSeeds: args.staticValueSeeds ?? []
85446
+ authoredValueSeeds: args.authoredValueSeeds ?? []
83939
85447
  });
83940
85448
  prepareServerOwnedValueInitializerBodies({
83941
85449
  document: args.document,
@@ -83944,6 +85452,13 @@ function prepareServerOwnedSchemaCommit(args) {
83944
85452
  requiresCompleteSweep,
83945
85453
  contentHashHeads: args.contentHashHeads
83946
85454
  });
85455
+ prepareServerOwnedDelegateValueBodies({
85456
+ document: args.document,
85457
+ postDocument,
85458
+ prepared,
85459
+ requiresCompleteSweep,
85460
+ contentHashHeads: args.contentHashHeads
85461
+ });
83947
85462
  const committedDocument = applyProjectVersionWriteChanges(
83948
85463
  args.document,
83949
85464
  prepared
@@ -84727,13 +86242,13 @@ function drainConstructedGraphValidations(args) {
84727
86242
  });
84728
86243
  }
84729
86244
  }
84730
- function materializeStaticValueSeeds(args) {
86245
+ function materializeAuthoredValueSeeds(args) {
84731
86246
  const pendingGraphValidations = [];
84732
86247
  materializeStaticSeedBindingMembers(args);
84733
86248
  const seedByMemberId = new Map(
84734
- args.staticValueSeeds.map((seed) => [seed.memberId, seed])
86249
+ args.authoredValueSeeds.map((seed) => [seed.memberId, seed])
84735
86250
  );
84736
- if (seedByMemberId.size !== args.staticValueSeeds.length) {
86251
+ if (seedByMemberId.size !== args.authoredValueSeeds.length) {
84737
86252
  throw new Error("Schema commit contains duplicate member value seeds.");
84738
86253
  }
84739
86254
  const consumedSeedMemberIds = /* @__PURE__ */ new Set();
@@ -84891,9 +86406,9 @@ function materializeStaticValueSeeds(args) {
84891
86406
  });
84892
86407
  }
84893
86408
  }
84894
- for (const seed of args.staticValueSeeds) {
86409
+ for (const seed of args.authoredValueSeeds) {
84895
86410
  if (consumedSeedMemberIds.has(seed.memberId)) continue;
84896
- materializeExistingStaticValueSeed({
86411
+ materializeExistingAuthoredValueSeed({
84897
86412
  document: args.document,
84898
86413
  prepared: args.prepared,
84899
86414
  pendingGraphValidations,
@@ -84907,7 +86422,7 @@ function materializeStaticValueSeeds(args) {
84907
86422
  pending: pendingGraphValidations
84908
86423
  });
84909
86424
  }
84910
- function materializeExistingStaticValueSeed(args) {
86425
+ function materializeExistingAuthoredValueSeed(args) {
84911
86426
  const member = args.document.members.find(
84912
86427
  (candidate) => candidate.id === args.seed.memberId
84913
86428
  );
@@ -85008,7 +86523,7 @@ function materializeExistingStaticValueSeed(args) {
85008
86523
  }
85009
86524
  }
85010
86525
  function materializeStaticSeedBindingMembers(args) {
85011
- const bindings = args.staticValueSeeds.flatMap(
86526
+ const bindings = args.authoredValueSeeds.flatMap(
85012
86527
  (seed) => seed.bindingMembers ?? []
85013
86528
  );
85014
86529
  const ids = new Set(bindings.map((binding) => binding.id));
@@ -85329,14 +86844,14 @@ function materializeSeedLocalizableStringWrites(args) {
85329
86844
  return [...args.seededLocalizedTexts, ...generatedTexts];
85330
86845
  }
85331
86846
  function seedValueContent(seed) {
85332
- if (isStaticMemberValueSeedInitContent(seed)) return { init: seed.init };
86847
+ if (isAuthoredValueSeedInitContent(seed)) return { init: seed.init };
85333
86848
  return {
85334
86849
  value: seed.value,
85335
86850
  ...seed.classId === null ? {} : { classId: seed.classId }
85336
86851
  };
85337
86852
  }
85338
86853
  function seedRootRow(member, seed, rootId) {
85339
- if (isStaticMemberValueSeedInitContent(seed)) {
86854
+ if (isAuthoredValueSeedInitContent(seed)) {
85340
86855
  return { id: rootId, memberId: member.id, init: seed.init };
85341
86856
  }
85342
86857
  return {
@@ -85347,7 +86862,7 @@ function seedRootRow(member, seed, rootId) {
85347
86862
  };
85348
86863
  }
85349
86864
  function authoredSeedRowMatchesValue(row, value) {
85350
- if (isStaticMemberValueSeedInitContent(row)) {
86865
+ if (isAuthoredValueSeedInitContent(row)) {
85351
86866
  return isInitValueContent(value) && value.init.code === row.init.code;
85352
86867
  }
85353
86868
  if (isInitValueContent(value)) return false;
@@ -85421,7 +86936,7 @@ function materializeAuthoredSeedRow(args) {
85421
86936
  );
85422
86937
  }
85423
86938
  if (args.authoredRows.has(args.row.id)) args.usedRows.add(args.row.id);
85424
- if (isStaticMemberValueSeedInitContent(args.row)) {
86939
+ if (isAuthoredValueSeedInitContent(args.row)) {
85425
86940
  const initRow = {
85426
86941
  id: args.row.id,
85427
86942
  projectId: args.document.project.id,
@@ -85945,6 +87460,119 @@ function prepareServerOwnedValueInitializerBodies(args) {
85945
87460
  });
85946
87461
  }
85947
87462
  }
87463
+ function delegateValueRow(value) {
87464
+ if (!isMemberValue(value) || !isLiteralValueContent(value)) return null;
87465
+ if (!isNSDelegateClosureValueDraft(value.value) && !isNSDelegateClosureValue(value.value)) {
87466
+ return null;
87467
+ }
87468
+ return typeof value.value.code === "string" ? value : null;
87469
+ }
87470
+ function prepareServerOwnedDelegateValueBodies(args) {
87471
+ const explicitRows = /* @__PURE__ */ new Map();
87472
+ for (let index = 0; index < args.prepared.length; index += 1) {
87473
+ const change = args.prepared[index];
87474
+ if (change?.recordKind !== "value" || change.operation === "delete") {
87475
+ continue;
87476
+ }
87477
+ const row = delegateValueRow(change.nextData);
87478
+ if (row !== null) explicitRows.set(index, row);
87479
+ }
87480
+ const sweepRows = args.requiresCompleteSweep ? args.postDocument.values.filter(
87481
+ (value) => delegateValueRow(value) !== null && !args.prepared.some(
87482
+ (change) => change.recordKind === "value" && change.recordId === value.id
87483
+ )
87484
+ ) : [];
87485
+ if (explicitRows.size === 0 && sweepRows.length === 0) return;
87486
+ const committedDocument = applyProjectVersionWriteChanges(
87487
+ args.postDocument,
87488
+ args.prepared
87489
+ );
87490
+ const targetIds = /* @__PURE__ */ new Set([
87491
+ ...[...explicitRows.values()].map((row) => row.id),
87492
+ ...sweepRows.map((row) => row.id)
87493
+ ]);
87494
+ const rootOwnerByValueId = /* @__PURE__ */ new Map();
87495
+ const ownerByValueId = resolveOwnerMembersForValues(
87496
+ committedDocument,
87497
+ targetIds,
87498
+ void 0,
87499
+ rootOwnerByValueId
87500
+ );
87501
+ const compileOne = (document, row) => {
87502
+ const member = ownerByValueId.get(row.id);
87503
+ if (!isMemberDelegateBase(member)) {
87504
+ throw new Error(
87505
+ `Value "${row.id}" carries a NeoDelegate closure but no NeoDelegate member in this project version stores it.`
87506
+ );
87507
+ }
87508
+ row.value = compileDelegateClosureValue(row.value.code, {
87509
+ project: document.project,
87510
+ projectFiles: document.projectFiles,
87511
+ members: document.members,
87512
+ classes: document.classes,
87513
+ enums: document.enums,
87514
+ interfaces: document.interfaces,
87515
+ constructors: document.constructors ?? [],
87516
+ thisClass: findSchemaPlacement(
87517
+ rootOwnerByValueId.get(row.id)?.id ?? "",
87518
+ document.classes
87519
+ )?.ownerClass ?? null,
87520
+ returnTypeInfo: member.returnTypeInfo,
87521
+ argumentTypes: member.argumentTypes,
87522
+ name: `${member.name} value`
87523
+ });
87524
+ };
87525
+ for (const [index, row] of explicitRows) {
87526
+ const compiled = { ...row, value: { ...row.value } };
87527
+ compileOne(committedDocument, compiled);
87528
+ const change = args.prepared[index];
87529
+ if (change !== void 0) {
87530
+ args.prepared[index] = { ...change, nextData: compiled };
87531
+ }
87532
+ }
87533
+ if (sweepRows.length === 0) return;
87534
+ const currentById = new Map(
87535
+ args.document.values.map((value) => [value.id, value])
87536
+ );
87537
+ const hashById = new Map(
87538
+ args.contentHashHeads.filter((head) => head.recordKind === "value" && !head.deleted).map((head) => [head.recordId, head.contentHash])
87539
+ );
87540
+ for (const row of sweepRows) {
87541
+ const compiled = { ...row, value: { ...row.value } };
87542
+ try {
87543
+ compileOne(committedDocument, compiled);
87544
+ } catch (postWriteError) {
87545
+ const current2 = delegateValueRow(
87546
+ structuredClone(currentById.get(row.id))
87547
+ );
87548
+ if (current2 === null) throw postWriteError;
87549
+ try {
87550
+ compileOne(args.document, current2);
87551
+ } catch (preWriteError) {
87552
+ if (sameCompileFailure(preWriteError, postWriteError)) continue;
87553
+ }
87554
+ throw postWriteError;
87555
+ }
87556
+ const current = currentById.get(row.id);
87557
+ if (current === void 0 || canonicallyEqual2(current, compiled)) continue;
87558
+ const contentHash = hashById.get(row.id);
87559
+ if (contentHash === void 0) {
87560
+ throw new Error(
87561
+ `Cannot safely refresh the compiled NeoDelegate closure for value "${row.id}": its current content hash is unavailable.`
87562
+ );
87563
+ }
87564
+ args.prepared.push({
87565
+ recordKind: "value",
87566
+ recordId: row.id,
87567
+ operation: "update",
87568
+ nextData: compiled,
87569
+ intent: createProjectVersionIntent("value.update", {
87570
+ source: "server-neoscript-recompile"
87571
+ }),
87572
+ expectedBaseContentHash: contentHash
87573
+ });
87574
+ }
87575
+ }
85948
87576
  function prepareServerOwnedConstructorBodies(args) {
85949
87577
  const currentById = new Map(
85950
87578
  (args.document.constructors ?? []).map((record3) => [record3.id, record3])
@@ -86234,6 +87862,7 @@ function cloneAndStripClientDerivedBodies(change) {
86234
87862
  if (nextData2 === null) return { ...change, nextData: change.nextData };
86235
87863
  const stripped = { ...nextData2 };
86236
87864
  stripInitializerCompanion(stripped, "init");
87865
+ stripDelegateClosureCompanion(stripped, "value");
86237
87866
  return { ...change, nextData: stripped };
86238
87867
  }
86239
87868
  if (change.recordKind !== "member") {
@@ -86312,9 +87941,26 @@ function stripDerivedBodies(member) {
86312
87941
  if (member.kind === 23 /* NSFunction */) {
86313
87942
  delete next.action;
86314
87943
  }
87944
+ if (member.kind === 25 /* NSDelegate */) {
87945
+ stripDelegateClosureCompanion(next, "defaultValue");
87946
+ }
86315
87947
  stripInitializerCompanion(next, "defaultValue");
86316
87948
  return next;
86317
87949
  }
87950
+ function stripDelegateClosureCompanion(record3, field) {
87951
+ const container = field === "value" ? record3 : asRecord2(record3.defaultValue);
87952
+ if (container === null) return;
87953
+ const delegate = asRecord2(container.value);
87954
+ if (delegate === null || typeof delegate.code !== "string") return;
87955
+ if (!("action" in delegate)) return;
87956
+ const authoredDelegate = { ...delegate };
87957
+ delete authoredDelegate.action;
87958
+ if (field === "value") {
87959
+ record3.value = authoredDelegate;
87960
+ return;
87961
+ }
87962
+ record3.defaultValue = { ...container, value: authoredDelegate };
87963
+ }
86318
87964
  function stripInitializerCompanion(record3, field) {
86319
87965
  const container = field === "init" ? record3 : asRecord2(record3.defaultValue);
86320
87966
  if (container === null) return;
@@ -89409,7 +91055,7 @@ function runServerPreparation(args) {
89409
91055
  document,
89410
91056
  contentHashHeads,
89411
91057
  changes: trustedChanges,
89412
- staticValueSeeds: args.staticValueSeeds,
91058
+ authoredValueSeeds: args.authoredValueSeeds,
89413
91059
  // A CLI push is always a trusted-source commit, so the server always
89414
91060
  // expands read-only source conversions for it.
89415
91061
  expandReadOnlySourceConversions: true
@@ -89683,7 +91329,7 @@ import {
89683
91329
  readFileSync as readFileSync14
89684
91330
  } from "node:fs";
89685
91331
  import { dirname as dirname7, join as join17, relative as relative5, sep as sep5 } from "node:path";
89686
- function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
91332
+ function assignPendingIds(changes, authoredValueSeeds, reconstructed3) {
89687
91333
  const assigned = /* @__PURE__ */ new Map();
89688
91334
  const assign = (pendingId2) => {
89689
91335
  const existing = assigned.get(pendingId2);
@@ -89732,7 +91378,7 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
89732
91378
  collect(change.recordId);
89733
91379
  collect(change.nextData);
89734
91380
  }
89735
- for (const [memberId, seed] of staticValueSeeds) {
91381
+ for (const [memberId, seed] of authoredValueSeeds) {
89736
91382
  collect(memberId);
89737
91383
  collect(seed);
89738
91384
  }
@@ -89778,7 +91424,7 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
89778
91424
  }
89779
91425
  }
89780
91426
  const rewrittenSeeds = /* @__PURE__ */ new Map();
89781
- for (const [memberId, seed] of staticValueSeeds) {
91427
+ for (const [memberId, seed] of authoredValueSeeds) {
89782
91428
  const rewrittenId = rewrite(memberId);
89783
91429
  if (typeof rewrittenId !== "string") {
89784
91430
  throw new Error(
@@ -89840,7 +91486,7 @@ function assignPendingIds(changes, staticValueSeeds, reconstructed3) {
89840
91486
  reconstructed3.set(key, record3);
89841
91487
  }
89842
91488
  }
89843
- return { assigned, staticValueSeeds: rewrittenSeeds };
91489
+ return { assigned, authoredValueSeeds: rewrittenSeeds };
89844
91490
  }
89845
91491
  function readAcceptedProjectVersionCommitResponse(value) {
89846
91492
  if (!isObjectRecord2(value) || value.kind !== "accepted") return null;
@@ -90310,7 +91956,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
90310
91956
  type: "push-plan",
90311
91957
  dryRun: options.dryRun,
90312
91958
  changeCount: status.changes.length,
90313
- staticValueSeedCount: status.staticValueSeeds.size,
91959
+ staticValueSeedCount: status.authoredValueSeeds.size,
90314
91960
  changes: status.changes.map((change) => ({
90315
91961
  kind: change.kind,
90316
91962
  recordKind: change.recordKind,
@@ -90335,9 +91981,9 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
90335
91981
  }
90336
91982
  }
90337
91983
  }
90338
- if (status.staticValueSeeds.size > 0) {
91984
+ if (status.authoredValueSeeds.size > 0) {
90339
91985
  console.log(
90340
- ` ${color.dim(`create ${status.staticValueSeeds.size} member value seed(s)`)}`
91986
+ ` ${color.dim(`create ${status.authoredValueSeeds.size} member value seed(s)`)}`
90341
91987
  );
90342
91988
  }
90343
91989
  }
@@ -90403,7 +92049,7 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
90403
92049
  {
90404
92050
  operation: transactionOperation,
90405
92051
  changes: transportChanges,
90406
- staticValueSeeds: transportSeeds,
92052
+ authoredValueSeeds: transportSeeds,
90407
92053
  stagedFiles,
90408
92054
  sourceBundle: source.bundle,
90409
92055
  pendingIdAssignments: Object.fromEntries(pendingAssignment.assigned),
@@ -90617,11 +92263,11 @@ async function prepareLocalPushArtifactsV4(workspace, status) {
90617
92263
  const source = await createPendingProjectSourceBundleV4(
90618
92264
  workspace,
90619
92265
  status,
90620
- status.staticValueSeeds
92266
+ status.authoredValueSeeds
90621
92267
  );
90622
92268
  const pendingAssignment = assignPendingIds(
90623
92269
  status.changes,
90624
- status.staticValueSeeds,
92270
+ status.authoredValueSeeds,
90625
92271
  status.reconstructed
90626
92272
  );
90627
92273
  const operations = new Set(status.changes.map((change) => change.kind));
@@ -90635,7 +92281,7 @@ async function prepareLocalPushArtifactsV4(workspace, status) {
90635
92281
  intent: createNeoCliPushIntent(change),
90636
92282
  expectedBaseContentHash: change.kind === "create" ? null : change.casBaseHash ?? null
90637
92283
  }));
90638
- const transportSeeds = [...pendingAssignment.staticValueSeeds].map(
92284
+ const transportSeeds = [...pendingAssignment.authoredValueSeeds].map(
90639
92285
  ([memberId, seed]) => ({ memberId, ...seed })
90640
92286
  );
90641
92287
  const preparedFiles = prepareProjectFilePushesV4({
@@ -90654,14 +92300,14 @@ async function prepareLocalPushArtifactsV4(workspace, status) {
90654
92300
  stateRecords: workspace.state.records,
90655
92301
  files: source.files,
90656
92302
  changes: transportChanges,
90657
- staticValueSeeds: transportSeeds,
92303
+ authoredValueSeeds: transportSeeds,
90658
92304
  pendingIdAssignments: Object.fromEntries(pendingAssignment.assigned),
90659
92305
  stagedFiles: preparedFiles
90660
92306
  });
90661
92307
  assertServerPreparationSucceeds({
90662
92308
  workspace,
90663
92309
  changes: transportChanges,
90664
- staticValueSeeds: transportSeeds,
92310
+ authoredValueSeeds: transportSeeds,
90665
92311
  sourceByRecord: status.reconstructed
90666
92312
  });
90667
92313
  return {
@@ -90725,7 +92371,7 @@ function cloneStatusForDryRun(status) {
90725
92371
  return {
90726
92372
  ...status,
90727
92373
  changes: structuredClone(status.changes),
90728
- staticValueSeeds: structuredClone(status.staticValueSeeds),
92374
+ authoredValueSeeds: structuredClone(status.authoredValueSeeds),
90729
92375
  reconstructed: structuredClone(status.reconstructed)
90730
92376
  };
90731
92377
  }
@@ -90743,7 +92389,7 @@ function reportDryRunFailure(error, json) {
90743
92389
  }
90744
92390
  console.error(`Dry run failed: ${message}`);
90745
92391
  }
90746
- async function createPendingProjectSourceBundleV4(workspace, status, staticValueSeeds) {
92392
+ async function createPendingProjectSourceBundleV4(workspace, status, authoredValueSeeds) {
90747
92393
  const records2 = /* @__PURE__ */ new Map();
90748
92394
  for (const [key, state] of Object.entries(workspace.state.records)) {
90749
92395
  records2.set(key, {
@@ -90783,7 +92429,7 @@ async function createPendingProjectSourceBundleV4(workspace, status, staticValue
90783
92429
  (record3) => record3.recordKind === "localization-config"
90784
92430
  );
90785
92431
  const mainLocale = isObjectRecord2(localizationConfig?.data) && typeof localizationConfig.data.mainLocale === "string" ? localizationConfig.data.mainLocale : "en-US";
90786
- for (const seed of staticValueSeeds.values()) {
92432
+ for (const seed of authoredValueSeeds.values()) {
90787
92433
  for (const bindingMember of seed.bindingMembers ?? []) {
90788
92434
  records2.set(`member:${bindingMember.id}`, {
90789
92435
  recordKind: "member",