@velarscript/web 0.29.2 → 0.30.1
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/README.md +10 -2
- package/dist/analysis/look-values.d.ts +76 -1
- package/dist/analysis/look-values.d.ts.map +1 -1
- package/dist/analysis/look-values.js +193 -0
- package/dist/analysis/look-values.js.map +1 -1
- package/dist/analysis/reactive-names.d.ts +50 -0
- package/dist/analysis/reactive-names.d.ts.map +1 -0
- package/dist/analysis/reactive-names.js +199 -0
- package/dist/analysis/reactive-names.js.map +1 -0
- package/dist/analysis/watch-cycles.d.ts +28 -0
- package/dist/analysis/watch-cycles.d.ts.map +1 -1
- package/dist/analysis/watch-cycles.js +47 -0
- package/dist/analysis/watch-cycles.js.map +1 -1
- package/dist/analyzer.d.ts +5 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +50 -60
- package/dist/analyzer.js.map +1 -1
- package/dist/compiler.d.ts +1 -1
- package/dist/compiler.js +2 -2
- package/dist/compiler.js.map +1 -1
- package/dist/css-string.d.ts +4 -10
- package/dist/css-string.d.ts.map +1 -1
- package/dist/css-string.js +4 -27
- package/dist/css-string.js.map +1 -1
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +11 -2090
- package/dist/emitter.js.map +1 -1
- package/dist/lexer.js +63 -43
- package/dist/lexer.js.map +1 -1
- package/dist/look-static.d.ts +15 -1
- package/dist/look-static.d.ts.map +1 -1
- package/dist/look-static.js +30 -11
- package/dist/look-static.js.map +1 -1
- package/dist/look.d.ts +4 -4
- package/dist/look.d.ts.map +1 -1
- package/dist/look.js +4 -4
- package/dist/look.js.map +1 -1
- package/dist/parser.js +1 -2
- package/dist/parser.js.map +1 -1
- package/dist/runtime-sources.generated.d.ts +89 -0
- package/dist/runtime-sources.generated.d.ts.map +1 -0
- package/dist/runtime-sources.generated.js +96 -0
- package/dist/runtime-sources.generated.js.map +1 -0
- package/dist/runtime.d.ts +18 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +31 -3742
- package/dist/runtime.js.map +1 -1
- package/package.json +3 -3
- package/dist/browser-host-runtime.d.ts +0 -23
- package/dist/browser-host-runtime.d.ts.map +0 -1
- package/dist/browser-host-runtime.js +0 -29
- package/dist/browser-host-runtime.js.map +0 -1
- package/dist/reactive-bridge-runtime.d.ts +0 -6
- package/dist/reactive-bridge-runtime.d.ts.map +0 -1
- package/dist/reactive-bridge-runtime.js +0 -114
- package/dist/reactive-bridge-runtime.js.map +0 -1
- package/dist/realtime-client-runtime.d.ts +0 -3
- package/dist/realtime-client-runtime.d.ts.map +0 -1
- package/dist/realtime-client-runtime.js +0 -382
- package/dist/realtime-client-runtime.js.map +0 -1
- package/dist/runtime-foundation.d.ts +0 -7
- package/dist/runtime-foundation.d.ts.map +0 -1
- package/dist/runtime-foundation.js +0 -1676
- package/dist/runtime-foundation.js.map +0 -1
- package/dist/websocket-runtime.d.ts +0 -2
- package/dist/websocket-runtime.d.ts.map +0 -1
- package/dist/websocket-runtime.js +0 -37
- package/dist/websocket-runtime.js.map +0 -1
- package/dist/worker-runtime.d.ts +0 -2
- package/dist/worker-runtime.d.ts.map +0 -1
- package/dist/worker-runtime.js +0 -83
- package/dist/worker-runtime.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @velarscript/web
|
|
2
2
|
|
|
3
|
+
**VelarScript 0.30.1 · Web surface `web@0.14`.** The counter is what a project
|
|
4
|
+
declares in `velar.json`'s `surfaces` and what a mismatch is refused by; the
|
|
5
|
+
release number every toolchain package steps to says only what you installed.
|
|
6
|
+
|
|
3
7
|
The official Web framework for VelarScript. This package is the versioned
|
|
4
8
|
authority for the `velar/look`, `velar/app`, `velar/config`, `velar/web`, `velar/forms`,
|
|
5
9
|
`velar/http`, `velar/storage`, `velar/browser`, `velar/files`,
|
|
@@ -20,15 +24,19 @@ checked symbols and members.
|
|
|
20
24
|
Applications keep the language-level imports:
|
|
21
25
|
|
|
22
26
|
```velar
|
|
23
|
-
|
|
24
27
|
import {Head, Link, Router, route} from "velar/web"
|
|
25
28
|
import {http} from "velar/http"
|
|
26
|
-
import {rgb, spacing} from "velar/look"
|
|
29
|
+
import {hsl, rgb, spacing} from "velar/look"
|
|
27
30
|
|
|
28
31
|
const accent = rgb(45, 79, 190)
|
|
32
|
+
const accentTint = hsl(224, 62%, 95%)
|
|
29
33
|
const pagePadding = spacing(24px, 16px)
|
|
30
34
|
```
|
|
31
35
|
|
|
36
|
+
`hsl`'s saturation and lightness are a `Percentage`, the spelling CSS uses for
|
|
37
|
+
those two slots; a bare number is refused with the percentage it meant, and
|
|
38
|
+
`velar fix` writes it where the argument is a literal. The hue stays a number.
|
|
39
|
+
|
|
32
40
|
One-off base properties use the same checked table through JSX directives, and
|
|
33
41
|
remain ordered after any composed Look:
|
|
34
42
|
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* D115 §三: one question about types, asked in two places, so it is written
|
|
6
6
|
* once here rather than twice in the middle of the Web analyzer.
|
|
7
7
|
*/
|
|
8
|
-
import { type
|
|
8
|
+
import { type Diagnostic } from "@velarscript/compiler";
|
|
9
|
+
import { type Expression, type Span, type ValueType } from "@velarscript/compiler/extension";
|
|
9
10
|
export declare function isLookNumericType(type: ValueType): boolean;
|
|
10
11
|
/**
|
|
11
12
|
* The type two visual operands add up to: the same kind on both sides keeps it,
|
|
@@ -27,4 +28,78 @@ export declare function lookAdditiveType(left: ValueType, right: ValueType, same
|
|
|
27
28
|
export declare function foldedLengthPercentage(expression: Extract<Expression, {
|
|
28
29
|
kind: "CallExpression";
|
|
29
30
|
}>, builderOf: (name: string) => string | undefined, inferSlot: (argument: Expression) => ValueType, join: (left: ValueType, right: ValueType) => ValueType | null): ValueType | null;
|
|
31
|
+
/**
|
|
32
|
+
* Where the bare number a builder slot refused is actually written, and the
|
|
33
|
+
* binding it came through when that is not the argument itself.
|
|
34
|
+
*
|
|
35
|
+
* D114 F9-web (WB-I7): `hsl(210, sat, 45%)` under `const sat = 70` folds to a
|
|
36
|
+
* number, and the report was drawn under `sat` while its remedy said `70%` — so
|
|
37
|
+
* an author editing at the caret replaced the binding's use with a literal. The
|
|
38
|
+
* number is written in the binding's initializer, so that is where the caret
|
|
39
|
+
* goes, and the sentence names the binding so the line it lands on is explained.
|
|
40
|
+
* A constant imported from another module has no site here and keeps the
|
|
41
|
+
* argument's own span, which is the only position this compile can point at.
|
|
42
|
+
*/
|
|
43
|
+
export type LookStaticSites = ReadonlyMap<string, Span>;
|
|
44
|
+
/**
|
|
45
|
+
* D114 P6 item 2 (LK-I3): a bare number written where a builder slot takes a
|
|
46
|
+
* `Percentage`.
|
|
47
|
+
*
|
|
48
|
+
* The refusal already exists and is already in the right place — it is core's
|
|
49
|
+
* assignability check on the argument — so this teaches that one the remedy
|
|
50
|
+
* instead of adding a second report of one mistake. The message names the
|
|
51
|
+
* percentage the author meant, and `velar fix` writes it where the argument is
|
|
52
|
+
* a literal; an identifier that folded to a number is a binding whose
|
|
53
|
+
* declaration is the place to change, so it earns the sentence there and no
|
|
54
|
+
* rewrite — retyping the binding is not a mechanical edit, because every other
|
|
55
|
+
* use of it is part of the answer.
|
|
56
|
+
*
|
|
57
|
+
* Returns whether the refusal was found and taught.
|
|
58
|
+
*/
|
|
59
|
+
export declare function teachLookPercentageSlot(diagnostics: Diagnostic[], slot: string, argument: Expression, literal: number, sites: LookStaticSites): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* D114 F7-web-b: a bare number written in a builder slot that will not take
|
|
62
|
+
* one — the mistake LK-I3 found on `hsl`, which on the length builders had been
|
|
63
|
+
* left drawing two reports about one number: core's `Cannot assign number to
|
|
64
|
+
* Length` and this analyzer's unit advice, side by side.
|
|
65
|
+
*
|
|
66
|
+
* Which slots those are is the builder's own published type, handed in by the
|
|
67
|
+
* caller, so there is no second table of builder positions kept in step by
|
|
68
|
+
* hand. Three shapes, three lessons:
|
|
69
|
+
*
|
|
70
|
+
* - a slot whose type is exactly `Length` — `blur`'s radius, `border`'s
|
|
71
|
+
* width, the offsets and spread of `shadow` and `dropShadow` — has one
|
|
72
|
+
* natural unit, so the sentence names it and `velar fix` writes `4px`;
|
|
73
|
+
* - a slot that takes a length *or* a percentage — `min`, `max` and `clamp`,
|
|
74
|
+
* the three builders that exist to mix them — names both spellings and
|
|
75
|
+
* offers no rewrite, because `100px` and `100%` are different pictures and
|
|
76
|
+
* the one the author meant is not the compiler's to guess;
|
|
77
|
+
* - a slot whose union admits `number` as well — `spacing`, `tracks`,
|
|
78
|
+
* `minmax` — draws no refusal from core at all, so the unit advice is the
|
|
79
|
+
* whole diagnosis, and zero passes because that union really does take it.
|
|
80
|
+
*
|
|
81
|
+
* D114 F9-web (WB-I2): all three sentences are one sentence, built from the
|
|
82
|
+
* slot's own published type, because the advice used to be written twice. The
|
|
83
|
+
* unit advice said "(only 0 is unitless)" for every builder that composes
|
|
84
|
+
* lengths — true of the third shape, whose union takes a bare `0`, and a
|
|
85
|
+
* falsehood on `blur` and `shadow`, where `blur(0)` is refused. A slot cannot
|
|
86
|
+
* now be told what it takes by anything but its type: `slotAccepts` reads it,
|
|
87
|
+
* and the "or 0" clause exists exactly where a bare number is accepted.
|
|
88
|
+
*
|
|
89
|
+
* Zero is refused in the first two: `blur(0)` and `min(0, 600px)` are not CSS,
|
|
90
|
+
* so the slot says what to write. A slot that admits no length at all — a
|
|
91
|
+
* colour, a border style, `inset` — is not this rule's business and earns
|
|
92
|
+
* nothing here.
|
|
93
|
+
*
|
|
94
|
+
* D114 WB-X1: `declared` is the builder's whole published type rather than one
|
|
95
|
+
* slot of it, because a rest parameter's type is the type of every position it
|
|
96
|
+
* collects and reading `parameters[position]` stopped at the last named one.
|
|
97
|
+
* `tracks(4, 8px)` was refused and `tracks(8px, 4)` drew nothing at all — the
|
|
98
|
+
* second argument of a builder whose signature declares one parameter had no
|
|
99
|
+
* published type to read, so the lesson never ran there.
|
|
100
|
+
*
|
|
101
|
+
* Returns whether the argument was refused here, which is the caller's record
|
|
102
|
+
* that this call failed its own argument check.
|
|
103
|
+
*/
|
|
104
|
+
export declare function teachLookLengthSlot(diagnostics: Diagnostic[], builder: string, position: number, declared: ValueType, argument: Expression, literal: number, sites: LookStaticSites): boolean;
|
|
30
105
|
//# sourceMappingURL=look-values.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"look-values.d.ts","sourceRoot":"","sources":["../../src/analysis/look-values.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"look-values.d.ts","sourceRoot":"","sources":["../../src/analysis/look-values.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAM7F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAO3G;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,EAC3D,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC/C,SAAS,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,SAAS,EAC9C,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,SAAS,GAAG,IAAI,GAC5D,SAAS,GAAG,IAAI,CAclB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAkBxD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,UAAU,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,eAAe,GACrB,OAAO,CAUT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,eAAe,GACrB,OAAO,CAiCT"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* D115 §三: one question about types, asked in two places, so it is written
|
|
6
6
|
* once here rather than twice in the middle of the Web analyzer.
|
|
7
7
|
*/
|
|
8
|
+
import { mechanicalFix } from "@velarscript/compiler";
|
|
8
9
|
import {} from "@velarscript/compiler/extension";
|
|
9
10
|
import { LOOK_BUILDER_SIGNATURES, LOOK_NUMERIC_TYPE_NAMES } from "../look.js";
|
|
10
11
|
const lookLengthPercentage = { kind: "named", name: "LengthPercentage" };
|
|
@@ -58,4 +59,196 @@ export function foldedLengthPercentage(expression, builderOf, inferSlot, join) {
|
|
|
58
59
|
}
|
|
59
60
|
return folded;
|
|
60
61
|
}
|
|
62
|
+
function lookSlotOrigin(argument, sites) {
|
|
63
|
+
if (argument.kind !== "IdentifierExpression")
|
|
64
|
+
return { span: argument.span, binding: null };
|
|
65
|
+
const site = sites.get(argument.name);
|
|
66
|
+
return site === undefined ? { span: argument.span, binding: null } : { span: site, binding: argument.name };
|
|
67
|
+
}
|
|
68
|
+
/** "4 is a number", or "'n' holds 4, a number" where the argument folded through a binding. */
|
|
69
|
+
function heldNumber(origin, written, refused) {
|
|
70
|
+
return origin.binding === null ? `${written} is ${refused}` : `'${origin.binding}' holds ${written}, ${refused}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* D114 P6 item 2 (LK-I3): a bare number written where a builder slot takes a
|
|
74
|
+
* `Percentage`.
|
|
75
|
+
*
|
|
76
|
+
* The refusal already exists and is already in the right place — it is core's
|
|
77
|
+
* assignability check on the argument — so this teaches that one the remedy
|
|
78
|
+
* instead of adding a second report of one mistake. The message names the
|
|
79
|
+
* percentage the author meant, and `velar fix` writes it where the argument is
|
|
80
|
+
* a literal; an identifier that folded to a number is a binding whose
|
|
81
|
+
* declaration is the place to change, so it earns the sentence there and no
|
|
82
|
+
* rewrite — retyping the binding is not a mechanical edit, because every other
|
|
83
|
+
* use of it is part of the answer.
|
|
84
|
+
*
|
|
85
|
+
* Returns whether the refusal was found and taught.
|
|
86
|
+
*/
|
|
87
|
+
export function teachLookPercentageSlot(diagnostics, slot, argument, literal, sites) {
|
|
88
|
+
const written = `${Number(literal.toPrecision(12))}%`;
|
|
89
|
+
const origin = lookSlotOrigin(argument, sites);
|
|
90
|
+
const rewritable = argument.kind === "LiteralExpression" && typeof argument.value === "number";
|
|
91
|
+
return teachSlotRefusal(diagnostics, argument, "Percentage", (item) => ({
|
|
92
|
+
...item,
|
|
93
|
+
span: origin.span,
|
|
94
|
+
message: `${slot} is a percentage, and ${heldNumber(origin, String(literal), "a number")}; write ${written}`,
|
|
95
|
+
...(rewritable ? { fix: mechanicalFix(argument.span, written, `Write ${written}`) } : {}),
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* D114 F7-web-b: a bare number written in a builder slot that will not take
|
|
100
|
+
* one — the mistake LK-I3 found on `hsl`, which on the length builders had been
|
|
101
|
+
* left drawing two reports about one number: core's `Cannot assign number to
|
|
102
|
+
* Length` and this analyzer's unit advice, side by side.
|
|
103
|
+
*
|
|
104
|
+
* Which slots those are is the builder's own published type, handed in by the
|
|
105
|
+
* caller, so there is no second table of builder positions kept in step by
|
|
106
|
+
* hand. Three shapes, three lessons:
|
|
107
|
+
*
|
|
108
|
+
* - a slot whose type is exactly `Length` — `blur`'s radius, `border`'s
|
|
109
|
+
* width, the offsets and spread of `shadow` and `dropShadow` — has one
|
|
110
|
+
* natural unit, so the sentence names it and `velar fix` writes `4px`;
|
|
111
|
+
* - a slot that takes a length *or* a percentage — `min`, `max` and `clamp`,
|
|
112
|
+
* the three builders that exist to mix them — names both spellings and
|
|
113
|
+
* offers no rewrite, because `100px` and `100%` are different pictures and
|
|
114
|
+
* the one the author meant is not the compiler's to guess;
|
|
115
|
+
* - a slot whose union admits `number` as well — `spacing`, `tracks`,
|
|
116
|
+
* `minmax` — draws no refusal from core at all, so the unit advice is the
|
|
117
|
+
* whole diagnosis, and zero passes because that union really does take it.
|
|
118
|
+
*
|
|
119
|
+
* D114 F9-web (WB-I2): all three sentences are one sentence, built from the
|
|
120
|
+
* slot's own published type, because the advice used to be written twice. The
|
|
121
|
+
* unit advice said "(only 0 is unitless)" for every builder that composes
|
|
122
|
+
* lengths — true of the third shape, whose union takes a bare `0`, and a
|
|
123
|
+
* falsehood on `blur` and `shadow`, where `blur(0)` is refused. A slot cannot
|
|
124
|
+
* now be told what it takes by anything but its type: `slotAccepts` reads it,
|
|
125
|
+
* and the "or 0" clause exists exactly where a bare number is accepted.
|
|
126
|
+
*
|
|
127
|
+
* Zero is refused in the first two: `blur(0)` and `min(0, 600px)` are not CSS,
|
|
128
|
+
* so the slot says what to write. A slot that admits no length at all — a
|
|
129
|
+
* colour, a border style, `inset` — is not this rule's business and earns
|
|
130
|
+
* nothing here.
|
|
131
|
+
*
|
|
132
|
+
* D114 WB-X1: `declared` is the builder's whole published type rather than one
|
|
133
|
+
* slot of it, because a rest parameter's type is the type of every position it
|
|
134
|
+
* collects and reading `parameters[position]` stopped at the last named one.
|
|
135
|
+
* `tracks(4, 8px)` was refused and `tracks(8px, 4)` drew nothing at all — the
|
|
136
|
+
* second argument of a builder whose signature declares one parameter had no
|
|
137
|
+
* published type to read, so the lesson never ran there.
|
|
138
|
+
*
|
|
139
|
+
* Returns whether the argument was refused here, which is the caller's record
|
|
140
|
+
* that this call failed its own argument check.
|
|
141
|
+
*/
|
|
142
|
+
export function teachLookLengthSlot(diagnostics, builder, position, declared, argument, literal, sites) {
|
|
143
|
+
const slot = lookSlotNoun(builder, position);
|
|
144
|
+
const accepts = slotAccepts(lookSlotType(declared, position));
|
|
145
|
+
if (slot === undefined || accepts === null)
|
|
146
|
+
return false;
|
|
147
|
+
const written = `${Number(literal.toPrecision(12))}`;
|
|
148
|
+
const origin = lookSlotOrigin(argument, sites);
|
|
149
|
+
const spellings = accepts === "a Length" ? `${written}px`
|
|
150
|
+
: accepts === "a Percentage" ? `${written}%` : `${written}px or ${written}%`;
|
|
151
|
+
// `tracks` is the one length builder whose name ends in an s, and "tracks's"
|
|
152
|
+
// is not how the possessive is written.
|
|
153
|
+
const lesson = `${builder}${builder.endsWith("s") ? "'" : "'s"} ${slot} is ${accepts},`
|
|
154
|
+
+ ` and ${heldNumber(origin, written, accepts.endsWith("or 0") ? "none of those" : "a number")}; write ${spellings}`;
|
|
155
|
+
if (accepts === "a Length" && teachSlotRefusal(diagnostics, argument, "Length", (item) => ({
|
|
156
|
+
...item,
|
|
157
|
+
span: origin.span,
|
|
158
|
+
message: lesson,
|
|
159
|
+
...(argument.kind === "LiteralExpression" && typeof argument.value === "number"
|
|
160
|
+
? { fix: mechanicalFix(argument.span, `${written}px`, `Write ${written}px`) }
|
|
161
|
+
: {}),
|
|
162
|
+
})))
|
|
163
|
+
return true;
|
|
164
|
+
// The refused type is the slot's own, so a slot that takes only a percentage
|
|
165
|
+
// finds its refusal too rather than falling through and reporting twice.
|
|
166
|
+
if (accepts !== "a Length" && teachSlotRefusal(diagnostics, argument, accepts === "a Percentage" ? "Percentage" : "LengthPercentage", (item) => ({
|
|
167
|
+
...item,
|
|
168
|
+
span: origin.span,
|
|
169
|
+
message: lesson,
|
|
170
|
+
})))
|
|
171
|
+
return true;
|
|
172
|
+
// A slot whose union takes a bare number takes `0`, and CSS writes that one
|
|
173
|
+
// length without a unit; every other number in it is the dead declaration
|
|
174
|
+
// this report exists for.
|
|
175
|
+
if (literal === 0 && accepts.endsWith("or 0"))
|
|
176
|
+
return false;
|
|
177
|
+
diagnostics.push({ code: "VEL5042", message: lesson, span: origin.span });
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The published type of the slot an argument lands in: the declared parameter
|
|
182
|
+
* at that position, or — past the last of those — the rest parameter's type,
|
|
183
|
+
* which is the type of every position it collects.
|
|
184
|
+
*/
|
|
185
|
+
function lookSlotType(declared, position) {
|
|
186
|
+
if (position < 0 || declared.kind !== "function")
|
|
187
|
+
return undefined;
|
|
188
|
+
return declared.parameters[position] ?? declared.rest;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* How the lesson refers to the slot an argument lands in, or undefined where
|
|
192
|
+
* the builder has no slot there at all.
|
|
193
|
+
*
|
|
194
|
+
* D114 WB-X1: a rest parameter collects every position from its own onward, and
|
|
195
|
+
* the signature has a name for only the first of them — so `tracks(8px, 4)`
|
|
196
|
+
* used to read past the end of the name table and teach nothing, while
|
|
197
|
+
* `tracks(4, 8px)` was refused. The collected positions are named by their
|
|
198
|
+
* number rather than by the rest parameter's name, because "tracks' first
|
|
199
|
+
* argument" pointing at the second argument would be a sentence that is not
|
|
200
|
+
* true. The named positions keep the wording F9-web gave them exactly.
|
|
201
|
+
*/
|
|
202
|
+
function lookSlotNoun(builder, position) {
|
|
203
|
+
if (position < 0)
|
|
204
|
+
return undefined;
|
|
205
|
+
const signature = LOOK_BUILDER_SIGNATURES.get(builder);
|
|
206
|
+
if (signature === undefined)
|
|
207
|
+
return undefined;
|
|
208
|
+
const named = signature.parameters[position];
|
|
209
|
+
if (named !== undefined)
|
|
210
|
+
return `${named} argument`;
|
|
211
|
+
return signature.rest === true ? `argument ${position + 1}` : undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* What a slot's published type accepts, in the words the lesson names it with,
|
|
215
|
+
* or null where the slot carries no length at all. The "or 0" tail is the one
|
|
216
|
+
* fact a reader has to be able to trust in both directions, so it is read from
|
|
217
|
+
* the type rather than written into a sentence by hand.
|
|
218
|
+
*/
|
|
219
|
+
function slotAccepts(type) {
|
|
220
|
+
if (type === undefined)
|
|
221
|
+
return null;
|
|
222
|
+
if (type.kind === "named") {
|
|
223
|
+
if (!lengthPercentageNames.has(type.name))
|
|
224
|
+
return null;
|
|
225
|
+
return type.name === "Length" ? "a Length" : type.name === "Percentage" ? "a Percentage" : "a Length or a Percentage";
|
|
226
|
+
}
|
|
227
|
+
if (type.kind !== "union")
|
|
228
|
+
return null;
|
|
229
|
+
if (!type.members.some((member) => member.kind === "named" && lengthPercentageNames.has(member.name)))
|
|
230
|
+
return null;
|
|
231
|
+
return type.members.some((member) => member.kind === "number") ? "a Length, a Percentage, or 0" : "a Length or a Percentage";
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The search both slot lessons make: core's assignability refusal for exactly
|
|
235
|
+
* this argument, rewritten in place. Diagnostics are collected in source order,
|
|
236
|
+
* so the scan walks back from the end and stops as soon as it is behind the
|
|
237
|
+
* argument. The refused type is named so that a slot's own lesson cannot land
|
|
238
|
+
* on some other refusal that happens to share the span.
|
|
239
|
+
*/
|
|
240
|
+
function teachSlotRefusal(diagnostics, argument, refused, rewrite) {
|
|
241
|
+
for (let index = diagnostics.length - 1; index >= 0; index -= 1) {
|
|
242
|
+
const item = diagnostics[index];
|
|
243
|
+
if (item.span.start < argument.span.start)
|
|
244
|
+
break;
|
|
245
|
+
if (item.code !== "VEL4001" || item.span.start !== argument.span.start || item.span.end !== argument.span.end)
|
|
246
|
+
continue;
|
|
247
|
+
if (!item.message.includes(refused))
|
|
248
|
+
continue;
|
|
249
|
+
diagnostics[index] = rewrite(item);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
61
254
|
//# sourceMappingURL=look-values.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"look-values.js","sourceRoot":"","sources":["../../src/analysis/look-values.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"look-values.js","sourceRoot":"","sources":["../../src/analysis/look-values.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reactive names of one module: which names read reactively without being a
|
|
3
|
+
* `state` themselves, which names *are* `state`, and what each `computed` is
|
|
4
|
+
* computed from.
|
|
5
|
+
*
|
|
6
|
+
* D115 §三: three questions about one module's declarations, asked by the Look
|
|
7
|
+
* freezing check and by the watch-ring refusals. They are one reading of the
|
|
8
|
+
* program body, so they are one module rather than three walks in the middle of
|
|
9
|
+
* the Web analyzer.
|
|
10
|
+
*/
|
|
11
|
+
import { type Program } from "@velarscript/compiler/extension";
|
|
12
|
+
/** The function spelling of a derived value; `computed` the declaration is what it becomes. */
|
|
13
|
+
export declare function isRetiredAccessorName(name: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Every name in a module or component body whose read is reactive but whose
|
|
16
|
+
* binding is not itself a state/prop reference: a computed accessor, a resource
|
|
17
|
+
* handle, an action handle. A Look literal that reads one of these freezes it
|
|
18
|
+
* exactly as it freezes a state read (LOK-D1).
|
|
19
|
+
*
|
|
20
|
+
* The retired `computed(...)` accessor stays in the callee test even though it
|
|
21
|
+
* is not a global any more (D71 replaced it with the declaration): analysis
|
|
22
|
+
* after a migration diagnostic still has to stay coherent, so the name a
|
|
23
|
+
* retired declaration binds is treated as derived exactly as it was before.
|
|
24
|
+
*/
|
|
25
|
+
export declare function collectDerivedReactiveNames(program: Program): ReadonlySet<string>;
|
|
26
|
+
/**
|
|
27
|
+
* D114 P6 item 6 (ST-U2): one same-module `computed` and the state it is
|
|
28
|
+
* computed *from*, so `watch doubled:` writing `count` is refused where the
|
|
29
|
+
* runtime's per-task observer budget used to stop it after 50,000 rounds.
|
|
30
|
+
*
|
|
31
|
+
* The hop is exactly one, and it is proved rather than guessed:
|
|
32
|
+
*
|
|
33
|
+
* - **Same module.** A cross-module `computed` is a name this program cannot
|
|
34
|
+
* read the body of, so it is not in this map and nothing is reported.
|
|
35
|
+
* - **One hop.** Only the names the computed's own initializer reads are
|
|
36
|
+
* sources. A computed that reads another computed contributes that other
|
|
37
|
+
* computed's name, not the state underneath it, so a two-hop chain fails
|
|
38
|
+
* the comparison and stays with the runtime budget.
|
|
39
|
+
* - **Unconditional.** A read inside a ternary branch, on the right of `and`,
|
|
40
|
+
* `or` or `??`, or inside a function body is a read this evaluation may not
|
|
41
|
+
* make, so it is not a proved cycle. The condition of a ternary and the left
|
|
42
|
+
* operand of a short-circuit are always evaluated and are read.
|
|
43
|
+
*
|
|
44
|
+
* A name declared twice answers null, for `collectReactiveWriters`'s reason: a
|
|
45
|
+
* refusal that has to be right every time cannot pick one of two bodies.
|
|
46
|
+
*/
|
|
47
|
+
export declare function collectReactiveDerivations(program: Program): ReadonlyMap<string, ReadonlySet<string> | null>;
|
|
48
|
+
/** Every `state name = ...` of one module: true where it is declared exactly once. */
|
|
49
|
+
export declare function collectReactiveStateNames(program: Program): ReadonlyMap<string, boolean>;
|
|
50
|
+
//# sourceMappingURL=reactive-names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive-names.d.ts","sourceRoot":"","sources":["../../src/analysis/reactive-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAmB,KAAK,OAAO,EAAkB,MAAM,iCAAiC,CAAC;AAGhG,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAiBjF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAoB5G;AAED,sFAAsF;AACtF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBxF"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reactive names of one module: which names read reactively without being a
|
|
3
|
+
* `state` themselves, which names *are* `state`, and what each `computed` is
|
|
4
|
+
* computed from.
|
|
5
|
+
*
|
|
6
|
+
* D115 §三: three questions about one module's declarations, asked by the Look
|
|
7
|
+
* freezing check and by the watch-ring refusals. They are one reading of the
|
|
8
|
+
* program body, so they are one module rather than three walks in the middle of
|
|
9
|
+
* the Web analyzer.
|
|
10
|
+
*/
|
|
11
|
+
import {} from "@velarscript/compiler/extension";
|
|
12
|
+
import { isWebStatement } from "../ast.js";
|
|
13
|
+
/** The function spelling of a derived value; `computed` the declaration is what it becomes. */
|
|
14
|
+
export function isRetiredAccessorName(name) {
|
|
15
|
+
return name === "computed";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Every name in a module or component body whose read is reactive but whose
|
|
19
|
+
* binding is not itself a state/prop reference: a computed accessor, a resource
|
|
20
|
+
* handle, an action handle. A Look literal that reads one of these freezes it
|
|
21
|
+
* exactly as it freezes a state read (LOK-D1).
|
|
22
|
+
*
|
|
23
|
+
* The retired `computed(...)` accessor stays in the callee test even though it
|
|
24
|
+
* is not a global any more (D71 replaced it with the declaration): analysis
|
|
25
|
+
* after a migration diagnostic still has to stay coherent, so the name a
|
|
26
|
+
* retired declaration binds is treated as derived exactly as it was before.
|
|
27
|
+
*/
|
|
28
|
+
export function collectDerivedReactiveNames(program) {
|
|
29
|
+
const names = new Set();
|
|
30
|
+
const record = (statements) => {
|
|
31
|
+
for (const statement of statements) {
|
|
32
|
+
if (statement.kind === "VariableDeclaration" && statement.pattern.kind === "NameBindingPattern"
|
|
33
|
+
&& statement.initializer.kind === "CallExpression" && statement.initializer.callee.kind === "IdentifierExpression"
|
|
34
|
+
&& isRetiredAccessorName(statement.initializer.callee.name)) {
|
|
35
|
+
names.add(statement.pattern.name);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!isWebStatement(statement))
|
|
39
|
+
continue;
|
|
40
|
+
if (statement.kind === "ExtensionStatement:web:resource" || statement.kind === "ExtensionStatement:web:action")
|
|
41
|
+
names.add(statement.name);
|
|
42
|
+
if (statement.kind === "ExtensionStatement:web:component")
|
|
43
|
+
record(statement.body);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
record(program.body);
|
|
47
|
+
return names;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* D114 P6 item 6 (ST-U2): one same-module `computed` and the state it is
|
|
51
|
+
* computed *from*, so `watch doubled:` writing `count` is refused where the
|
|
52
|
+
* runtime's per-task observer budget used to stop it after 50,000 rounds.
|
|
53
|
+
*
|
|
54
|
+
* The hop is exactly one, and it is proved rather than guessed:
|
|
55
|
+
*
|
|
56
|
+
* - **Same module.** A cross-module `computed` is a name this program cannot
|
|
57
|
+
* read the body of, so it is not in this map and nothing is reported.
|
|
58
|
+
* - **One hop.** Only the names the computed's own initializer reads are
|
|
59
|
+
* sources. A computed that reads another computed contributes that other
|
|
60
|
+
* computed's name, not the state underneath it, so a two-hop chain fails
|
|
61
|
+
* the comparison and stays with the runtime budget.
|
|
62
|
+
* - **Unconditional.** A read inside a ternary branch, on the right of `and`,
|
|
63
|
+
* `or` or `??`, or inside a function body is a read this evaluation may not
|
|
64
|
+
* make, so it is not a proved cycle. The condition of a ternary and the left
|
|
65
|
+
* operand of a short-circuit are always evaluated and are read.
|
|
66
|
+
*
|
|
67
|
+
* A name declared twice answers null, for `collectReactiveWriters`'s reason: a
|
|
68
|
+
* refusal that has to be right every time cannot pick one of two bodies.
|
|
69
|
+
*/
|
|
70
|
+
export function collectReactiveDerivations(program) {
|
|
71
|
+
const derivations = new Map();
|
|
72
|
+
const record = (statements) => {
|
|
73
|
+
for (const statement of statements) {
|
|
74
|
+
if (statement.kind === "FunctionDeclaration") {
|
|
75
|
+
record(statement.body);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (!isWebStatement(statement))
|
|
79
|
+
continue;
|
|
80
|
+
if (statement.kind === "ExtensionStatement:web:computed") {
|
|
81
|
+
derivations.set(statement.name, derivations.has(statement.name) ? null : unconditionalReads(statement.initializer));
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (statement.kind === "ExtensionStatement:web:component" || statement.kind === "ExtensionStatement:web:action") {
|
|
85
|
+
record(statement.body);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
record(program.body);
|
|
90
|
+
return derivations;
|
|
91
|
+
}
|
|
92
|
+
/** Every `state name = ...` of one module: true where it is declared exactly once. */
|
|
93
|
+
export function collectReactiveStateNames(program) {
|
|
94
|
+
const states = new Map();
|
|
95
|
+
const record = (statements) => {
|
|
96
|
+
for (const statement of statements) {
|
|
97
|
+
if (statement.kind === "FunctionDeclaration") {
|
|
98
|
+
record(statement.body);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (!isWebStatement(statement))
|
|
102
|
+
continue;
|
|
103
|
+
if (statement.kind === "ExtensionStatement:web:state") {
|
|
104
|
+
states.set(statement.name, !states.has(statement.name));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (statement.kind === "ExtensionStatement:web:component" || statement.kind === "ExtensionStatement:web:action") {
|
|
108
|
+
record(statement.body);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
record(program.body);
|
|
113
|
+
return states;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The names an expression reads on every evaluation. A branch a value may not
|
|
117
|
+
* take, and a function body this expression only *builds*, are excluded: the
|
|
118
|
+
* refusal this feeds must be right every time, and "reads it sometimes" is the
|
|
119
|
+
* runtime budget's case rather than a provable ring.
|
|
120
|
+
*
|
|
121
|
+
* The walk is written out rather than reflected over the node's own fields,
|
|
122
|
+
* because "which of my children does every evaluation reach" is a question only
|
|
123
|
+
* each shape can answer -- a ternary's branches and an arrow's body are fields
|
|
124
|
+
* like any other, and a structural walk would read them as reads. A shape this
|
|
125
|
+
* switch does not name contributes nothing, which is the safe direction: a
|
|
126
|
+
* missing source is a refusal not made, and a surplus one is a refusal made
|
|
127
|
+
* wrongly.
|
|
128
|
+
*/
|
|
129
|
+
function unconditionalReads(expression) {
|
|
130
|
+
const names = new Set();
|
|
131
|
+
const walk = (node) => {
|
|
132
|
+
switch (node.kind) {
|
|
133
|
+
case "IdentifierExpression":
|
|
134
|
+
names.add(node.name);
|
|
135
|
+
return;
|
|
136
|
+
case "FStringExpression":
|
|
137
|
+
for (const part of node.parts)
|
|
138
|
+
if (part.kind === "expression")
|
|
139
|
+
walk(part.value);
|
|
140
|
+
return;
|
|
141
|
+
case "ListExpression":
|
|
142
|
+
for (const element of node.elements)
|
|
143
|
+
walk(element);
|
|
144
|
+
return;
|
|
145
|
+
case "ObjectExpression":
|
|
146
|
+
for (const entry of node.properties)
|
|
147
|
+
walk(entry.value);
|
|
148
|
+
return;
|
|
149
|
+
case "SpreadExpression":
|
|
150
|
+
case "RequiredExpression":
|
|
151
|
+
case "TryExpression":
|
|
152
|
+
case "IsExpression":
|
|
153
|
+
walk(node.value);
|
|
154
|
+
return;
|
|
155
|
+
case "UnaryExpression":
|
|
156
|
+
walk(node.operand);
|
|
157
|
+
return;
|
|
158
|
+
case "ComparisonChainExpression":
|
|
159
|
+
for (const operand of node.operands)
|
|
160
|
+
walk(operand);
|
|
161
|
+
return;
|
|
162
|
+
case "BinaryExpression":
|
|
163
|
+
// The left operand of `and`, `or` and `??` is always evaluated; the
|
|
164
|
+
// right one is exactly what those operators may skip.
|
|
165
|
+
walk(node.left);
|
|
166
|
+
if (node.operator !== "and" && node.operator !== "or" && node.operator !== "??")
|
|
167
|
+
walk(node.right);
|
|
168
|
+
return;
|
|
169
|
+
case "ConditionalExpression":
|
|
170
|
+
// The condition decides; the branches are the conditional reads the
|
|
171
|
+
// ruling leaves to the runtime budget.
|
|
172
|
+
walk(node.condition);
|
|
173
|
+
return;
|
|
174
|
+
case "CallExpression":
|
|
175
|
+
// An optional call evaluates its arguments only when the callee is
|
|
176
|
+
// there, so those reads are conditional like a branch's.
|
|
177
|
+
walk(node.callee);
|
|
178
|
+
if (!node.optional)
|
|
179
|
+
for (const argument of node.arguments)
|
|
180
|
+
walk(argument);
|
|
181
|
+
return;
|
|
182
|
+
case "MemberExpression":
|
|
183
|
+
walk(node.object);
|
|
184
|
+
return;
|
|
185
|
+
case "IndexExpression":
|
|
186
|
+
walk(node.object);
|
|
187
|
+
if (!node.optional)
|
|
188
|
+
walk(node.index);
|
|
189
|
+
return;
|
|
190
|
+
default:
|
|
191
|
+
// A literal, an arrow function's body, an extension expression: nothing
|
|
192
|
+
// this analysis can prove is read on every evaluation.
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
walk(expression);
|
|
197
|
+
return names;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=reactive-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive-names.js","sourceRoot":"","sources":["../../src/analysis/reactive-names.ts"],"names":[],"mappings":"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"}
|
|
@@ -173,4 +173,32 @@ export declare function finallySelfWrite(subject: Expression, place: ReactivePat
|
|
|
173
173
|
readonly message: string;
|
|
174
174
|
readonly span: Span;
|
|
175
175
|
} | null;
|
|
176
|
+
/**
|
|
177
|
+
* D114 P6 item 6 (ST-U2): the VEL5077 message a plain body statement earns for
|
|
178
|
+
* writing the state that the watched `computed` is computed from, or null.
|
|
179
|
+
*
|
|
180
|
+
* The charter's exclusion -- "a write of a different state leaves the watch
|
|
181
|
+
* untouched" -- read this shape as untouched, and it is not: `doubled` is
|
|
182
|
+
* `count`, one hop away, so a write of `count` at the top of the body
|
|
183
|
+
* invalidates `doubled` and re-triggers the watch. The runtime saw it only as a
|
|
184
|
+
* task that ran out of observer budget after 50,000 rounds, with no line to
|
|
185
|
+
* point at.
|
|
186
|
+
*
|
|
187
|
+
* Every limit the ruling names is a condition here rather than a caveat in a
|
|
188
|
+
* comment: the subject is a plain name this module declares as `computed`
|
|
189
|
+
* exactly once (a cross-module source is not in `derivations`), the write's root
|
|
190
|
+
* is a name this module declares as `state` exactly once, and that state is one
|
|
191
|
+
* the computed reads on every evaluation and directly -- a second `computed` in
|
|
192
|
+
* between contributes its own name, not the state under it, so a two-hop chain
|
|
193
|
+
* is not this refusal's.
|
|
194
|
+
*
|
|
195
|
+
* Shadowing is closed from both sides, because a name is not a binding. The
|
|
196
|
+
* module-wide roster answers "declared once", so a component that declares its
|
|
197
|
+
* own `state` of the same name makes the question unanswerable and nothing is
|
|
198
|
+
* reported; `writesState` answers "the write here really is a write of reactive
|
|
199
|
+
* state", resolved lexically, so an ordinary `let` of that spelling in front of
|
|
200
|
+
* the watch is not one. Only a write that passes both is the one the computed
|
|
201
|
+
* read.
|
|
202
|
+
*/
|
|
203
|
+
export declare function watchDerivedSourceWrite(subject: Expression, statement: Statement, derivations: ReadonlyMap<string, ReadonlySet<string> | null>, states: ReadonlyMap<string, boolean>, writesState: (name: string) => boolean): string | null;
|
|
176
204
|
//# sourceMappingURL=watch-cycles.d.ts.map
|