@neocompose/cli 0.24.6 → 0.24.8
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,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.24.8] - 2026-08-08
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Preserve generated Generic-slot initializers while closing their concrete
|
|
8
|
+
type. `NeoAnimationSegmentFrame<int>(value: 60)` now materializes `Value` as
|
|
9
|
+
`60` instead of replacing the initializer with the Int binding's fallback
|
|
10
|
+
`0`, keeping local and server construction graphs identical.
|
|
11
|
+
- Keep constructor-pane preview graphs stable while runtime values change, and
|
|
12
|
+
invalidate each animation segment lane only from the value rows that its
|
|
13
|
+
getter actually reads. Direction changes update the affected leaves without
|
|
14
|
+
reconstructing the ephemeral character graph.
|
|
15
|
+
|
|
16
|
+
## [0.24.7] - 2026-08-08
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Lower named delegate method groups such as `this.SelectTorso` to the P60
|
|
21
|
+
member-target wire form, then bind their receiver to each constructed
|
|
22
|
+
instance. Constructor-pane previews now retain that binding when replacing
|
|
23
|
+
the evaluator's provisional root, so animation tracks resolve against the
|
|
24
|
+
ephemeral preview graph instead of disappearing.
|
|
25
|
+
- Reconstruct stored inline-closure `this` from the nearest compatible lexical
|
|
26
|
+
owner in nested declaration graphs, keeping closures distinct from named
|
|
27
|
+
method groups as required by P60.
|
|
28
|
+
|
|
3
29
|
## [0.24.6] - 2026-08-08
|
|
4
30
|
|
|
5
31
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -10058,7 +10058,7 @@ var init_strict_resolver = __esm({
|
|
|
10058
10058
|
}
|
|
10059
10059
|
return void 0;
|
|
10060
10060
|
}
|
|
10061
|
-
resolveDelegateMethodGroup(expression, expected, scope) {
|
|
10061
|
+
resolveDelegateMethodGroup(expression, expected, scope, options = {}) {
|
|
10062
10062
|
let symbol;
|
|
10063
10063
|
let receiver = null;
|
|
10064
10064
|
let owner;
|
|
@@ -10133,29 +10133,17 @@ var init_strict_resolver = __esm({
|
|
|
10133
10133
|
expression.pos
|
|
10134
10134
|
);
|
|
10135
10135
|
}
|
|
10136
|
-
|
|
10137
|
-
|
|
10136
|
+
if (receiver?.kind === "instance" && options.allowUnboundInstanceTarget !== true && (receiver.expression.pointer.type !== "variable" /* Variable */ || receiver.expression.pointer.variableId !== this.thisVariable.id)) {
|
|
10137
|
+
throw new CompileError(
|
|
10138
|
+
"NeoDelegate method groups currently require the current 'this' receiver.",
|
|
10139
|
+
expression.pos
|
|
10140
|
+
);
|
|
10141
|
+
}
|
|
10142
|
+
return literal(
|
|
10143
|
+
expected,
|
|
10144
|
+
{ memberId: symbol.id, valueId: null },
|
|
10145
|
+
this.project
|
|
10138
10146
|
);
|
|
10139
|
-
const call = {
|
|
10140
|
-
type: "callFunction" /* CallFunction */,
|
|
10141
|
-
memberId: symbol.id,
|
|
10142
|
-
receiver: receiver?.kind === "static" ? { kind: "static", memberId: receiver.memberId } : {
|
|
10143
|
-
kind: "instance",
|
|
10144
|
-
pointer: receiver?.expression.pointer ?? this.thisVariable.pointer
|
|
10145
|
-
},
|
|
10146
|
-
args: parameters.map((parameter4) => ({
|
|
10147
|
-
type: "variable" /* Variable */,
|
|
10148
|
-
variableId: parameter4.id
|
|
10149
|
-
})),
|
|
10150
|
-
callSiteId: this.nextCallSite(expression.pos)
|
|
10151
|
-
};
|
|
10152
|
-
const action = {
|
|
10153
|
-
compilerRevision: NEOSCRIPT_COMPILER_REVISION,
|
|
10154
|
-
parameters: [this.thisVariable, this.rootVariable, ...parameters],
|
|
10155
|
-
instructions: expectedVoid ? [{ type: "functionCall" /* FunctionCall */, call }] : [{ type: "return" /* Return */, pointer: call }],
|
|
10156
|
-
typeInfo: expectedVoid ? toWireType({ kind: "primitive", name: "null" }, this.project) : toWireType(expected.returnType, this.project)
|
|
10157
|
-
};
|
|
10158
|
-
return literal(expected, { action }, this.project);
|
|
10159
10147
|
}
|
|
10160
10148
|
/** Derives the exact expected delegate signature for a test mock target. */
|
|
10161
10149
|
inferDelegateMethodGroupType(expression, scope) {
|
|
@@ -11830,7 +11818,10 @@ var init_strict_resolver = __esm({
|
|
|
11830
11818
|
const target = this.resolveDelegateMethodGroup(
|
|
11831
11819
|
targetAst,
|
|
11832
11820
|
delegateType,
|
|
11833
|
-
scope
|
|
11821
|
+
scope,
|
|
11822
|
+
// Mock targets are member-identity metadata. They are never invoked as
|
|
11823
|
+
// delegates, and mockHandle.on(receiver) owns receiver scoping.
|
|
11824
|
+
{ allowUnboundInstanceTarget: true }
|
|
11834
11825
|
);
|
|
11835
11826
|
if (target === null) {
|
|
11836
11827
|
throw new CompileError(
|
|
@@ -40053,6 +40044,9 @@ function substituteMember(member, env, members) {
|
|
|
40053
40044
|
accessModifierKind: resolved.accessModifierKind,
|
|
40054
40045
|
system: resolved.system ?? void 0
|
|
40055
40046
|
};
|
|
40047
|
+
if (resolved.defaultValue !== void 0) {
|
|
40048
|
+
substituted.defaultValue = resolved.defaultValue;
|
|
40049
|
+
}
|
|
40056
40050
|
const slotId = getOptionalString(member, "id");
|
|
40057
40051
|
if (slotId !== void 0) {
|
|
40058
40052
|
substituted.id = slotId;
|
|
@@ -42238,6 +42232,7 @@ function evaluateLiteralContainer(args) {
|
|
|
42238
42232
|
}
|
|
42239
42233
|
return {
|
|
42240
42234
|
literal: literal2,
|
|
42235
|
+
...evaluated.provisionalRootId === void 0 ? {} : { provisionalRootId: evaluated.provisionalRootId },
|
|
42241
42236
|
...evaluated.existingValueRow === void 0 ? {} : { existingValueRow: evaluated.existingValueRow }
|
|
42242
42237
|
};
|
|
42243
42238
|
}
|
|
@@ -42259,6 +42254,13 @@ function buildDefaultMemberValue(args) {
|
|
|
42259
42254
|
return evaluated.existingValueRow;
|
|
42260
42255
|
}
|
|
42261
42256
|
const value2 = buildNewValue(args.projectId, evaluated.literal);
|
|
42257
|
+
if (evaluated.provisionalRootId !== void 0) {
|
|
42258
|
+
retargetDelegateReceiverValueIds(
|
|
42259
|
+
[value2, ...args.createdValues],
|
|
42260
|
+
evaluated.provisionalRootId,
|
|
42261
|
+
value2.id
|
|
42262
|
+
);
|
|
42263
|
+
}
|
|
42262
42264
|
args.createdValues.push(value2);
|
|
42263
42265
|
recordStorageKeyDeclaration(args.storageKeyDeclarations, value2.id, member);
|
|
42264
42266
|
return value2;
|
|
@@ -42465,6 +42467,28 @@ function buildNewValue(projectId, body) {
|
|
|
42465
42467
|
};
|
|
42466
42468
|
return props;
|
|
42467
42469
|
}
|
|
42470
|
+
function retargetDelegateReceiverValueIds(rows, fromValueId, toValueId) {
|
|
42471
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
42472
|
+
const visit = (value) => {
|
|
42473
|
+
if (typeof value !== "object" || value === null) return;
|
|
42474
|
+
if (visited.has(value)) return;
|
|
42475
|
+
visited.add(value);
|
|
42476
|
+
if (isMemberDelegateTarget(value)) {
|
|
42477
|
+
if (value.valueId === fromValueId) value.valueId = toValueId;
|
|
42478
|
+
return;
|
|
42479
|
+
}
|
|
42480
|
+
if (Array.isArray(value)) {
|
|
42481
|
+
for (const entry of value) visit(entry);
|
|
42482
|
+
return;
|
|
42483
|
+
}
|
|
42484
|
+
for (const entry of Object.values(value)) visit(entry);
|
|
42485
|
+
};
|
|
42486
|
+
for (const row of rows) {
|
|
42487
|
+
if (!isLiteralValueContent(row)) continue;
|
|
42488
|
+
visit(row.value);
|
|
42489
|
+
visit(row.constructorArgs);
|
|
42490
|
+
}
|
|
42491
|
+
}
|
|
42468
42492
|
function cloneDefaultClassRecord(args) {
|
|
42469
42493
|
const sourceValue = args.sourceBody?.value;
|
|
42470
42494
|
if (!isStringRecord(sourceValue)) return {};
|
|
@@ -42601,6 +42625,13 @@ function cloneDefaultValueForMember(args) {
|
|
|
42601
42625
|
return evaluated.existingValueRow;
|
|
42602
42626
|
}
|
|
42603
42627
|
const evaluatedRow = buildNewValue(args.projectId, evaluated.literal);
|
|
42628
|
+
if (evaluated.provisionalRootId !== void 0) {
|
|
42629
|
+
retargetDelegateReceiverValueIds(
|
|
42630
|
+
[evaluatedRow, ...args.createdValues],
|
|
42631
|
+
evaluated.provisionalRootId,
|
|
42632
|
+
evaluatedRow.id
|
|
42633
|
+
);
|
|
42634
|
+
}
|
|
42604
42635
|
evaluatedRow.sourceValueId = sourceValue.sourceValueId ?? args.sourceValueId;
|
|
42605
42636
|
args.createdValues.push(evaluatedRow);
|
|
42606
42637
|
recordStorageKeyDeclaration(
|
|
@@ -56610,7 +56641,8 @@ function evalMemberById(vm, id2) {
|
|
|
56610
56641
|
if (vm.databaseVM?.memberById) return vm.databaseVM.memberById(id2);
|
|
56611
56642
|
return vm.members.find((a) => a.id === id2) ?? null;
|
|
56612
56643
|
}
|
|
56613
|
-
function evalValueById(
|
|
56644
|
+
function evalValueById(ctx, id2, runtimeValues, overlayValues) {
|
|
56645
|
+
const vm = ctx.vm;
|
|
56614
56646
|
const runtime = runtimeValues?.get(id2);
|
|
56615
56647
|
if (runtime !== void 0) return runtime;
|
|
56616
56648
|
const overlay = overlayValues?.get(id2);
|
|
@@ -56880,7 +56912,7 @@ function evaluatorOwnershipDistances(rowId, indexes) {
|
|
|
56880
56912
|
}
|
|
56881
56913
|
function resolveRuntimeReferenceRow(sourceValueId, ctx) {
|
|
56882
56914
|
const direct = evalValueById(
|
|
56883
|
-
ctx
|
|
56915
|
+
ctx,
|
|
56884
56916
|
sourceValueId,
|
|
56885
56917
|
ctx.__runtimeSessionValues,
|
|
56886
56918
|
ctx.__valueOverlay
|
|
@@ -57319,7 +57351,7 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
|
|
|
57319
57351
|
if (scannedRows.has(valueId)) return;
|
|
57320
57352
|
scannedRows.add(valueId);
|
|
57321
57353
|
const row = evalValueById(
|
|
57322
|
-
ctx
|
|
57354
|
+
ctx,
|
|
57323
57355
|
valueId,
|
|
57324
57356
|
ctx.__runtimeSessionValues,
|
|
57325
57357
|
ctx.__valueOverlay
|
|
@@ -57329,7 +57361,7 @@ function finalizeConstructorAllocations(ctx, returnValue, ownsInvocationState, r
|
|
|
57329
57361
|
const { id: argumentId, typeInfo } = argument2;
|
|
57330
57362
|
if (groupByRowId.has(argumentId)) scanOwnedRow(argumentId);
|
|
57331
57363
|
const argumentRow = evalValueById(
|
|
57332
|
-
ctx
|
|
57364
|
+
ctx,
|
|
57333
57365
|
argumentId,
|
|
57334
57366
|
ctx.__runtimeSessionValues,
|
|
57335
57367
|
ctx.__valueOverlay
|
|
@@ -58182,7 +58214,7 @@ function applyOverlayAssignment(target, targetTypeInfo, value, scope, ctx) {
|
|
|
58182
58214
|
const existing2 = receiver[index];
|
|
58183
58215
|
if (typeof existing2 === "string") {
|
|
58184
58216
|
const row = evalValueById(
|
|
58185
|
-
ctx
|
|
58217
|
+
ctx,
|
|
58186
58218
|
existing2,
|
|
58187
58219
|
ctx.__runtimeSessionValues,
|
|
58188
58220
|
ctx.__valueOverlay
|
|
@@ -58219,7 +58251,7 @@ function applyOverlayAssignment(target, targetTypeInfo, value, scope, ctx) {
|
|
|
58219
58251
|
const existing = object2[stringKey];
|
|
58220
58252
|
if (typeof existing === "string") {
|
|
58221
58253
|
const row = evalValueById(
|
|
58222
|
-
ctx
|
|
58254
|
+
ctx,
|
|
58223
58255
|
existing,
|
|
58224
58256
|
ctx.__runtimeSessionValues,
|
|
58225
58257
|
ctx.__valueOverlay
|
|
@@ -58269,7 +58301,7 @@ function applyOverlayStaticAssignment(memberId, value, ctx) {
|
|
|
58269
58301
|
}
|
|
58270
58302
|
if (!referenceAssignment && currentId !== null) {
|
|
58271
58303
|
const row2 = evalValueById(
|
|
58272
|
-
ctx
|
|
58304
|
+
ctx,
|
|
58273
58305
|
currentId,
|
|
58274
58306
|
ctx.__runtimeSessionValues,
|
|
58275
58307
|
ctx.__valueOverlay
|
|
@@ -58775,7 +58807,7 @@ function evalStaticMember(memberId, ctx) {
|
|
|
58775
58807
|
return null;
|
|
58776
58808
|
}
|
|
58777
58809
|
const row = evalValueById(
|
|
58778
|
-
ctx
|
|
58810
|
+
ctx,
|
|
58779
58811
|
targetId,
|
|
58780
58812
|
ctx.__runtimeSessionValues,
|
|
58781
58813
|
ctx.__valueOverlay
|
|
@@ -58785,6 +58817,7 @@ function evalStaticMember(memberId, ctx) {
|
|
|
58785
58817
|
`Static member '${member.name}' is bound to missing value '${targetId}'.`
|
|
58786
58818
|
);
|
|
58787
58819
|
}
|
|
58820
|
+
ctx.valueDependencies?.add(row.id);
|
|
58788
58821
|
return row.value;
|
|
58789
58822
|
}
|
|
58790
58823
|
function evalPointer(pointer, scope, ctx) {
|
|
@@ -58794,10 +58827,16 @@ function evalPointer(pointer, scope, ctx) {
|
|
|
58794
58827
|
if (isNSDelegateClosureValue(value)) {
|
|
58795
58828
|
return {
|
|
58796
58829
|
...value,
|
|
58797
|
-
[DELEGATE_LEXICAL_THIS]: ctx.thisValue,
|
|
58830
|
+
...ctx.thisValue === null || ctx.thisValue === void 0 ? {} : { [DELEGATE_LEXICAL_THIS]: ctx.thisValue },
|
|
58798
58831
|
[DELEGATE_LEXICAL_ROOT]: ctx.rootValue
|
|
58799
58832
|
};
|
|
58800
58833
|
}
|
|
58834
|
+
if (isMemberDelegateTarget(value) && value.valueId === null) {
|
|
58835
|
+
const member = evalMemberById(ctx.vm, value.memberId);
|
|
58836
|
+
if (member === null || member.isStatic === true) return value;
|
|
58837
|
+
const receiver = trackedRowForValueReference(ctx.thisValue, ctx);
|
|
58838
|
+
return receiver === null ? value : { ...value, valueId: receiver.id };
|
|
58839
|
+
}
|
|
58801
58840
|
return value;
|
|
58802
58841
|
}
|
|
58803
58842
|
case "variable" /* variable */: {
|
|
@@ -59064,7 +59103,7 @@ function invokeDelegateValue(value, args, ctx, callSiteId) {
|
|
|
59064
59103
|
let receiver = null;
|
|
59065
59104
|
if (value.valueId !== null) {
|
|
59066
59105
|
const row = evalValueById(
|
|
59067
|
-
ctx
|
|
59106
|
+
ctx,
|
|
59068
59107
|
value.valueId,
|
|
59069
59108
|
ctx.__runtimeSessionValues,
|
|
59070
59109
|
ctx.__valueOverlay
|
|
@@ -59173,50 +59212,49 @@ function delegateClosureLexicalThis(closure, ctx) {
|
|
|
59173
59212
|
if (Object.prototype.hasOwnProperty.call(closure, DELEGATE_LEXICAL_THIS)) {
|
|
59174
59213
|
return closure[DELEGATE_LEXICAL_THIS];
|
|
59175
59214
|
}
|
|
59215
|
+
const lexicalThisType = closure.action.parameters[0]?.typeInfo;
|
|
59216
|
+
if (lexicalThisType === void 0 || lexicalThisType.type === NS_TYPE_UNKNOWN || lexicalThisType.type === 0 /* Null */) {
|
|
59217
|
+
return null;
|
|
59218
|
+
}
|
|
59176
59219
|
const closureRow = trackedRowForValueReference(closure, ctx);
|
|
59177
59220
|
if (closureRow === null) {
|
|
59178
59221
|
throw new NSGetterRuntimeError(
|
|
59179
59222
|
"Stored NeoDelegate closure has no resolvable value row; lexical this cannot be reconstructed from ownership."
|
|
59180
59223
|
);
|
|
59181
59224
|
}
|
|
59182
|
-
const owners =
|
|
59183
|
-
|
|
59184
|
-
|
|
59185
|
-
closureRow.id
|
|
59225
|
+
const owners = [];
|
|
59226
|
+
const indexes = evaluatorIndexes(ctx);
|
|
59227
|
+
for (const [ancestorId, distance] of evaluatorOwnershipDistances(
|
|
59228
|
+
closureRow.id,
|
|
59229
|
+
indexes
|
|
59186
59230
|
)) {
|
|
59187
|
-
|
|
59188
|
-
|
|
59189
|
-
|
|
59231
|
+
if (ancestorId === closureRow.id) continue;
|
|
59232
|
+
const ancestor = evalValueById(
|
|
59233
|
+
ctx,
|
|
59234
|
+
ancestorId,
|
|
59190
59235
|
ctx.__runtimeSessionValues,
|
|
59191
59236
|
ctx.__valueOverlay
|
|
59192
59237
|
);
|
|
59193
|
-
if (
|
|
59194
|
-
if (typeof
|
|
59195
|
-
if (
|
|
59196
|
-
if (
|
|
59197
|
-
|
|
59198
|
-
|
|
59199
|
-
const owningMember = memberForCustomSchemaValue(classId, link.key, ctx);
|
|
59200
|
-
if (owningMember?.kind !== 25 /* NSDelegate */) continue;
|
|
59201
|
-
owners.set(parent.id, parent.value);
|
|
59238
|
+
if (ancestor === null) continue;
|
|
59239
|
+
if (typeof ancestor.value !== "object") continue;
|
|
59240
|
+
if (ancestor.value === null || Array.isArray(ancestor.value)) continue;
|
|
59241
|
+
if (!runtimeValueMatchesType(ancestor.value, lexicalThisType, ctx))
|
|
59242
|
+
continue;
|
|
59243
|
+
owners.push({ id: ancestor.id, value: ancestor.value, distance });
|
|
59202
59244
|
}
|
|
59203
|
-
if (owners.
|
|
59245
|
+
if (owners.length === 0) {
|
|
59204
59246
|
throw new NSGetterRuntimeError(
|
|
59205
59247
|
`Stored NeoDelegate closure value '${closureRow.id}' has no owning class instance; lexical this cannot be reconstructed from ownership.`
|
|
59206
59248
|
);
|
|
59207
59249
|
}
|
|
59208
|
-
|
|
59209
|
-
|
|
59210
|
-
|
|
59211
|
-
);
|
|
59212
|
-
}
|
|
59213
|
-
const owner = owners.values().next();
|
|
59214
|
-
if (owner.done) {
|
|
59250
|
+
const nearestDistance = Math.min(...owners.map((owner) => owner.distance));
|
|
59251
|
+
const nearest = owners.filter((owner) => owner.distance === nearestDistance);
|
|
59252
|
+
if (nearest.length > 1) {
|
|
59215
59253
|
throw new NSGetterRuntimeError(
|
|
59216
|
-
`Stored NeoDelegate closure value '${closureRow.id}'
|
|
59254
|
+
`Stored NeoDelegate closure value '${closureRow.id}' has multiple owning class instances (${nearest.map((owner) => owner.id).join(", ")}); lexical this is ambiguous.`
|
|
59217
59255
|
);
|
|
59218
59256
|
}
|
|
59219
|
-
return
|
|
59257
|
+
return nearest[0].value;
|
|
59220
59258
|
}
|
|
59221
59259
|
function resolveCallableSignature(memberId, memberKind, ctx) {
|
|
59222
59260
|
const cacheKey = `${memberKind}:${memberId}`;
|
|
@@ -59338,7 +59376,7 @@ function runtimeParentGenericEnv(row, ctx, visited) {
|
|
|
59338
59376
|
const result = /* @__PURE__ */ new Map();
|
|
59339
59377
|
for (const link of evaluatorParentLinks(evaluatorIndexes(ctx), row.id)) {
|
|
59340
59378
|
const parent = evalValueById(
|
|
59341
|
-
ctx
|
|
59379
|
+
ctx,
|
|
59342
59380
|
link.parentId,
|
|
59343
59381
|
ctx.__runtimeSessionValues,
|
|
59344
59382
|
ctx.__valueOverlay
|
|
@@ -60009,12 +60047,13 @@ function resolveAssetRuntimeMember(receiver, memberName, ctx) {
|
|
|
60009
60047
|
function resolveValueIfId(at, ctx) {
|
|
60010
60048
|
if (typeof at !== "string") return at;
|
|
60011
60049
|
const row = evalValueById(
|
|
60012
|
-
ctx
|
|
60050
|
+
ctx,
|
|
60013
60051
|
at,
|
|
60014
60052
|
ctx.__runtimeSessionValues,
|
|
60015
60053
|
ctx.__valueOverlay
|
|
60016
60054
|
);
|
|
60017
60055
|
if (!row) return at;
|
|
60056
|
+
ctx.valueDependencies?.add(row.id);
|
|
60018
60057
|
const member = memberForValueRow(row, ctx);
|
|
60019
60058
|
const value = member === null ? resolveLocalizedRowValue(row, ctx) : resolveLocalizedRowValueForMember(row, member, ctx);
|
|
60020
60059
|
return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
|
|
@@ -60022,12 +60061,13 @@ function resolveValueIfId(at, ctx) {
|
|
|
60022
60061
|
function resolveValueIfIdForMember(at, member, ctx) {
|
|
60023
60062
|
if (typeof at !== "string") return at;
|
|
60024
60063
|
const row = evalValueById(
|
|
60025
|
-
ctx
|
|
60064
|
+
ctx,
|
|
60026
60065
|
at,
|
|
60027
60066
|
ctx.__runtimeSessionValues,
|
|
60028
60067
|
ctx.__valueOverlay
|
|
60029
60068
|
);
|
|
60030
60069
|
if (!row) return at;
|
|
60070
|
+
ctx.valueDependencies?.add(row.id);
|
|
60031
60071
|
const value = resolveLocalizedRowValueForMember(row, member, ctx);
|
|
60032
60072
|
return shouldUnwrapSingleLookupValue(member) ? unwrapSingleLookupValue(value, ctx) : value;
|
|
60033
60073
|
}
|
|
@@ -60039,12 +60079,15 @@ function shouldUnwrapSingleLookupValue(member) {
|
|
|
60039
60079
|
function unwrapSingleLookupValue(value, ctx) {
|
|
60040
60080
|
if (Array.isArray(value) && value.length === 1 && typeof value[0] === "string") {
|
|
60041
60081
|
const next = evalValueById(
|
|
60042
|
-
ctx
|
|
60082
|
+
ctx,
|
|
60043
60083
|
value[0],
|
|
60044
60084
|
ctx.__runtimeSessionValues,
|
|
60045
60085
|
ctx.__valueOverlay
|
|
60046
60086
|
);
|
|
60047
|
-
if (next)
|
|
60087
|
+
if (next) {
|
|
60088
|
+
ctx.valueDependencies?.add(next.id);
|
|
60089
|
+
return next.value;
|
|
60090
|
+
}
|
|
60048
60091
|
}
|
|
60049
60092
|
return value;
|
|
60050
60093
|
}
|
|
@@ -60085,7 +60128,7 @@ function resolveMemberForValueRow(row, ctx, visited) {
|
|
|
60085
60128
|
}
|
|
60086
60129
|
for (const link of evaluatorParentLinks(indexes, row.id)) {
|
|
60087
60130
|
const parent = evalValueById(
|
|
60088
|
-
ctx
|
|
60131
|
+
ctx,
|
|
60089
60132
|
link.parentId,
|
|
60090
60133
|
ctx.__runtimeSessionValues,
|
|
60091
60134
|
ctx.__valueOverlay
|
|
@@ -60410,7 +60453,7 @@ function evalDeclaredListIndex(info, scope, ctx) {
|
|
|
60410
60453
|
for (const valueId of collection) {
|
|
60411
60454
|
if (typeof valueId !== "string") continue;
|
|
60412
60455
|
const row = evalValueById(
|
|
60413
|
-
ctx
|
|
60456
|
+
ctx,
|
|
60414
60457
|
valueId,
|
|
60415
60458
|
ctx.__runtimeSessionValues,
|
|
60416
60459
|
ctx.__valueOverlay
|
|
@@ -60995,7 +61038,7 @@ function applyConstructorFields(args) {
|
|
|
60995
61038
|
const trackedValueId = findKnownRowIdByValueReference(value, ctx);
|
|
60996
61039
|
if (trackedValueId !== null && isMemberClassBase(member)) {
|
|
60997
61040
|
const source = evalValueById(
|
|
60998
|
-
ctx
|
|
61041
|
+
ctx,
|
|
60999
61042
|
trackedValueId,
|
|
61000
61043
|
ctx.__runtimeSessionValues,
|
|
61001
61044
|
ctx.__valueOverlay
|
|
@@ -61097,6 +61140,74 @@ function stageConstructedRows(createdValues, ctx) {
|
|
|
61097
61140
|
if (ctx.__indexes !== void 0) indexEvaluatorRow(ctx.__indexes, row);
|
|
61098
61141
|
}
|
|
61099
61142
|
}
|
|
61143
|
+
function bindConstructedDelegateTargets(rootId, ctx) {
|
|
61144
|
+
const indexes = evaluatorIndexes(ctx);
|
|
61145
|
+
const pending = [rootId];
|
|
61146
|
+
const visited = /* @__PURE__ */ new Set();
|
|
61147
|
+
while (pending.length > 0) {
|
|
61148
|
+
const rowId = pending.pop();
|
|
61149
|
+
if (rowId === void 0 || visited.has(rowId)) continue;
|
|
61150
|
+
visited.add(rowId);
|
|
61151
|
+
const row = evalValueById(
|
|
61152
|
+
ctx,
|
|
61153
|
+
rowId,
|
|
61154
|
+
ctx.__runtimeSessionValues,
|
|
61155
|
+
ctx.__valueOverlay
|
|
61156
|
+
);
|
|
61157
|
+
if (row === null) continue;
|
|
61158
|
+
if (Array.isArray(row.value)) {
|
|
61159
|
+
for (const childId of row.value) {
|
|
61160
|
+
if (typeof childId === "string") pending.push(childId);
|
|
61161
|
+
}
|
|
61162
|
+
} else if (typeof row.value === "object" && row.value !== null) {
|
|
61163
|
+
for (const childId of Object.values(row.value)) {
|
|
61164
|
+
if (typeof childId === "string") pending.push(childId);
|
|
61165
|
+
}
|
|
61166
|
+
}
|
|
61167
|
+
if (!isMemberDelegateTarget(row.value) || row.value.valueId !== null) {
|
|
61168
|
+
continue;
|
|
61169
|
+
}
|
|
61170
|
+
const target = evalMemberById(ctx.vm, row.value.memberId);
|
|
61171
|
+
if (target === null || target.isStatic === true) continue;
|
|
61172
|
+
const placement = findSchemaPlacement(target.id, ctx.vm.classes);
|
|
61173
|
+
if (placement === null) {
|
|
61174
|
+
throw new NSGetterRuntimeError(
|
|
61175
|
+
`NeoDelegate method target '${target.name}' has no declaring Class placement.`
|
|
61176
|
+
);
|
|
61177
|
+
}
|
|
61178
|
+
const matches = [];
|
|
61179
|
+
for (const [ancestorId, distance] of evaluatorOwnershipDistances(
|
|
61180
|
+
row.id,
|
|
61181
|
+
indexes
|
|
61182
|
+
)) {
|
|
61183
|
+
const ancestor = evalValueById(
|
|
61184
|
+
ctx,
|
|
61185
|
+
ancestorId,
|
|
61186
|
+
ctx.__runtimeSessionValues,
|
|
61187
|
+
ctx.__valueOverlay
|
|
61188
|
+
);
|
|
61189
|
+
if (ancestor === null) continue;
|
|
61190
|
+
const ancestorClassId = classIdForValueRow(ancestor, ctx);
|
|
61191
|
+
if (ancestorClassId === void 0) continue;
|
|
61192
|
+
const ownsTarget = resolveInheritanceChain(
|
|
61193
|
+
ancestorClassId,
|
|
61194
|
+
ctx.vm.classes
|
|
61195
|
+
).some((schemaClass2) => schemaClass2.id === placement.ownerClass.id);
|
|
61196
|
+
if (ownsTarget) matches.push({ id: ancestor.id, distance });
|
|
61197
|
+
}
|
|
61198
|
+
if (matches.length === 0) continue;
|
|
61199
|
+
const nearestDistance = Math.min(...matches.map((match) => match.distance));
|
|
61200
|
+
const nearest = matches.filter(
|
|
61201
|
+
(match) => match.distance === nearestDistance
|
|
61202
|
+
);
|
|
61203
|
+
if (nearest.length !== 1) {
|
|
61204
|
+
throw new NSGetterRuntimeError(
|
|
61205
|
+
`NeoDelegate method target '${target.name}' has multiple equally near receiver instances (${nearest.map((match) => match.id).join(", ")}).`
|
|
61206
|
+
);
|
|
61207
|
+
}
|
|
61208
|
+
row.value = { ...row.value, valueId: nearest[0].id };
|
|
61209
|
+
}
|
|
61210
|
+
}
|
|
61100
61211
|
function publishConstructedRows(args) {
|
|
61101
61212
|
const { root, createdValues, ctx } = args;
|
|
61102
61213
|
assertConstructorRowsHaveSingleStructuralOwner(createdValues, ctx);
|
|
@@ -61158,6 +61269,7 @@ function publishConstructedRows(args) {
|
|
|
61158
61269
|
destination.set(row.id, row);
|
|
61159
61270
|
if (ctx.__indexes !== void 0) indexEvaluatorRow(ctx.__indexes, row);
|
|
61160
61271
|
}
|
|
61272
|
+
bindConstructedDelegateTargets(root.id, ctx);
|
|
61161
61273
|
state.constructorGroups.set(root.id, retained);
|
|
61162
61274
|
state.ownedValueAttachments.clear();
|
|
61163
61275
|
}
|
|
@@ -61855,6 +61967,7 @@ function evaluateInitializerInContext(init, member, ctx, createdValues, argument
|
|
|
61855
61967
|
return {
|
|
61856
61968
|
value: result.value,
|
|
61857
61969
|
classId: rootRow.classId ?? null,
|
|
61970
|
+
provisionalRootId: rootRow.id,
|
|
61858
61971
|
...constructorArgs === void 0 ? {} : { constructorArgs: structuredClone(constructorArgs) }
|
|
61859
61972
|
};
|
|
61860
61973
|
}
|
|
@@ -62146,6 +62259,7 @@ function constructDeclaredClassValueWithinFrame(descriptor, record3, info, scope
|
|
|
62146
62259
|
root.constructorArgs = structuredClone(encoded);
|
|
62147
62260
|
}
|
|
62148
62261
|
stageConstructedRows(createdValues, ctx);
|
|
62262
|
+
bindConstructedDelegateTargets(root.id, ctx);
|
|
62149
62263
|
if (record3 !== null) {
|
|
62150
62264
|
runDeclaredConstructorChain({
|
|
62151
62265
|
record: record3,
|
|
@@ -62214,7 +62328,7 @@ function constructDeclaredClassValueWithinFrame(descriptor, record3, info, scope
|
|
|
62214
62328
|
}
|
|
62215
62329
|
function assertOwnedValueAttachable(valueId, destination, destinationName2, ctx, reserveUntilPublished = false) {
|
|
62216
62330
|
const row = evalValueById(
|
|
62217
|
-
ctx
|
|
62331
|
+
ctx,
|
|
62218
62332
|
valueId,
|
|
62219
62333
|
ctx.__runtimeSessionValues,
|
|
62220
62334
|
ctx.__valueOverlay
|
|
@@ -62260,7 +62374,7 @@ function currentOwnedValueAttachments(valueId, ctx) {
|
|
|
62260
62374
|
found.set(attachment.identity, attachment);
|
|
62261
62375
|
};
|
|
62262
62376
|
const row = evalValueById(
|
|
62263
|
-
ctx
|
|
62377
|
+
ctx,
|
|
62264
62378
|
valueId,
|
|
62265
62379
|
ctx.__runtimeSessionValues,
|
|
62266
62380
|
ctx.__valueOverlay
|
|
@@ -62297,7 +62411,7 @@ function currentOwnedValueAttachments(valueId, ctx) {
|
|
|
62297
62411
|
);
|
|
62298
62412
|
for (const parentId of parentIds) {
|
|
62299
62413
|
const parent = evalValueById(
|
|
62300
|
-
ctx
|
|
62414
|
+
ctx,
|
|
62301
62415
|
parentId,
|
|
62302
62416
|
ctx.__runtimeSessionValues,
|
|
62303
62417
|
ctx.__valueOverlay
|
|
@@ -62365,7 +62479,7 @@ function constructorArgumentStorage(valueId, ctx, visiting = /* @__PURE__ */ new
|
|
|
62365
62479
|
if (visiting.has(valueId)) return null;
|
|
62366
62480
|
visiting.add(valueId);
|
|
62367
62481
|
const row = evalValueById(
|
|
62368
|
-
ctx
|
|
62482
|
+
ctx,
|
|
62369
62483
|
valueId,
|
|
62370
62484
|
ctx.__runtimeSessionValues,
|
|
62371
62485
|
ctx.__valueOverlay
|
|
@@ -62387,7 +62501,7 @@ function constructorArgumentStorage(valueId, ctx, visiting = /* @__PURE__ */ new
|
|
|
62387
62501
|
const parentIds = /* @__PURE__ */ new Set();
|
|
62388
62502
|
for (const owner of currentOwnedValueAttachments(valueId, ctx)) {
|
|
62389
62503
|
if (evalValueById(
|
|
62390
|
-
ctx
|
|
62504
|
+
ctx,
|
|
62391
62505
|
owner.label,
|
|
62392
62506
|
ctx.__runtimeSessionValues,
|
|
62393
62507
|
ctx.__valueOverlay
|
|
@@ -62497,7 +62611,7 @@ function cloneConstructorArgumentGraph(args) {
|
|
|
62497
62611
|
args.ctx
|
|
62498
62612
|
);
|
|
62499
62613
|
const child = evalValueById(
|
|
62500
|
-
args.ctx
|
|
62614
|
+
args.ctx,
|
|
62501
62615
|
childId,
|
|
62502
62616
|
args.ctx.__runtimeSessionValues,
|
|
62503
62617
|
args.ctx.__valueOverlay
|
|
@@ -62533,7 +62647,7 @@ function cloneConstructorArgumentGraph(args) {
|
|
|
62533
62647
|
);
|
|
62534
62648
|
}
|
|
62535
62649
|
const child = evalValueById(
|
|
62536
|
-
args.ctx
|
|
62650
|
+
args.ctx,
|
|
62537
62651
|
childId,
|
|
62538
62652
|
args.ctx.__runtimeSessionValues,
|
|
62539
62653
|
args.ctx.__valueOverlay
|
|
@@ -62580,7 +62694,7 @@ function cloneConstructorArgumentGraph(args) {
|
|
|
62580
62694
|
);
|
|
62581
62695
|
}
|
|
62582
62696
|
const child = evalValueById(
|
|
62583
|
-
args.ctx
|
|
62697
|
+
args.ctx,
|
|
62584
62698
|
childId,
|
|
62585
62699
|
args.ctx.__runtimeSessionValues,
|
|
62586
62700
|
args.ctx.__valueOverlay
|
|
@@ -62622,7 +62736,7 @@ function materializeConstructorArgumentValue(args) {
|
|
|
62622
62736
|
}
|
|
62623
62737
|
if (trackedValueId !== null) {
|
|
62624
62738
|
const tracked = evalValueById(
|
|
62625
|
-
args.ctx
|
|
62739
|
+
args.ctx,
|
|
62626
62740
|
trackedValueId,
|
|
62627
62741
|
args.ctx.__runtimeSessionValues,
|
|
62628
62742
|
args.ctx.__valueOverlay
|
|
@@ -62805,7 +62919,7 @@ function assertConstructorClassValueAdmitted(args) {
|
|
|
62805
62919
|
function constructorCollectionEntryValue(value, ctx, resolveStoredId) {
|
|
62806
62920
|
if (!resolveStoredId || typeof value !== "string") return value;
|
|
62807
62921
|
const row = evalValueById(
|
|
62808
|
-
ctx
|
|
62922
|
+
ctx,
|
|
62809
62923
|
value,
|
|
62810
62924
|
ctx.__runtimeSessionValues,
|
|
62811
62925
|
ctx.__valueOverlay
|
|
@@ -62855,7 +62969,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
|
|
|
62855
62969
|
);
|
|
62856
62970
|
}
|
|
62857
62971
|
const source = evalValueById(
|
|
62858
|
-
ctx
|
|
62972
|
+
ctx,
|
|
62859
62973
|
sourceId3,
|
|
62860
62974
|
ctx.__runtimeSessionValues,
|
|
62861
62975
|
ctx.__valueOverlay
|
|
@@ -62920,7 +63034,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
|
|
|
62920
63034
|
const childTypeInfo = sourceTypeInfo?.type === 5 /* Dictionary */ ? sourceTypeInfo.entryTypeInfo : void 0;
|
|
62921
63035
|
if (childMember === null && childTypeInfo === void 0) continue;
|
|
62922
63036
|
const child = evalValueById(
|
|
62923
|
-
ctx
|
|
63037
|
+
ctx,
|
|
62924
63038
|
childId,
|
|
62925
63039
|
ctx.__runtimeSessionValues,
|
|
62926
63040
|
ctx.__valueOverlay
|
|
@@ -62941,7 +63055,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
|
|
|
62941
63055
|
clone.value = sourceRow.value.map((childId) => {
|
|
62942
63056
|
if (typeof childId !== "string") return childId;
|
|
62943
63057
|
const child = evalValueById(
|
|
62944
|
-
ctx
|
|
63058
|
+
ctx,
|
|
62945
63059
|
childId,
|
|
62946
63060
|
ctx.__runtimeSessionValues,
|
|
62947
63061
|
ctx.__valueOverlay
|
|
@@ -62971,7 +63085,7 @@ function cloneClassValueGraph(receiver, expectedClassId, ctx) {
|
|
|
62971
63085
|
}
|
|
62972
63086
|
if (constructorArgumentReferenceCounts.get(argument2.id) !== 1) continue;
|
|
62973
63087
|
const argumentRow = evalValueById(
|
|
62974
|
-
ctx
|
|
63088
|
+
ctx,
|
|
62975
63089
|
argument2.id,
|
|
62976
63090
|
ctx.__runtimeSessionValues,
|
|
62977
63091
|
ctx.__valueOverlay
|
|
@@ -63430,6 +63544,7 @@ function evaluateMemberInitializer(args) {
|
|
|
63430
63544
|
return {
|
|
63431
63545
|
value: result.value,
|
|
63432
63546
|
classId: rootRow.classId ?? null,
|
|
63547
|
+
provisionalRootId: rootRow.id,
|
|
63433
63548
|
...constructorArgs === void 0 ? {} : { constructorArgs: structuredClone(constructorArgs) }
|
|
63434
63549
|
};
|
|
63435
63550
|
}
|
|
@@ -63490,6 +63605,13 @@ function materializeInitializerValue(args) {
|
|
|
63490
63605
|
...evaluated.classId === null ? {} : { classId: evaluated.classId },
|
|
63491
63606
|
...evaluated.constructorArgs === void 0 ? {} : { constructorArgs: structuredClone(evaluated.constructorArgs) }
|
|
63492
63607
|
};
|
|
63608
|
+
if (evaluated.provisionalRootId !== void 0) {
|
|
63609
|
+
retargetDelegateReceiverValueIds(
|
|
63610
|
+
[root, ...createdValues],
|
|
63611
|
+
evaluated.provisionalRootId,
|
|
63612
|
+
root.id
|
|
63613
|
+
);
|
|
63614
|
+
}
|
|
63493
63615
|
const allCreated = [root, ...createdValues];
|
|
63494
63616
|
for (const created of createdValues) {
|
|
63495
63617
|
if (created.classId === void 0) delete created.classId;
|
|
@@ -88472,13 +88594,15 @@ function lowerFunctionReference(context, expression, ownerClassId) {
|
|
|
88472
88594
|
return { functionMemberId: target.id };
|
|
88473
88595
|
}
|
|
88474
88596
|
function lowerDelegateValue(context, expression, ownerClassId, authoredSlice) {
|
|
88475
|
-
|
|
88476
|
-
|
|
88477
|
-
|
|
88478
|
-
|
|
88479
|
-
|
|
88597
|
+
if (expression.kind === "lambda") {
|
|
88598
|
+
const code = initializerExpressionSlice(authoredSlice);
|
|
88599
|
+
if (code === void 0) {
|
|
88600
|
+
throw new Error(
|
|
88601
|
+
"Delegate lambdas require recoverable authored source so the server can compile their closure."
|
|
88602
|
+
);
|
|
88603
|
+
}
|
|
88604
|
+
return { code };
|
|
88480
88605
|
}
|
|
88481
|
-
if (expression.kind === "lambda") return { code };
|
|
88482
88606
|
const path = memberPath(expression);
|
|
88483
88607
|
const symbol = path?.startsWith("this.") ? path.slice("this.".length) : path;
|
|
88484
88608
|
if (symbol === null || symbol === void 0 || symbol.includes(".")) {
|
|
@@ -88497,7 +88621,7 @@ function lowerDelegateValue(context, expression, ownerClassId, authoredSlice) {
|
|
|
88497
88621
|
`Delegate ${symbol} does not resolve to a function, NSFunction, or NSDelegate member.`
|
|
88498
88622
|
);
|
|
88499
88623
|
}
|
|
88500
|
-
return {
|
|
88624
|
+
return { memberId: target.id, valueId: null };
|
|
88501
88625
|
}
|
|
88502
88626
|
function fileTargetId(context, expression, registry) {
|
|
88503
88627
|
const path = memberPath(expression);
|
|
@@ -101546,7 +101670,7 @@ var init_registry2 = __esm({
|
|
|
101546
101670
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
101547
101671
|
formatVersion: 3,
|
|
101548
101672
|
contractVersion: "3.9",
|
|
101549
|
-
cliVersion: "0.24.
|
|
101673
|
+
cliVersion: "0.24.8",
|
|
101550
101674
|
projectFileUploadBatchSize: 32,
|
|
101551
101675
|
documentRecords: {
|
|
101552
101676
|
member: {
|
|
@@ -102951,21 +103075,7 @@ function errorMessage2(error) {
|
|
|
102951
103075
|
return error instanceof Error ? error.message : String(error);
|
|
102952
103076
|
}
|
|
102953
103077
|
function findDelegateTargetMemberId(value) {
|
|
102954
|
-
|
|
102955
|
-
const pending = [value.action.instructions];
|
|
102956
|
-
while (pending.length > 0) {
|
|
102957
|
-
const current = pending.shift();
|
|
102958
|
-
if (Array.isArray(current)) {
|
|
102959
|
-
pending.push(...current);
|
|
102960
|
-
continue;
|
|
102961
|
-
}
|
|
102962
|
-
if (!isRecord10(current)) continue;
|
|
102963
|
-
if (current.type === "callFunction" && typeof current.memberId === "string") {
|
|
102964
|
-
return current.memberId;
|
|
102965
|
-
}
|
|
102966
|
-
pending.push(...Object.values(current));
|
|
102967
|
-
}
|
|
102968
|
-
return null;
|
|
103078
|
+
return isRecord10(value) && typeof value.memberId === "string" ? value.memberId : null;
|
|
102969
103079
|
}
|
|
102970
103080
|
function makeEvaluatorContext(rawDocument, interceptor, documentAlreadyIsolated = false) {
|
|
102971
103081
|
const isolatedDocument = documentAlreadyIsolated ? rawDocument : structuredClone(rawDocument);
|
|
@@ -104081,7 +104191,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
104081
104191
|
cliVersion: PROJECT_SCHEMA_CONTRACT.cliVersion,
|
|
104082
104192
|
runnerRevision: 3,
|
|
104083
104193
|
compilerRevision: NEOSCRIPT_COMPILER_REVISION,
|
|
104084
|
-
evaluatorRevision:
|
|
104194
|
+
evaluatorRevision: 4,
|
|
104085
104195
|
projectFingerprint,
|
|
104086
104196
|
configurationSha256: createHash10("sha256").update(JSON.stringify(workspace.config.test ?? {})).digest("hex"),
|
|
104087
104197
|
dependencyGraph: Object.fromEntries(
|
package/package.json
CHANGED
|
@@ -127,6 +127,10 @@ Use `NeoAnimationSegment<T>` for a frame-indexed value lane. The shipped
|
|
|
127
127
|
sprite specialization is `NeoSpriteAnimationSegment`, whose
|
|
128
128
|
`NeoAnimationSegmentFrame<SpriteInfo>` rows each provide `Index` and
|
|
129
129
|
`Value`. Sparse frame values hold until the next row or `Duration`.
|
|
130
|
+
Pass `Value` through the frame constructor (for example,
|
|
131
|
+
`new NeoAnimationSegmentFrame<int>(value: 60)`). The constructor argument is
|
|
132
|
+
the frame's authored value; it must not collapse to the concrete generic
|
|
133
|
+
binding's fallback while the segment is materialized.
|
|
130
134
|
|
|
131
135
|
Use one polymorphic `NeoAnimationClip.Tracks` list:
|
|
132
136
|
|
|
@@ -181,9 +185,11 @@ pulled rows.
|
|
|
181
185
|
A selector argument such as `this.SelectPants` is evaluated in the lexical
|
|
182
186
|
scope of the class that declares the clip. Here `this` is the `LegPart`, not
|
|
183
187
|
the nested track row or an outer object instance that later receives a copy of
|
|
184
|
-
the declaration default.
|
|
185
|
-
|
|
186
|
-
|
|
188
|
+
the declaration default. A named method group lowers to the P60 member-target
|
|
189
|
+
form. Its declaration default carries `valueId: null` because no instance row
|
|
190
|
+
exists yet; materializing the declaration binds it to the concrete `LegPart`
|
|
191
|
+
row. An inline closure remains compiled closure source and reconstructs its
|
|
192
|
+
lexical owner from the materialized graph. Do not interchange these two forms.
|
|
187
193
|
|
|
188
194
|
Each track has `StartFrame`, `Direction` (`.Forward` or `.Reverse`), and a
|
|
189
195
|
crop window `OffsetStartIndex`/`OffsetEndIndex`. Crop before reversing, then
|
|
@@ -82,7 +82,7 @@ wrappers.
|
|
|
82
82
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
83
83
|
|
|
84
84
|
```html
|
|
85
|
-
<!-- reviewed-through-cli: 0.24.
|
|
85
|
+
<!-- reviewed-through-cli: 0.24.8 -->
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
The quoted version above is checked too, so this instruction cannot go stale
|