@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.
Files changed (72) hide show
  1. package/README.md +10 -2
  2. package/dist/analysis/look-values.d.ts +76 -1
  3. package/dist/analysis/look-values.d.ts.map +1 -1
  4. package/dist/analysis/look-values.js +193 -0
  5. package/dist/analysis/look-values.js.map +1 -1
  6. package/dist/analysis/reactive-names.d.ts +50 -0
  7. package/dist/analysis/reactive-names.d.ts.map +1 -0
  8. package/dist/analysis/reactive-names.js +199 -0
  9. package/dist/analysis/reactive-names.js.map +1 -0
  10. package/dist/analysis/watch-cycles.d.ts +28 -0
  11. package/dist/analysis/watch-cycles.d.ts.map +1 -1
  12. package/dist/analysis/watch-cycles.js +47 -0
  13. package/dist/analysis/watch-cycles.js.map +1 -1
  14. package/dist/analyzer.d.ts +5 -1
  15. package/dist/analyzer.d.ts.map +1 -1
  16. package/dist/analyzer.js +50 -60
  17. package/dist/analyzer.js.map +1 -1
  18. package/dist/compiler.d.ts +1 -1
  19. package/dist/compiler.js +2 -2
  20. package/dist/compiler.js.map +1 -1
  21. package/dist/css-string.d.ts +4 -10
  22. package/dist/css-string.d.ts.map +1 -1
  23. package/dist/css-string.js +4 -27
  24. package/dist/css-string.js.map +1 -1
  25. package/dist/emitter.d.ts.map +1 -1
  26. package/dist/emitter.js +11 -2090
  27. package/dist/emitter.js.map +1 -1
  28. package/dist/lexer.js +63 -43
  29. package/dist/lexer.js.map +1 -1
  30. package/dist/look-static.d.ts +15 -1
  31. package/dist/look-static.d.ts.map +1 -1
  32. package/dist/look-static.js +30 -11
  33. package/dist/look-static.js.map +1 -1
  34. package/dist/look.d.ts +4 -4
  35. package/dist/look.d.ts.map +1 -1
  36. package/dist/look.js +4 -4
  37. package/dist/look.js.map +1 -1
  38. package/dist/parser.js +1 -2
  39. package/dist/parser.js.map +1 -1
  40. package/dist/runtime-sources.generated.d.ts +89 -0
  41. package/dist/runtime-sources.generated.d.ts.map +1 -0
  42. package/dist/runtime-sources.generated.js +96 -0
  43. package/dist/runtime-sources.generated.js.map +1 -0
  44. package/dist/runtime.d.ts +18 -0
  45. package/dist/runtime.d.ts.map +1 -1
  46. package/dist/runtime.js +31 -3742
  47. package/dist/runtime.js.map +1 -1
  48. package/package.json +3 -3
  49. package/dist/browser-host-runtime.d.ts +0 -23
  50. package/dist/browser-host-runtime.d.ts.map +0 -1
  51. package/dist/browser-host-runtime.js +0 -29
  52. package/dist/browser-host-runtime.js.map +0 -1
  53. package/dist/reactive-bridge-runtime.d.ts +0 -6
  54. package/dist/reactive-bridge-runtime.d.ts.map +0 -1
  55. package/dist/reactive-bridge-runtime.js +0 -114
  56. package/dist/reactive-bridge-runtime.js.map +0 -1
  57. package/dist/realtime-client-runtime.d.ts +0 -3
  58. package/dist/realtime-client-runtime.d.ts.map +0 -1
  59. package/dist/realtime-client-runtime.js +0 -382
  60. package/dist/realtime-client-runtime.js.map +0 -1
  61. package/dist/runtime-foundation.d.ts +0 -7
  62. package/dist/runtime-foundation.d.ts.map +0 -1
  63. package/dist/runtime-foundation.js +0 -1676
  64. package/dist/runtime-foundation.js.map +0 -1
  65. package/dist/websocket-runtime.d.ts +0 -2
  66. package/dist/websocket-runtime.d.ts.map +0 -1
  67. package/dist/websocket-runtime.js +0 -37
  68. package/dist/websocket-runtime.js.map +0 -1
  69. package/dist/worker-runtime.d.ts +0 -2
  70. package/dist/worker-runtime.d.ts.map +0 -1
  71. package/dist/worker-runtime.js +0 -83
  72. 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 Expression, type ValueType } from "@velarscript/compiler/extension";
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;AAMlF,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"}
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,EAAmC,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE9E,MAAM,oBAAoB,GAAc,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;AACpF,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEpF,MAAM,UAAU,iBAAiB,CAAC,IAAe;IAC/C,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAe,EAAE,KAAgB,EAAE,YAAqB;IACvF,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,IAAI,YAAY;QAAE,OAAO,IAAI,CAAC;IAC9B,OAAO,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;WACjD,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;QAChF,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAA2D,EAC3D,SAA+C,EAC/C,SAA8C,EAC9C,IAA6D;IAE7D,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,sBAAsB;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3F,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,mBAAmB;QAAE,OAAO,IAAI,CAAC;IACxE,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,UAAU,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,MAAM,GAAqB,IAAI,CAAC;IACpC,KAAK,MAAM,QAAQ,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACrD,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
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