@neocompose/cli 0.52.3 → 0.52.4
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,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.52.4] - 2026-09-17
|
|
4
|
+
|
|
5
|
+
- Accept declared list-index lookups in constructor arguments, including readable string keys such as `root.Assets.Items.Index.Slug["stone"]!`.
|
|
6
|
+
- Convert session-constructed tiles with either `TryConvert` overload, preserving their identity and Cell, and persist their final class in migrations.
|
|
7
|
+
- Allow object initializers in executable NeoScript and specs. Construct first, then apply entries in order using ordinary assignment rules, including property setters and readonly checks.
|
|
8
|
+
- Encode constructor-assigned collections as value rows when exporting initializers so seeding an Assets list preserves existing NeoCellPattern values. List-shape errors name the list kind.
|
|
9
|
+
|
|
3
10
|
## [0.52.3] - 2026-09-17
|
|
4
11
|
|
|
5
12
|
- Replay stored collection constructor arguments as typed literals, including evaluated NeoCellPattern values.
|
package/dist/neo.mjs
CHANGED
|
@@ -6401,6 +6401,7 @@ var init_strict_resolver = __esm({
|
|
|
6401
6401
|
callSiteCounter = 0;
|
|
6402
6402
|
lambdaDepth = 0;
|
|
6403
6403
|
delegateClosureCounter = 0;
|
|
6404
|
+
objectInitializerCounter = 0;
|
|
6404
6405
|
delegateCaptureContexts = [];
|
|
6405
6406
|
sourceTokens;
|
|
6406
6407
|
source;
|
|
@@ -8013,6 +8014,14 @@ var init_strict_resolver = __esm({
|
|
|
8013
8014
|
expression.pos
|
|
8014
8015
|
);
|
|
8015
8016
|
const declaredTarget = this.project.typeByName.get(className);
|
|
8017
|
+
if (declaredTarget?.kind === "class" && (expression.initializer?.length ?? 0) > 0 && this.context.storedConstructionReplay !== true) {
|
|
8018
|
+
return this.resolveExecutableObjectInitializer(
|
|
8019
|
+
declaredTarget,
|
|
8020
|
+
expression,
|
|
8021
|
+
scope,
|
|
8022
|
+
expected
|
|
8023
|
+
);
|
|
8024
|
+
}
|
|
8016
8025
|
const declared = declaredTarget?.declaredConstructors ?? [];
|
|
8017
8026
|
const requiredConstructor = neoScriptRequiredConstructor(declaredTarget);
|
|
8018
8027
|
const generatedPositionalCall = requiredConstructor === null && declaredTarget?.constructorSignature !== void 0 && expression.argumentNames === void 0 && callHasPositionalArguments(expression);
|
|
@@ -8031,12 +8040,6 @@ var init_strict_resolver = __esm({
|
|
|
8031
8040
|
expression.pos
|
|
8032
8041
|
);
|
|
8033
8042
|
}
|
|
8034
|
-
if (expression.initializer && expression.initializer.length > 0 && !generatedPositionalCall && this.context.storedConstructionReplay !== true) {
|
|
8035
|
-
throw new CompileError(
|
|
8036
|
-
"Object initializers are available to project source construction and are not executable NeoScript constructors.",
|
|
8037
|
-
expression.pos
|
|
8038
|
-
);
|
|
8039
|
-
}
|
|
8040
8043
|
return this.resolveClassConstructor(
|
|
8041
8044
|
className,
|
|
8042
8045
|
expression,
|
|
@@ -10263,6 +10266,75 @@ var init_strict_resolver = __esm({
|
|
|
10263
10266
|
type: optional2 ? { ...delegateType.returnType, nullable: true } : delegateType.returnType
|
|
10264
10267
|
};
|
|
10265
10268
|
}
|
|
10269
|
+
resolveExecutableObjectInitializer(schemaClass2, expression, scope, expected) {
|
|
10270
|
+
const constructed = this.resolveExpression(
|
|
10271
|
+
{ ...expression, className: schemaClass2.name, initializer: [] },
|
|
10272
|
+
scope,
|
|
10273
|
+
expected
|
|
10274
|
+
);
|
|
10275
|
+
const name = `$initialized_${this.objectInitializerCounter++}`;
|
|
10276
|
+
const receiver = variable(
|
|
10277
|
+
name,
|
|
10278
|
+
constructed.type,
|
|
10279
|
+
constructed.pointer,
|
|
10280
|
+
this.project
|
|
10281
|
+
);
|
|
10282
|
+
const initializerScope = new Scope(scope);
|
|
10283
|
+
initializerScope.define(
|
|
10284
|
+
scopeVariable(
|
|
10285
|
+
name,
|
|
10286
|
+
receiver,
|
|
10287
|
+
constructed.type,
|
|
10288
|
+
"local" /* Local */,
|
|
10289
|
+
"session" /* Session */,
|
|
10290
|
+
"local"
|
|
10291
|
+
)
|
|
10292
|
+
);
|
|
10293
|
+
const assignments = [];
|
|
10294
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10295
|
+
for (const entry of expression.initializer ?? []) {
|
|
10296
|
+
const key = entry.name.toLowerCase();
|
|
10297
|
+
if (seen.has(key)) {
|
|
10298
|
+
throw new CompileError(
|
|
10299
|
+
`Object initializer sets '${entry.name}' more than once.`,
|
|
10300
|
+
entry.pos
|
|
10301
|
+
);
|
|
10302
|
+
}
|
|
10303
|
+
seen.add(key);
|
|
10304
|
+
const assignment = this.resolveAssignment(
|
|
10305
|
+
{
|
|
10306
|
+
kind: "assign",
|
|
10307
|
+
op: "=",
|
|
10308
|
+
pos: entry.pos,
|
|
10309
|
+
value: entry.value,
|
|
10310
|
+
target: {
|
|
10311
|
+
kind: "member",
|
|
10312
|
+
name: entry.name,
|
|
10313
|
+
pos: entry.pos,
|
|
10314
|
+
receiver: { kind: "ident", name, pos: entry.pos }
|
|
10315
|
+
}
|
|
10316
|
+
},
|
|
10317
|
+
initializerScope
|
|
10318
|
+
);
|
|
10319
|
+
if (assignment.type !== "assign" /* Assign */) {
|
|
10320
|
+
throw new CompileError(
|
|
10321
|
+
"Object initializer entries must be assignments.",
|
|
10322
|
+
entry.pos
|
|
10323
|
+
);
|
|
10324
|
+
}
|
|
10325
|
+
assignments.push(assignment);
|
|
10326
|
+
}
|
|
10327
|
+
return {
|
|
10328
|
+
pointer: {
|
|
10329
|
+
type: "objectInitializer" /* ObjectInitializer */,
|
|
10330
|
+
receiver,
|
|
10331
|
+
assignments
|
|
10332
|
+
},
|
|
10333
|
+
type: constructed.type,
|
|
10334
|
+
writability: "session" /* Session */,
|
|
10335
|
+
writeRoot: "local"
|
|
10336
|
+
};
|
|
10337
|
+
}
|
|
10266
10338
|
resolveClassConstructor(className, expression, scope, pos, expected) {
|
|
10267
10339
|
const schemaClass2 = this.project.typeByName.get(className);
|
|
10268
10340
|
if (!schemaClass2 || schemaClass2.kind !== "class") {
|
|
@@ -12371,11 +12443,7 @@ var init_strict_resolver = __esm({
|
|
|
12371
12443
|
*/
|
|
12372
12444
|
localWriteTargetRoot(initial, scope) {
|
|
12373
12445
|
if (this.context.kind !== "constructor") return "local";
|
|
12374
|
-
|
|
12375
|
-
return CONSTRUCTING_FUNCTION_KINDS.has(initial.pointer.function.type) ? "local" : "unknown";
|
|
12376
|
-
}
|
|
12377
|
-
if (initial.pointer.type === "value" /* Value */) return "local";
|
|
12378
|
-
return this.writeThroughRoot(initial.pointer, scope);
|
|
12446
|
+
return this.expressionWriteRoot(initial, scope);
|
|
12379
12447
|
}
|
|
12380
12448
|
validateCallableInContext(symbol, pos) {
|
|
12381
12449
|
if (symbol.native === true && !NEO_CELL_PATTERN_PURE_NATIVE_MEMBER_IDS.has(symbol.id) && isNeoScriptConstructionDocumentKind(this.context.kind)) {
|
|
@@ -22364,7 +22432,7 @@ function validateDeclaration(uri, declaration, documentKind, environment, diagno
|
|
|
22364
22432
|
}
|
|
22365
22433
|
}
|
|
22366
22434
|
for (const member of declaration.members) {
|
|
22367
|
-
scope.set(member.name,
|
|
22435
|
+
scope.set(member.name, semanticMemberType(member, environment));
|
|
22368
22436
|
}
|
|
22369
22437
|
for (const member of declaration.members) {
|
|
22370
22438
|
validateMember(
|
|
@@ -23748,7 +23816,7 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
23748
23816
|
if (expression.kind === "unary" || expression.kind === "force") {
|
|
23749
23817
|
validateExpression(
|
|
23750
23818
|
expression.operand,
|
|
23751
|
-
expected,
|
|
23819
|
+
expression.kind === "force" && expected ? { ...expected, nullable: true } : expected,
|
|
23752
23820
|
scope,
|
|
23753
23821
|
environment,
|
|
23754
23822
|
uri,
|
|
@@ -23780,7 +23848,9 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
23780
23848
|
);
|
|
23781
23849
|
validateExpression(
|
|
23782
23850
|
expression.index,
|
|
23783
|
-
|
|
23851
|
+
subscriptKeyType(
|
|
23852
|
+
inferExpressionType2(expression.receiver, scope, environment)
|
|
23853
|
+
),
|
|
23784
23854
|
scope,
|
|
23785
23855
|
environment,
|
|
23786
23856
|
uri,
|
|
@@ -23867,10 +23937,10 @@ function anchorPosition(anchor, offset) {
|
|
|
23867
23937
|
}
|
|
23868
23938
|
return { line: anchor.start.line + line, character };
|
|
23869
23939
|
}
|
|
23870
|
-
function sourceClassFieldByName(declaration, name, environment) {
|
|
23940
|
+
function sourceClassFieldByName(declaration, name, environment, initialBindings = /* @__PURE__ */ new Map()) {
|
|
23871
23941
|
const visited = /* @__PURE__ */ new Set();
|
|
23872
23942
|
let current = declaration;
|
|
23873
|
-
let bindings =
|
|
23943
|
+
let bindings = initialBindings;
|
|
23874
23944
|
while (current !== void 0 && !visited.has(current.name)) {
|
|
23875
23945
|
visited.add(current.name);
|
|
23876
23946
|
const member = current.members.find(
|
|
@@ -24013,6 +24083,21 @@ function inferExpressionType2(expression, scope, environment) {
|
|
|
24013
24083
|
return primitiveType("string");
|
|
24014
24084
|
if (expression.kind === "new")
|
|
24015
24085
|
return expression.className ? { name: expression.className } : void 0;
|
|
24086
|
+
if (expression.kind === "force") {
|
|
24087
|
+
const operand = inferExpressionType2(expression.operand, scope, environment);
|
|
24088
|
+
return operand ? { ...operand, nullable: false } : void 0;
|
|
24089
|
+
}
|
|
24090
|
+
if (expression.kind === "index") {
|
|
24091
|
+
const receiver = inferExpressionType2(
|
|
24092
|
+
expression.receiver,
|
|
24093
|
+
scope,
|
|
24094
|
+
environment
|
|
24095
|
+
);
|
|
24096
|
+
if (receiver?.name !== "Dictionary" && receiver?.name !== "List")
|
|
24097
|
+
return void 0;
|
|
24098
|
+
const value = receiver.arguments?.[receiver.name === "Dictionary" ? 1 : 0];
|
|
24099
|
+
return expression.optional && value ? { ...value, nullable: true } : value;
|
|
24100
|
+
}
|
|
24016
24101
|
if (expression.kind === "conditional") {
|
|
24017
24102
|
const whenTrue = inferExpressionType2(
|
|
24018
24103
|
expression.whenTrue,
|
|
@@ -24030,15 +24115,48 @@ function inferExpressionType2(expression, scope, environment) {
|
|
|
24030
24115
|
if (expression.receiver.kind === "ident" && environment.enums.has(expression.receiver.name)) {
|
|
24031
24116
|
return { name: expression.receiver.name };
|
|
24032
24117
|
}
|
|
24033
|
-
const
|
|
24118
|
+
const receiverType = inferExpressionType2(
|
|
24034
24119
|
expression.receiver,
|
|
24035
24120
|
scope,
|
|
24036
24121
|
environment
|
|
24037
24122
|
);
|
|
24123
|
+
const staticDeclaration = receiverType === void 0 && expression.receiver.kind === "ident" ? environment.types.get(expression.receiver.name) : void 0;
|
|
24124
|
+
const receiver = receiverType ?? (staticDeclaration ? { name: staticDeclaration.name } : void 0);
|
|
24125
|
+
if (receiver?.name === "Root") {
|
|
24126
|
+
const slot = PROJECT_ROOT_SOURCE_SLOTS.find(
|
|
24127
|
+
(slot2) => slot2.name === expression.name
|
|
24128
|
+
);
|
|
24129
|
+
return slot ? { name: slot.type } : void 0;
|
|
24130
|
+
}
|
|
24131
|
+
if (receiver?.name === "List" && receiver.listIndexes && expression.name === "Index") {
|
|
24132
|
+
return { name: "Index", listIndexes: receiver.listIndexes };
|
|
24133
|
+
}
|
|
24134
|
+
if (receiver?.name === "Index" && receiver.listIndexes)
|
|
24135
|
+
return receiver.listIndexes.get(expression.name);
|
|
24038
24136
|
const declaration = receiver ? environment.types.get(receiver.name) : void 0;
|
|
24039
|
-
|
|
24137
|
+
if (!declaration) return void 0;
|
|
24138
|
+
const bindings = new Map(
|
|
24139
|
+
declaration.genericParameters.flatMap((parameter4, index) => {
|
|
24140
|
+
const argument2 = receiver?.arguments?.[index];
|
|
24141
|
+
return argument2 ? [[parameter4.name, argument2]] : [];
|
|
24142
|
+
})
|
|
24143
|
+
);
|
|
24144
|
+
const field = sourceClassFieldByName(
|
|
24145
|
+
declaration,
|
|
24146
|
+
expression.name,
|
|
24147
|
+
environment,
|
|
24148
|
+
bindings
|
|
24149
|
+
);
|
|
24150
|
+
if (field) {
|
|
24151
|
+
if (staticDeclaration && !field.member.modifiers.includes("static"))
|
|
24152
|
+
return void 0;
|
|
24153
|
+
return semanticMemberType(field.member, environment, field.bindings);
|
|
24154
|
+
}
|
|
24155
|
+
const member = declaration.members.find(
|
|
24040
24156
|
(candidate) => candidate.name === expression.name
|
|
24041
24157
|
);
|
|
24158
|
+
if (staticDeclaration && !member?.modifiers.includes("static"))
|
|
24159
|
+
return void 0;
|
|
24042
24160
|
return member ? semanticType(member.type) : void 0;
|
|
24043
24161
|
}
|
|
24044
24162
|
if (expression.kind === "call" && expression.callee.kind === "ident") {
|
|
@@ -24052,6 +24170,34 @@ function inferExpressionType2(expression, scope, environment) {
|
|
|
24052
24170
|
}
|
|
24053
24171
|
return void 0;
|
|
24054
24172
|
}
|
|
24173
|
+
function semanticMemberType(member, environment, bindings = /* @__PURE__ */ new Map()) {
|
|
24174
|
+
const type = substituteSemanticType(semanticType(member.type), bindings);
|
|
24175
|
+
if (type.name !== "List") return type;
|
|
24176
|
+
const entryType = type.arguments?.[0];
|
|
24177
|
+
if (!entryType) return type;
|
|
24178
|
+
const entryClass = environment.types.get(entryType.name);
|
|
24179
|
+
if (!entryClass) return type;
|
|
24180
|
+
const indexes2 = /* @__PURE__ */ new Map();
|
|
24181
|
+
for (const annotation2 of member.annotations) {
|
|
24182
|
+
if (annotation2.name !== "index") continue;
|
|
24183
|
+
const key = memberKeyArgument(annotation2)?.key;
|
|
24184
|
+
if (!key) continue;
|
|
24185
|
+
const field = resolveEntryField(entryClass, key, environment);
|
|
24186
|
+
if (!field) continue;
|
|
24187
|
+
const unique = contextualAnnotationEnum([annotation2], "index", "kind") === "Unique";
|
|
24188
|
+
const valueType = unique ? { ...entryType, nullable: true } : { name: "List", arguments: [{ ...entryType, nullable: false }] };
|
|
24189
|
+
indexes2.set(key, {
|
|
24190
|
+
name: "Dictionary",
|
|
24191
|
+
arguments: [semanticType(field.type), valueType]
|
|
24192
|
+
});
|
|
24193
|
+
}
|
|
24194
|
+
return indexes2.size === 0 ? type : { ...type, listIndexes: indexes2 };
|
|
24195
|
+
}
|
|
24196
|
+
function subscriptKeyType(receiver) {
|
|
24197
|
+
if (receiver?.name === "Dictionary") return receiver.arguments?.[0];
|
|
24198
|
+
if (receiver?.name === "List") return primitiveType("int");
|
|
24199
|
+
return void 0;
|
|
24200
|
+
}
|
|
24055
24201
|
function validateReferenceExpression(expression, expected, environment, uri, range2, diagnostics) {
|
|
24056
24202
|
const typeArguments = expression.typeArguments ?? [];
|
|
24057
24203
|
const names = expression.argumentNames ?? [];
|
|
@@ -45932,6 +46078,13 @@ function isNSPointerCallFunction(value) {
|
|
|
45932
46078
|
}
|
|
45933
46079
|
return true;
|
|
45934
46080
|
}
|
|
46081
|
+
function isNSPointerObjectInitializer(value) {
|
|
46082
|
+
if (typeof value !== "object" || value === null) return false;
|
|
46083
|
+
if (!("type" in value) || value.type !== "objectInitializer" /* objectInitializer */)
|
|
46084
|
+
return false;
|
|
46085
|
+
if (!("receiver" in value) || !isNSVariable(value.receiver)) return false;
|
|
46086
|
+
return "assignments" in value && Array.isArray(value.assignments) && value.assignments.every(isNSInstructionAssign);
|
|
46087
|
+
}
|
|
45935
46088
|
function isNSPointerCallDelegate(value) {
|
|
45936
46089
|
const v = value;
|
|
45937
46090
|
if (v?.type !== "callDelegate" /* callDelegate */) return false;
|
|
@@ -45970,7 +46123,7 @@ function isNSPointerFunctionErrorCheck(value) {
|
|
|
45970
46123
|
return isNSFunctionErrorCheckMode(v.mode);
|
|
45971
46124
|
}
|
|
45972
46125
|
function isNSPointer(value) {
|
|
45973
|
-
return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerStaticMember(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerConditional(value) || isNSPointerDelegateClosure(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerTileConvert(value) || isNSPointerCallFunction(value) || isNSPointerCallDelegate(value) || isNSPointerCallAction(value) || isNSPointerVariant(value) || isNSPointerFunctionErrorCheck(value);
|
|
46126
|
+
return isNSPointerReference(value) || isNSPointerVariable(value) || isNSPointerStaticMember(value) || isNSPointerValue(value) || isNSPointerOperation(value) || isNSPointerFunction(value) || isNSPointerKeyOf(value) || isNSPointerListLiteral(value) || isNSPointerDictLiteral(value) || isNSPointerForceUnwrap(value) || isNSPointerIsCheck(value) || isNSPointerCallGetter(value) || isNSPointerCoalesce(value) || isNSPointerConditional(value) || isNSPointerDelegateClosure(value) || isNSPointerObjectInitializer(value) || isNSPointerToBool(value) || isNSPointerStringify(value) || isNSPointerTileConvert(value) || isNSPointerCallFunction(value) || isNSPointerCallDelegate(value) || isNSPointerCallAction(value) || isNSPointerVariant(value) || isNSPointerFunctionErrorCheck(value);
|
|
45974
46127
|
}
|
|
45975
46128
|
function isNSPointers(value) {
|
|
45976
46129
|
return Array.isArray(value) && value.every(isNSPointer);
|
|
@@ -71060,10 +71213,98 @@ function createdSessionValuesSince(ctx, checkpoint) {
|
|
|
71060
71213
|
}
|
|
71061
71214
|
return created;
|
|
71062
71215
|
}
|
|
71216
|
+
function exportInitializerCollections(created, writes, ctx) {
|
|
71217
|
+
const assignedValues = /* @__PURE__ */ new Set();
|
|
71218
|
+
for (const write of writes) {
|
|
71219
|
+
if (write.kind === "assign" && write.valueId === void 0 && typeof write.value === "object" && write.value !== null) {
|
|
71220
|
+
assignedValues.add(write.value);
|
|
71221
|
+
}
|
|
71222
|
+
}
|
|
71223
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
71224
|
+
for (const row of created) {
|
|
71225
|
+
if (assignedValues.has(row.value) || Array.isArray(row.value) && row.value.length > 0 && ctx.__unorderedListProjections?.byContainerId.has(row.id)) {
|
|
71226
|
+
candidates.add(row.id);
|
|
71227
|
+
}
|
|
71228
|
+
}
|
|
71229
|
+
if (candidates.size === 0) return created;
|
|
71230
|
+
invalidateEvaluatorIndexes(ctx, null);
|
|
71231
|
+
const extra = [];
|
|
71232
|
+
const exported = created.map((row) => {
|
|
71233
|
+
if (!candidates.has(row.id)) return row;
|
|
71234
|
+
const member = memberForValueRow(row, ctx);
|
|
71235
|
+
if (member === null) return row;
|
|
71236
|
+
if (!isMemberListBase(member) && !isMemberDictionaryBase(member))
|
|
71237
|
+
return row;
|
|
71238
|
+
if (isMemberListBase(member) && listKindOf(member) === 1 /* Unordered */) {
|
|
71239
|
+
return { ...row, value: [] };
|
|
71240
|
+
}
|
|
71241
|
+
if (!assignedValues.has(row.value)) return row;
|
|
71242
|
+
const values = [];
|
|
71243
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
71244
|
+
const genericEnv = runtimeGenericEnvForValueRow(row, ctx, /* @__PURE__ */ new Set());
|
|
71245
|
+
overlayConcreteGenericEntries(
|
|
71246
|
+
genericEnv,
|
|
71247
|
+
envFromStamp(row.genericBindings)
|
|
71248
|
+
);
|
|
71249
|
+
const materialized = materializeConstructorArgumentValue({
|
|
71250
|
+
member,
|
|
71251
|
+
value: row.value,
|
|
71252
|
+
genericEnv,
|
|
71253
|
+
ctx,
|
|
71254
|
+
createdValues: values,
|
|
71255
|
+
createdById: /* @__PURE__ */ new Map(),
|
|
71256
|
+
storageKeyDeclarations: declarations,
|
|
71257
|
+
collectionEntriesAreReferences: false,
|
|
71258
|
+
collectionOwnerId: row.id
|
|
71259
|
+
});
|
|
71260
|
+
const encoded = { ...row, value: materialized.value };
|
|
71261
|
+
const children = values.filter((value) => value !== materialized);
|
|
71262
|
+
declarations.delete(materialized.id);
|
|
71263
|
+
const groupId = constructorGroupForRow(row.id, ctx);
|
|
71264
|
+
retargetConstructorGroupDependencies(
|
|
71265
|
+
materialized.id,
|
|
71266
|
+
groupId ?? row.id,
|
|
71267
|
+
ctx
|
|
71268
|
+
);
|
|
71269
|
+
if (groupId !== null) {
|
|
71270
|
+
const state = ctx.__executionState;
|
|
71271
|
+
const group = state?.constructorGroups.get(groupId);
|
|
71272
|
+
for (const child of children) {
|
|
71273
|
+
retargetConstructorGroupDependencies(child.id, groupId, ctx);
|
|
71274
|
+
group?.add(child.id);
|
|
71275
|
+
state?.constructorGroupByRowId.set(child.id, groupId);
|
|
71276
|
+
}
|
|
71277
|
+
}
|
|
71278
|
+
stampCreatedValuesMapKey(children, row.mapKey);
|
|
71279
|
+
applyDeclaredStorageKeyOverrides({
|
|
71280
|
+
createdValues: [encoded, ...children],
|
|
71281
|
+
declarationByValueId: declarations
|
|
71282
|
+
});
|
|
71283
|
+
consumeBudget(
|
|
71284
|
+
ctx,
|
|
71285
|
+
"constructedSessionRows",
|
|
71286
|
+
children.length,
|
|
71287
|
+
"constructed Session row"
|
|
71288
|
+
);
|
|
71289
|
+
for (const child of children) {
|
|
71290
|
+
if (!isLiteralValueContent(child)) {
|
|
71291
|
+
throw new NSGetterRuntimeError(
|
|
71292
|
+
"Initializer collection produced an unevaluated row."
|
|
71293
|
+
);
|
|
71294
|
+
}
|
|
71295
|
+
extra.push(child);
|
|
71296
|
+
}
|
|
71297
|
+
for (const [id2, declaration] of declarations) {
|
|
71298
|
+
ctx.__createdStorageKeyDeclarations?.set(id2, declaration);
|
|
71299
|
+
}
|
|
71300
|
+
return encoded;
|
|
71301
|
+
});
|
|
71302
|
+
return [...exported, ...extra];
|
|
71303
|
+
}
|
|
71063
71304
|
function evaluateNSGetter(getter, ctx) {
|
|
71064
71305
|
return evaluateNSGetterWithEffects(getter, ctx).value;
|
|
71065
71306
|
}
|
|
71066
|
-
function evaluateNSGetterWithEffects(getter, ctx, argumentValues = []) {
|
|
71307
|
+
function evaluateNSGetterWithEffects(getter, ctx, argumentValues = [], options = {}) {
|
|
71067
71308
|
const ownsInvocationState = ctx.__executionState === void 0;
|
|
71068
71309
|
const requestedWrites = [];
|
|
71069
71310
|
const runtimeCtx = withEvaluationRuntime(ctx, requestedWrites);
|
|
@@ -71093,6 +71334,27 @@ function evaluateNSGetterWithEffects(getter, ctx, argumentValues = []) {
|
|
|
71093
71334
|
if (getter.typeInfo.type === 20 /* Decimal */ && typeof result.value === "number") {
|
|
71094
71335
|
result.value = coerceDecimalOperand(result.value, "return");
|
|
71095
71336
|
}
|
|
71337
|
+
if (options.exportInitializerValues) {
|
|
71338
|
+
const created = createdSessionValuesSince(
|
|
71339
|
+
runtimeCtx,
|
|
71340
|
+
creationCheckpoint
|
|
71341
|
+
);
|
|
71342
|
+
const rootIndex = created.findIndex(
|
|
71343
|
+
(row) => row.value === result.value
|
|
71344
|
+
);
|
|
71345
|
+
const exported = exportInitializerCollections(
|
|
71346
|
+
created,
|
|
71347
|
+
writes,
|
|
71348
|
+
runtimeCtx
|
|
71349
|
+
);
|
|
71350
|
+
if (exported !== created) {
|
|
71351
|
+
for (const row of exported)
|
|
71352
|
+
registerRuntimeSessionValue(runtimeCtx, row);
|
|
71353
|
+
invalidateEvaluatorIndexes(runtimeCtx, null);
|
|
71354
|
+
}
|
|
71355
|
+
const exportedRoot = exported[rootIndex];
|
|
71356
|
+
if (exportedRoot !== void 0) result.value = exportedRoot.value;
|
|
71357
|
+
}
|
|
71096
71358
|
finalizeConstructorAllocations(
|
|
71097
71359
|
runtimeCtx,
|
|
71098
71360
|
result.value,
|
|
@@ -73454,6 +73716,18 @@ function evalPointer(pointer, scope, ctx) {
|
|
|
73454
73716
|
state.functionStack.pop();
|
|
73455
73717
|
}
|
|
73456
73718
|
}
|
|
73719
|
+
case "objectInitializer" /* objectInitializer */: {
|
|
73720
|
+
const receiver = evalPointer(pointer.receiver.pointer, scope, ctx);
|
|
73721
|
+
const initializerScope = createChildScope(scope);
|
|
73722
|
+
initializerScope.setLocal(pointer.receiver.id, receiver);
|
|
73723
|
+
evalInstructions(
|
|
73724
|
+
pointer.assignments,
|
|
73725
|
+
initializerScope,
|
|
73726
|
+
ctx,
|
|
73727
|
+
evaluationOptions(ctx, true)
|
|
73728
|
+
);
|
|
73729
|
+
return receiver;
|
|
73730
|
+
}
|
|
73457
73731
|
case "callDelegate" /* callDelegate */: {
|
|
73458
73732
|
const delegate = evalPointer(pointer.delegate, scope, ctx);
|
|
73459
73733
|
if (delegate === null || delegate === void 0) {
|
|
@@ -75172,8 +75446,6 @@ function evalTileConvert(pointer, scope, ctx) {
|
|
|
75172
75446
|
);
|
|
75173
75447
|
}
|
|
75174
75448
|
if (receiverClassId === targetClassId) return true;
|
|
75175
|
-
const storedReceiver = ctx.vm.databaseVM?.storedValueById?.(receiverRow.id) ?? ctx.vm.values.find((row) => row.id === receiverRow.id) ?? null;
|
|
75176
|
-
if (storedReceiver === null) return false;
|
|
75177
75449
|
const cell = readSystemNativeField(receiver, "Cell", ctx);
|
|
75178
75450
|
const cellRow = trackedRowForValueReference(cell, ctx);
|
|
75179
75451
|
const nextValue = { Cell: cellRow?.id ?? cell };
|
|
@@ -75194,6 +75466,13 @@ function evalTileConvert(pointer, scope, ctx) {
|
|
|
75194
75466
|
targetClassId
|
|
75195
75467
|
);
|
|
75196
75468
|
ctx.__valueOverlay?.set(receiverRow.id, nextRow);
|
|
75469
|
+
const sessionRow = ctx.__runtimeSessionValues?.get(receiverRow.id);
|
|
75470
|
+
if (sessionRow !== void 0) {
|
|
75471
|
+
for (const key of Object.keys(sessionRow)) {
|
|
75472
|
+
if (!Object.hasOwn(nextRow, key)) Reflect.deleteProperty(sessionRow, key);
|
|
75473
|
+
}
|
|
75474
|
+
Object.assign(sessionRow, nextRow);
|
|
75475
|
+
}
|
|
75197
75476
|
ctx.__executionState?.writes.push({
|
|
75198
75477
|
kind: "replaceClass",
|
|
75199
75478
|
target: receiver,
|
|
@@ -79429,20 +79708,25 @@ function materializeConstructorArgumentValue(args) {
|
|
|
79429
79708
|
for (const entry of rows) sourceEntries.push(entry.value);
|
|
79430
79709
|
}
|
|
79431
79710
|
const ids = [];
|
|
79711
|
+
const referenceIndexes = args.ctx.__unorderedListProjections?.referenceEntryIndexesByArray.get(
|
|
79712
|
+
sourceEntries
|
|
79713
|
+
);
|
|
79432
79714
|
for (const [index, rawEntry] of sourceEntries.entries()) {
|
|
79433
79715
|
const entryValue = constructorCollectionEntryValue(
|
|
79434
79716
|
rawEntry,
|
|
79435
79717
|
args.ctx,
|
|
79436
|
-
trackedValueId !== null
|
|
79718
|
+
isMemberClassBase(resolvedEntry) || isMemberListBase(resolvedEntry) || isMemberDictionaryBase(resolvedEntry) || (referenceIndexes?.has(index) ?? args.collectionEntriesAreReferences ?? trackedValueId !== null)
|
|
79437
79719
|
);
|
|
79438
79720
|
const child = materializeConstructorArgumentValue({
|
|
79439
79721
|
...args,
|
|
79722
|
+
collectionEntriesAreReferences: void 0,
|
|
79723
|
+
collectionOwnerId: void 0,
|
|
79440
79724
|
member: resolvedEntry,
|
|
79441
79725
|
genericEnv: entryEnv,
|
|
79442
79726
|
value: entryValue,
|
|
79443
79727
|
owner: {
|
|
79444
|
-
identity: `value:${row.id}:index:${index}`,
|
|
79445
|
-
label: row.id
|
|
79728
|
+
identity: `value:${args.collectionOwnerId ?? row.id}:index:${index}`,
|
|
79729
|
+
label: args.collectionOwnerId ?? row.id
|
|
79446
79730
|
},
|
|
79447
79731
|
destinationName: `${args.member.name}[${index}]`
|
|
79448
79732
|
});
|
|
@@ -79479,16 +79763,18 @@ function materializeConstructorArgumentValue(args) {
|
|
|
79479
79763
|
const entry = constructorCollectionEntryValue(
|
|
79480
79764
|
rawEntry,
|
|
79481
79765
|
args.ctx,
|
|
79482
|
-
trackedValueId !== null
|
|
79766
|
+
isMemberClassBase(resolvedEntry) || isMemberListBase(resolvedEntry) || isMemberDictionaryBase(resolvedEntry) || (args.collectionEntriesAreReferences ?? trackedValueId !== null)
|
|
79483
79767
|
);
|
|
79484
79768
|
record6[key] = materializeConstructorArgumentValue({
|
|
79485
79769
|
...args,
|
|
79770
|
+
collectionEntriesAreReferences: void 0,
|
|
79771
|
+
collectionOwnerId: void 0,
|
|
79486
79772
|
member: resolvedEntry,
|
|
79487
79773
|
genericEnv: entryEnv,
|
|
79488
79774
|
value: entry,
|
|
79489
79775
|
owner: {
|
|
79490
|
-
identity: `value:${row.id}:slot:${key}`,
|
|
79491
|
-
label: row.id
|
|
79776
|
+
identity: `value:${args.collectionOwnerId ?? row.id}:slot:${key}`,
|
|
79777
|
+
label: args.collectionOwnerId ?? row.id
|
|
79492
79778
|
},
|
|
79493
79779
|
destinationName: `${args.member.name}[${key}]`
|
|
79494
79780
|
}).id;
|
|
@@ -83485,7 +83771,8 @@ function evaluateMemberInitializer(args) {
|
|
|
83485
83771
|
const result = evaluateNSGetterWithEffects(
|
|
83486
83772
|
compiled,
|
|
83487
83773
|
ctx,
|
|
83488
|
-
args.argumentValues ?? []
|
|
83774
|
+
args.argumentValues ?? [],
|
|
83775
|
+
{ exportInitializerValues: true }
|
|
83489
83776
|
);
|
|
83490
83777
|
const created = result.createdSessionValues ?? [];
|
|
83491
83778
|
if (isMemberLookupBase(args.member)) {
|
|
@@ -94462,7 +94749,7 @@ function inspectCollection(options, member) {
|
|
|
94462
94749
|
if (member.kind === 6 /* List */) {
|
|
94463
94750
|
listKind = listKindOf(member);
|
|
94464
94751
|
if (!isValidListValueShape(member, body)) {
|
|
94465
|
-
const label =
|
|
94752
|
+
const label = ListKind[listKind].toLowerCase();
|
|
94466
94753
|
fail(`${options.path} has an invalid ${label} List value shape.`);
|
|
94467
94754
|
}
|
|
94468
94755
|
if (listKind === 1 /* Unordered */) body = [];
|
|
@@ -137435,7 +137722,7 @@ var init_registry2 = __esm({
|
|
|
137435
137722
|
"schema-contract/registry.mjs"() {
|
|
137436
137723
|
"use strict";
|
|
137437
137724
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
137438
|
-
cliVersion: "0.52.
|
|
137725
|
+
cliVersion: "0.52.4",
|
|
137439
137726
|
projectFileUploadBatchSize: 32,
|
|
137440
137727
|
documentRecords: {
|
|
137441
137728
|
member: {
|
|
@@ -141699,6 +141986,7 @@ async function runPendingMigrations(workspace, raw, migrations, onlyRef) {
|
|
|
141699
141986
|
`Migration "${migrationName}" produced an invalid tile class replacement.`
|
|
141700
141987
|
);
|
|
141701
141988
|
}
|
|
141989
|
+
if (createdById.has(write.valueId)) continue;
|
|
141702
141990
|
const storedRoot = valueById.get(write.valueId);
|
|
141703
141991
|
if (storedRoot === void 0 || !isMemberValue(storedRoot)) {
|
|
141704
141992
|
throw new Error(
|
|
@@ -145307,7 +145595,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
145307
145595
|
async function main() {
|
|
145308
145596
|
const args = parseArgs(process.argv.slice(2));
|
|
145309
145597
|
if (args.command === "--version") {
|
|
145310
|
-
console.log("0.52.
|
|
145598
|
+
console.log("0.52.4");
|
|
145311
145599
|
return;
|
|
145312
145600
|
}
|
|
145313
145601
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -97,7 +97,7 @@ wrappers.
|
|
|
97
97
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
98
98
|
|
|
99
99
|
```html
|
|
100
|
-
<!-- reviewed-through-cli: 0.52.
|
|
100
|
+
<!-- reviewed-through-cli: 0.52.4 -->
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -120,6 +120,16 @@ runtime Class's one-argument `Equals` Function or NSFunction when it returns
|
|
|
120
120
|
`bool`, including the effective override. Values without that member fall back
|
|
121
121
|
to ordinary NeoScript equality.
|
|
122
122
|
|
|
123
|
+
Object initializers are available in method bodies and `.spec.neo` tests:
|
|
124
|
+
|
|
125
|
+
```neo
|
|
126
|
+
var tile = new DirtWetTile { Cell = Vector2Int(3, -2) };
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Construction runs first. Each initializer entry then uses ordinary assignment
|
|
130
|
+
rules in source order, including property setters, access checks, and readonly
|
|
131
|
+
restrictions. Initializer expressions read the caller's scope.
|
|
132
|
+
|
|
123
133
|
## Nullability and ownership
|
|
124
134
|
|
|
125
135
|
Do not access a nullable receiver directly. First narrow it with a condition, or
|