@velarscript/web 0.10.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 (95) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +89 -0
  3. package/dist/analyzer.d.ts +302 -0
  4. package/dist/analyzer.d.ts.map +1 -0
  5. package/dist/analyzer.js +2931 -0
  6. package/dist/analyzer.js.map +1 -0
  7. package/dist/ast.d.ts +220 -0
  8. package/dist/ast.d.ts.map +1 -0
  9. package/dist/ast.js +102 -0
  10. package/dist/ast.js.map +1 -0
  11. package/dist/browser-test.d.ts +29 -0
  12. package/dist/browser-test.d.ts.map +1 -0
  13. package/dist/browser-test.js +33 -0
  14. package/dist/browser-test.js.map +1 -0
  15. package/dist/compiler.d.ts +9 -0
  16. package/dist/compiler.d.ts.map +1 -0
  17. package/dist/compiler.js +715 -0
  18. package/dist/compiler.js.map +1 -0
  19. package/dist/css-tokens.d.ts +46 -0
  20. package/dist/css-tokens.d.ts.map +1 -0
  21. package/dist/css-tokens.js +363 -0
  22. package/dist/css-tokens.js.map +1 -0
  23. package/dist/editor.d.ts +3 -0
  24. package/dist/editor.d.ts.map +1 -0
  25. package/dist/editor.js +147 -0
  26. package/dist/editor.js.map +1 -0
  27. package/dist/elements.d.ts +11 -0
  28. package/dist/elements.d.ts.map +1 -0
  29. package/dist/elements.js +24 -0
  30. package/dist/elements.js.map +1 -0
  31. package/dist/emitter.d.ts +79 -0
  32. package/dist/emitter.d.ts.map +1 -0
  33. package/dist/emitter.js +2699 -0
  34. package/dist/emitter.js.map +1 -0
  35. package/dist/host.d.ts +7 -0
  36. package/dist/host.d.ts.map +1 -0
  37. package/dist/host.js +224 -0
  38. package/dist/host.js.map +1 -0
  39. package/dist/index.d.ts +11 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +23 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/inspection.d.ts +3 -0
  44. package/dist/inspection.d.ts.map +1 -0
  45. package/dist/inspection.js +82 -0
  46. package/dist/inspection.js.map +1 -0
  47. package/dist/keyframes.d.ts +16 -0
  48. package/dist/keyframes.d.ts.map +1 -0
  49. package/dist/keyframes.js +29 -0
  50. package/dist/keyframes.js.map +1 -0
  51. package/dist/lexer.d.ts +85 -0
  52. package/dist/lexer.d.ts.map +1 -0
  53. package/dist/lexer.js +422 -0
  54. package/dist/lexer.js.map +1 -0
  55. package/dist/look-static.d.ts +31 -0
  56. package/dist/look-static.d.ts.map +1 -0
  57. package/dist/look-static.js +266 -0
  58. package/dist/look-static.js.map +1 -0
  59. package/dist/look.d.ts +134 -0
  60. package/dist/look.d.ts.map +1 -0
  61. package/dist/look.js +627 -0
  62. package/dist/look.js.map +1 -0
  63. package/dist/parser.d.ts +71 -0
  64. package/dist/parser.d.ts.map +1 -0
  65. package/dist/parser.js +976 -0
  66. package/dist/parser.js.map +1 -0
  67. package/dist/project-config.d.ts +33 -0
  68. package/dist/project-config.d.ts.map +1 -0
  69. package/dist/project-config.js +199 -0
  70. package/dist/project-config.js.map +1 -0
  71. package/dist/runtime-foundation.d.ts +7 -0
  72. package/dist/runtime-foundation.d.ts.map +1 -0
  73. package/dist/runtime-foundation.js +1245 -0
  74. package/dist/runtime-foundation.js.map +1 -0
  75. package/dist/runtime.d.ts +7 -0
  76. package/dist/runtime.d.ts.map +1 -0
  77. package/dist/runtime.js +3444 -0
  78. package/dist/runtime.js.map +1 -0
  79. package/dist/semantic.d.ts +3 -0
  80. package/dist/semantic.d.ts.map +1 -0
  81. package/dist/semantic.js +150 -0
  82. package/dist/semantic.js.map +1 -0
  83. package/dist/types.d.ts +56 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +178 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/websocket-runtime.d.ts +2 -0
  88. package/dist/websocket-runtime.d.ts.map +1 -0
  89. package/dist/websocket-runtime.js +30 -0
  90. package/dist/websocket-runtime.js.map +1 -0
  91. package/dist/worker-runtime.d.ts +2 -0
  92. package/dist/worker-runtime.d.ts.map +1 -0
  93. package/dist/worker-runtime.js +72 -0
  94. package/dist/worker-runtime.js.map +1 -0
  95. package/package.json +52 -0
@@ -0,0 +1,715 @@
1
+ import { optionalOf as optional } from "@velarscript/compiler";
2
+ import { inferWebIntrinsic, routeContextIdentity, VelarWebAnalyzer } from "./analyzer.js";
3
+ import { WEB_STATEMENT_CONSTRUCTS, webExpressionContainsDirectAwait, webStatementConstructKey, webStatementContainsDirectAwait, } from "./ast.js";
4
+ import { BROWSER_TEST_MODULE, BROWSER_TEST_SOURCE_SUFFIX, browserTestDrivingGuidance } from "./browser-test.js";
5
+ import { WEB_VOID_ELEMENTS } from "./elements.js";
6
+ import { WebJavaScriptEmitter } from "./emitter.js";
7
+ import { velarWebProjectEditorExtension } from "./editor.js";
8
+ import { velarWebInspectionExtension } from "./inspection.js";
9
+ import { VelarWebParser } from "./parser.js";
10
+ import { scanWebToken, scanWebUnsafeCssLiteral, WEB_CONTEXTUAL_KEYWORDS } from "./lexer.js";
11
+ import { webModuleSource, webModuleSources } from "./runtime.js";
12
+ import { velarWebSemanticExtension } from "./semantic.js";
13
+ import { LOOK_BUILDER_SIGNATURES, LOOK_BUILDERS, LOOK_MEDIA_SUBJECTS, LOOK_PUBLIC_TYPE_NAMES, LOOK_UNIT_TYPES } from "./look.js";
14
+ import { CACHED_INTRINSIC_TYPE, isWebTypeAssignable, resolveWebTypeSyntax, WEB_OWNED_TYPE_NAMES, webComponentConstructor, webNodeType } from "./types.js";
15
+ export const VELAR_WEB_API_VERSION = "0.10";
16
+ const bytesType = { kind: "named", name: "Bytes", identity: "velar/binary#type:Bytes" };
17
+ // D57 rule 138 gave the browser-test boundary teeth, so the two names it is
18
+ // written in are part of the published contract: the framework host hands the
19
+ // suffix to the CLI runner, and tooling that has to name a browser test module
20
+ // reads both from here instead of spelling them again.
21
+ export { BROWSER_TEST_MODULE, BROWSER_TEST_SOURCE_SUFFIX } from "./browser-test.js";
22
+ const anyType = { kind: "any" };
23
+ const nullType = { kind: "null" };
24
+ const stringType = { kind: "string" };
25
+ const numberType = { kind: "number" };
26
+ const boolType = { kind: "bool" };
27
+ const nodeType = webNodeType;
28
+ const elementType = { kind: "named", name: "Element" };
29
+ const inputElementType = { kind: "named", name: "InputElement" };
30
+ const textAreaElementType = { kind: "named", name: "TextAreaElement" };
31
+ const canvasElementType = { kind: "named", name: "CanvasElement" };
32
+ const dialogElementType = { kind: "named", name: "DialogElement" };
33
+ const blobType = { kind: "named", name: "Blob" };
34
+ const lengthType = { kind: "named", name: "Length" };
35
+ const percentageType = { kind: "named", name: "Percentage" };
36
+ const lengthPercentageType = { kind: "named", name: "LengthPercentage" };
37
+ const trackFractionType = { kind: "named", name: "TrackFraction" };
38
+ const colorType = { kind: "named", name: "Color" };
39
+ const colorInputType = colorType;
40
+ const borderType = { kind: "named", name: "Border" };
41
+ const shadowType = { kind: "named", name: "Shadow" };
42
+ const imageType = { kind: "named", name: "Image" };
43
+ const trackType = { kind: "named", name: "Track" };
44
+ const trackListType = { kind: "named", name: "TrackList" };
45
+ const transitionType = { kind: "named", name: "Transition" };
46
+ const keyframesType = { kind: "named", name: "Keyframes" };
47
+ const animationType = { kind: "named", name: "Animation" };
48
+ const durationType = { kind: "named", name: "Duration" };
49
+ const angleType = { kind: "named", name: "Angle" };
50
+ const spacingType = { kind: "named", name: "Spacing" };
51
+ const mountTargetType = { kind: "union", members: [stringType, elementType] };
52
+ const lookScalarType = { kind: "union", members: [numberType, stringType, lengthType, percentageType, lengthPercentageType] };
53
+ const trackInputType = { kind: "union", members: [numberType, stringType, lengthType, percentageType, lengthPercentageType, trackFractionType, trackType, trackListType] };
54
+ const repeatCountType = { kind: "union", members: [numberType, stringType] };
55
+ function namedFunction(parameterNames, parameters, result, requiredParameters = parameters.length) {
56
+ return { kind: "function", parameterNames, parameters, requiredParameters, result };
57
+ }
58
+ /**
59
+ * A velar/look builder's published type, with its parameter names and required
60
+ * count read from LOOK_BUILDER_SIGNATURES rather than repeated here. The static
61
+ * keyframe lowering places named arguments from that same table, so the two
62
+ * cannot disagree about what `spread=0px` means.
63
+ */
64
+ function lookBuilder(name, parameters, result, rest) {
65
+ const signature = LOOK_BUILDER_SIGNATURES.get(name);
66
+ if (!signature)
67
+ throw new Error(`velar/look builder '${name}' has no declared signature`);
68
+ if (signature.parameters.length !== parameters.length) {
69
+ throw new Error(`velar/look builder '${name}' declares ${signature.parameters.length} parameters but types ${parameters.length}`);
70
+ }
71
+ if ((signature.rest ?? false) !== (rest !== undefined)) {
72
+ throw new Error(`velar/look builder '${name}' disagrees with its declared rest parameter`);
73
+ }
74
+ return {
75
+ kind: "function",
76
+ parameterNames: signature.parameters,
77
+ parameters,
78
+ requiredParameters: signature.required,
79
+ ...(rest ? { rest } : {}),
80
+ result,
81
+ };
82
+ }
83
+ const unknownType = { kind: "unknown" };
84
+ const webGlobals = new Map([
85
+ ["mount", namedFunction(["node", "target"], [nodeType, mountTargetType], nullType)],
86
+ ["tick", namedFunction([], [], { kind: "promise", value: nullType })],
87
+ // D71 rule 183: the word `computed` names the declaration; the function that
88
+ // returns a passable cached reader is `cached`. `computed` is a contextual
89
+ // keyword now rather than a global, exactly as `state` is — the Web analyzer
90
+ // answers a leftover `computed(...)` with its migration on the way past.
91
+ ["cached", CACHED_INTRINSIC_TYPE],
92
+ ]);
93
+ const lookModuleExports = new Map([
94
+ ...LOOK_PUBLIC_TYPE_NAMES.map((name) => [name, { kind: "typeObject", name, value: { kind: "named", name } }]),
95
+ ["color", lookBuilder("color", [stringType], colorType)],
96
+ ["rgb", lookBuilder("rgb", [numberType, numberType, numberType], colorType)],
97
+ ["rgba", lookBuilder("rgba", [numberType, numberType, numberType, numberType], colorType)],
98
+ ["hsl", lookBuilder("hsl", [numberType, numberType, numberType], colorType)],
99
+ ["alpha", lookBuilder("alpha", [colorInputType, numberType], colorType)],
100
+ ["lighten", lookBuilder("lighten", [colorInputType, numberType], colorType)],
101
+ ["darken", lookBuilder("darken", [colorInputType, numberType], colorType)],
102
+ ["border", lookBuilder("border", [lengthType, colorInputType, stringType], borderType)],
103
+ ["shadow", lookBuilder("shadow", [lengthType, lengthType, lengthType, colorInputType, lengthType, boolType], shadowType)],
104
+ ["linearGradient", lookBuilder("linearGradient", [angleType, colorInputType, colorInputType], imageType)],
105
+ ["asset", lookBuilder("asset", [stringType], imageType)],
106
+ ["minmax", lookBuilder("minmax", [trackInputType, trackInputType], trackType)],
107
+ ["repeat", lookBuilder("repeat", [repeatCountType, trackInputType], trackListType)],
108
+ ["tracks", lookBuilder("tracks", [trackInputType], trackListType, trackInputType)],
109
+ ["transition", lookBuilder("transition", [stringType, durationType, stringType, durationType], transitionType)],
110
+ ["spacing", lookBuilder("spacing", [lookScalarType, lookScalarType, lookScalarType, lookScalarType], spacingType)],
111
+ ["min", lookBuilder("min", [lengthType, lengthType], lengthType)],
112
+ ["max", lookBuilder("max", [lengthType, lengthType], lengthType)],
113
+ ["clamp", lookBuilder("clamp", [lengthType, lengthType, lengthType], lengthType)],
114
+ ["animate", lookBuilder("animate", [keyframesType, durationType, stringType, durationType, numberType, boolType, stringType, stringType], animationType)],
115
+ ]);
116
+ // D52 rule 114: `Look.` is gone. JavaScript has no `Look` global, so the
117
+ // prefix was ours to invent and ours to withdraw — and a look block is the
118
+ // densest run of calls in the language, which is the worst place to spend four
119
+ // characters per call on a word that adds nothing. The builders are named
120
+ // imports again; `Look` survives only as the type of a look value.
121
+ const webTextFormTypes = new Set(LOOK_UNIT_TYPES.values());
122
+ // D72 rule 186: derived from the one published table. `Component` is the only
123
+ // name that answers `textForm` differently — it is a constructor contract
124
+ // rather than a value type — so it is subtracted here rather than kept in a
125
+ // second list.
126
+ const webOwnedNamedTypes = new Set([...WEB_OWNED_TYPE_NAMES].filter((name) => name !== "Component"));
127
+ function functionType(parameters, result, requiredParameters = parameters.length) {
128
+ return { kind: "function", parameters, requiredParameters, result };
129
+ }
130
+ function namedIntrinsic(name, parameterNames, parameters, result, requiredParameters = parameters.length) {
131
+ return { kind: "intrinsic", name, parameterNames, parameters, requiredParameters, result };
132
+ }
133
+ function promise(value) {
134
+ return { kind: "promise", value };
135
+ }
136
+ function object(fields) {
137
+ return { kind: "object", fields: new Map(Object.entries(fields)) };
138
+ }
139
+ /** A structurally declared standard capability handle; see ValueType.capabilityHandle. */
140
+ function capabilityHandle(fields) {
141
+ return { kind: "object", fields: new Map(Object.entries(fields)), capabilityHandle: true };
142
+ }
143
+ const errorType = { kind: "class", name: "Error" };
144
+ const cleanupType = namedFunction([], [], nullType);
145
+ const arrayString = { kind: "list", element: stringType };
146
+ const mapString = (value) => ({ kind: "map", key: stringType, value });
147
+ const webElementType = { kind: "union", members: [elementType, inputElementType, canvasElementType, dialogElementType] };
148
+ const fileType = { kind: "named", name: "File" };
149
+ const fileArrayType = { kind: "list", element: fileType };
150
+ const formBodyType = object({
151
+ field: namedFunction(["name", "value"], [stringType, stringType], nullType),
152
+ file: namedFunction(["name", "value", "fileName"], [stringType, fileType, stringType], nullType, 2),
153
+ files: namedFunction(["name", "values"], [stringType, fileArrayType], nullType),
154
+ remove: namedFunction(["name"], [stringType], nullType),
155
+ has: namedFunction(["name"], [stringType], boolType),
156
+ names: namedFunction([], [], arrayString),
157
+ });
158
+ const httpChunkConsumerType = namedFunction(["chunk"], [stringType], promise(nullType));
159
+ const httpTransportPhaseIdentity = "velar/http#enum:HttpTransportPhase";
160
+ const httpTransportPhaseMembers = new Set(["request", "response"]);
161
+ const httpTransportPhaseType = { kind: "enum", name: "HttpTransportPhase", identity: httpTransportPhaseIdentity };
162
+ const httpTransportErrorIdentity = "velar/http#class:HttpTransportError";
163
+ const httpResponseType = object({
164
+ ok: boolType,
165
+ status: numberType,
166
+ statusText: stringType,
167
+ url: stringType,
168
+ headers: mapString(stringType),
169
+ json: namedFunction([], [], promise(unknownType)),
170
+ text: namedFunction([], [], promise(stringType)),
171
+ bytes: namedFunction([], [], promise(bytesType)),
172
+ streamText: namedFunction(["consume"], [httpChunkConsumerType], promise(nullType)),
173
+ blob: namedFunction([], [], promise(blobType)),
174
+ parse: namedIntrinsic("runtime.parseAsync", ["target"], [anyType], promise(anyType)),
175
+ });
176
+ const requestType = object({
177
+ response: namedFunction([], [], promise(httpResponseType)),
178
+ json: namedFunction([], [], promise(unknownType)),
179
+ text: namedFunction([], [], promise(stringType)),
180
+ bytes: namedFunction([], [], promise(bytesType)),
181
+ streamText: namedFunction(["consume"], [httpChunkConsumerType], promise(nullType)),
182
+ blob: namedFunction([], [], promise(blobType)),
183
+ parse: namedIntrinsic("runtime.parseAsync", ["target"], [anyType], promise(anyType)),
184
+ cancel: namedFunction([], [], nullType),
185
+ });
186
+ const httpOptionsType = object({
187
+ headers: optional(mapString(stringType)),
188
+ body: optional(anyType),
189
+ timeout: optional(numberType),
190
+ maxBytes: optional(numberType),
191
+ credentials: optional(stringType),
192
+ cache: optional(stringType),
193
+ });
194
+ const httpType = object({
195
+ request: namedIntrinsic("http.request", ["method", "url", "options"], [stringType, stringType, httpOptionsType], requestType, 2),
196
+ get: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
197
+ post: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
198
+ put: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
199
+ patch: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
200
+ delete: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
201
+ head: namedIntrinsic("http.request", ["url", "options"], [stringType, httpOptionsType], requestType, 1),
202
+ });
203
+ function createStorageType() {
204
+ const common = () => new Map([
205
+ ["get", namedIntrinsic("storage.get", ["key", "target", "fallback", "maxBytes"], [stringType, anyType, anyType, numberType], anyType, 2)],
206
+ ["set", namedIntrinsic("storage.set", ["key", "value", "maxBytes"], [stringType, anyType, numberType], nullType, 2)],
207
+ ["has", namedFunction(["key"], [stringType], boolType)],
208
+ ["keys", namedFunction([], [], arrayString)],
209
+ ["remove", namedFunction(["key"], [stringType], nullType)],
210
+ ["clear", namedFunction([], [], nullType)],
211
+ ["watch", namedIntrinsic("storage.watch", ["key", "target", "callback", "maxBytes"], [stringType, anyType, anyType, numberType], cleanupType, 3)],
212
+ ]);
213
+ const scoped = { kind: "object", fields: common() };
214
+ const fields = common();
215
+ fields.set("scope", namedFunction(["name"], [stringType], scoped));
216
+ return { kind: "object", fields };
217
+ }
218
+ const storageType = createStorageType();
219
+ const storageBatchChangeType = object({ key: stringType, bytes: optional(bytesType) });
220
+ const databaseType = object({
221
+ get: namedIntrinsic("storage.databaseGet", ["key", "target", "fallback", "maxBytes"], [stringType, anyType, anyType, numberType], promise(anyType), 2),
222
+ set: namedIntrinsic("storage.set", ["key", "value", "maxBytes"], [stringType, anyType, numberType], promise(nullType), 2),
223
+ getBytes: namedFunction(["key", "fallback", "maxBytes"], [stringType, optional(bytesType), numberType], promise(optional(bytesType)), 1),
224
+ setBytes: namedFunction(["key", "value", "maxBytes"], [stringType, bytesType, numberType], promise(nullType), 2),
225
+ batch: namedFunction(["changes"], [{ kind: "list", element: storageBatchChangeType }], promise(nullType)),
226
+ has: namedFunction(["key"], [stringType], promise(boolType)),
227
+ keys: namedFunction([], [], promise(arrayString)),
228
+ remove: namedFunction(["key"], [stringType], promise(nullType)),
229
+ clear: namedFunction([], [], promise(nullType)),
230
+ });
231
+ const storageQuotaErrorIdentity = "velar/storage#class:StorageQuotaError";
232
+ const storageTransactionErrorIdentity = "velar/storage#class:StorageTransactionError";
233
+ const storageUpgradeErrorIdentity = "velar/storage#class:StorageUpgradeError";
234
+ function storageErrorClass(identity) {
235
+ return {
236
+ identity, parameters: [stringType], parameterNames: ["message"], requiredParameters: 0,
237
+ base: "Error", abstract: false, fields: new Map(), getters: new Set(), abstractGetters: new Set(),
238
+ methods: new Map(), abstractMethods: new Set(), staticFields: new Map(), staticGetters: new Set(), staticMethods: new Map(),
239
+ };
240
+ }
241
+ const routeType = object({
242
+ path: stringType,
243
+ component: anyType,
244
+ });
245
+ const routeContextFields = new Map([
246
+ ["path", stringType],
247
+ ["params", mapString(stringType)],
248
+ ["query", mapString(stringType)],
249
+ ["hash", stringType],
250
+ ]);
251
+ const routeContextType = { kind: "named", name: "RouteContext", identity: routeContextIdentity };
252
+ const navigationOptionsType = object({ replace: optional(boolType), scroll: optional(boolType) });
253
+ const formValuesType = { kind: "map", key: stringType, value: unknownType };
254
+ const browserLocationType = object({
255
+ href: stringType,
256
+ origin: stringType,
257
+ path: stringType,
258
+ query: mapString(stringType),
259
+ hash: stringType,
260
+ });
261
+ const browserEnvironmentType = object({
262
+ language: stringType,
263
+ languages: arrayString,
264
+ online: boolType,
265
+ visible: boolType,
266
+ colorScheme: stringType,
267
+ reducedMotion: boolType,
268
+ touch: boolType,
269
+ });
270
+ const rectType = object({
271
+ x: numberType, y: numberType, width: numberType, height: numberType,
272
+ top: numberType, right: numberType, bottom: numberType, left: numberType,
273
+ });
274
+ const scrollMetricsType = object({
275
+ x: numberType, y: numberType,
276
+ viewportWidth: numberType, viewportHeight: numberType,
277
+ contentWidth: numberType, contentHeight: numberType,
278
+ });
279
+ const textSelectionType = object({ start: numberType, end: numberType, direction: stringType });
280
+ const fileOptionsType = object({ accept: optional(stringType), multiple: optional(boolType) });
281
+ const socketHandlersType = object({
282
+ open: optional(functionType([], unknownType)),
283
+ message: optional(functionType([stringType], unknownType)),
284
+ error: optional(functionType([stringType], unknownType)),
285
+ close: optional(functionType([numberType, stringType], unknownType)),
286
+ });
287
+ // D51 (audit 12): both realtime handles are standard capability handles that
288
+ // publish `close()`, so `using` supplies their release contract (charter
289
+ // section 16). They are declared structurally rather than as named types, and
290
+ // the marker is what lets Core see them without ever detecting a shape.
291
+ const socketType = capabilityHandle({
292
+ url: stringType,
293
+ state: namedFunction([], [], stringType),
294
+ send: namedFunction(["data"], [stringType], nullType),
295
+ sendJson: namedIntrinsic("realtime.sendJson", ["data"], [anyType], nullType),
296
+ close: namedFunction(["code", "reason"], [numberType, stringType], nullType, 0),
297
+ });
298
+ const eventStreamHandlersType = object({
299
+ open: optional(functionType([], unknownType)),
300
+ message: optional(functionType([stringType, stringType], unknownType)),
301
+ error: optional(functionType([stringType], unknownType)),
302
+ });
303
+ const eventStreamType = capabilityHandle({ url: stringType, state: namedFunction([], [], stringType), close: namedFunction([], [], nullType) });
304
+ const appErrorType = object({
305
+ error: errorType,
306
+ phase: stringType,
307
+ detail: stringType,
308
+ component: stringType,
309
+ timestamp: numberType,
310
+ });
311
+ const browserTestNavigationTimingType = object({
312
+ firstContentfulPaintMs: optional(numberType),
313
+ domContentLoadedMs: numberType,
314
+ loadMs: numberType,
315
+ });
316
+ const browserTestInteractionTimingType = object({
317
+ inputDelayMs: numberType,
318
+ processingDurationMs: numberType,
319
+ nextFrameMs: numberType,
320
+ });
321
+ const browserTestAnimationType = object({
322
+ count: numberType,
323
+ name: stringType,
324
+ rotating: boolType,
325
+ });
326
+ const browserTestControllerType = object({
327
+ open: namedFunction(["path"], [stringType], promise(nullType), 0),
328
+ reload: namedFunction([], [], promise(nullType)),
329
+ click: namedFunction(["selector"], [stringType], promise(nullType)),
330
+ fill: namedFunction(["selector", "value"], [stringType, stringType], promise(nullType)),
331
+ select: namedFunction(["selector", "value"], [stringType, stringType], promise(nullType)),
332
+ press: namedFunction(["selector", "key"], [stringType, stringType], promise(nullType)),
333
+ scroll: namedFunction(["selector", "x", "y"], [stringType, numberType, numberType], promise(nullType)),
334
+ text: namedFunction(["selector"], [stringType], promise(stringType)),
335
+ attribute: namedFunction(["selector", "name"], [stringType, stringType], promise(optional(stringType))),
336
+ box: namedFunction(["selector"], [stringType], promise(rectType)),
337
+ style: namedFunction(["selector", "property"], [stringType, stringType], promise(stringType)),
338
+ namespace: namedFunction(["selector"], [stringType], promise(stringType)),
339
+ count: namedFunction(["selector"], [stringType], promise(numberType)),
340
+ visible: namedFunction(["selector"], [stringType], promise(boolType)),
341
+ waitFor: namedFunction(["selector", "until"], [stringType, stringType], promise(nullType), 1),
342
+ waitForText: namedFunction(["selector", "text"], [stringType, stringType], promise(nullType)),
343
+ currentPath: namedFunction([], [], promise(stringType)),
344
+ viewport: namedFunction(["width", "height"], [numberType, numberType], promise(nullType)),
345
+ timings: namedFunction([], [], promise(browserTestNavigationTimingType)),
346
+ animation: namedFunction(["selector"], [stringType], promise(browserTestAnimationType)),
347
+ measureClick: namedFunction(["selector"], [stringType], promise(browserTestInteractionTimingType)),
348
+ measureFill: namedFunction(["selector", "value"], [stringType, stringType], promise(browserTestInteractionTimingType)),
349
+ measurePress: namedFunction(["selector", "key"], [stringType, stringType], promise(browserTestInteractionTimingType)),
350
+ });
351
+ const browserTestStorageControllerType = object({
352
+ get: namedFunction(["key"], [stringType], promise(optional(stringType))),
353
+ set: namedFunction(["key", "value"], [stringType, stringType], promise(nullType)),
354
+ remove: namedFunction(["key"], [stringType], promise(nullType)),
355
+ clear: namedFunction([], [], promise(nullType)),
356
+ });
357
+ const browserTestNetworkControllerType = object({
358
+ respond: namedFunction(["path", "body", "status", "contentType", "delayMs"], [stringType, stringType, numberType, stringType, numberType], promise(nullType), 2),
359
+ clear: namedFunction([], [], promise(nullType)),
360
+ });
361
+ export const webModuleInterfaces = new Map([
362
+ ["velar/look", moduleInterface(lookModuleExports)],
363
+ ["velar/app", moduleInterface(new Map([
364
+ ["onError", namedFunction(["handler"], [functionType([appErrorType], unknownType)], cleanupType)],
365
+ ["reportError", namedFunction(["error", "phase", "detail"], [errorType, stringType, stringType], nullType, 1)],
366
+ ]))],
367
+ ["velar/config", moduleInterface(new Map([
368
+ ["publicConfig", namedIntrinsic("config.public", ["target"], [anyType], anyType)],
369
+ ["has", namedFunction(["key"], [stringType], boolType)],
370
+ ["keys", namedFunction([], [], arrayString)],
371
+ ]))],
372
+ ["velar/web", moduleInterface(new Map([
373
+ ["RouteContext", { kind: "typeObject", name: "RouteContext" }],
374
+ ["route", namedIntrinsic("web.route", ["path", "view"], [stringType, anyType], routeType)],
375
+ ["lazy", namedIntrinsic("web.lazy", ["loader", "exportName", "loading", "failed"], [functionType([], promise(anyType)), stringType, anyType, anyType], anyType, 2)],
376
+ ["navigate", namedFunction(["to", "options"], [stringType, navigationOptionsType], nullType, 1)],
377
+ ["redirect", namedFunction(["to"], [stringType], nullType)],
378
+ ["back", namedFunction([], [], nullType)],
379
+ ["forward", namedFunction([], [], nullType)],
380
+ ["reload", namedFunction([], [], nullType)],
381
+ ["currentRoute", namedFunction([], [], routeContextType)],
382
+ ["announce", namedFunction(["message", "priority"], [stringType, stringType], nullType, 1)],
383
+ ["domId", namedFunction(["prefix"], [stringType], stringType, 0)],
384
+ ["Head", webComponentConstructor("Head", new Map([
385
+ ["title", stringType], ["description", stringType], ["canonical", stringType], ["robots", stringType],
386
+ ["image", stringType], ["themeColor", stringType], ["language", stringType],
387
+ ]), new Set(["title"]), null)],
388
+ ["Router", webComponentConstructor("Router", new Map([["routes", { kind: "list", element: routeType }], ["fallback", anyType]]), new Set(["routes"]), null, "web.router")],
389
+ ["Link", webComponentConstructor("Link", new Map([["to", stringType], ["replace", boolType], ["class", optional(stringType)], ["look", optional({ kind: "named", name: "Look" })], ["children", nodeType]]), new Set(["to"]), null)],
390
+ ["NavLink", webComponentConstructor("NavLink", new Map([["to", stringType], ["exact", boolType], ["replace", boolType], ["class", optional(stringType)], ["look", optional({ kind: "named", name: "Look" })], ["children", nodeType]]), new Set(["to"]), null)],
391
+ ]), new Map(), new Map([["RouteContext", routeContextFields]]), new Map([
392
+ ["RouteContext", "@velarscript/web:velar/web#type:RouteContext"],
393
+ ]))],
394
+ ["velar/http", moduleInterface(new Map([
395
+ ["http", httpType],
396
+ ["formBody", namedFunction([], [], formBodyType)],
397
+ ["HttpTransportPhase", { kind: "enumObject", name: "HttpTransportPhase", identity: httpTransportPhaseIdentity, members: httpTransportPhaseMembers }],
398
+ ["HttpAbortError", { kind: "classConstructor", name: "HttpAbortError" }],
399
+ ["HttpError", { kind: "classConstructor", name: "HttpError" }],
400
+ ["HttpTransportError", { kind: "classConstructor", name: "HttpTransportError", identity: httpTransportErrorIdentity }],
401
+ ]), new Map([
402
+ ["HttpAbortError", {
403
+ parameters: [stringType],
404
+ parameterNames: ["reason"],
405
+ requiredParameters: 1,
406
+ base: "Error",
407
+ abstract: false,
408
+ fields: new Map([["reason", { mutable: false, type: stringType }]]),
409
+ getters: new Set(),
410
+ abstractGetters: new Set(),
411
+ methods: new Map(),
412
+ abstractMethods: new Set(),
413
+ staticFields: new Map(),
414
+ staticGetters: new Set(),
415
+ staticMethods: new Map(),
416
+ }],
417
+ ["HttpError", {
418
+ parameters: [stringType, numberType, stringType, unknownType],
419
+ parameterNames: ["message", "status", "url", "body"],
420
+ requiredParameters: 3,
421
+ base: "Error",
422
+ abstract: false,
423
+ fields: new Map([
424
+ ["status", { mutable: false, type: numberType }],
425
+ ["url", { mutable: false, type: stringType }],
426
+ ["body", { mutable: false, type: unknownType }],
427
+ ]),
428
+ getters: new Set(),
429
+ abstractGetters: new Set(),
430
+ methods: new Map(),
431
+ abstractMethods: new Set(),
432
+ staticFields: new Map(),
433
+ staticGetters: new Set(),
434
+ staticMethods: new Map(),
435
+ }],
436
+ ["HttpTransportError", {
437
+ identity: httpTransportErrorIdentity,
438
+ parameters: [stringType, httpTransportPhaseType],
439
+ parameterNames: ["message", "phase"],
440
+ requiredParameters: 2,
441
+ base: "Error",
442
+ abstract: false,
443
+ fields: new Map([["phase", { mutable: false, type: httpTransportPhaseType }]]),
444
+ getters: new Set(),
445
+ abstractGetters: new Set(),
446
+ methods: new Map(),
447
+ abstractMethods: new Set(),
448
+ staticFields: new Map(),
449
+ staticGetters: new Set(),
450
+ staticMethods: new Map(),
451
+ }],
452
+ ]), new Map(), new Map(), new Map([["HttpTransportPhase", { identity: httpTransportPhaseIdentity, members: httpTransportPhaseMembers }]]))],
453
+ ["velar/storage", moduleInterface(new Map([
454
+ ["storage", storageType],
455
+ ["session", storageType],
456
+ ["database", namedFunction(["name"], [stringType], databaseType)],
457
+ ["StorageQuotaError", { kind: "classConstructor", name: "StorageQuotaError", identity: storageQuotaErrorIdentity }],
458
+ ["StorageTransactionError", { kind: "classConstructor", name: "StorageTransactionError", identity: storageTransactionErrorIdentity }],
459
+ ["StorageUpgradeError", { kind: "classConstructor", name: "StorageUpgradeError", identity: storageUpgradeErrorIdentity }],
460
+ ]), new Map([
461
+ ["StorageQuotaError", storageErrorClass(storageQuotaErrorIdentity)],
462
+ ["StorageTransactionError", storageErrorClass(storageTransactionErrorIdentity)],
463
+ ["StorageUpgradeError", storageErrorClass(storageUpgradeErrorIdentity)],
464
+ ]))],
465
+ ["velar/forms", moduleInterface(new Map([
466
+ ["values", namedFunction(["form"], [elementType], formValuesType)],
467
+ ["read", namedIntrinsic("forms.read", ["form", "target"], [elementType, anyType], anyType)],
468
+ ["fieldValue", namedFunction(["form", "name"], [elementType, stringType], optional(unknownType))],
469
+ ["textValue", namedFunction(["form", "name", "fallback"], [elementType, stringType, stringType], stringType, 2)],
470
+ ["numberValue", namedFunction(["form", "name"], [elementType, stringType], optional(numberType))],
471
+ ["checkedValue", namedFunction(["form", "name"], [elementType, stringType], boolType)],
472
+ ["fieldValues", namedFunction(["form", "name"], [elementType, stringType], arrayString)],
473
+ ["setError", namedFunction(["form", "name", "message"], [elementType, stringType, stringType], nullType)],
474
+ ["clearError", namedFunction(["form", "name"], [elementType, stringType], nullType)],
475
+ ["clearErrors", namedFunction(["form"], [elementType], nullType)],
476
+ ["errors", namedFunction(["form"], [elementType], mapString(stringType))],
477
+ ["focusFirstError", namedFunction(["form"], [elementType], boolType)],
478
+ ["setPending", namedFunction(["form", "pending"], [elementType, boolType], nullType)],
479
+ ["reset", namedFunction(["form"], [elementType], nullType)],
480
+ ]))],
481
+ ["velar/browser", moduleInterface(new Map([
482
+ ["after", namedFunction(["duration", "callback"], [durationType, functionType([], unknownType)], cleanupType)],
483
+ ["location", namedFunction([], [], browserLocationType)],
484
+ ["environment", namedFunction([], [], browserEnvironmentType)],
485
+ ["copyText", namedFunction(["value"], [stringType], promise(nullType))],
486
+ ["readClipboardText", namedFunction([], [], promise(stringType))],
487
+ ["open", namedFunction(["url", "target"], [stringType, stringType], nullType, 1)],
488
+ ["scrollTo", namedFunction(["x", "y", "behavior"], [numberType, numberType, stringType], nullType, 2)],
489
+ ["scrollIntoView", namedFunction(["element", "behavior"], [webElementType, stringType], nullType, 1)],
490
+ ["scrollMetrics", namedFunction(["element"], [webElementType], scrollMetricsType)],
491
+ ["scrollElementTo", namedFunction(["element", "x", "y", "behavior"], [webElementType, numberType, numberType, stringType], nullType, 3)],
492
+ ["focus", namedFunction(["element", "preventScroll"], [webElementType, boolType], nullType, 1)],
493
+ ["blur", namedFunction(["element"], [webElementType], nullType)],
494
+ ["measure", namedFunction(["element"], [webElementType], rectType)],
495
+ ["textSelection", namedFunction(["element"], [textAreaElementType], textSelectionType)],
496
+ ["setTextSelection", namedFunction(["element", "start", "end", "direction"], [textAreaElementType, numberType, numberType, stringType], nullType, 3)],
497
+ ["clipboardText", namedFunction(["event"], [{ kind: "named", name: "ClipboardEvent" }], stringType)],
498
+ ["setClipboardText", namedFunction(["event", "value"], [{ kind: "named", name: "ClipboardEvent" }, stringType], nullType)],
499
+ ["capturePointer", namedFunction(["element", "pointerId"], [webElementType, numberType], nullType)],
500
+ ["releasePointer", namedFunction(["element", "pointerId"], [webElementType, numberType], nullType)],
501
+ ["media", namedFunction(["query"], [stringType], boolType)],
502
+ ["watchMedia", namedFunction(["query", "callback"], [stringType, functionType([boolType], unknownType)], cleanupType)],
503
+ ["watchOnline", namedFunction(["callback"], [functionType([boolType], unknownType)], cleanupType)],
504
+ ["watchVisibility", namedFunction(["callback"], [functionType([boolType], unknownType)], cleanupType)],
505
+ ["showDialog", namedFunction(["dialog"], [dialogElementType], nullType)],
506
+ ["closeDialog", namedFunction(["dialog", "result"], [dialogElementType, stringType], nullType, 1)],
507
+ ["dialogResult", namedFunction(["dialog"], [dialogElementType], stringType)],
508
+ ["every", namedFunction(["duration", "callback"], [durationType, functionType([], unknownType)], cleanupType)],
509
+ ["frame", namedFunction([], [], promise(numberType))],
510
+ ]))],
511
+ ["velar/files", moduleInterface(new Map([
512
+ ["pick", namedFunction(["options"], [fileOptionsType], promise(fileArrayType), 0)],
513
+ ["readText", namedFunction(["file", "maxBytes"], [fileType, numberType], promise(stringType), 1)],
514
+ ["readDataUrl", namedFunction(["file", "maxBytes"], [fileType, numberType], promise(stringType), 1)],
515
+ ["download", namedFunction(["name", "data", "mime"], [stringType, stringType, stringType], nullType, 2)],
516
+ ]))],
517
+ ["velar/realtime", moduleInterface(new Map([
518
+ ["socket", namedFunction(["url", "handlers"], [stringType, socketHandlersType], socketType, 1)],
519
+ ["eventStream", namedFunction(["url", "handlers", "credentials"], [stringType, eventStreamHandlersType, boolType], eventStreamType, 1)],
520
+ ]))],
521
+ [BROWSER_TEST_MODULE, moduleInterface(new Map([
522
+ ["browser", browserTestControllerType],
523
+ ["localStorage", browserTestStorageControllerType],
524
+ ["sessionStorage", browserTestStorageControllerType],
525
+ ["network", browserTestNetworkControllerType],
526
+ ]))],
527
+ ]);
528
+ function moduleInterface(exports, classes = new Map(), namedTypes = new Map(), namedTypeIdentities = new Map(), enums = new Map()) {
529
+ return { exports, mutableExports: new Set(), reactiveExports: new Map(), reExports: new Map(), namedTypes, namedTypeIdentities, typeAliases: new Map(), enums, classes, tests: [], extensionExports: new Map(), extensionData: new Map() };
530
+ }
531
+ export const velarCompilerExtension = Object.freeze({
532
+ id: "@velarscript/web",
533
+ contract: Object.freeze({ protocolVersion: 1, apiVersion: VELAR_WEB_API_VERSION, kind: "application", extends: Object.freeze({}) }),
534
+ capabilities: Object.freeze(["web"]),
535
+ formatting: Object.freeze({
536
+ angleBracketEmbedding: Object.freeze({ voidElements: WEB_VOID_ELEMENTS }),
537
+ scanOpaqueSource: scanWebUnsafeCssLiteral,
538
+ }),
539
+ lexical: Object.freeze({
540
+ // D30 item 16: every word the Web extension adds is contextual. Each is an
541
+ // ordinary name until its own declaration shape appears, so a Web module
542
+ // and a Core module accept exactly the same bindings.
543
+ contextualKeywords: WEB_CONTEXTUAL_KEYWORDS,
544
+ forbiddenIdentifiers: Object.freeze({
545
+ effect: "Effects are internal to @velarscript/web; use watch, @mounted, or @cleanup",
546
+ onMount: "Use the Web extension's component-level '@mounted:' block",
547
+ onMounted: "Use the Web extension's component-level '@mounted:' block",
548
+ on_mount: "Use the Web extension's component-level '@mounted:' block",
549
+ }),
550
+ numericSuffixes: new Set(LOOK_UNIT_TYPES.keys()),
551
+ scan: scanWebToken,
552
+ }),
553
+ parser: Object.freeze({
554
+ create(tokens, lexicalExtensions) {
555
+ return new VelarWebParser(tokens, lexicalExtensions);
556
+ },
557
+ }),
558
+ // D56 rule 129: the parser above adds eleven statement constructs to the
559
+ // language, and a coverage gate that only reads vocabulary tables cannot see
560
+ // one of them. This is how they are required of `examples/tour/`.
561
+ syntax: Object.freeze({
562
+ statementConstructs: WEB_STATEMENT_CONSTRUCTS,
563
+ statementConstructKey: webStatementConstructKey,
564
+ }),
565
+ analyzer: Object.freeze({
566
+ create(context, extensions) {
567
+ return new VelarWebAnalyzer(context, extensions);
568
+ },
569
+ }),
570
+ semantic: velarWebSemanticExtension,
571
+ inspection: velarWebInspectionExtension,
572
+ analysis: Object.freeze({
573
+ directAwaitExpression: webExpressionContainsDirectAwait,
574
+ directAwaitStatement: webStatementContainsDirectAwait,
575
+ // `Duration` is Core's own primitive; the Web extension reads it but does
576
+ // not register it a second time.
577
+ primitiveTypes: new Set([...WEB_OWNED_TYPE_NAMES].filter((name) => name !== "Duration")),
578
+ primitiveParents: new Map([
579
+ ["InputElement", new Set(["Element"])],
580
+ ["TextAreaElement", new Set(["InputElement"])],
581
+ ["CanvasElement", new Set(["Element"])],
582
+ ["DialogElement", new Set(["Element"])],
583
+ ["KeyboardEvent", new Set(["Event"])],
584
+ ["PointerEvent", new Set(["Event"])],
585
+ ["InputEvent", new Set(["Event"])],
586
+ ["CompositionEvent", new Set(["Event"])],
587
+ ["ClipboardEvent", new Set(["Event"])],
588
+ ]),
589
+ primitiveMutableFields: new Map([
590
+ ["InputElement", new Set(["value", "checked"])],
591
+ ["CanvasElement", new Set(["width", "height"])],
592
+ ]),
593
+ globals: webGlobals,
594
+ // D52 rule 114: `Look.spacing(...)` still parses, so it still has to be
595
+ // answered — with the named import that replaced it, and with the rewrite
596
+ // that gets there in one step.
597
+ retiredNamespaces: new Map([["Look", { module: "velar/look", members: LOOK_BUILDERS }]]),
598
+ // LOK-D4: the Look media subjects are matched by name inside a Look
599
+ // condition, ahead of ordinary lexical resolution. A user binding of the
600
+ // same name used to be reverse-shadowed with no diagnostic anywhere, so the
601
+ // three names are reserved in a Web module.
602
+ reservedBindings: new Set(["mount", "tick", "cached", ...LOOK_MEDIA_SUBJECTS.keys()]),
603
+ globalGuidance: new Map([
604
+ // D52 rule 114: the destination is the spelling that survives, so the
605
+ // guidance names the import outright rather than a prefix the next
606
+ // compile would retire in turn.
607
+ ...[...LOOK_BUILDERS].map((name) => [name, `Import the builder — import {${name}} from "velar/look" — then call ${name}(...)`]),
608
+ ["document", "Use JSX, refs, and velar/browser instead of the untyped document global"],
609
+ ["window", "Use velar/browser or an explicit JavaScript boundary instead of the untyped window global"],
610
+ ["navigator", "Use velar/browser instead of the navigator global"],
611
+ ["location", "Use velar/browser location() or velar/web navigation instead of the location global"],
612
+ ["history", "Use velar/web navigation instead of the history global"],
613
+ ["fetch", "Use velar/http instead of the raw fetch global"],
614
+ ]),
615
+ // A `.browser.test.vel` body runs in the test process and drives a page
616
+ // that already runs the built application, so the DOM globals do not point
617
+ // at velar/browser there: the door is velar/web-test.
618
+ globalGuidanceByPathSuffix: new Map([
619
+ [BROWSER_TEST_SOURCE_SUFFIX, new Map([
620
+ ["document", browserTestDrivingGuidance("document")],
621
+ ["window", browserTestDrivingGuidance("window")],
622
+ ["navigator", browserTestDrivingGuidance("navigator")],
623
+ ["localStorage", browserTestDrivingGuidance("localStorage")],
624
+ ["sessionStorage", browserTestDrivingGuidance("sessionStorage")],
625
+ ])],
626
+ ]),
627
+ resolveTypeSyntax: resolveWebTypeSyntax,
628
+ isTypeAssignable: isWebTypeAssignable,
629
+ textForm(type) {
630
+ if (type.kind === "extension" && type.extensionId === "@velarscript/web")
631
+ return false;
632
+ if (type.kind !== "named" || !webOwnedNamedTypes.has(type.name))
633
+ return undefined;
634
+ return webTextFormTypes.has(type.name);
635
+ },
636
+ inferIntrinsic: inferWebIntrinsic,
637
+ }),
638
+ editor: Object.freeze({
639
+ project: velarWebProjectEditorExtension,
640
+ keywordDocumentation: Object.freeze({
641
+ component: "Declares a compiler-managed Web component that initializes once.",
642
+ state: "Declares writable reactive state in the current lexical scope.",
643
+ computed: "Declares a read-only reactive value derived from what its expression reads.",
644
+ resource: "Declares component-owned asynchronous data with reactive value, loading, ready, error, and reload fields.",
645
+ action: "Declares an asynchronous operation with reactive pending and error fields at module or component scope.",
646
+ watch: "Runs a block after a watched expression changes and DOM updates commit.",
647
+ "@mounted": "Runs once after the component DOM is inserted.",
648
+ "@cleanup": "Runs once before the component and its owned resources are destroyed.",
649
+ exposes: "Declares the explicit typed control Handle a component makes available through JSX ref.",
650
+ expose: "Provides the component Handle value declared by exposes.",
651
+ look: "Builds a typed, composable Web appearance value.",
652
+ keyframes: "Builds checked CSS animation stops as a first-class Keyframes value.",
653
+ css: "Marks an unsafe native CSS resource or inline raw block whose order against Look is explicit.",
654
+ }),
655
+ typeDocumentation: Object.freeze({
656
+ WebNode: "A value that can be rendered as component or JSX children.",
657
+ Element: "A general native element reference obtained through JSX `ref`.",
658
+ InputElement: "A native input, select, or textarea reference obtained through JSX `ref`.",
659
+ TextAreaElement: "A native textarea reference whose selection is accessed through velar/browser code-point APIs.",
660
+ CanvasElement: "A native canvas reference obtained through JSX `ref`.",
661
+ DialogElement: "A native dialog reference obtained from `<dialog ref={value}>` and operated through `velar/browser`.",
662
+ Blob: "An opaque binary HTTP body returned by `blob()` and accepted by HTTP request bodies.",
663
+ File: "An opaque selected file returned by `velar/files.pick()` with checked read-only metadata.",
664
+ Event: "A restricted Web event value exposed to VelarScript event handlers.",
665
+ Look: "A typed, composable Web appearance value applied through JSX look={...}.",
666
+ }),
667
+ completions: Object.freeze([
668
+ ...["component", "state", "computed", "resource", "action", "watch", "@mounted", "@cleanup", "exposes", "expose", "look", "keyframes"].map((label) => ({ label, kind: 14 })),
669
+ { label: "mount", kind: 3, detail: "mount(node, target) -> null" },
670
+ { label: "tick", kind: 3, detail: "tick() -> Promise<null>" },
671
+ { label: "cached", kind: 3, detail: "cached(() => T) -> () -> T" },
672
+ { label: "bind:value", kind: 10, detail: "Two-way string state binding" },
673
+ { label: "bind:checked", kind: 10, detail: "Two-way boolean state binding" },
674
+ { label: "bind:group", kind: 10, detail: "Two-way radio or checkbox group binding" },
675
+ { label: "on:click", kind: 10, detail: "DOM click handler" },
676
+ { label: "on:submit.prevent", kind: 10, detail: "DOM event with a preventDefault modifier" },
677
+ { label: "class:", kind: 10, detail: "Reactive class directive" },
678
+ { label: "look={value}", kind: 10, detail: "Apply a typed Look value" },
679
+ { label: "style:color={value}", kind: 10, detail: "High-priority checked inline Style compatibility override" },
680
+ { label: "import css unsafe", kind: 14, detail: "Import native CSS before Look output" },
681
+ { label: "unsafe css", kind: 14, detail: "Embed multiline raw CSS before or after Look output" },
682
+ { label: "after look", kind: 14, detail: "Place an unsafe CSS import after Look output" },
683
+ { label: "velar/look", kind: 9, detail: "Named visual builders and visual value Type objects" },
684
+ { label: "velar/app", kind: 9, detail: "Application error reports and explicit handler ownership" },
685
+ { label: "velar/config", kind: 9, detail: "Validated manifest-declared public application configuration" },
686
+ { label: "velar/web", kind: 9, detail: "Typed routing, navigation, metadata, and announcements" },
687
+ { label: "velar/forms", kind: 9, detail: "Form values, pending state, and accessible field errors" },
688
+ { label: "velar/http", kind: 9, detail: "Typed HTTP responses, runtime parsing, timeout, and cancellation" },
689
+ { label: "velar/storage", kind: 9, detail: "Typed local, session, scoped, observed, and IndexedDB storage" },
690
+ { label: "velar/browser", kind: 9, detail: "Browser state, cancellable timers, clipboard, media, visibility, layout, and frames" },
691
+ { label: "velar/files", kind: 9, detail: "Cross-browser file selection, reading, and downloads" },
692
+ { label: "velar/realtime", kind: 9, detail: "WebSocket and server-sent event connections" },
693
+ { label: BROWSER_TEST_MODULE, kind: 9, detail: `Restricted browser automation, imported only from a *${BROWSER_TEST_SOURCE_SUFFIX} module` },
694
+ ]),
695
+ }),
696
+ modules: Object.freeze({
697
+ apiVersion: VELAR_WEB_API_VERSION,
698
+ interfaces: webModuleInterfaces,
699
+ sources: webModuleSources,
700
+ dependencies: new Map([
701
+ ["velar/worker", ["velar/worker-manifest", "velar/task"]],
702
+ ["velar/http", ["velar/binary"]],
703
+ ["velar/storage", ["velar/binary"]],
704
+ ]),
705
+ source(specifier, projectConfig) {
706
+ return webModuleSource(specifier, (projectConfig ?? { base: "/" }));
707
+ },
708
+ }),
709
+ createEmitter(hints, forcedFunctionExports, resourceContents, extensionImports, options) {
710
+ return new WebJavaScriptEmitter(hints, forcedFunctionExports, resourceContents, extensionImports, options);
711
+ },
712
+ });
713
+ export { webModuleSource, webModuleSources };
714
+ export { velarProjectExtension } from "./project-config.js";
715
+ //# sourceMappingURL=compiler.js.map