@neocompose/cli 0.72.2 → 0.72.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 +9 -0
- package/dist/neo.mjs +252 -176
- package/dist/test-worker.mjs +108 -125
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/neoscript.md +7 -1
- package/skills/neocompose-cli/references/values-identities-and-references.md +4 -1
package/dist/test-worker.mjs
CHANGED
|
@@ -33780,14 +33780,17 @@ var Scope = class {
|
|
|
33780
33780
|
return this.invalidatedRoots;
|
|
33781
33781
|
}
|
|
33782
33782
|
effectiveNarrowedPaths() {
|
|
33783
|
-
const effective =
|
|
33784
|
-
|
|
33785
|
-
|
|
33786
|
-
|
|
33783
|
+
const effective = new Map(this.narrowedPaths);
|
|
33784
|
+
const invalidated = new Set(this.invalidatedRoots);
|
|
33785
|
+
for (const root of this.hiddenNarrowingRoots) invalidated.add(root);
|
|
33786
|
+
for (let current = this.parent; current; current = current.parent) {
|
|
33787
|
+
for (const [path, narrowed] of current.narrowedPaths) {
|
|
33788
|
+
if (!effective.has(path) && !invalidated.has(narrowed.rootEntry)) {
|
|
33789
|
+
effective.set(path, narrowed);
|
|
33790
|
+
}
|
|
33787
33791
|
}
|
|
33788
|
-
|
|
33789
|
-
|
|
33790
|
-
effective.set(path, narrowed);
|
|
33792
|
+
for (const root of current.invalidatedRoots) invalidated.add(root);
|
|
33793
|
+
for (const root of current.hiddenNarrowingRoots) invalidated.add(root);
|
|
33791
33794
|
}
|
|
33792
33795
|
return effective;
|
|
33793
33796
|
}
|
|
@@ -33813,6 +33816,9 @@ var Scope = class {
|
|
|
33813
33816
|
hideInheritedNarrowing(rootEntry) {
|
|
33814
33817
|
this.hiddenNarrowingRoots.add(rootEntry);
|
|
33815
33818
|
this.updatePatternType(rootEntry, rootEntry.type);
|
|
33819
|
+
for (const [path, narrowed] of this.narrowedPaths) {
|
|
33820
|
+
if (narrowed.rootEntry === rootEntry) this.narrowedPaths.delete(path);
|
|
33821
|
+
}
|
|
33816
33822
|
}
|
|
33817
33823
|
invalidate(rootEntry) {
|
|
33818
33824
|
this.invalidatedRoots.add(rootEntry);
|
|
@@ -34370,24 +34376,26 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
34370
34376
|
const branchExitNarrowings = [];
|
|
34371
34377
|
const branchExitOwnershipScopes = [];
|
|
34372
34378
|
const branches = statement.branches.map((branch) => {
|
|
34379
|
+
const conditionScope = new Scope(scope);
|
|
34380
|
+
this.applyFactsToScope(conditionScope, cumulativeFalseFacts);
|
|
34373
34381
|
const condition = this.toBool(
|
|
34374
|
-
this.resolveExpression(branch.cond,
|
|
34382
|
+
this.resolveExpression(branch.cond, conditionScope),
|
|
34375
34383
|
branch.cond.pos
|
|
34376
34384
|
);
|
|
34377
34385
|
const child = new Scope(scope);
|
|
34378
34386
|
const branchFacts = [
|
|
34379
34387
|
...cumulativeFalseFacts,
|
|
34380
|
-
...this.conditionFacts(branch.cond,
|
|
34388
|
+
...this.conditionFacts(branch.cond, conditionScope, true)
|
|
34381
34389
|
];
|
|
34382
34390
|
this.applyFactsToScope(child, branchFacts);
|
|
34383
34391
|
const instructions = this.resolveStatements(branch.body, child);
|
|
34384
34392
|
if (!instructionsTerminate(instructions)) {
|
|
34385
34393
|
branchExitFacts.push(branchFacts);
|
|
34386
|
-
branchExitNarrowings.push(
|
|
34394
|
+
branchExitNarrowings.push(child.effectiveNarrowedPaths());
|
|
34387
34395
|
branchExitOwnershipScopes.push(child);
|
|
34388
34396
|
}
|
|
34389
34397
|
cumulativeFalseFacts.push(
|
|
34390
|
-
...this.conditionFacts(branch.cond,
|
|
34398
|
+
...this.conditionFacts(branch.cond, conditionScope, false)
|
|
34391
34399
|
);
|
|
34392
34400
|
return {
|
|
34393
34401
|
expression: pointerToBooleanExpression(condition.pointer),
|
|
@@ -34401,14 +34409,14 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
34401
34409
|
otherwise = this.resolveStatements(statement.elseBody, elseScope);
|
|
34402
34410
|
if (!instructionsTerminate(otherwise)) {
|
|
34403
34411
|
branchExitFacts.push([...cumulativeFalseFacts]);
|
|
34404
|
-
branchExitNarrowings.push(
|
|
34412
|
+
branchExitNarrowings.push(elseScope.effectiveNarrowedPaths());
|
|
34405
34413
|
branchExitOwnershipScopes.push(elseScope);
|
|
34406
34414
|
}
|
|
34407
34415
|
} else {
|
|
34408
34416
|
const noBranchScope = new Scope(scope);
|
|
34409
34417
|
this.applyFactsToScope(noBranchScope, cumulativeFalseFacts);
|
|
34410
34418
|
branchExitFacts.push([...cumulativeFalseFacts]);
|
|
34411
|
-
branchExitNarrowings.push(
|
|
34419
|
+
branchExitNarrowings.push(noBranchScope.effectiveNarrowedPaths());
|
|
34412
34420
|
branchExitOwnershipScopes.push(noBranchScope);
|
|
34413
34421
|
}
|
|
34414
34422
|
mergeBranchInvalidations(scope, branchExitOwnershipScopes);
|
|
@@ -34642,12 +34650,15 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
34642
34650
|
statement.body,
|
|
34643
34651
|
conditionLocals
|
|
34644
34652
|
);
|
|
34645
|
-
|
|
34646
|
-
|
|
34647
|
-
|
|
34648
|
-
|
|
34649
|
-
|
|
34650
|
-
|
|
34653
|
+
const bodyFlow = statementFlow(statement.body, /* @__PURE__ */ new WeakMap());
|
|
34654
|
+
if (bodyFlow.has("fallthrough") || bodyFlow.has("continue")) {
|
|
34655
|
+
this.invalidateLoopEntryNarrowingsAssignedBy(
|
|
34656
|
+
loopEntryScope,
|
|
34657
|
+
loopScope,
|
|
34658
|
+
[statement.iterator],
|
|
34659
|
+
conditionLocals
|
|
34660
|
+
);
|
|
34661
|
+
}
|
|
34651
34662
|
const condition = this.toBool(
|
|
34652
34663
|
this.resolveExpression(statement.condition, loopEntryScope),
|
|
34653
34664
|
statement.condition.pos
|
|
@@ -35514,13 +35525,13 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
35514
35525
|
if (assignedPath) {
|
|
35515
35526
|
const rootEntry = scope.lookup(pathRoot(assignedPath));
|
|
35516
35527
|
if (rootEntry) {
|
|
35517
|
-
const
|
|
35528
|
+
const retainedFacts = unaffectedNarrowings(
|
|
35518
35529
|
assignedPath,
|
|
35519
35530
|
rootEntry,
|
|
35520
35531
|
scope
|
|
35521
35532
|
);
|
|
35522
35533
|
scope.invalidate(rootEntry);
|
|
35523
|
-
for (const [path, type] of
|
|
35534
|
+
for (const [path, type] of retainedFacts) {
|
|
35524
35535
|
scope.narrow(path, rootEntry, type);
|
|
35525
35536
|
}
|
|
35526
35537
|
if (statement.op === "=" && !isNullable(value.type)) {
|
|
@@ -35737,13 +35748,13 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
35737
35748
|
if (assignedPath) {
|
|
35738
35749
|
const rootEntry = scope.lookup(pathRoot(assignedPath));
|
|
35739
35750
|
if (rootEntry) {
|
|
35740
|
-
const
|
|
35751
|
+
const retainedFacts = unaffectedNarrowings(
|
|
35741
35752
|
assignedPath,
|
|
35742
35753
|
rootEntry,
|
|
35743
35754
|
scope
|
|
35744
35755
|
);
|
|
35745
35756
|
scope.invalidate(rootEntry);
|
|
35746
|
-
for (const [path, type] of
|
|
35757
|
+
for (const [path, type] of retainedFacts) {
|
|
35747
35758
|
scope.narrow(path, rootEntry, type);
|
|
35748
35759
|
}
|
|
35749
35760
|
}
|
|
@@ -36358,18 +36369,19 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
36358
36369
|
case "coalesce": {
|
|
36359
36370
|
const left = this.resolveExpression(expression.left, scope);
|
|
36360
36371
|
const leftOptional = { ...left.type, nullable: true };
|
|
36372
|
+
const nullLeft = isNull(left.type);
|
|
36361
36373
|
const right = this.resolveExpression(
|
|
36362
36374
|
expression.right,
|
|
36363
36375
|
scope,
|
|
36364
|
-
leftOptional
|
|
36376
|
+
nullLeft ? expected : leftOptional
|
|
36365
36377
|
);
|
|
36366
|
-
if (!isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
|
|
36378
|
+
if (!nullLeft && !isNeoScriptTypeAssignable(right.type, leftOptional, this.project)) {
|
|
36367
36379
|
throw new CompileError(
|
|
36368
36380
|
`\`??\` right operand ${this.describe(right.type)} is not assignable to ${this.describe(leftOptional)}`,
|
|
36369
36381
|
expression.pos
|
|
36370
36382
|
);
|
|
36371
36383
|
}
|
|
36372
|
-
const resultType = {
|
|
36384
|
+
const resultType = nullLeft ? right.type : {
|
|
36373
36385
|
...left.type,
|
|
36374
36386
|
nullable: isNullable(left.type) && isNullable(right.type)
|
|
36375
36387
|
};
|
|
@@ -37070,20 +37082,25 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
37070
37082
|
return whenTrue ? factsWhenTrue(expression, pathOf) : factsWhenFalse(expression, pathOf);
|
|
37071
37083
|
}
|
|
37072
37084
|
/**
|
|
37073
|
-
* A loop body is resolved once but can execute repeatedly.
|
|
37074
|
-
*
|
|
37075
|
-
*
|
|
37076
|
-
* shared iteration so only the loop's own condition can narrow them again.
|
|
37085
|
+
* A loop body is resolved once but can execute repeatedly. Hide facts about
|
|
37086
|
+
* paths it may replace before resolving the shared iteration; unrelated facts
|
|
37087
|
+
* still hold, and the loop condition can narrow the written paths again.
|
|
37077
37088
|
*/
|
|
37078
37089
|
invalidateLoopEntryNarrowingsAssignedBy(loopEntryScope, outerScope, statements, locals = /* @__PURE__ */ new Set()) {
|
|
37079
|
-
for (const
|
|
37090
|
+
for (const assignedPath of collectAssignedPaths(
|
|
37080
37091
|
statements,
|
|
37081
37092
|
/* @__PURE__ */ new Set(),
|
|
37082
37093
|
locals
|
|
37083
37094
|
)) {
|
|
37084
|
-
const path = this.narrowingPath(
|
|
37095
|
+
const path = this.narrowingPath(assignedPath, outerScope);
|
|
37085
37096
|
const outerEntry = path === null ? null : outerScope.lookup(pathRoot(path));
|
|
37086
|
-
if (outerEntry)
|
|
37097
|
+
if (outerEntry && path !== null) {
|
|
37098
|
+
const retained = unaffectedNarrowings(path, outerEntry, loopEntryScope);
|
|
37099
|
+
loopEntryScope.hideInheritedNarrowing(outerEntry);
|
|
37100
|
+
for (const [retainedPath, type] of retained) {
|
|
37101
|
+
loopEntryScope.narrow(retainedPath, outerEntry, type);
|
|
37102
|
+
}
|
|
37103
|
+
}
|
|
37087
37104
|
}
|
|
37088
37105
|
}
|
|
37089
37106
|
applyFactsToScope(targetScope, facts, mode = "all") {
|
|
@@ -41503,12 +41520,18 @@ function identPathSegments(expression) {
|
|
|
41503
41520
|
if (receiver === null) return null;
|
|
41504
41521
|
return [...receiver, expression.name];
|
|
41505
41522
|
}
|
|
41506
|
-
function
|
|
41523
|
+
function unaffectedNarrowings(path, rootEntry, scope) {
|
|
41507
41524
|
const facts = [];
|
|
41508
|
-
|
|
41509
|
-
|
|
41510
|
-
|
|
41511
|
-
|
|
41525
|
+
const prefix = `${path}.`;
|
|
41526
|
+
const dot = path.lastIndexOf(".");
|
|
41527
|
+
if (dot === -1) return facts;
|
|
41528
|
+
const member = path.slice(dot);
|
|
41529
|
+
for (const [candidate, narrowed] of scope.effectiveNarrowedPaths()) {
|
|
41530
|
+
if (narrowed.rootEntry !== rootEntry) continue;
|
|
41531
|
+
if (candidate === path || candidate.startsWith(prefix)) continue;
|
|
41532
|
+
if (candidate.endsWith(member) || candidate.includes(`${member}.`))
|
|
41533
|
+
continue;
|
|
41534
|
+
facts.push([candidate, narrowed.type]);
|
|
41512
41535
|
}
|
|
41513
41536
|
return facts;
|
|
41514
41537
|
}
|
|
@@ -41832,22 +41855,22 @@ function localsWithBindings(locals, expression, whenTrue) {
|
|
|
41832
41855
|
...facts.flatMap((fact) => fact.bindingName ? [fact.bindingName] : [])
|
|
41833
41856
|
]);
|
|
41834
41857
|
}
|
|
41835
|
-
function
|
|
41858
|
+
function collectAssignedPaths(statements, roots = /* @__PURE__ */ new Set(), inheritedLocals = /* @__PURE__ */ new Set(), flowCache = /* @__PURE__ */ new WeakMap()) {
|
|
41836
41859
|
const locals = new Set(inheritedLocals);
|
|
41837
41860
|
for (const statement of statements) {
|
|
41838
41861
|
if (statement.kind === "assign") {
|
|
41839
41862
|
const assignedPath = canonicalPath(statement.target);
|
|
41840
41863
|
if (assignedPath && !locals.has(pathRoot(assignedPath))) {
|
|
41841
|
-
roots.add(
|
|
41864
|
+
roots.add(assignedPath);
|
|
41842
41865
|
}
|
|
41843
|
-
|
|
41866
|
+
collectAssignedPathsInExpression(
|
|
41844
41867
|
statement.target,
|
|
41845
41868
|
roots,
|
|
41846
41869
|
locals,
|
|
41847
41870
|
flowCache
|
|
41848
41871
|
);
|
|
41849
41872
|
if (statement.value)
|
|
41850
|
-
|
|
41873
|
+
collectAssignedPathsInExpression(
|
|
41851
41874
|
statement.value,
|
|
41852
41875
|
roots,
|
|
41853
41876
|
locals,
|
|
@@ -41856,7 +41879,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41856
41879
|
continue;
|
|
41857
41880
|
}
|
|
41858
41881
|
if (statement.kind === "varDecl") {
|
|
41859
|
-
|
|
41882
|
+
collectAssignedPathsInExpression(
|
|
41860
41883
|
statement.init,
|
|
41861
41884
|
roots,
|
|
41862
41885
|
locals,
|
|
@@ -41870,7 +41893,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41870
41893
|
const falseFacts = [];
|
|
41871
41894
|
const fallthroughFacts = [];
|
|
41872
41895
|
for (const branch of statement.branches) {
|
|
41873
|
-
|
|
41896
|
+
collectAssignedPathsInExpression(
|
|
41874
41897
|
branch.cond,
|
|
41875
41898
|
roots,
|
|
41876
41899
|
falseLocals,
|
|
@@ -41880,7 +41903,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41880
41903
|
...falseFacts,
|
|
41881
41904
|
...factsWhenTrue(branch.cond, canonicalPath)
|
|
41882
41905
|
];
|
|
41883
|
-
|
|
41906
|
+
collectAssignedPaths(
|
|
41884
41907
|
branch.body,
|
|
41885
41908
|
roots,
|
|
41886
41909
|
localsWithBindings(falseLocals, branch.cond, true),
|
|
@@ -41892,12 +41915,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41892
41915
|
falseLocals = localsWithBindings(falseLocals, branch.cond, false);
|
|
41893
41916
|
}
|
|
41894
41917
|
if (statement.elseBody) {
|
|
41895
|
-
|
|
41896
|
-
statement.elseBody,
|
|
41897
|
-
roots,
|
|
41898
|
-
falseLocals,
|
|
41899
|
-
flowCache
|
|
41900
|
-
);
|
|
41918
|
+
collectAssignedPaths(statement.elseBody, roots, falseLocals, flowCache);
|
|
41901
41919
|
if (statementFlow(statement.elseBody, flowCache).has("fallthrough"))
|
|
41902
41920
|
fallthroughFacts.push(falseFacts);
|
|
41903
41921
|
} else {
|
|
@@ -41909,18 +41927,18 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41909
41927
|
continue;
|
|
41910
41928
|
}
|
|
41911
41929
|
if (statement.kind === "try") {
|
|
41912
|
-
|
|
41930
|
+
collectAssignedPaths(statement.body, roots, locals, flowCache);
|
|
41913
41931
|
for (const clause of statement.catches) {
|
|
41914
41932
|
const catchLocals = /* @__PURE__ */ new Set([...locals, clause.name]);
|
|
41915
41933
|
if (clause.filter) {
|
|
41916
|
-
|
|
41934
|
+
collectAssignedPathsInExpression(
|
|
41917
41935
|
clause.filter,
|
|
41918
41936
|
roots,
|
|
41919
41937
|
catchLocals,
|
|
41920
41938
|
flowCache
|
|
41921
41939
|
);
|
|
41922
41940
|
}
|
|
41923
|
-
|
|
41941
|
+
collectAssignedPaths(
|
|
41924
41942
|
clause.body,
|
|
41925
41943
|
roots,
|
|
41926
41944
|
clause.filter ? localsWithBindings(catchLocals, clause.filter, true) : catchLocals,
|
|
@@ -41930,13 +41948,13 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41930
41948
|
continue;
|
|
41931
41949
|
}
|
|
41932
41950
|
if (statement.kind === "while" || statement.kind === "doWhile") {
|
|
41933
|
-
|
|
41951
|
+
collectAssignedPathsInExpression(
|
|
41934
41952
|
statement.condition,
|
|
41935
41953
|
roots,
|
|
41936
41954
|
locals,
|
|
41937
41955
|
flowCache
|
|
41938
41956
|
);
|
|
41939
|
-
|
|
41957
|
+
collectAssignedPaths(
|
|
41940
41958
|
statement.body,
|
|
41941
41959
|
roots,
|
|
41942
41960
|
statement.kind === "while" ? localsWithBindings(locals, statement.condition, true) : locals,
|
|
@@ -41945,14 +41963,14 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41945
41963
|
continue;
|
|
41946
41964
|
}
|
|
41947
41965
|
if (statement.kind === "for") {
|
|
41948
|
-
|
|
41966
|
+
collectAssignedPathsInExpression(
|
|
41949
41967
|
statement.initializer.init,
|
|
41950
41968
|
roots,
|
|
41951
41969
|
locals,
|
|
41952
41970
|
flowCache
|
|
41953
41971
|
);
|
|
41954
41972
|
const loopLocals = /* @__PURE__ */ new Set([...locals, statement.initializer.name]);
|
|
41955
|
-
|
|
41973
|
+
collectAssignedPathsInExpression(
|
|
41956
41974
|
statement.condition,
|
|
41957
41975
|
roots,
|
|
41958
41976
|
loopLocals,
|
|
@@ -41963,22 +41981,17 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41963
41981
|
statement.condition,
|
|
41964
41982
|
true
|
|
41965
41983
|
);
|
|
41966
|
-
|
|
41984
|
+
collectAssignedPaths(
|
|
41967
41985
|
[statement.iterator],
|
|
41968
41986
|
roots,
|
|
41969
41987
|
iterationLocals,
|
|
41970
41988
|
flowCache
|
|
41971
41989
|
);
|
|
41972
|
-
|
|
41973
|
-
statement.body,
|
|
41974
|
-
roots,
|
|
41975
|
-
iterationLocals,
|
|
41976
|
-
flowCache
|
|
41977
|
-
);
|
|
41990
|
+
collectAssignedPaths(statement.body, roots, iterationLocals, flowCache);
|
|
41978
41991
|
continue;
|
|
41979
41992
|
}
|
|
41980
41993
|
if (statement.kind === "forEach") {
|
|
41981
|
-
|
|
41994
|
+
collectAssignedPathsInExpression(
|
|
41982
41995
|
statement.collection,
|
|
41983
41996
|
roots,
|
|
41984
41997
|
locals,
|
|
@@ -41986,11 +41999,11 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41986
41999
|
);
|
|
41987
42000
|
const loopLocals = /* @__PURE__ */ new Set([...locals, statement.name]);
|
|
41988
42001
|
if (statement.key) loopLocals.add(statement.key.name);
|
|
41989
|
-
|
|
42002
|
+
collectAssignedPaths(statement.body, roots, loopLocals, flowCache);
|
|
41990
42003
|
continue;
|
|
41991
42004
|
}
|
|
41992
42005
|
if (statement.kind === "switch") {
|
|
41993
|
-
|
|
42006
|
+
collectAssignedPathsInExpression(
|
|
41994
42007
|
statement.selector,
|
|
41995
42008
|
roots,
|
|
41996
42009
|
locals,
|
|
@@ -41999,7 +42012,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
41999
42012
|
for (const section of statement.sections) {
|
|
42000
42013
|
for (const label of section.labels) {
|
|
42001
42014
|
if (label.kind === "case") {
|
|
42002
|
-
|
|
42015
|
+
collectAssignedPathsInExpression(
|
|
42003
42016
|
label.expression,
|
|
42004
42017
|
roots,
|
|
42005
42018
|
locals,
|
|
@@ -42007,13 +42020,13 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
42007
42020
|
);
|
|
42008
42021
|
}
|
|
42009
42022
|
}
|
|
42010
|
-
|
|
42023
|
+
collectAssignedPaths(section.body, roots, locals, flowCache);
|
|
42011
42024
|
}
|
|
42012
42025
|
continue;
|
|
42013
42026
|
}
|
|
42014
42027
|
if (statement.kind === "return" || statement.kind === "throw") {
|
|
42015
42028
|
if (statement.expr)
|
|
42016
|
-
|
|
42029
|
+
collectAssignedPathsInExpression(
|
|
42017
42030
|
statement.expr,
|
|
42018
42031
|
roots,
|
|
42019
42032
|
locals,
|
|
@@ -42022,7 +42035,7 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
42022
42035
|
continue;
|
|
42023
42036
|
}
|
|
42024
42037
|
if (statement.kind === "exprStmt") {
|
|
42025
|
-
|
|
42038
|
+
collectAssignedPathsInExpression(
|
|
42026
42039
|
statement.expr,
|
|
42027
42040
|
roots,
|
|
42028
42041
|
locals,
|
|
@@ -42032,43 +42045,28 @@ function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(),
|
|
|
42032
42045
|
}
|
|
42033
42046
|
return roots;
|
|
42034
42047
|
}
|
|
42035
|
-
function
|
|
42048
|
+
function collectAssignedPathsInExpression(expression, roots, locals, flowCache) {
|
|
42036
42049
|
switch (expression.kind) {
|
|
42037
42050
|
case "litInterp":
|
|
42038
42051
|
for (const part of expression.parts) {
|
|
42039
42052
|
if (part.kind === "expr") {
|
|
42040
|
-
|
|
42041
|
-
part.expr,
|
|
42042
|
-
roots,
|
|
42043
|
-
locals,
|
|
42044
|
-
flowCache
|
|
42045
|
-
);
|
|
42053
|
+
collectAssignedPathsInExpression(part.expr, roots, locals, flowCache);
|
|
42046
42054
|
}
|
|
42047
42055
|
}
|
|
42048
42056
|
return;
|
|
42049
42057
|
case "litList":
|
|
42050
42058
|
for (const element of expression.elements) {
|
|
42051
|
-
|
|
42059
|
+
collectAssignedPathsInExpression(element, roots, locals, flowCache);
|
|
42052
42060
|
}
|
|
42053
42061
|
return;
|
|
42054
42062
|
case "litDict":
|
|
42055
42063
|
for (const entry of expression.entries) {
|
|
42056
|
-
|
|
42057
|
-
|
|
42058
|
-
roots,
|
|
42059
|
-
locals,
|
|
42060
|
-
flowCache
|
|
42061
|
-
);
|
|
42062
|
-
collectAssignedPathRootsInExpression(
|
|
42063
|
-
entry.value,
|
|
42064
|
-
roots,
|
|
42065
|
-
locals,
|
|
42066
|
-
flowCache
|
|
42067
|
-
);
|
|
42064
|
+
collectAssignedPathsInExpression(entry.key, roots, locals, flowCache);
|
|
42065
|
+
collectAssignedPathsInExpression(entry.value, roots, locals, flowCache);
|
|
42068
42066
|
}
|
|
42069
42067
|
return;
|
|
42070
42068
|
case "member":
|
|
42071
|
-
|
|
42069
|
+
collectAssignedPathsInExpression(
|
|
42072
42070
|
expression.receiver,
|
|
42073
42071
|
roots,
|
|
42074
42072
|
locals,
|
|
@@ -42076,13 +42074,13 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42076
42074
|
);
|
|
42077
42075
|
return;
|
|
42078
42076
|
case "index":
|
|
42079
|
-
|
|
42077
|
+
collectAssignedPathsInExpression(
|
|
42080
42078
|
expression.receiver,
|
|
42081
42079
|
roots,
|
|
42082
42080
|
locals,
|
|
42083
42081
|
flowCache
|
|
42084
42082
|
);
|
|
42085
|
-
|
|
42083
|
+
collectAssignedPathsInExpression(
|
|
42086
42084
|
expression.index,
|
|
42087
42085
|
roots,
|
|
42088
42086
|
locals,
|
|
@@ -42090,32 +42088,22 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42090
42088
|
);
|
|
42091
42089
|
return;
|
|
42092
42090
|
case "call":
|
|
42093
|
-
|
|
42091
|
+
collectAssignedPathsInExpression(
|
|
42094
42092
|
expression.callee,
|
|
42095
42093
|
roots,
|
|
42096
42094
|
locals,
|
|
42097
42095
|
flowCache
|
|
42098
42096
|
);
|
|
42099
42097
|
for (const argument2 of expression.args) {
|
|
42100
|
-
|
|
42101
|
-
argument2,
|
|
42102
|
-
roots,
|
|
42103
|
-
locals,
|
|
42104
|
-
flowCache
|
|
42105
|
-
);
|
|
42098
|
+
collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
|
|
42106
42099
|
}
|
|
42107
42100
|
return;
|
|
42108
42101
|
case "new":
|
|
42109
42102
|
for (const argument2 of expression.args) {
|
|
42110
|
-
|
|
42111
|
-
argument2,
|
|
42112
|
-
roots,
|
|
42113
|
-
locals,
|
|
42114
|
-
flowCache
|
|
42115
|
-
);
|
|
42103
|
+
collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
|
|
42116
42104
|
}
|
|
42117
42105
|
for (const initializer of expression.initializer ?? []) {
|
|
42118
|
-
|
|
42106
|
+
collectAssignedPathsInExpression(
|
|
42119
42107
|
initializer.value,
|
|
42120
42108
|
roots,
|
|
42121
42109
|
locals,
|
|
@@ -42126,15 +42114,10 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42126
42114
|
case "annotated":
|
|
42127
42115
|
for (const annotation2 of expression.annotations) {
|
|
42128
42116
|
for (const argument2 of annotation2.args) {
|
|
42129
|
-
|
|
42130
|
-
argument2,
|
|
42131
|
-
roots,
|
|
42132
|
-
locals,
|
|
42133
|
-
flowCache
|
|
42134
|
-
);
|
|
42117
|
+
collectAssignedPathsInExpression(argument2, roots, locals, flowCache);
|
|
42135
42118
|
}
|
|
42136
42119
|
}
|
|
42137
|
-
|
|
42120
|
+
collectAssignedPathsInExpression(
|
|
42138
42121
|
expression.expression,
|
|
42139
42122
|
roots,
|
|
42140
42123
|
locals,
|
|
@@ -42143,13 +42126,13 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42143
42126
|
return;
|
|
42144
42127
|
case "binary":
|
|
42145
42128
|
case "coalesce":
|
|
42146
|
-
|
|
42129
|
+
collectAssignedPathsInExpression(
|
|
42147
42130
|
expression.left,
|
|
42148
42131
|
roots,
|
|
42149
42132
|
locals,
|
|
42150
42133
|
flowCache
|
|
42151
42134
|
);
|
|
42152
|
-
|
|
42135
|
+
collectAssignedPathsInExpression(
|
|
42153
42136
|
expression.right,
|
|
42154
42137
|
roots,
|
|
42155
42138
|
locals,
|
|
@@ -42157,19 +42140,19 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42157
42140
|
);
|
|
42158
42141
|
return;
|
|
42159
42142
|
case "conditional":
|
|
42160
|
-
|
|
42143
|
+
collectAssignedPathsInExpression(
|
|
42161
42144
|
expression.condition,
|
|
42162
42145
|
roots,
|
|
42163
42146
|
locals,
|
|
42164
42147
|
flowCache
|
|
42165
42148
|
);
|
|
42166
|
-
|
|
42149
|
+
collectAssignedPathsInExpression(
|
|
42167
42150
|
expression.whenTrue,
|
|
42168
42151
|
roots,
|
|
42169
42152
|
locals,
|
|
42170
42153
|
flowCache
|
|
42171
42154
|
);
|
|
42172
|
-
|
|
42155
|
+
collectAssignedPathsInExpression(
|
|
42173
42156
|
expression.whenFalse,
|
|
42174
42157
|
roots,
|
|
42175
42158
|
locals,
|
|
@@ -42178,7 +42161,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42178
42161
|
return;
|
|
42179
42162
|
case "unary":
|
|
42180
42163
|
case "force":
|
|
42181
|
-
|
|
42164
|
+
collectAssignedPathsInExpression(
|
|
42182
42165
|
expression.operand,
|
|
42183
42166
|
roots,
|
|
42184
42167
|
locals,
|
|
@@ -42186,7 +42169,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42186
42169
|
);
|
|
42187
42170
|
return;
|
|
42188
42171
|
case "is":
|
|
42189
|
-
|
|
42172
|
+
collectAssignedPathsInExpression(
|
|
42190
42173
|
expression.operand,
|
|
42191
42174
|
roots,
|
|
42192
42175
|
locals,
|
|
@@ -42194,7 +42177,7 @@ function collectAssignedPathRootsInExpression(expression, roots, locals, flowCac
|
|
|
42194
42177
|
);
|
|
42195
42178
|
return;
|
|
42196
42179
|
case "lambda":
|
|
42197
|
-
|
|
42180
|
+
collectAssignedPaths(
|
|
42198
42181
|
expression.body,
|
|
42199
42182
|
roots,
|
|
42200
42183
|
/* @__PURE__ */ new Set([
|
|
@@ -54658,7 +54641,7 @@ var SPECIALIZED_RELATION_KINDS = /* @__PURE__ */ new Set([
|
|
|
54658
54641
|
|
|
54659
54642
|
// ../packages/manifest/schema-contract/registry.mjs
|
|
54660
54643
|
var PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
54661
|
-
cliVersion: "0.72.
|
|
54644
|
+
cliVersion: "0.72.4",
|
|
54662
54645
|
projectFileUploadBatchSize: 32,
|
|
54663
54646
|
documentRecords: {
|
|
54664
54647
|
member: {
|
package/package.json
CHANGED
|
@@ -118,7 +118,7 @@ wrappers.
|
|
|
118
118
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
119
119
|
|
|
120
120
|
```html
|
|
121
|
-
<!-- reviewed-through-cli: 0.72.
|
|
121
|
+
<!-- reviewed-through-cli: 0.72.4 -->
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -178,7 +178,13 @@ or narrowing guard before the next access.
|
|
|
178
178
|
Inside an instance body, `Member` and `this.Member` share null and type-check
|
|
179
179
|
narrowing. A local or parameter named `Member` shadows the implicit member;
|
|
180
180
|
`this.Member` still names the instance field. Reassigning a narrowed path to a
|
|
181
|
-
nullable value clears its non-null fact.
|
|
181
|
+
nullable value clears its non-null fact and facts about its descendants. Writes to
|
|
182
|
+
unrelated members preserve existing guards, including inside loops. Earlier
|
|
183
|
+
conditions being false also narrow receivers in later `else if` conditions.
|
|
184
|
+
|
|
185
|
+
A nullable value coalesced with a non-null fallback produces a non-null result,
|
|
186
|
+
including in constructor arguments: `new Sprite(item.Sprite ?? SpriteInfo.Empty)`.
|
|
187
|
+
A nullable fallback keeps the result nullable when the left operand can be null.
|
|
182
188
|
|
|
183
189
|
Treat lookup-return values with the same nullable narrowing rules.
|
|
184
190
|
|
|
@@ -57,7 +57,10 @@ keys as quoted IDs when their option has been deleted.
|
|
|
57
57
|
|
|
58
58
|
## Identity rules
|
|
59
59
|
|
|
60
|
-
Preserve every existing ID through rename, reorder, and file moves.
|
|
60
|
+
Preserve every existing ID through rename, reorder, and file moves. Renaming a
|
|
61
|
+
schema member while keeping its ID preserves its owned value graph. Update
|
|
62
|
+
initializer keys to the new name and retain existing child IDs, including when
|
|
63
|
+
editing those children in the same change. A copy
|
|
61
64
|
must get a new ID. A stored nested class value may keep its UUID-v4 when moved
|
|
62
65
|
to an empty, compatible class field on another existing parent. Remove its
|
|
63
66
|
old owning declaration in the same push. Both fields must declare the same
|