@neocompose/cli 0.22.4 → 0.22.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.22.5] - 2026-08-04
4
+
5
+ ### Fixed
6
+
7
+ - Pull reconstructs required constructor calls from legacy declaration rows
8
+ whose projected fields remain initializer-backed, including animation segment
9
+ frames that depend on their declaring class's parameters.
10
+ - Existing call-site initializer blocks may repeat a field settled by a required
11
+ constructor, preserving the language's normal last-write-wins semantics while
12
+ old canonical source converges.
13
+ - System-schema repair restores tombstoned constructor-projected declaration
14
+ rows, rewrites only callers that reference retired member identities, and
15
+ recompiles only the impacted records through the normal push pipeline.
16
+
3
17
  ## [0.22.4] - 2026-08-04
4
18
 
5
19
  ### Fixed
package/dist/neo.mjs CHANGED
@@ -8954,7 +8954,8 @@ var init_strict_resolver = __esm({
8954
8954
  className,
8955
8955
  expression,
8956
8956
  scope,
8957
- expression.pos
8957
+ expression.pos,
8958
+ expected
8958
8959
  );
8959
8960
  }
8960
8961
  if (expression.argumentNames && !projectionCall) {
@@ -10588,7 +10589,7 @@ var init_strict_resolver = __esm({
10588
10589
  * the call site's initializer block is carried through to be applied last
10589
10590
  * (§6.1 step 4).
10590
10591
  */
10591
- resolveDeclaredConstructor(className, expression, scope, pos) {
10592
+ resolveDeclaredConstructor(className, expression, scope, pos, expected) {
10592
10593
  const schemaClass2 = this.project.typeByName.get(className);
10593
10594
  if (!schemaClass2 || schemaClass2.kind !== "class") {
10594
10595
  throw new CompileError(
@@ -10608,7 +10609,24 @@ var init_strict_resolver = __esm({
10608
10609
  pos
10609
10610
  );
10610
10611
  }
10611
- const declared = schemaClass2.declaredConstructors ?? [];
10612
+ const targetType = this.constructorTargetType(
10613
+ schemaClass2,
10614
+ expression,
10615
+ expected
10616
+ );
10617
+ const declared = (schemaClass2.declaredConstructors ?? []).map(
10618
+ (constructor2) => ({
10619
+ ...constructor2,
10620
+ parameters: constructor2.parameters.map((parameter3) => ({
10621
+ ...parameter3,
10622
+ type: substituteTypeParameters(
10623
+ parameter3.type,
10624
+ targetType,
10625
+ schemaClass2
10626
+ )
10627
+ }))
10628
+ })
10629
+ );
10612
10630
  const argumentNames = expression.args.map(
10613
10631
  (_, index) => expression.argumentNames?.[index] ?? null
10614
10632
  );
@@ -10649,10 +10667,7 @@ var init_strict_resolver = __esm({
10649
10667
  expression,
10650
10668
  scope
10651
10669
  );
10652
- const classType = {
10653
- kind: "named",
10654
- typeId: schemaClass2.id
10655
- };
10670
+ const classType = targetType;
10656
10671
  const schemaClassInfo = toWireType(classType, this.project);
10657
10672
  if (schemaClassInfo.type !== 7 /* Class */) {
10658
10673
  throw new Error(
@@ -38855,8 +38870,145 @@ function substituteMember(member, env, members) {
38855
38870
  };
38856
38871
  return substituted;
38857
38872
  }
38873
+ if (isMemberDelegateBase(resolved)) {
38874
+ const returnTypeInfo = substituteNestedTypeInfo(
38875
+ resolved.returnTypeInfo,
38876
+ env,
38877
+ members
38878
+ );
38879
+ let argumentsChanged = false;
38880
+ const argumentTypes = resolved.argumentTypes.map((argument2) => {
38881
+ const substituted2 = substituteNestedTypeInfo(argument2, env, members);
38882
+ if (substituted2 === argument2) return argument2;
38883
+ argumentsChanged = true;
38884
+ return { ...substituted2, name: argument2.name };
38885
+ });
38886
+ if (returnTypeInfo === resolved.returnTypeInfo && !argumentsChanged) {
38887
+ return resolved;
38888
+ }
38889
+ const substituted = {
38890
+ ...resolved,
38891
+ returnTypeInfo,
38892
+ argumentTypes
38893
+ };
38894
+ return substituted;
38895
+ }
38858
38896
  return resolved;
38859
38897
  }
38898
+ function substituteNestedTypeInfo(typeInfo, env, members) {
38899
+ if (typeInfo.type === 21 /* Generic */) {
38900
+ const entry = env.get(typeInfo.genericParamId);
38901
+ if (entry === void 0) {
38902
+ throw new Error(
38903
+ `substituteMember: callable type references generic param "${typeInfo.genericParamId}", which is not present in the binding environment.`
38904
+ );
38905
+ }
38906
+ if (entry.kind === "unbound") return typeInfo;
38907
+ const binding = members.find(
38908
+ (candidate) => candidate.id === entry.memberId
38909
+ );
38910
+ if (binding === void 0) {
38911
+ throw new Error(
38912
+ `substituteMember: callable type binding member "${entry.memberId}" for generic param "${typeInfo.genericParamId}" does not exist in the document.`
38913
+ );
38914
+ }
38915
+ return genericBindingTypeInfo(binding, env, members);
38916
+ }
38917
+ if (typeInfo.type === 6 /* List */ || typeInfo.type === 5 /* Dictionary */ || typeInfo.type === 9 /* Lookup */) {
38918
+ return {
38919
+ ...typeInfo,
38920
+ entryTypeInfo: substituteNestedTypeInfo(
38921
+ typeInfo.entryTypeInfo,
38922
+ env,
38923
+ members
38924
+ )
38925
+ };
38926
+ }
38927
+ if (typeInfo.type === 7 /* Class */) {
38928
+ const typeArguments = typeInfo.typeArguments;
38929
+ if (typeArguments === void 0) return typeInfo;
38930
+ return {
38931
+ ...typeInfo,
38932
+ typeArguments: Object.fromEntries(
38933
+ Object.entries(typeArguments).map(([parameterId, argument2]) => [
38934
+ parameterId,
38935
+ substituteNestedTypeInfo(argument2, env, members)
38936
+ ])
38937
+ )
38938
+ };
38939
+ }
38940
+ if (typeInfo.type === 25 /* NSDelegate */) {
38941
+ return {
38942
+ ...typeInfo,
38943
+ returnTypeInfo: substituteNestedTypeInfo(
38944
+ typeInfo.returnTypeInfo,
38945
+ env,
38946
+ members
38947
+ ),
38948
+ argumentTypes: typeInfo.argumentTypes.map(
38949
+ (argument2) => substituteNestedTypeInfo(argument2, env, members)
38950
+ )
38951
+ };
38952
+ }
38953
+ return typeInfo;
38954
+ }
38955
+ function genericBindingTypeInfo(rawMember, env, members) {
38956
+ return typeInfoFromArgumentSignature(
38957
+ typeArgumentSignatureOfMember(rawMember, env, members)
38958
+ );
38959
+ }
38960
+ function typeInfoFromArgumentSignature(signature) {
38961
+ if (signature.type === 7 /* Class */) {
38962
+ const classSignature = signature;
38963
+ return {
38964
+ type: 7 /* Class */,
38965
+ required: classSignature.required,
38966
+ classId: classSignature.classId,
38967
+ ...Object.keys(classSignature.args).length === 0 ? {} : {
38968
+ typeArguments: Object.fromEntries(
38969
+ Object.entries(classSignature.args).map(
38970
+ ([parameterId, argument2]) => [
38971
+ parameterId,
38972
+ typeInfoFromArgumentSignature(argument2)
38973
+ ]
38974
+ )
38975
+ )
38976
+ }
38977
+ };
38978
+ }
38979
+ if (signature.type === 8 /* Enum */) {
38980
+ const enumSignature = signature;
38981
+ return {
38982
+ type: 8 /* Enum */,
38983
+ required: enumSignature.required,
38984
+ enumId: enumSignature.enumId
38985
+ };
38986
+ }
38987
+ if (signature.type === 6 /* List */) {
38988
+ const listSignature = signature;
38989
+ return {
38990
+ type: 6 /* List */,
38991
+ required: listSignature.required,
38992
+ entryTypeInfo: typeInfoFromArgumentSignature(listSignature.entry)
38993
+ };
38994
+ }
38995
+ if (signature.type === 5 /* Dictionary */) {
38996
+ const dictionarySignature = signature;
38997
+ return {
38998
+ type: 5 /* Dictionary */,
38999
+ required: dictionarySignature.required,
39000
+ entryTypeInfo: typeInfoFromArgumentSignature(dictionarySignature.entry),
39001
+ ...dictionarySignature.keyEnumId === void 0 ? {} : { keyEnumId: dictionarySignature.keyEnumId }
39002
+ };
39003
+ }
39004
+ const typeInfo = { type: signature.type, required: signature.required };
39005
+ if (!isNSTypeInfo(typeInfo)) {
39006
+ throw new Error(
39007
+ `substituteMember: generic binding kind ${signature.type} cannot appear in a NeoScript callable type.`
39008
+ );
39009
+ }
39010
+ return typeInfo;
39011
+ }
38860
39012
  function resolveTerminalBinding(genericParamId, slotName, env, members) {
38861
39013
  const entry = env.get(genericParamId);
38862
39014
  if (entry === void 0) {
@@ -39137,6 +39289,7 @@ var init_generics = __esm({
39137
39289
  "../src/models/classes/generics.ts"() {
39138
39290
  "use strict";
39139
39291
  init_member_kinds();
39292
+ init_neoscript();
39140
39293
  init_world_system_classes();
39141
39294
  init_structural_narrow();
39142
39295
  init_inheritance();
@@ -58936,7 +59089,14 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
58936
59089
  `Cannot construct abstract Class '${schemaClass2.name}'.`
58937
59090
  );
58938
59091
  }
58939
- if (!isClosedClass(classId, ctx.vm.classes)) {
59092
+ const replaySlot = ctx.__storedConstructionReplaySlot;
59093
+ const classArguments2 = replaySlot?.classId === classId ? replaySlot.classArguments : void 0;
59094
+ const instanceEnv = resolveInstanceEnv(
59095
+ classId,
59096
+ classArguments2,
59097
+ ctx.vm.classes
59098
+ );
59099
+ if (firstUnboundParamId(instanceEnv) !== null) {
58940
59100
  throw new NSGetterRuntimeError(
58941
59101
  `Cannot construct open generic Class '${schemaClass2.name}'.`
58942
59102
  );
@@ -58961,7 +59121,6 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
58961
59121
  const schemaByKey = new Map(
58962
59122
  mergedSchema.map((entry) => [entry.schemaKey, entry])
58963
59123
  );
58964
- const instanceEnv = resolveInstanceEnv(classId, void 0, ctx.vm.classes);
58965
59124
  const seenSchemaKeys = /* @__PURE__ */ new Set();
58966
59125
  const seenMemberIds = /* @__PURE__ */ new Set();
58967
59126
  const fields = [];
@@ -59012,7 +59171,7 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
59012
59171
  );
59013
59172
  }
59014
59173
  if (!requireEveryRequiredField) {
59015
- return { schemaClass: schemaClass2, fields, instanceEnv };
59174
+ return { schemaClass: schemaClass2, fields, instanceEnv, classArguments: classArguments2 };
59016
59175
  }
59017
59176
  for (const entry of mergedSchema) {
59018
59177
  const rawMember = evalMemberById(ctx.vm, entry.memberId);
@@ -59035,7 +59194,7 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
59035
59194
  );
59036
59195
  }
59037
59196
  }
59038
- return { schemaClass: schemaClass2, fields, instanceEnv };
59197
+ return { schemaClass: schemaClass2, fields, instanceEnv, classArguments: classArguments2 };
59039
59198
  }
59040
59199
  function assertConstructorFieldSlotWritable(args) {
59041
59200
  const surfaceEntry = mergeInstanceSchema(
@@ -59118,11 +59277,12 @@ function evaluateConstructorFields(descriptor, scope, ctx) {
59118
59277
  return { validated, value };
59119
59278
  });
59120
59279
  }
59121
- function syntheticConstructorMember(schemaClass2) {
59280
+ function syntheticConstructorMember(schemaClass2, classArguments2) {
59122
59281
  return {
59123
59282
  name: `new ${schemaClass2.name}`,
59124
59283
  kind: 7 /* Class */,
59125
59284
  classId: schemaClass2.id,
59285
+ ...classArguments2 === void 0 ? {} : { classArguments: classArguments2 },
59126
59286
  locked: false,
59127
59287
  required: true,
59128
59288
  isStatic: false,
@@ -59353,7 +59513,10 @@ function constructClassValueWithinFrame(descriptor, scope, ctx) {
59353
59513
  const schemaClass2 = descriptor.schemaClass;
59354
59514
  const classId = schemaClass2.id;
59355
59515
  const supplied = evaluateConstructorFields(descriptor, scope, ctx);
59356
- const syntheticMember = syntheticConstructorMember(schemaClass2);
59516
+ const syntheticMember = syntheticConstructorMember(
59517
+ schemaClass2,
59518
+ descriptor.classArguments
59519
+ );
59357
59520
  const createdValues = [];
59358
59521
  const storageKeyDeclarations = /* @__PURE__ */ new Map();
59359
59522
  let root;
@@ -60137,7 +60300,10 @@ function constructDeclaredClassValueWithinFrame(descriptor, record3, info, scope
60137
60300
  textureTemplates: ctx.vm.textureTemplates ?? []
60138
60301
  },
60139
60302
  projectId: ctx.vm.project.id,
60140
- member: syntheticConstructorMember(schemaClass2),
60303
+ member: syntheticConstructorMember(
60304
+ schemaClass2,
60305
+ descriptor.classArguments
60306
+ ),
60141
60307
  topLevelClassId: classId,
60142
60308
  createdValues,
60143
60309
  storageKeyDeclarations,
@@ -61403,7 +61569,15 @@ function evaluateMemberInitializer(args) {
61403
61569
  rootValue: buildInitializerRootValue(args.document),
61404
61570
  saveStaticBindings: args.saveStaticBindings,
61405
61571
  sessionStaticBindings: args.sessionStaticBindings,
61406
- ...args.storedConstructionReplay === true ? { storedConstructionReplay: true } : {},
61572
+ ...args.storedConstructionReplay === true ? {
61573
+ storedConstructionReplay: true,
61574
+ ...isMemberClassBase(args.member) ? {
61575
+ __storedConstructionReplaySlot: {
61576
+ classId: args.member.classId,
61577
+ classArguments: args.member.classArguments ?? {}
61578
+ }
61579
+ } : {}
61580
+ } : {},
61407
61581
  __constructedArgumentsByValue: /* @__PURE__ */ new WeakMap(),
61408
61582
  __createdStorageKeyDeclarations: args.storageKeyDeclarations ?? /* @__PURE__ */ new Map()
61409
61583
  };
@@ -61426,6 +61600,7 @@ var evaluatorLookupsByDocument;
61426
61600
  var init_evaluateInitializer = __esm({
61427
61601
  "../src/view-models/neoscript-evaluator/evaluateInitializer.ts"() {
61428
61602
  "use strict";
61603
+ init_members();
61429
61604
  init_project2();
61430
61605
  init_NSGetterRuntimeError();
61431
61606
  init_evaluateNSGetter();
@@ -77210,22 +77385,29 @@ function prepareServerOwnedDelegateValueBodies(args) {
77210
77385
  `Value "${row.id}" carries a NeoDelegate closure but no NeoDelegate member in this project version stores it.`
77211
77386
  );
77212
77387
  }
77213
- row.value = compileDelegateClosureValue(row.value.code, {
77214
- project: document.project,
77215
- projectFiles: document.projectFiles,
77216
- members: document.members,
77217
- classes: document.classes,
77218
- enums: document.enums,
77219
- interfaces: document.interfaces,
77220
- constructors: document.constructors ?? [],
77221
- thisClass: findSchemaPlacement(
77222
- rootOwnerByValueId.get(row.id)?.id ?? "",
77223
- document.classes
77224
- )?.ownerClass ?? null,
77225
- returnTypeInfo: member.returnTypeInfo,
77226
- argumentTypes: member.argumentTypes,
77227
- name: `${member.name} value`
77228
- });
77388
+ const rootOwner = rootOwnerByValueId.get(row.id);
77389
+ const thisClass = findSchemaPlacement(rootOwner?.id ?? "", document.classes)?.ownerClass ?? null;
77390
+ try {
77391
+ row.value = compileDelegateClosureValue(row.value.code, {
77392
+ project: document.project,
77393
+ projectFiles: document.projectFiles,
77394
+ members: document.members,
77395
+ classes: document.classes,
77396
+ enums: document.enums,
77397
+ interfaces: document.interfaces,
77398
+ constructors: document.constructors ?? [],
77399
+ thisClass,
77400
+ returnTypeInfo: member.returnTypeInfo,
77401
+ argumentTypes: member.argumentTypes,
77402
+ name: `${member.name} value`
77403
+ });
77404
+ } catch (error) {
77405
+ const detail = error instanceof Error ? error.message : String(error);
77406
+ throw new Error(
77407
+ `Value "${row.id}" NeoDelegate closure failed under member "${member.name}" (${getOptionalString(member, "id") ?? "unknown"}), root owner "${rootOwner?.name ?? "unknown"}" (${getOptionalString(rootOwner, "id") ?? "unknown"}), lexical class "${thisClass?.name ?? "none"}" (${thisClass?.id ?? "none"}), and return type ${canonicalJsonStringify(member.returnTypeInfo)}: ${detail}`,
77408
+ { cause: error }
77409
+ );
77410
+ }
77229
77411
  };
77230
77412
  for (const [index, row] of explicitRows) {
77231
77413
  const compiled = { ...row, value: { ...row.value } };
@@ -77780,6 +77962,7 @@ var init_project_version_schema_commit = __esm({
77780
77962
  init_members();
77781
77963
  init_inheritance();
77782
77964
  init_generics();
77965
+ init_core();
77783
77966
  init_world_content_sidecar_validation();
77784
77967
  init_project_document_value_overlay();
77785
77968
  init_project2();
@@ -81227,7 +81410,11 @@ function replayStoredConstructionV4(args) {
81227
81410
  if (!(error instanceof UncompiledInitializerRuntimeError) || error.memberId === null || compiledDependencies.has(error.memberId)) {
81228
81411
  throw error;
81229
81412
  }
81230
- compilePulledMemberInitializerBodyV4(document, error.memberId);
81413
+ compilePulledMemberInitializerBodyV4(
81414
+ document,
81415
+ error.memberId,
81416
+ args.compilationProject
81417
+ );
81231
81418
  compiledDependencies.add(error.memberId);
81232
81419
  }
81233
81420
  }
@@ -81277,7 +81464,7 @@ function assertPulledConstructorsCompiled(document) {
81277
81464
  );
81278
81465
  }
81279
81466
  }
81280
- function compilePulledMemberInitializerBodyV4(document, memberId) {
81467
+ function compilePulledMemberInitializerBodyV4(document, memberId, compilationProject) {
81281
81468
  const compileArgs = {
81282
81469
  project: document.project,
81283
81470
  projectFiles: document.projectFiles,
@@ -81299,7 +81486,8 @@ function compilePulledMemberInitializerBodyV4(document, memberId) {
81299
81486
  compileMemberInitializerBody({
81300
81487
  ...compileArgs,
81301
81488
  member,
81302
- thisClass
81489
+ thisClass,
81490
+ ...compilationProject === void 0 ? {} : { compilationProject }
81303
81491
  });
81304
81492
  }
81305
81493
  function readPulledProjectDocumentV4(records2) {
@@ -81373,10 +81561,13 @@ function buildValueEmitContext(records2, manifest) {
81373
81561
  const symbolsByValueId = staticSymbols(classes, members);
81374
81562
  let document;
81375
81563
  const readDocument = () => document ??= readPulledProjectDocumentV4(records2);
81564
+ let compilationProject;
81565
+ const readCompilationProject = () => compilationProject ??= createNeoScriptCompilationProject(readDocument());
81376
81566
  let materializedGraph;
81377
81567
  return {
81378
81568
  records: records2,
81379
81569
  readDocument,
81570
+ readCompilationProject,
81380
81571
  readMaterializedGraph: () => {
81381
81572
  if (materializedGraph !== void 0) return materializedGraph;
81382
81573
  materializedGraph = new MaterializedValueGraphContext(
@@ -81524,8 +81715,10 @@ function animationConstructorProjectionTargetValueIds(context, classId, value) {
81524
81715
  return [];
81525
81716
  }
81526
81717
  const targetIds = [];
81527
- for (const projection of inheritedConstructorProjections2(
81718
+ for (const projection of effectiveConstructorProjections(
81528
81719
  context.manifestClasses,
81720
+ context.manifestConstructors,
81721
+ context.manifestMembers,
81529
81722
  classId
81530
81723
  )) {
81531
81724
  const schemaKey = inheritedProjectionSchemaKey(
@@ -82503,9 +82696,10 @@ function lowerRowBackedDefault(context, member, backed, baseData3, binding) {
82503
82696
  const assignmentSlices = objectInitializerSlices(binding.initializer);
82504
82697
  for (const assignment of expression.initializer ?? []) {
82505
82698
  const childMember = classMemberByName(context, classId, assignment.name);
82506
- if (inheritedConstructorProjections2(context.classes, schemaClass2.id).some(
82507
- (projection) => projection.memberId === childMember.id
82508
- )) {
82699
+ if (inheritedLegacyConstructorProjections(
82700
+ context.classes,
82701
+ schemaClass2.id
82702
+ ).some((projection) => projection.memberId === childMember.id)) {
82509
82703
  throw new Error(
82510
82704
  `Default value ${binding.label}.${assignment.name} is constructor-projected and must be set through its named constructor argument.`
82511
82705
  );
@@ -82916,7 +83110,7 @@ function lowerSeedRow(context, member, sourceExpression, source, valueId, path,
82916
83110
  effectiveClass.id,
82917
83111
  assignment.name
82918
83112
  );
82919
- if (inheritedConstructorProjections2(
83113
+ if (inheritedLegacyConstructorProjections(
82920
83114
  context.classes,
82921
83115
  effectiveClass.id
82922
83116
  ).some((projection) => projection.memberId === childMember.id)) {
@@ -83419,9 +83613,10 @@ function lowerClassValue(context, member, expression, base, source, outerEnviron
83419
83613
  }
83420
83614
  for (const assignment of expression.initializer ?? []) {
83421
83615
  const childMember = classMemberByName(context, classId, assignment.name);
83422
- if (inheritedConstructorProjections2(context.classes, schemaClass2.id).some(
83423
- (projection) => projection.memberId === childMember.id
83424
- )) {
83616
+ if (inheritedLegacyConstructorProjections(
83617
+ context.classes,
83618
+ schemaClass2.id
83619
+ ).some((projection) => projection.memberId === childMember.id)) {
83425
83620
  throw new Error(
83426
83621
  `Class value ${String(base.id)}.${assignment.name} is constructor-projected and must be set through its named constructor argument.`
83427
83622
  );
@@ -83601,7 +83796,7 @@ function classInheritanceChain(classes, classId) {
83601
83796
  }
83602
83797
  return chain;
83603
83798
  }
83604
- function inheritedConstructorProjections2(classes, classId) {
83799
+ function inheritedLegacyConstructorProjections(classes, classId) {
83605
83800
  const resolved = [];
83606
83801
  const claimed = /* @__PURE__ */ new Set();
83607
83802
  for (const schemaClass2 of classInheritanceChain(classes, classId)) {
@@ -83613,6 +83808,67 @@ function inheritedConstructorProjections2(classes, classId) {
83613
83808
  }
83614
83809
  return resolved;
83615
83810
  }
83811
+ function effectiveConstructorProjections(classes, constructors, members, classId) {
83812
+ const schemaClass2 = classes.get(classId);
83813
+ const requiredId = schemaClass2?.requiredConstructorId;
83814
+ if (schemaClass2 === void 0 || requiredId === void 0) {
83815
+ return inheritedLegacyConstructorProjections(classes, classId);
83816
+ }
83817
+ const required2 = constructors.get(requiredId);
83818
+ if (required2 === void 0) return [];
83819
+ const projected = requiredConstructorProjectionMap(
83820
+ classes,
83821
+ constructors,
83822
+ members,
83823
+ classId,
83824
+ /* @__PURE__ */ new Set()
83825
+ );
83826
+ if (required2.arguments.some((parameter3) => !projected.has(parameter3.name))) {
83827
+ return [];
83828
+ }
83829
+ return required2.arguments.map((parameter3) => ({
83830
+ parameterName: parameter3.name,
83831
+ memberId: projected.get(parameter3.name)
83832
+ }));
83833
+ }
83834
+ function requiredConstructorProjectionMap(classes, constructors, members, classId, visited) {
83835
+ if (visited.has(classId)) return /* @__PURE__ */ new Map();
83836
+ const schemaClass2 = classes.get(classId);
83837
+ const requiredId = schemaClass2?.requiredConstructorId;
83838
+ const required2 = requiredId === void 0 ? void 0 : constructors.get(requiredId);
83839
+ if (schemaClass2 === void 0 || required2 === void 0) return /* @__PURE__ */ new Map();
83840
+ const result = /* @__PURE__ */ new Map();
83841
+ for (const memberId of Object.values(schemaClass2.schema)) {
83842
+ const initializer = members.get(memberId)?.defaultValue;
83843
+ if (initializer === null || initializer === void 0 || !("init" in initializer)) {
83844
+ continue;
83845
+ }
83846
+ const parameterName = initializer.init.code.trim();
83847
+ if (required2.arguments.some((parameter3) => parameter3.name === parameterName)) {
83848
+ result.set(parameterName, memberId);
83849
+ }
83850
+ }
83851
+ const baseClassId = schemaClass2.extendsClassId;
83852
+ if (baseClassId === null) return result;
83853
+ const base = requiredConstructorProjectionMap(
83854
+ classes,
83855
+ constructors,
83856
+ members,
83857
+ baseClassId,
83858
+ /* @__PURE__ */ new Set([...visited, classId])
83859
+ );
83860
+ for (const forwarded of required2.baseArguments ?? []) {
83861
+ const sourceName = forwarded.code.trim();
83862
+ if (!required2.arguments.some((parameter3) => parameter3.name === sourceName)) {
83863
+ continue;
83864
+ }
83865
+ const memberId = base.get(forwarded.name);
83866
+ if (memberId !== void 0 && !result.has(sourceName)) {
83867
+ result.set(sourceName, memberId);
83868
+ }
83869
+ }
83870
+ return result;
83871
+ }
83616
83872
  function inheritedProjectionSchemaKey(classes, classId, memberId) {
83617
83873
  for (const schemaClass2 of classInheritanceChain(classes, classId)) {
83618
83874
  for (const [schemaKey, declared] of Object.entries(schemaClass2.schema)) {
@@ -83622,8 +83878,10 @@ function inheritedProjectionSchemaKey(classes, classId, memberId) {
83622
83878
  return null;
83623
83879
  }
83624
83880
  function resolveConstructorProjectionArguments(context, schemaClass2, expression, ownerValueId, environment, source) {
83625
- const projections = inheritedConstructorProjections2(
83881
+ const projections = effectiveConstructorProjections(
83626
83882
  context.classes,
83883
+ context.manifestConstructors,
83884
+ context.members,
83627
83885
  schemaClass2.id
83628
83886
  );
83629
83887
  const signature = describeProjectedConstructor(schemaClass2.name, projections);
@@ -85277,13 +85535,37 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
85277
85535
  if (!isObjectRecord2(value.value))
85278
85536
  return targetTyped ? "new()" : `new ${classValueTypeName(context, classId, member, storedEnvironment)}()`;
85279
85537
  const schema = isObjectRecord2(schemaClass2.schema) ? schemaClass2.schema : {};
85280
- const projection = constructorProjectionSource(
85281
- context,
85282
- classId,
85283
- value.value,
85284
- visited,
85285
- storedEnvironment
85286
- );
85538
+ const hasStoredConstruction = isObjectRecord2(value.constructorArgs);
85539
+ let projection;
85540
+ try {
85541
+ projection = hasStoredConstruction ? {
85542
+ arguments: [],
85543
+ memberIds: new Set(
85544
+ effectiveConstructorProjections(
85545
+ context.manifestClasses,
85546
+ context.manifestConstructors,
85547
+ context.manifestMembers,
85548
+ classId
85549
+ ).map((entry) => entry.memberId)
85550
+ ),
85551
+ targetValueIds: animationConstructorProjectionTargetValueIds(
85552
+ context,
85553
+ classId,
85554
+ value
85555
+ )
85556
+ } : constructorProjectionSource(
85557
+ context,
85558
+ classId,
85559
+ value.value,
85560
+ visited,
85561
+ storedEnvironment
85562
+ );
85563
+ } catch (error) {
85564
+ throw new Error(
85565
+ `Constructor projection for value "${String(value.id ?? "unknown")}" of class "${schemaClass2.name}" cannot be emitted: ${error instanceof Error ? error.message : String(error)}`,
85566
+ { cause: error }
85567
+ );
85568
+ }
85287
85569
  const environment = inferAnimationChildOverrideEmitEnvironment(
85288
85570
  context,
85289
85571
  classId,
@@ -85291,15 +85573,23 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
85291
85573
  storedEnvironment
85292
85574
  );
85293
85575
  const name = classValueTypeName(context, classId, member, environment);
85294
- const storedConstruction = storedConstructorCallSource(
85295
- context,
85296
- schemaClass2,
85297
- value,
85298
- name,
85299
- environment,
85300
- visited,
85301
- targetTyped
85302
- );
85576
+ let storedConstruction;
85577
+ try {
85578
+ storedConstruction = storedConstructorCallSource(
85579
+ context,
85580
+ schemaClass2,
85581
+ value,
85582
+ name,
85583
+ environment,
85584
+ visited,
85585
+ targetTyped
85586
+ );
85587
+ } catch (error) {
85588
+ throw new Error(
85589
+ `Stored construction for value "${String(value.id ?? "unknown")}" of class "${name}" cannot be emitted: ${error instanceof Error ? error.message : String(error)}`,
85590
+ { cause: error }
85591
+ );
85592
+ }
85303
85593
  if (storedConstruction !== null && typeof value.id === "string") {
85304
85594
  context.materializedConstructors.set(value.id, storedConstruction);
85305
85595
  }
@@ -85317,7 +85607,7 @@ function classValue(context, member, value, visited, targetTyped, outerEnvironme
85317
85607
  context,
85318
85608
  value.id,
85319
85609
  replayConstruction,
85320
- member
85610
+ concreteClassMemberForReplay(member, environment)
85321
85611
  );
85322
85612
  const replayRoot = replayRows === null || typeof value.id !== "string" ? void 0 : replayRows.get(value.id);
85323
85613
  const replayGraph = replayRows === null || typeof value.id !== "string" ? null : context.readMaterializedGraph().withRowOverrides(
@@ -85403,11 +85693,27 @@ function storedConstructionReplayRows(context, valueId, code, member) {
85403
85693
  document: context.readDocument(),
85404
85694
  valueId,
85405
85695
  code,
85406
- member
85696
+ member,
85697
+ compilationProject: context.readCompilationProject()
85407
85698
  });
85408
85699
  context.constructionReplays.set(valueId, replay);
85409
85700
  return replay;
85410
85701
  }
85702
+ function concreteClassMemberForReplay(member, environment) {
85703
+ if (numberField(member, "kind") !== 7 /* Class */) return member;
85704
+ const classArguments2 = isObjectRecord2(member.classArguments) ? member.classArguments : {};
85705
+ let changed = false;
85706
+ const concreteArguments = Object.fromEntries(
85707
+ Object.entries(classArguments2).map(([genericParamId, binding]) => {
85708
+ const forwardedParamId = isObjectRecord2(binding) && binding.kind === "generic" && typeof binding.genericParamId === "string" ? binding.genericParamId : null;
85709
+ const bindingMemberId = environment.get(genericParamId) ?? (forwardedParamId === null ? void 0 : environment.get(forwardedParamId));
85710
+ if (bindingMemberId === void 0) return [genericParamId, binding];
85711
+ changed = true;
85712
+ return [genericParamId, { kind: "member", memberId: bindingMemberId }];
85713
+ })
85714
+ );
85715
+ return changed ? { ...member, classArguments: concreteArguments } : member;
85716
+ }
85411
85717
  function materializedValueSubgraphsEqual(context, currentGraph, replayGraph, currentId, replayId, member, environment) {
85412
85718
  const resolvedMember = resolveGenericValueMember(
85413
85719
  context,
@@ -85579,8 +85885,30 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
85579
85885
  false
85580
85886
  );
85581
85887
  }
85888
+ case "generic": {
85889
+ const bindingId = environment.get(type.genericParamId);
85890
+ const inferredClassId = inferredGenericClassId(bindingId);
85891
+ const resolvedType = inferredClassId === null ? bindingId === void 0 ? null : schemaTypeForBindingMember(context, bindingId, environment) : {
85892
+ kind: "class",
85893
+ nullable: type.nullable,
85894
+ classId: inferredClassId,
85895
+ classArguments: {}
85896
+ };
85897
+ if (resolvedType === null) {
85898
+ throw new Error(
85899
+ `Stored Generic constructor argument cannot resolve parameter ${type.genericParamId}.`
85900
+ );
85901
+ }
85902
+ return storedConstructorArgumentSource(
85903
+ context,
85904
+ { ...resolvedType, nullable: type.nullable || resolvedType.nullable },
85905
+ value,
85906
+ environment,
85907
+ visited,
85908
+ cloneAggregateArguments
85909
+ );
85910
+ }
85582
85911
  case "interface":
85583
- case "generic":
85584
85912
  case "list":
85585
85913
  case "dictionary":
85586
85914
  if (typeof value !== "string") {
@@ -85631,6 +85959,147 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
85631
85959
  );
85632
85960
  }
85633
85961
  }
85962
+ function schemaTypeForBindingMember(context, memberId, environment, visited = /* @__PURE__ */ new Set()) {
85963
+ if (visited.has(memberId)) {
85964
+ throw new Error(
85965
+ `Stored constructor argument generic binding contains a member cycle at ${memberId}.`
85966
+ );
85967
+ }
85968
+ const member = context.manifestMembers.get(memberId);
85969
+ if (member === void 0) {
85970
+ throw new Error(
85971
+ `Stored constructor argument generic binding names missing member ${memberId}.`
85972
+ );
85973
+ }
85974
+ const nullable = !member.required;
85975
+ const nextVisited = /* @__PURE__ */ new Set([...visited, memberId]);
85976
+ switch (member.kind) {
85977
+ case "null":
85978
+ case "bool":
85979
+ case "int":
85980
+ case "string":
85981
+ case "float":
85982
+ case "decimal":
85983
+ case "sprite":
85984
+ case "audio":
85985
+ case "vector2":
85986
+ case "vector2Int":
85987
+ case "vector3":
85988
+ case "vector3Int":
85989
+ case "color":
85990
+ return { kind: member.kind, nullable };
85991
+ case "class":
85992
+ return {
85993
+ kind: "class",
85994
+ nullable,
85995
+ classId: member.classId,
85996
+ classArguments: Object.fromEntries(
85997
+ Object.entries(member.classArguments).map(
85998
+ ([parameterId, binding]) => [
85999
+ parameterId,
86000
+ binding.kind === "member" ? schemaTypeForBindingMember(
86001
+ context,
86002
+ binding.memberId,
86003
+ environment,
86004
+ nextVisited
86005
+ ) : schemaTypeForBindingMember(
86006
+ context,
86007
+ requiredGenericBindingMemberId(
86008
+ environment,
86009
+ binding.genericParamId
86010
+ ),
86011
+ environment,
86012
+ nextVisited
86013
+ )
86014
+ ]
86015
+ )
86016
+ )
86017
+ };
86018
+ case "enum":
86019
+ return { kind: "enum", nullable, enumId: member.enumId };
86020
+ case "list":
86021
+ return {
86022
+ kind: "list",
86023
+ nullable,
86024
+ entryType: schemaTypeForBindingMember(
86025
+ context,
86026
+ member.entryMemberId,
86027
+ environment,
86028
+ nextVisited
86029
+ ),
86030
+ listMemberId: member.id,
86031
+ readOnly: member.isReadOnly
86032
+ };
86033
+ case "dictionary":
86034
+ return {
86035
+ kind: "dictionary",
86036
+ nullable,
86037
+ entryType: schemaTypeForBindingMember(
86038
+ context,
86039
+ member.entryMemberId,
86040
+ environment,
86041
+ nextVisited
86042
+ ),
86043
+ keyEnumId: member.key.kind === "enum" ? member.key.enumId : null,
86044
+ readOnly: member.isReadOnly
86045
+ };
86046
+ case "lookup": {
86047
+ if (member.declaredType !== null) {
86048
+ return { ...member.declaredType, nullable };
86049
+ }
86050
+ const collection = context.manifestMembers.get(member.collectionMemberId);
86051
+ if (collection?.kind !== "list" && collection?.kind !== "dictionary") {
86052
+ throw new Error(
86053
+ `Stored constructor argument Lookup binding ${member.id} has no collection entry type.`
86054
+ );
86055
+ }
86056
+ return {
86057
+ kind: "lookup",
86058
+ nullable,
86059
+ entryType: schemaTypeForBindingMember(
86060
+ context,
86061
+ collection.entryMemberId,
86062
+ environment,
86063
+ nextVisited
86064
+ ),
86065
+ collectionMemberId: member.collectionMemberId,
86066
+ collectionValueId: member.collectionValueId
86067
+ };
86068
+ }
86069
+ case "dialogueLookup":
86070
+ return { kind: "dialogueLookup", nullable };
86071
+ case "delegate":
86072
+ return {
86073
+ kind: "delegate",
86074
+ nullable,
86075
+ returnType: member.returnType,
86076
+ argumentTypes: member.arguments.map((argument2) => argument2.type)
86077
+ };
86078
+ case "generic":
86079
+ return schemaTypeForBindingMember(
86080
+ context,
86081
+ requiredGenericBindingMemberId(environment, member.genericParamId),
86082
+ environment,
86083
+ nextVisited
86084
+ );
86085
+ case "computed":
86086
+ case "function":
86087
+ case "scriptFunction":
86088
+ case "functionRef":
86089
+ throw new Error(
86090
+ `Stored constructor argument cannot use ${member.kind} member ${member.id} as a generic type binding.`
86091
+ );
86092
+ }
86093
+ }
86094
+ function requiredGenericBindingMemberId(environment, genericParamId) {
86095
+ const bindingId = environment.get(genericParamId);
86096
+ if (bindingId === void 0 || inferredGenericClassId(bindingId) !== null) {
86097
+ throw new Error(
86098
+ `Stored constructor argument cannot resolve generic binding ${genericParamId} to a member.`
86099
+ );
86100
+ }
86101
+ return bindingId;
86102
+ }
85634
86103
  function storedAggregateCloneSource(context, type, valueId, environment) {
85635
86104
  if (!context.values.has(valueId)) {
85636
86105
  throw new Error(
@@ -85930,8 +86399,10 @@ function manifestMemberTypeName(context, member) {
85930
86399
  return fixedSourceTypeNameForKind(member.kind) ?? member.kind;
85931
86400
  }
85932
86401
  function constructorProjectionSource(context, classId, body, visited, environment) {
85933
- const projections = inheritedConstructorProjections2(
86402
+ const projections = effectiveConstructorProjections(
85934
86403
  context.manifestClasses,
86404
+ context.manifestConstructors,
86405
+ context.manifestMembers,
85935
86406
  classId
85936
86407
  );
85937
86408
  const argumentsValue = [];
@@ -86525,6 +86996,7 @@ var init_value_sources = __esm({
86525
86996
  init_member_value_id();
86526
86997
  init_members();
86527
86998
  init_compile_ns_property();
86999
+ init_compile();
86528
87000
  init_constructor_argument_ownership();
86529
87001
  init_structured_leaf_source();
86530
87002
  init_member_kind_type_names();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.22.4",
3
+ "version": "0.22.5",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ description: >-
9
9
  `@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
10
10
  ---
11
11
 
12
- <!-- reviewed-through-cli: 0.22.4 -->
12
+ <!-- reviewed-through-cli: 0.22.5 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -78,7 +78,7 @@ wrappers.
78
78
  The marker near the top of `SKILL.md` must exactly match the package version:
79
79
 
80
80
  ```html
81
- <!-- reviewed-through-cli: 0.22.4 -->
81
+ <!-- reviewed-through-cli: 0.22.5 -->
82
82
  ```
83
83
 
84
84
  The quoted version above is checked too, so this instruction cannot go stale