@neocompose/cli 0.24.2 → 0.24.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,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.24.4] - 2026-08-07
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Preserve every operand and its grouping when compiling chained NeoScript
|
|
8
|
+
`&&` and `||` expressions. The previous lowering overwrote the left
|
|
9
|
+
expression's connective, so `a || b || c` evaluated as `a || c`.
|
|
10
|
+
- Short-circuit logical expressions in the local evaluator instead of eagerly
|
|
11
|
+
evaluating an unused right-hand operand.
|
|
12
|
+
|
|
13
|
+
## [0.24.3] - 2026-08-07
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Close generic classes constructed by normal member-default evaluation from
|
|
18
|
+
the concrete member slot, so local candidate preparation no longer rejects
|
|
19
|
+
values such as `NeoAnimationSegmentFrame<int>` as open generics before
|
|
20
|
+
`neo test` can discover or execute tests.
|
|
21
|
+
- Key compiled spec artifacts by the prepared candidate document as well as
|
|
22
|
+
source, preventing stale pending class and enum IDs from leaking across
|
|
23
|
+
repeated `neo test` runs.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Require full-project `neo test` validation in the bundled CLI development
|
|
28
|
+
guidance when evaluator or candidate-materialization behavior changes.
|
|
29
|
+
|
|
3
30
|
## [0.24.2] - 2026-08-07
|
|
4
31
|
|
|
5
32
|
### Fixed
|
package/dist/neo.mjs
CHANGED
|
@@ -7323,7 +7323,7 @@ var NEOSCRIPT_COMPILER_REVISION;
|
|
|
7323
7323
|
var init_strict_ir = __esm({
|
|
7324
7324
|
"../packages/neoscript-language/src/strict-ir.ts"() {
|
|
7325
7325
|
"use strict";
|
|
7326
|
-
NEOSCRIPT_COMPILER_REVISION =
|
|
7326
|
+
NEOSCRIPT_COMPILER_REVISION = 8;
|
|
7327
7327
|
}
|
|
7328
7328
|
});
|
|
7329
7329
|
|
|
@@ -8157,6 +8157,9 @@ function pointerToBooleanExpression(pointer) {
|
|
|
8157
8157
|
if (pointer.type === "operation" /* Operation */ && pointer.operation.type === "boolean" /* Boolean */) {
|
|
8158
8158
|
return pointer.operation.expression;
|
|
8159
8159
|
}
|
|
8160
|
+
return pointerToBooleanOperandExpression(pointer);
|
|
8161
|
+
}
|
|
8162
|
+
function pointerToBooleanOperandExpression(pointer) {
|
|
8160
8163
|
return {
|
|
8161
8164
|
condition: {
|
|
8162
8165
|
type: "equalTo" /* EqualTo */,
|
|
@@ -12701,7 +12704,7 @@ var init_strict_resolver = __esm({
|
|
|
12701
12704
|
operation: {
|
|
12702
12705
|
type: "boolean" /* Boolean */,
|
|
12703
12706
|
expression: {
|
|
12704
|
-
...
|
|
12707
|
+
...pointerToBooleanOperandExpression(l.pointer),
|
|
12705
12708
|
connective: {
|
|
12706
12709
|
type: expression.op === "&&" ? "&&" /* And */ : "||" /* Or */,
|
|
12707
12710
|
to: pointerToBooleanExpression(r.pointer)
|
|
@@ -60276,12 +60279,11 @@ function stringifyForInterp(v) {
|
|
|
60276
60279
|
function evalBooleanExpression(expression, scope, ctx) {
|
|
60277
60280
|
const head = evalCondition(expression.condition, scope, ctx);
|
|
60278
60281
|
if (!expression.connective) return head;
|
|
60279
|
-
const tail = evalBooleanExpression(expression.connective.to, scope, ctx);
|
|
60280
60282
|
switch (expression.connective.type) {
|
|
60281
60283
|
case "&&" /* and */:
|
|
60282
|
-
return head
|
|
60284
|
+
return head ? evalBooleanExpression(expression.connective.to, scope, ctx) : false;
|
|
60283
60285
|
case "||" /* or */:
|
|
60284
|
-
return head
|
|
60286
|
+
return head ? true : evalBooleanExpression(expression.connective.to, scope, ctx);
|
|
60285
60287
|
}
|
|
60286
60288
|
}
|
|
60287
60289
|
function evalCondition(condition, scope, ctx) {
|
|
@@ -60764,8 +60766,8 @@ function validateClassConstructorDescriptor(info, ctx, requireEveryRequiredField
|
|
|
60764
60766
|
`Cannot construct abstract Class '${schemaClass2.name}'.`
|
|
60765
60767
|
);
|
|
60766
60768
|
}
|
|
60767
|
-
const
|
|
60768
|
-
const classArguments2 =
|
|
60769
|
+
const genericSlot = ctx.__constructionGenericSlots?.toReversed().find((slot) => slot.classId === classId) ?? ctx.__storedConstructionReplaySlot;
|
|
60770
|
+
const classArguments2 = genericSlot?.classId === classId ? genericSlot.classArguments : void 0;
|
|
60769
60771
|
const instanceEnv = resolveInstanceEnv(
|
|
60770
60772
|
classId,
|
|
60771
60773
|
classArguments2,
|
|
@@ -61621,7 +61623,7 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
|
|
|
61621
61623
|
};
|
|
61622
61624
|
return (member, init, sourceValueId) => {
|
|
61623
61625
|
const evaluate = (argumentValues = []) => {
|
|
61624
|
-
if (
|
|
61626
|
+
if (!isMemberClassBase(member) || Object.keys(member.classArguments ?? {}).length === 0) {
|
|
61625
61627
|
return evaluateInitializerInContext(
|
|
61626
61628
|
init,
|
|
61627
61629
|
member,
|
|
@@ -61631,8 +61633,8 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
|
|
|
61631
61633
|
sourceValueId ?? null
|
|
61632
61634
|
);
|
|
61633
61635
|
}
|
|
61634
|
-
const previousSlots = ctx.
|
|
61635
|
-
ctx.
|
|
61636
|
+
const previousSlots = ctx.__constructionGenericSlots;
|
|
61637
|
+
ctx.__constructionGenericSlots = [
|
|
61636
61638
|
...previousSlots ?? [],
|
|
61637
61639
|
{
|
|
61638
61640
|
classId: member.classId,
|
|
@@ -61649,7 +61651,7 @@ function constructionInitEvaluator(ctx, createdValues, argumentScopes, construct
|
|
|
61649
61651
|
sourceValueId ?? null
|
|
61650
61652
|
);
|
|
61651
61653
|
} finally {
|
|
61652
|
-
ctx.
|
|
61654
|
+
ctx.__constructionGenericSlots = previousSlots;
|
|
61653
61655
|
}
|
|
61654
61656
|
};
|
|
61655
61657
|
if (init.compiled === void 0) {
|
|
@@ -101546,7 +101548,7 @@ var init_registry2 = __esm({
|
|
|
101546
101548
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
101547
101549
|
formatVersion: 3,
|
|
101548
101550
|
contractVersion: "3.9",
|
|
101549
|
-
cliVersion: "0.24.
|
|
101551
|
+
cliVersion: "0.24.4",
|
|
101550
101552
|
projectFileUploadBatchSize: 32,
|
|
101551
101553
|
documentRecords: {
|
|
101552
101554
|
member: {
|
|
@@ -103077,7 +103079,7 @@ function preparedHookCandidate(workspace) {
|
|
|
103077
103079
|
);
|
|
103078
103080
|
}
|
|
103079
103081
|
}
|
|
103080
|
-
function compileSpec(workspace, document, absolutePath,
|
|
103082
|
+
function compileSpec(workspace, document, absolutePath, projectCompilationHash2) {
|
|
103081
103083
|
const scriptDocument = readDocumentArrays(document);
|
|
103082
103084
|
const path = relative6(workspace.root, absolutePath).split(sep6).join("/");
|
|
103083
103085
|
const source = readFileSync17(absolutePath, "utf8");
|
|
@@ -103087,12 +103089,12 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
|
|
|
103087
103089
|
".neo",
|
|
103088
103090
|
"test-build",
|
|
103089
103091
|
"v1",
|
|
103090
|
-
|
|
103092
|
+
projectCompilationHash2,
|
|
103091
103093
|
`${sourceHash}.json`
|
|
103092
103094
|
);
|
|
103093
103095
|
try {
|
|
103094
103096
|
const cached = JSON.parse(readFileSync17(artifactPath, "utf8"));
|
|
103095
|
-
if (isRecord10(cached) && cached.version === 1 && cached.compilerRevision === NEOSCRIPT_COMPILER_REVISION && cached.
|
|
103097
|
+
if (isRecord10(cached) && cached.version === 1 && cached.compilerRevision === NEOSCRIPT_COMPILER_REVISION && cached.projectCompilationHash === projectCompilationHash2 && cached.sourceHash === sourceHash && isRecord10(cached.action) && typeof cached.artifactSha256 === "string" && createHash10("sha256").update(JSON.stringify(cached.action)).digest("hex") === cached.artifactSha256 && cached.action.compilerRevision === NEOSCRIPT_COMPILER_REVISION && Array.isArray(cached.action.parameters) && Array.isArray(cached.action.instructions) && isRecord10(cached.action.typeInfo)) {
|
|
103096
103098
|
return {
|
|
103097
103099
|
path,
|
|
103098
103100
|
source,
|
|
@@ -103122,7 +103124,7 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
|
|
|
103122
103124
|
`${JSON.stringify({
|
|
103123
103125
|
version: 1,
|
|
103124
103126
|
compilerRevision: NEOSCRIPT_COMPILER_REVISION,
|
|
103125
|
-
|
|
103127
|
+
projectCompilationHash: projectCompilationHash2,
|
|
103126
103128
|
sourceHash,
|
|
103127
103129
|
artifactSha256: createHash10("sha256").update(JSON.stringify(compiled.action)).digest("hex"),
|
|
103128
103130
|
action: compiled.action
|
|
@@ -103131,6 +103133,9 @@ function compileSpec(workspace, document, absolutePath, projectSourceHash) {
|
|
|
103131
103133
|
);
|
|
103132
103134
|
return compiled;
|
|
103133
103135
|
}
|
|
103136
|
+
function projectCompilationHash(projectSourceHash, document) {
|
|
103137
|
+
return createHash10("sha256").update(projectSourceHash).update("\0").update(JSON.stringify(document)).digest("hex");
|
|
103138
|
+
}
|
|
103134
103139
|
function selectedSpecPaths(workspace, selectors) {
|
|
103135
103140
|
const all = listProjectTestFilesV1(workspace.root);
|
|
103136
103141
|
const relativePaths = new Map(
|
|
@@ -104006,6 +104011,10 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
104006
104011
|
}
|
|
104007
104012
|
projectFingerprint = `sha256:${candidate.sourceHash}`;
|
|
104008
104013
|
const rawDocument = documentRecord(candidate.document);
|
|
104014
|
+
const compilationHash = projectCompilationHash(
|
|
104015
|
+
candidate.sourceHash,
|
|
104016
|
+
rawDocument
|
|
104017
|
+
);
|
|
104009
104018
|
phase = "select";
|
|
104010
104019
|
let selectedPaths;
|
|
104011
104020
|
try {
|
|
@@ -104023,7 +104032,7 @@ async function runTest(workspace, options, dependencies = {}) {
|
|
|
104023
104032
|
}
|
|
104024
104033
|
phase = "compile";
|
|
104025
104034
|
specs = selectedPaths.map(
|
|
104026
|
-
(path) => compileSpec(workspace, rawDocument, path,
|
|
104035
|
+
(path) => compileSpec(workspace, rawDocument, path, compilationHash)
|
|
104027
104036
|
);
|
|
104028
104037
|
let pattern = null;
|
|
104029
104038
|
if (options.testNamePattern !== null) {
|
|
@@ -104216,10 +104225,14 @@ async function inspectNeoTestCompilation(workspace, dependencies = {}) {
|
|
|
104216
104225
|
};
|
|
104217
104226
|
}
|
|
104218
104227
|
const document = documentRecord(candidate.document);
|
|
104228
|
+
const compilationHash = projectCompilationHash(
|
|
104229
|
+
candidate.sourceHash,
|
|
104230
|
+
document
|
|
104231
|
+
);
|
|
104219
104232
|
const errors = [];
|
|
104220
104233
|
for (const path of selectedPaths) {
|
|
104221
104234
|
try {
|
|
104222
|
-
compileSpec(workspace, document, path,
|
|
104235
|
+
compileSpec(workspace, document, path, compilationHash);
|
|
104223
104236
|
} catch (error) {
|
|
104224
104237
|
errors.push({
|
|
104225
104238
|
file: relative6(workspace.root, path).split(sep6).join("/"),
|
package/package.json
CHANGED
|
@@ -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.4 -->
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -115,5 +115,7 @@ npm run doctor
|
|
|
115
115
|
|
|
116
116
|
Also run contract/corpus checks, Monaco/browser parity, VSIX packaging, and
|
|
117
117
|
interactive sample no-op verification when the corresponding implementation
|
|
118
|
-
surface changes.
|
|
119
|
-
|
|
118
|
+
surface changes. Evaluator or candidate-materialization changes also require an
|
|
119
|
+
actual `neo test` run against the affected full-project candidate; focused
|
|
120
|
+
Vitest coverage does not replace that end-to-end command. Run `npm run doctor`
|
|
121
|
+
last; do not rerun successful suites only because doctor formatted files.
|
|
@@ -7,6 +7,7 @@ runtime ownership, evaluation, and migrations.
|
|
|
7
7
|
|
|
8
8
|
- Inline bodies and snippets
|
|
9
9
|
- Nullability and ownership
|
|
10
|
+
- Logical operators
|
|
10
11
|
- Loops and transfer
|
|
11
12
|
- Switch
|
|
12
13
|
- Try/catch
|
|
@@ -53,6 +54,13 @@ Save, Session, Setter, or otherwise writable. A constructor writes only its
|
|
|
53
54
|
`this` instance. A writable structured-leaf field still inherits the receiver's
|
|
54
55
|
effective storage restrictions.
|
|
55
56
|
|
|
57
|
+
## Logical operators
|
|
58
|
+
|
|
59
|
+
Use `&&` and `||` with C# precedence: `&&` binds tighter than `||`, and
|
|
60
|
+
parentheses preserve explicit grouping. Both operators short-circuit, so the
|
|
61
|
+
right operand is evaluated only when it can change the result. Chained
|
|
62
|
+
expressions retain every operand; `a || b || c` never skips `b`.
|
|
63
|
+
|
|
56
64
|
## Loops and transfer
|
|
57
65
|
|
|
58
66
|
Use C#-shaped loops:
|