@velarscript/web 0.29.1 → 0.30.0

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 (68) hide show
  1. package/dist/analysis/look-values.d.ts +38 -0
  2. package/dist/analysis/look-values.d.ts.map +1 -1
  3. package/dist/analysis/look-values.js +86 -0
  4. package/dist/analysis/look-values.js.map +1 -1
  5. package/dist/analysis/reactive-names.d.ts +50 -0
  6. package/dist/analysis/reactive-names.d.ts.map +1 -0
  7. package/dist/analysis/reactive-names.js +199 -0
  8. package/dist/analysis/reactive-names.js.map +1 -0
  9. package/dist/analysis/watch-cycles.d.ts +28 -0
  10. package/dist/analysis/watch-cycles.d.ts.map +1 -1
  11. package/dist/analysis/watch-cycles.js +47 -0
  12. package/dist/analysis/watch-cycles.js.map +1 -1
  13. package/dist/analyzer.d.ts +4 -0
  14. package/dist/analyzer.d.ts.map +1 -1
  15. package/dist/analyzer.js +36 -47
  16. package/dist/analyzer.js.map +1 -1
  17. package/dist/compiler.d.ts +1 -1
  18. package/dist/compiler.js +2 -2
  19. package/dist/compiler.js.map +1 -1
  20. package/dist/css-string.d.ts +4 -10
  21. package/dist/css-string.d.ts.map +1 -1
  22. package/dist/css-string.js +4 -27
  23. package/dist/css-string.js.map +1 -1
  24. package/dist/emitter.d.ts.map +1 -1
  25. package/dist/emitter.js +11 -2090
  26. package/dist/emitter.js.map +1 -1
  27. package/dist/lexer.js +63 -43
  28. package/dist/lexer.js.map +1 -1
  29. package/dist/look-static.d.ts.map +1 -1
  30. package/dist/look-static.js +20 -7
  31. package/dist/look-static.js.map +1 -1
  32. package/dist/look.d.ts +4 -4
  33. package/dist/look.d.ts.map +1 -1
  34. package/dist/look.js +4 -4
  35. package/dist/look.js.map +1 -1
  36. package/dist/runtime-sources.generated.d.ts +89 -0
  37. package/dist/runtime-sources.generated.d.ts.map +1 -0
  38. package/dist/runtime-sources.generated.js +96 -0
  39. package/dist/runtime-sources.generated.js.map +1 -0
  40. package/dist/runtime.d.ts +18 -0
  41. package/dist/runtime.d.ts.map +1 -1
  42. package/dist/runtime.js +31 -3742
  43. package/dist/runtime.js.map +1 -1
  44. package/package.json +3 -3
  45. package/dist/browser-host-runtime.d.ts +0 -23
  46. package/dist/browser-host-runtime.d.ts.map +0 -1
  47. package/dist/browser-host-runtime.js +0 -29
  48. package/dist/browser-host-runtime.js.map +0 -1
  49. package/dist/reactive-bridge-runtime.d.ts +0 -6
  50. package/dist/reactive-bridge-runtime.d.ts.map +0 -1
  51. package/dist/reactive-bridge-runtime.js +0 -114
  52. package/dist/reactive-bridge-runtime.js.map +0 -1
  53. package/dist/realtime-client-runtime.d.ts +0 -3
  54. package/dist/realtime-client-runtime.d.ts.map +0 -1
  55. package/dist/realtime-client-runtime.js +0 -382
  56. package/dist/realtime-client-runtime.js.map +0 -1
  57. package/dist/runtime-foundation.d.ts +0 -7
  58. package/dist/runtime-foundation.d.ts.map +0 -1
  59. package/dist/runtime-foundation.js +0 -1676
  60. package/dist/runtime-foundation.js.map +0 -1
  61. package/dist/websocket-runtime.d.ts +0 -2
  62. package/dist/websocket-runtime.d.ts.map +0 -1
  63. package/dist/websocket-runtime.js +0 -37
  64. package/dist/websocket-runtime.js.map +0 -1
  65. package/dist/worker-runtime.d.ts +0 -2
  66. package/dist/worker-runtime.d.ts.map +0 -1
  67. package/dist/worker-runtime.js +0 -83
  68. package/dist/worker-runtime.js.map +0 -1
package/dist/emitter.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { cssPropertyName, LOOK_ARITHMETIC_HINT, LOOK_MEDIA_LENGTH_UNITS, LOOK_PROPERTIES, LOOK_PROPERTY_KEYWORDS, LOOK_PROPERTY_VALUE_KINDS } from "./look.js";
2
2
  import { isCssDeclarationValue } from "./css-tokens.js";
3
- import { CSS_STRING_RUNTIME } from "./css-string.js";
4
3
  import { collectLookStaticValues, evaluateLookStaticExpression, isLookStaticValue, lookStaticCss } from "./look-static.js";
5
4
  import { keyframeCssValue, keyframesCanonical, keyframesName } from "./keyframes.js";
6
5
  import { JavaScriptEmitter, spanIdentity, VELAR_ERROR_NORMALIZATION_MODULE, VELAR_RUNTIME_REGISTRY_KEY } from "@velarscript/compiler/extension";
7
- import { WEB_RUNTIME_FOUNDATION, WEB_RUNTIME_FOUNDATION_SHARED_ERROR } from "./runtime-foundation.js";
6
+ import { CSS_STRING_RUNTIME_BODY, LOOK_ARITHMETIC_RUNTIME, WEB_FILE_TYPE_RUNTIME, WEB_LOCAL_REACTIVE_BRIDGE_RUNTIME, WEB_LOCAL_REACTIVE_COLLECTION_BRIDGE_RUNTIME, WEB_RUNTIME_BODY, WEB_RUNTIME_FOUNDATION, WEB_RUNTIME_FOUNDATION_SHARED_ERROR, } from "./runtime-sources.generated.js";
8
7
  import { isWebExpression, isWebJsx, isWebKeyframes, isWebLook, isWebStatement, isWebUnit, webExpressionContainsDirectAwait, webStatementContainsDirectAwait, webWatchSubjectLabel, } from "./ast.js";
9
8
  /**
10
9
  * Statements whose body is not module evaluation. A `def`, a class method, and
@@ -19,32 +18,6 @@ const DEFERRED_BODY_STATEMENT_KINDS = new Set([
19
18
  "TestDeclaration",
20
19
  "TryStatement",
21
20
  ]);
22
- const FILE_TYPE_RUNTIME = String.raw `
23
- function __velarFileTypeIs(value) {
24
- const descriptor = Object.getOwnPropertyDescriptor(globalThis, Symbol.for("velar.file.registry.v1"));
25
- if (!descriptor || !("value" in descriptor) || descriptor.configurable || descriptor.enumerable || descriptor.writable) return false;
26
- try { return WeakMap.prototype.has.call(descriptor.value, value); }
27
- catch { return false; }
28
- }
29
- `.trimStart();
30
- const WEB_LOCAL_REACTIVE_BRIDGE_RUNTIME = String.raw `
31
- const __velarReactiveRaw = __velarToRaw;
32
- function __velarHostRaw(value) { return __velarToRaw(value); }
33
- `.trimStart();
34
- const WEB_LOCAL_REACTIVE_COLLECTION_BRIDGE_RUNTIME = String.raw `
35
- const __velarReactiveIterateKey = Symbol.for("velar.reactive.iterate.v1");
36
- const __velarReactiveStructureKey = Symbol.for("velar.reactive.structure.v1");
37
- const __velarReactiveCollectionReadOperation = __velarRuntime.collectionRead;
38
- const __velarReactiveCollectionTriggerOperation = __velarRuntime.collectionTrigger;
39
- const __velarReactiveCollectionUnlinkOperation = __velarRuntime.collectionUnlink;
40
- const __velarReactiveOperation = __velarRuntime.reactive;
41
- const __velarReactiveTrackOperation = __velarRuntime.track;
42
- function __velarReactiveCollectionRead(value, key, child) { return __velarReactiveCollectionReadOperation(value, key, child === undefined ? null : child); }
43
- function __velarReactiveCollectionTrack(value, key = __velarReactiveIterateKey) { __velarReactiveTrackOperation(__velarToRaw(value), key); }
44
- function __velarReactiveCollectionLink(value, child) { __velarReactiveOperation(child, __velarToRaw(value)); }
45
- function __velarReactiveCollectionTrigger(value, key, iterate = true, structure = false, indexFrom = null, allKeys = false) { __velarReactiveCollectionTriggerOperation(value, key, iterate, structure, indexFrom, allKeys); }
46
- function __velarReactiveCollectionUnlink(value, child) { __velarReactiveCollectionUnlinkOperation(value, child); }
47
- `.trimStart();
48
21
  export class WebJavaScriptEmitter extends JavaScriptEmitter {
49
22
  currentScope = null;
50
23
  /**
@@ -155,7 +128,7 @@ export class WebJavaScriptEmitter extends JavaScriptEmitter {
155
128
  return [
156
129
  ...(this.needsLookArithmeticRuntime ? [LOOK_ARITHMETIC_RUNTIME] : []),
157
130
  ...(this.webOutput ? this.webRuntimeHelpers() : []),
158
- ...(this.needsFileTypeHelper ? [FILE_TYPE_RUNTIME] : []),
131
+ ...(this.needsFileTypeHelper ? [WEB_FILE_TYPE_RUNTIME] : []),
159
132
  ];
160
133
  }
161
134
  webRuntimeHelpers() {
@@ -1328,2067 +1301,15 @@ function containsWebSyntax(value) {
1328
1301
  return true;
1329
1302
  return Object.values(record).some((child) => Array.isArray(child) ? child.some(containsWebSyntax) : containsWebSyntax(child));
1330
1303
  }
1331
- const LOOK_ARITHMETIC_RUNTIME = String.raw `
1332
- function __velarLookDimension(value) {
1333
- if (typeof value !== "string") return null;
1334
- const match = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(px|rem|em|vw|vh|vmin|vmax|%|fr|ms|s|deg|turn)$/.exec(value);
1335
- if (!match) return null;
1336
- const number = Number(match[1]);
1337
- return Number.isFinite(number) ? { number, unit: match[2] } : null;
1338
- }
1339
-
1340
- function __velarLookNumber(value, label) {
1341
- if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(label + " must be a finite number");
1342
- return value;
1343
- }
1344
-
1345
- function __velarLookDimensionResult(number, unit) {
1346
- if (!Number.isFinite(number)) throw new RangeError("Look arithmetic must produce a finite value");
1347
- return String(Object.is(number, -0) ? 0 : number) + unit;
1348
- }
1349
-
1350
- function __velarLookConvertibleDimension(value) {
1351
- if (value.unit === "s") return { number: value.number * 1000, unit: "ms" };
1352
- if (value.unit === "turn") return { number: value.number * 360, unit: "deg" };
1353
- return value;
1354
- }
1355
-
1356
- function __velarLookUnary(operator, value) {
1357
- if (typeof value === "number") return operator === "-" ? -__velarLookNumber(value, "Look operand") : __velarLookNumber(value, "Look operand");
1358
- if (typeof value !== "string") throw new TypeError("Look unit arithmetic requires a number or typed visual value");
1359
- if (operator === "+") return value;
1360
- const dimension = __velarLookDimension(value);
1361
- if (dimension) return __velarLookDimensionResult(-dimension.number, dimension.unit);
1362
- return "calc(-1 * (" + value + "))";
1363
- }
1364
-
1365
- function __velarLookMath(operator, left, right) {
1366
- if (typeof left === "number" && typeof right === "number") {
1367
- const first = __velarLookNumber(left, "Left Look operand");
1368
- const second = __velarLookNumber(right, "Right Look operand");
1369
- if (operator === "/" && second === 0) throw new RangeError("Look division cannot use zero");
1370
- const result = operator === "+" ? first + second : operator === "-" ? first - second : operator === "*" ? first * second : first / second;
1371
- return __velarLookNumber(result, "Look arithmetic result");
1372
- }
1373
- const leftDimension = __velarLookDimension(left);
1374
- const rightDimension = __velarLookDimension(right);
1375
- if ((operator === "+" || operator === "-") && leftDimension && rightDimension) {
1376
- const first = __velarLookConvertibleDimension(leftDimension);
1377
- const second = __velarLookConvertibleDimension(rightDimension);
1378
- if (first.unit === second.unit) {
1379
- return __velarLookDimensionResult(operator === "+" ? first.number + second.number : first.number - second.number, first.unit);
1380
- }
1381
- }
1382
- if (operator === "*" && leftDimension && typeof right === "number") {
1383
- return __velarLookDimensionResult(leftDimension.number * __velarLookNumber(right, "Right Look operand"), leftDimension.unit);
1384
- }
1385
- if (operator === "*" && typeof left === "number" && rightDimension) {
1386
- return __velarLookDimensionResult(__velarLookNumber(left, "Left Look operand") * rightDimension.number, rightDimension.unit);
1387
- }
1388
- if (operator === "/" && leftDimension && typeof right === "number") {
1389
- const divisor = __velarLookNumber(right, "Right Look operand");
1390
- if (divisor === 0) throw new RangeError("Look unit division cannot use zero");
1391
- return __velarLookDimensionResult(leftDimension.number / divisor, leftDimension.unit);
1392
- }
1393
- if ((typeof left !== "string" && typeof left !== "number") || (typeof right !== "string" && typeof right !== "number")) {
1394
- throw new TypeError("Look unit arithmetic requires numbers or typed visual values");
1395
- }
1396
- return "calc(" + left + " " + operator + " " + right + ")";
1397
- }
1398
- `.trimStart();
1399
- const WEB_RUNTIME_BODY = String.raw `
1400
- function __velarReport(value, phase, scope = null, detail = "", unhandled = true) {
1401
- return __velarRuntime.report(value, { phase, detail, component: scope ? scope.component : "", unhandled });
1402
- }
1403
-
1404
- function __velarReportEvent(value, scope, detail) {
1405
- if (__velarIsError(value) && __velarGraphWeakSetRemove(__velarRuntime.actionFailures, value)) return null;
1406
- return __velarReport(value, "event", scope, detail);
1407
- }
1408
-
1409
- const __velarWebIterateKey = Symbol.for("velar.reactive.iterate.v1");
1410
- const __velarWebNativeJson = globalThis.JSON;
1411
- const __velarWebJsonText = Object.getOwnPropertyDescriptor(__velarWebNativeJson, "stringify")?.value;
1412
- const __velarEventReflectApply = Object.getOwnPropertyDescriptor(Reflect, "apply")?.value;
1413
- const __velarEventConstructorDescriptor = Object.getOwnPropertyDescriptor(globalThis, "Event");
1414
- const __velarEventConstructor = __velarEventConstructorDescriptor && "value" in __velarEventConstructorDescriptor ? __velarEventConstructorDescriptor.value : null;
1415
- const __velarEventPrototype = typeof __velarEventConstructor === "function" ? Object.getOwnPropertyDescriptor(__velarEventConstructor, "prototype")?.value : null;
1416
- const __velarEventTargetGetter = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "target")?.get;
1417
- const __velarEventPreventDefault = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "preventDefault")?.value;
1418
- const __velarEventStopPropagation = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "stopPropagation")?.value;
1419
- const __velarEventMissingField = __velarGraphFreeze({});
1420
- function __velarQuotedText(value) {
1421
- return __velarGraphApply(__velarWebJsonText, __velarWebNativeJson, [value], "JSON.stringify");
1422
- }
1423
- function __velarAppendOwned(values, value) {
1424
- values[values.length] = value;
1425
- return value;
1426
- }
1427
- function __velarHasName(values, name) {
1428
- for (let index = 0; index < values.length; index += 1) if (values[index] === name) return true;
1429
- return false;
1430
- }
1431
- function __velarEventField(value, name, nativeGetter) {
1432
- if (typeof nativeGetter === "function" && typeof __velarEventReflectApply === "function") {
1433
- try { return __velarEventReflectApply(nativeGetter, value, []); } catch {}
1434
- }
1435
- if (value === null || (typeof value !== "object" && typeof value !== "function")) return __velarEventMissingField;
1436
- const descriptor = __velarGraphOwnDescriptor(value, name);
1437
- return descriptor?.enumerable && "value" in descriptor ? descriptor.value : __velarEventMissingField;
1438
- }
1439
- function __velarEventCall(value, name, nativeMethod) {
1440
- if (typeof nativeMethod === "function" && typeof __velarEventReflectApply === "function") {
1441
- try { return __velarEventReflectApply(nativeMethod, value, []); } catch {}
1442
- }
1443
- const method = __velarEventField(value, name, null);
1444
- if (typeof method !== "function" || typeof __velarEventReflectApply !== "function") throw new TypeError("DOM event does not expose native " + name);
1445
- return __velarEventReflectApply(method, value, []);
1446
- }
1447
-
1448
- function __velarTrack(subscribers) {
1449
- __velarRuntime.trackSubscribers(subscribers);
1450
- }
1451
-
1452
- function __velarToRaw(value) { return __velarRuntime.toRaw(value); }
1453
- function __velarReactive(value, parent = null) { return __velarRuntime.reactive(value, parent); }
1454
-
1455
- function __velarWebListPop(value, requested = -1) {
1456
- return __velarReactive(__velarListPop(value, requested));
1457
- }
1458
-
1459
- function __velarUntracked(read) {
1460
- const previous = __velarRuntime.activeObserver;
1461
- __velarRuntime.activeObserver = null;
1462
- try { return read(); } finally { __velarRuntime.activeObserver = previous; }
1463
- }
1464
-
1465
- function __velarCleanupObserver(observer) {
1466
- __velarRuntime.cleanupObserver(observer);
1467
- }
1468
-
1469
- // P2b-9: a self-invalidating render used to report only that it happened. The
1470
- // stack top was the graph's own trigger, so it named neither the collection
1471
- // being written nor the scope reading it, and the distance between symptom and
1472
- // cause was the whole debugging cost. Everything below is already known where
1473
- // the budget trips: the observer carries its component and its watch subject,
1474
- // and the graph has just recorded which path re-triggered it. Naming the write
1475
- // is the difference between bisecting a render and reading one line.
1476
- //
1477
- // The advice is attached to the shape that earns it. A "collection" subject
1478
- // means a collection was read for its size or contents and then written in the
1479
- // same pass, and the two spellings that end it are the same two every time:
1480
- // take the position from the loop instead of from the collection, or read the
1481
- // value out before writing. The kind arrives beside the phrase, so nothing here
1482
- // reads a sentence back apart to decide.
1483
- function __velarSelfInvalidationMessage(mode, component, label, subject, kind) {
1484
- let message = "A reactive " + mode + " cannot invalidate itself more than 100 times";
1485
- if (component) message += " (" + component + ")";
1486
- else if (label) message += " (watching " + label + ")";
1487
- if (!subject) return message;
1488
- message += ": it writes " + subject + " while reading it";
1489
- if (kind === "collection") {
1490
- return message + ". A position taken from the collection being written -- 'items.get(built.size)' inside the loop that appends to 'built' -- reads it on every pass; take the position from a two-slot 'for value, index in ...' instead, or read what you need into a binding before the loop.";
1491
- }
1492
- return message + ". Read it into a binding before the code that writes it, so the write cannot reach the read that tracked it.";
1493
- }
1494
-
1495
- // D90 R21: "label" names the observer in a report -- a watch carries its
1496
- // subject as the author spelled it -- and "sequence" is its registration
1497
- // number, which is the order the flush runs the watch tier in. The counter is
1498
- // application-wide rather than per module, so two modules' watches order by the
1499
- // order the two modules initialized.
1500
- function __velarObserver(read, mode, scope, label = "") {
1501
- // The first run of a DOM observer executes while its JSX position is being
1502
- // constructed, and construction is transactional: the failure must reach
1503
- // the surrounding owner (the mount transaction at the root, the containing
1504
- // child position otherwise) so the promised fatal state or contained
1505
- // placeholder appears instead of a silently empty region. Later runs are
1506
- // updates; their failures are reported and the last valid DOM survives.
1507
- let initial = mode === "dom";
1508
- const observer = {
1509
- mode,
1510
- label,
1511
- sequence: __velarNextObserverSequence(),
1512
- component: scope !== null && scope !== undefined && typeof scope.component === "string" ? scope.component : "",
1513
- stopped: false,
1514
- running: false,
1515
- selfInvalidations: 0,
1516
- // P2b-9: the reactive path whose write landed while this observer was
1517
- // reading. The graph fills it in only on a self-invalidating write, so the
1518
- // runaway report can name what to go and look at.
1519
- selfInvalidationSubject: "",
1520
- selfInvalidationKind: "",
1521
- dependencies: __velarGraphCreateSet(),
1522
- run() {
1523
- if (observer.stopped) return;
1524
- observer.running = true;
1525
- try { __velarRuntime.runTracked(observer, read); }
1526
- catch (error) {
1527
- if (initial) throw error;
1528
- __velarReport(error, mode === "watch" ? "watch" : "render", scope);
1529
- }
1530
- finally {
1531
- observer.running = false;
1532
- initial = false;
1533
- }
1534
- },
1535
- notify() {
1536
- if (observer.stopped) return;
1537
- if (observer.running) {
1538
- observer.selfInvalidations += 1;
1539
- if (observer.selfInvalidations > 100) {
1540
- observer.stop();
1541
- __velarReport(new RangeError(__velarSelfInvalidationMessage(
1542
- mode === "watch" ? "watch" : "render",
1543
- observer.component,
1544
- observer.label,
1545
- observer.selfInvalidationSubject,
1546
- observer.selfInvalidationKind,
1547
- )), mode === "watch" ? "watch" : "render", scope);
1548
- return;
1549
- }
1550
- } else {
1551
- observer.selfInvalidations = 0;
1552
- }
1553
- // The registry owns the one scheduler: the emitted prelude used to carry
1554
- // its own copy of the queue insert and the flush drain, and the two
1555
- // definitions of one concept is what let a watch be classified three
1556
- // different ways. The capability observers in packages/web/src/runtime.ts
1557
- // have always scheduled this way.
1558
- __velarRuntime.schedule(observer);
1559
- },
1560
- stop() { observer.stopped = true; __velarCleanupObserver(observer); },
1561
- };
1562
- __velarAppendOwned(scope.cleanups, () => observer.stop());
1563
- observer.run();
1564
- return observer;
1565
- }
1566
-
1567
- // D70 rule 180: a reactive source read during component setup and stored in a
1568
- // plain binding is frozen. That is what const means, and a snapshot is a
1569
- // legitimate thing to want -- so the report fires when the source *diverges*
1570
- // from the snapshot, never when the snapshot is taken. A warning that fires on
1571
- // correct code is a warning people learn to ignore; one that fires only after
1572
- // the value on screen has actually gone stale cannot be wrong about that.
1573
- //
1574
- // The whole mechanism is installed only when the development host published its
1575
- // hooks, so a production build pays nothing for it: no map, no stack capture,
1576
- // and one already-false constant on the read path.
1577
- // One module's copy of this runtime cannot own the state: a component in one
1578
- // module reads a cell created in another, so the setup stack and the recorded
1579
- // reads live on the shared hooks object every copy sees.
1580
- const __velarFrozenHooks = (() => {
1581
- const hooks = globalThis.__velarDevelopmentHooks;
1582
- if (!hooks || typeof hooks.frozenRead !== "function") return null;
1583
- if (hooks.setupScopes === undefined) {
1584
- hooks.setupScopes = [];
1585
- hooks.reads = __velarGraphCreateWeakMap();
1586
- hooks.derived = [];
1587
- hooks.internalDepth = 0;
1588
- }
1589
- return hooks;
1590
- })();
1591
- const __velarFrozenReadLimit = 32;
1592
-
1593
- function __velarSetupBegin(scope) {
1594
- if (__velarFrozenHooks) __velarAppendOwned(__velarFrozenHooks.setupScopes, scope);
1595
- return scope;
1596
- }
1597
-
1598
- function __velarSetupEnd(value) {
1599
- if (__velarFrozenHooks && __velarFrozenHooks.setupScopes.length > 0) __velarFrozenHooks.setupScopes.length -= 1;
1600
- return value;
1601
- }
1602
-
1603
- // The framework's own reads on the author's behalf -- checking a prop is
1604
- // present, building the content a children slot holds, reading a handler
1605
- // thunk. None of them freezes anything the author wrote: the
1606
- // prop handle behind them stays live. Reporting them would be the false-positive
1607
- // flood D70 rule 180 rejected, in its most literal form.
1608
- function __velarInternalRead(read) {
1609
- if (!__velarFrozenHooks) return __velarUntracked(read);
1610
- __velarFrozenHooks.internalDepth += 1;
1611
- try { return __velarUntracked(read); } finally { __velarFrozenHooks.internalDepth -= 1; }
1612
- }
1613
-
1614
- function __velarRecordFrozenRead(cell, value) {
1615
- if (!__velarFrozenHooks) return;
1616
- if (__velarFrozenHooks.setupScopes.length === 0 || __velarFrozenHooks.internalDepth > 0) return;
1617
- if (__velarRuntime.activeObserver !== null) return;
1618
- // Only a value the reader can show is worth naming in the report; an object
1619
- // read out of setup is followed through the deep graph, not frozen by this
1620
- // read, so recording it would produce a report about the wrong thing.
1621
- if (value !== null && typeof value === "object") return;
1622
- const scope = __velarFrozenHooks.setupScopes[__velarFrozenHooks.setupScopes.length - 1];
1623
- const existing = __velarGraphWeakMapRead(__velarFrozenHooks.reads, cell);
1624
- if (existing) {
1625
- if (existing.length >= __velarFrozenReadLimit) return;
1626
- __velarAppendOwned(existing, { value, scope, site: new Error("velar frozen read") });
1627
- return;
1628
- }
1629
- __velarGraphWeakMapWrite(__velarFrozenHooks.reads, cell, [{ value, scope, site: new Error("velar frozen read") }]);
1630
- }
1631
-
1632
- // A derived value frozen during setup has no cell to hang a report on, and a
1633
- // read that left no subscriber is a read the cache never tells anything about.
1634
- // So the entries are kept in one dev-mode list and re-read after a state write
1635
- // -- the only thing that can move a derived value -- which is the same
1636
- // "report on divergence" rule the cells follow, reached the only way it can be.
1637
- function __velarRecordFrozenDerived(access, value) {
1638
- if (!__velarFrozenHooks) return;
1639
- if (__velarFrozenHooks.setupScopes.length === 0 || __velarFrozenHooks.internalDepth > 0) return;
1640
- if (__velarRuntime.activeObserver !== null) return;
1641
- if (value !== null && typeof value === "object") return;
1642
- if (__velarFrozenHooks.derived.length >= __velarFrozenReadLimit * 4) return;
1643
- const scope = __velarFrozenHooks.setupScopes[__velarFrozenHooks.setupScopes.length - 1];
1644
- __velarAppendOwned(__velarFrozenHooks.derived, { access, value, scope, site: new Error("velar frozen read") });
1645
- }
1646
-
1647
- function __velarReportFrozenDerived() {
1648
- if (!__velarFrozenHooks || __velarFrozenHooks.derived.length === 0) return;
1649
- const entries = __velarFrozenHooks.derived;
1650
- const remaining = [];
1651
- for (let index = 0; index < entries.length; index += 1) {
1652
- const entry = entries[index];
1653
- let current = entry.value;
1654
- let failed = false;
1655
- try { current = __velarUntracked(entry.access); }
1656
- catch { failed = true; }
1657
- if (failed || __velarGraphSame(entry.value, current)) { remaining[remaining.length] = entry; continue; }
1658
- __velarPublishFrozenRead(entry, current);
1659
- }
1660
- __velarFrozenHooks.derived = remaining;
1661
- }
1662
-
1663
- function __velarReportFrozenReads(cell, next) {
1664
- if (!__velarFrozenHooks) return;
1665
- __velarReportFrozenDerived();
1666
- const entries = __velarGraphWeakMapRead(__velarFrozenHooks.reads, cell);
1667
- if (!entries) return;
1668
- __velarGraphWeakMapRemove(__velarFrozenHooks.reads, cell);
1669
- for (let index = 0; index < entries.length; index += 1) {
1670
- if (__velarGraphSame(entries[index].value, next)) continue;
1671
- __velarPublishFrozenRead(entries[index], next);
1672
- }
1673
- }
1674
-
1675
- function __velarPublishFrozenRead(entry, next) {
1676
- const component = entry.scope && entry.scope.component ? entry.scope.component : "a component";
1677
- __velarFrozenHooks.frozenRead({
1678
- message: "A reactive value read while " + component + " was being built was frozen at "
1679
- + __velarFrozenText(entry.value) + ", and the source has now changed to " + __velarFrozenText(next)
1680
- + ". Whatever was built from that read still shows the old value. If it is meant to follow, declare it with 'computed name = <expression>'; if the snapshot was intended, nothing here needs changing.",
1681
- stack: __velarDomString(entry.site && entry.site.stack ? entry.site.stack : ""),
1682
- });
1683
- }
1684
-
1685
- function __velarFrozenText(value) {
1686
- return typeof value === "string" ? __velarQuotedText(value) : __velarDomString(value);
1687
- }
1688
-
1689
- // "name" is the declared name an author "state" wrote, carried on the cell and
1690
- // visible in the emitted source. The cells __velarResource and __velarAction
1691
- // build for their own pending/error fields are created without one, because
1692
- // they are the runtime's bookkeeping rather than state anyone declared.
1693
- //
1694
- // D90 R21: nothing read it any more. It existed for the two watch referees --
1695
- // only a cell with a declared name could be a declared write target -- and they
1696
- // went with the clause. It was left in place rather than removed with them,
1697
- // because it is a fact about the cell rather than a mechanism, and it is what a
1698
- // report naming the state a runaway wrote would have to read. D114 0.28.0 H-U1
1699
- // is that report: __velarSelfInvalidationWrite below reads it.
1700
- function __velarState(initial, name) {
1701
- let value = __velarToRaw(initial);
1702
- const subscribers = __velarGraphCreateSet();
1703
- const cell = {
1704
- velarStateName: name,
1705
- // Named rather than shorthand so a captured stack shows a compiler frame
1706
- // here: D70's report walks past its own frames to find the reading line,
1707
- // and every JavaScript engine spells an anonymous getter differently.
1708
- get: function __velarCellRead() {
1709
- __velarTrack(subscribers);
1710
- const current = __velarReactive(value, cell);
1711
- __velarRecordFrozenRead(cell, current);
1712
- return current;
1713
- },
1714
- set(next) {
1715
- next = __velarToRaw(next);
1716
- if (__velarGraphSame(value, next)) return next;
1717
- const previous = value;
1718
- value = next;
1719
- __velarReportFrozenReads(cell, next);
1720
- // Keep deep-change bubbling attached only to the value currently owned
1721
- // by this cell. Otherwise every replaced object remains linked to the
1722
- // state cell and continues to occupy the parent graph indefinitely.
1723
- __velarRuntime.collectionUnlink(cell, previous);
1724
- __velarReactive(value, cell);
1725
- for (const observer of __velarGraphSetItems(subscribers)) {
1726
- __velarSelfInvalidationWrite(observer, name);
1727
- observer.notify();
1728
- }
1729
- return next;
1730
- },
1731
- };
1732
- __velarReactive(value, cell);
1733
- return cell;
1734
- }
1735
-
1736
- // D114 0.28.0 H-U1: a state cell notifies its own subscriber set rather than
1737
- // going through the graph's keyed notify, so the write path the runaway report
1738
- // names was recorded for every deep write and for no write of a declared
1739
- // state -- and a scalar self-write only ever reaches the 100-round cap through
1740
- // a helper, which is why the gap read as "a write through a plain def". The
1741
- // condition is the graph's own, verbatim: a write that lands while its own
1742
- // reader is still running is the self-invalidating shape, and it is the only
1743
- // one worth describing. A cell with no declared name is runtime bookkeeping --
1744
- // __velarResource and __velarAction build theirs that way -- so it falls back
1745
- // to the same phrase describeSubject uses for a place it cannot name.
1746
- function __velarSelfInvalidationWrite(observer, name) {
1747
- if (!observer.running) return;
1748
- observer.selfInvalidationSubject = name ? "state '" + name + "'" : "a tracked value";
1749
- observer.selfInvalidationKind = "value";
1750
- }
1751
-
1752
- // D71 rule 182: a declared derived value reads bare, so it presents the same
1753
- // .get() face a state cell does. The cache underneath is the runtime's own
1754
- // memo; only the face it is read through differs.
1755
- function __velarComputed(read) {
1756
- const access = __velarRuntime.computed(read);
1757
- if (!__velarFrozenHooks) return __velarGraphFreeze({ get: access });
1758
- return __velarGraphFreeze({
1759
- get: function __velarDerivedRead() {
1760
- const value = access();
1761
- __velarRecordFrozenDerived(access, value);
1762
- return value;
1763
- },
1764
- });
1765
- }
1766
-
1767
- const __velarManagedAsyncNativePromise = globalThis.Promise;
1768
- const __velarManagedAsyncPromisePrototype = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "prototype")?.value;
1769
- const __velarManagedAsyncResolveOperation = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "resolve")?.value;
1770
- const __velarManagedAsyncRejectOperation = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "reject")?.value;
1771
- const __velarManagedAsyncThenOperation = __velarManagedAsyncPromisePrototype
1772
- ? __velarGraphOwnDescriptor(__velarManagedAsyncPromisePrototype, "then")?.value
1773
- : null;
1774
- function __velarManagedAsyncResolve(value) {
1775
- return __velarGraphApply(__velarManagedAsyncResolveOperation, __velarManagedAsyncNativePromise, [value], "Promise.resolve");
1776
- }
1777
- function __velarManagedAsyncReject(error) {
1778
- return __velarGraphApply(__velarManagedAsyncRejectOperation, __velarManagedAsyncNativePromise, [error], "Promise.reject");
1779
- }
1780
- function __velarManagedAsyncThen(value, fulfilled, rejected) {
1781
- return __velarGraphApply(__velarManagedAsyncThenOperation, value, [fulfilled, rejected], "Promise.then");
1782
- }
1783
- function __velarManagedAsyncCreate(executor) {
1784
- if (typeof __velarManagedAsyncNativePromise !== "function") throw new TypeError("The JavaScript Promise API is unavailable");
1785
- return new __velarManagedAsyncNativePromise(executor);
1786
- }
1787
-
1788
- function __velarResource(load, scope, name) {
1789
- const value = __velarState(null);
1790
- const loading = __velarState(true);
1791
- const ready = __velarState(false);
1792
- const error = __velarState(null);
1793
- let generation = 0;
1794
- let started = false;
1795
- let disposed = false;
1796
-
1797
- const reload = () => {
1798
- if (disposed) return __velarManagedAsyncResolve(null);
1799
- started = true;
1800
- const current = ++generation;
1801
- loading.set(true);
1802
- error.set(null);
1803
- return __velarManagedAsyncThen(__velarManagedAsyncThen(__velarManagedAsyncResolve(), load),
1804
- (next) => {
1805
- if (disposed || current !== generation) return null;
1806
- value.set(next);
1807
- ready.set(true);
1808
- loading.set(false);
1809
- return null;
1810
- },
1811
- (failure) => {
1812
- if (disposed || current !== generation) return null;
1813
- const report = __velarRuntime.report(failure, { phase: "resource", detail: name, component: scope.component, unhandled: false });
1814
- error.set(report.error);
1815
- ready.set(true);
1816
- loading.set(false);
1817
- return null;
1818
- },
1819
- );
1820
- };
1821
-
1822
- __velarAppendOwned(scope.mounts, () => started ? null : reload());
1823
- __velarAppendOwned(scope.cleanups, () => { disposed = true; generation += 1; });
1824
- return __velarGraphFreeze({
1825
- get value() { return value.get(); },
1826
- get loading() { return loading.get(); },
1827
- get ready() { return ready.get(); },
1828
- get error() { return error.get(); },
1829
- reload,
1830
- });
1831
- }
1832
-
1833
- function __velarAction(execute, scope, name) {
1834
- const pending = __velarState(false);
1835
- const error = __velarState(null);
1836
- let active = 0;
1837
- let generation = 0;
1838
- let disposed = false;
1839
-
1840
- const run = (...arguments_) => {
1841
- // D114 W2: the one place an action call enters the runtime. An action
1842
- // started from inside an observer run is asynchronous work that observer
1843
- // started, so the reactive window carries into the flush its completion
1844
- // schedules; started from anywhere else it records nothing.
1845
- __velarNoteAsyncWork();
1846
- if (disposed) return __velarManagedAsyncReject(__velarNormalizeError(
1847
- "Action '" + name + "' cannot run after its component is destroyed",
1848
- ));
1849
- const current = ++generation;
1850
- active += 1;
1851
- pending.set(true);
1852
- error.set(null);
1853
- return __velarManagedAsyncThen(__velarManagedAsyncThen(__velarManagedAsyncResolve(), () => __velarGraphApply(execute, null, arguments_, "action body")),
1854
- (value) => {
1855
- active -= 1;
1856
- if (!disposed) pending.set(active > 0);
1857
- return value;
1858
- },
1859
- (failure) => {
1860
- active -= 1;
1861
- let actionError = __velarNormalizeError(failure);
1862
- if (!disposed) {
1863
- pending.set(active > 0);
1864
- // Every action failure reports exactly once, through the action
1865
- // phase, carrying the action's name as its detail -- including a
1866
- // failure superseded by a newer call. Only the newest generation
1867
- // owns the public error field. The actionFailures mark lets the
1868
- // event and detached observers of the same rejection skip an
1869
- // already-reported failure instead of reporting it a second time.
1870
- const report = __velarRuntime.report(failure, { phase: "action", detail: name, component: scope.component, unhandled: false });
1871
- actionError = report.error;
1872
- __velarGraphWeakSetInsert(__velarRuntime.actionFailures, actionError);
1873
- if (current === generation) error.set(report.error);
1874
- }
1875
- throw actionError;
1876
- },
1877
- );
1878
- };
1879
-
1880
- __velarGraphDefine(run, "pending", { enumerable: true, get: () => pending.get() });
1881
- __velarGraphDefine(run, "error", { enumerable: true, get: () => error.get() });
1882
- __velarAppendOwned(scope.cleanups, () => { disposed = true; generation += 1; });
1883
- return __velarGraphFreeze(run);
1884
- }
1885
-
1886
- function __velarScope(component = "") {
1887
- return { cleanups: [], mounts: [], mounted: false, component };
1888
- }
1889
-
1890
- const __velarGlobalScope = __velarScope();
1891
-
1892
- function __velarMountScope(scope) {
1893
- if (scope.mounted) return;
1894
- scope.mounted = true;
1895
- for (let index = 0; index < scope.mounts.length; index += 1) {
1896
- try {
1897
- const result = __velarUntracked(scope.mounts[index]);
1898
- __velarObservePromise(result, (error) => __velarReport(error, "mounted", scope));
1899
- } catch (error) { __velarReport(error, "mounted", scope); }
1900
- }
1901
- }
1902
-
1903
- function __velarDestroyScope(scope) {
1904
- for (let index = scope.cleanups.length - 1; index >= 0; index -= 1) {
1905
- // A reentrant destroy can empty the list underneath this walk; a missing
1906
- // slot means the step already ran and must not run again.
1907
- const cleanup = scope.cleanups[index];
1908
- if (typeof cleanup !== "function") continue;
1909
- try {
1910
- const result = __velarUntracked(cleanup);
1911
- __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
1912
- } catch (error) { __velarReport(error, "cleanup", scope); }
1913
- }
1914
- scope.cleanups.length = 0;
1915
- }
1916
-
1917
- function __velarCleanupStep(run, scope) {
1918
- try {
1919
- const result = __velarUntracked(run);
1920
- __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
1921
- } catch (error) { __velarReport(error, "cleanup", scope); }
1922
- }
1923
-
1924
- // D90 R21: nothing here asks whether this watch writes. Execution order is
1925
- // source order, so the only thing the flush needs of a watch is when it was
1926
- // registered, and __velarObserver stamps that on it. The label is the subject
1927
- // as the author spelled it, carried so a runaway flush can name the watches
1928
- // that ran away.
1929
- function __velarWatch(read, callback, scope, label = "") {
1930
- let current;
1931
- let currentVersion = 0;
1932
- let initialized = false;
1933
- let observer = null;
1934
- observer = __velarObserver(() => {
1935
- const next = read();
1936
- __velarRuntime.trackDeep(next);
1937
- const nextVersion = __velarRuntime.versionOf(next);
1938
- if (initialized && (!__velarGraphSame(next, current) || nextVersion !== currentVersion)) {
1939
- // The body is the author's effect, not part of the watched expression:
1940
- // its own reactive reads must never become dependencies of what is being
1941
- // watched, or one write re-evaluates the expression twice and an
1942
- // unwatched value re-runs the watch.
1943
- __velarUntracked(() => callback(next, current));
1944
- }
1945
- current = next;
1946
- currentVersion = nextVersion;
1947
- initialized = true;
1948
- }, "watch", scope, label);
1949
- }
1950
-
1951
- function __velarComponentHandle(value, componentName) {
1952
- if (value === null || typeof value !== "object") throw new TypeError("Component " + componentName + " must expose an ordinary Handle record");
1953
- const prototype = __velarGraphPrototype(value);
1954
- if (prototype !== __velarGraphPrototype({}) && prototype !== null) throw new TypeError("Component " + componentName + " must expose an ordinary Handle record");
1955
- const output = {};
1956
- let active = true;
1957
- const names = __velarGraphOwnNames(value);
1958
- for (let index = 0; index < names.length; index += 1) {
1959
- const name = names[index];
1960
- const descriptor = __velarGraphOwnDescriptor(value, name);
1961
- if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) throw new TypeError("Component " + componentName + " Handle fields must be enumerable data values");
1962
- const member = typeof descriptor.value === "function"
1963
- ? (...arguments_) => {
1964
- if (!active) throw new Error("Component " + componentName + " Handle is no longer active");
1965
- return __velarGraphApply(descriptor.value, null, arguments_, "component Handle method");
1966
- }
1967
- : descriptor.value;
1968
- __velarGraphDefine(output, name, { enumerable: true, value: member });
1969
- }
1970
- return __velarGraphFreeze({
1971
- value: __velarGraphFreeze(output),
1972
- revoke() { active = false; },
1973
- });
1974
- }
1975
-
1976
- function __velarComponent(node, scope, mounted, cleanup, handleState) {
1977
- let destroyed = false;
1978
- const refCleanups = [];
1979
- const ownedNodes = node && __velarDomNodeType(node) === 11 ? __velarDomChildNodes(node) : [node];
1980
- // An enclosing component forwards to a nested component's host only when that
1981
- // component's root sits at its own root level. Marking the nodes here is what
1982
- // lets the enclosing scan walk past a nested host buried inside one of its
1983
- // own elements instead of counting it as a second host of its own.
1984
- for (let index = 0; index < ownedNodes.length; index += 1) {
1985
- if (ownedNodes[index] && __velarDomNodeType(ownedNodes[index]) === 1) {
1986
- __velarGraphDefine(ownedNodes[index], "__velarComponentNode", { value: true, enumerable: true, configurable: true });
1987
- }
1988
- }
1989
- if (mounted) __velarAppendOwned(scope.mounts, mounted);
1990
- return {
1991
- __velarComponent: true,
1992
- node,
1993
- __bindRef(setRef) {
1994
- if (!handleState) throw new TypeError("This component does not expose a Handle");
1995
- const handle = handleState.value;
1996
- let bound = true;
1997
- setRef(handle, undefined);
1998
- __velarAppendOwned(refCleanups, () => {
1999
- if (!bound) return;
2000
- bound = false;
2001
- setRef(null, handle);
2002
- });
2003
- return null;
2004
- },
2005
- mount(target, before = null) {
2006
- if (destroyed) throw new Error("Cannot mount a destroyed VelarScript component");
2007
- if (scope.mounted) throw new Error("Cannot mount a VelarScript component more than once");
2008
- const parent = typeof target === "string" ? __velarDomQuerySelector(target) : target;
2009
- if (!parent) throw new Error("VelarScript mount target was not found");
2010
- __velarDomInsertBefore(parent, node, before);
2011
- __velarMountScope(scope);
2012
- return null;
2013
- },
2014
- __mount() { if (!destroyed) __velarMountScope(scope); },
2015
- destroy(remove = true) {
2016
- if (destroyed) return null;
2017
- destroyed = true;
2018
- for (let index = refCleanups.length - 1; index >= 0; index -= 1) refCleanups[index]();
2019
- refCleanups.length = 0;
2020
- if (handleState) handleState.revoke();
2021
- if (cleanup) {
2022
- try {
2023
- const result = __velarUntracked(cleanup);
2024
- __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
2025
- } catch (error) { __velarReport(error, "cleanup", scope); }
2026
- }
2027
- __velarDestroyScope(scope);
2028
- if (remove) for (let index = 0; index < ownedNodes.length; index += 1) __velarDomRemove(ownedNodes[index]);
2029
- return null;
2030
- },
2031
- };
2032
- }
2033
-
2034
- function __velarScopeComponentRoot(node, attribute) {
2035
- if (!attribute || !node) return;
2036
- if (__velarDomNodeType(node) === 1) {
2037
- __velarDomSetAttribute(node, attribute, "");
2038
- return;
2039
- }
2040
- if (__velarDomNodeType(node) === 11) {
2041
- const children = __velarDomChildNodes(node);
2042
- for (let index = 0; index < children.length; index += 1) {
2043
- if (__velarDomNodeType(children[index]) === 1) __velarDomSetAttribute(children[index], attribute, "");
2044
- }
2045
- }
2046
- }
2047
-
2048
- function __velarUseComponent(instance, scope, parentStyleScope = "") {
2049
- __velarScopeComponentRoot(instance.node, parentStyleScope);
2050
- __velarAppendOwned(scope.mounts, () => instance.__mount());
2051
- __velarAppendOwned(scope.cleanups, () => instance.destroy(false));
2052
- return instance.node;
2053
- }
2054
-
2055
- function __velarFatal(parent, error) {
2056
- const fallback = __velarDomCreateElement("section");
2057
- __velarDomSetAttribute(fallback, "role", "alert");
2058
- __velarDomSetAttribute(fallback, "data-velar-fatal", "");
2059
- __velarDomSetText(fallback, "The application could not start: " + error.message);
2060
- __velarDomReplaceChildren(parent, fallback);
2061
- }
2062
-
2063
- // Whether any root has actually mounted, which is the whole question the
2064
- // deferred module failure below has to answer: the no-blank-page promise is
2065
- // about a page with nothing on it, and a page that already has an application
2066
- // on it is not one the fatal state may replace.
2067
- let __velarMountedRoot = false;
2068
-
2069
- // A component element built while the module evaluates sits outside every
2070
- // transaction the runtime owns, so a construction throw there used to escape
2071
- // module evaluation and leave the page blank -- the one initial-render path the
2072
- // promise did not cover. The failure is caught into this value instead, and the
2073
- // module keeps evaluating so the '@main' region still runs: that is where the
2074
- // error handlers are installed and where 'mount' is called, and reporting ahead
2075
- // of both would report to nobody.
2076
- function __velarModuleInstantiate(component, thunks, children, scope, namespace, setRef) {
2077
- try {
2078
- return __velarInstantiate(component, thunks, children, scope, namespace, setRef);
2079
- } catch (error) {
2080
- const failure = { error, surfaced: false };
2081
- // The mount that takes this root surfaces the failure at its own target.
2082
- // Nothing having taken it by the first microtask means nothing ever will,
2083
- // and a root that was built to be mounted and never was is still a blank
2084
- // page: it surfaces there instead, into the document body.
2085
- __velarEnqueue(() => __velarSurfaceModuleFailure(failure, null));
2086
- return { __velarModuleFailure: failure };
2087
- }
2088
- }
2089
-
2090
- function __velarSurfaceModuleFailure(failure, parent) {
2091
- if (failure.surfaced) return null;
2092
- failure.surfaced = true;
2093
- // The phase is 'mount' because this is the same failure 'mount(<App />, ...)'
2094
- // reports under that phase; the two spellings of one root differ in where the
2095
- // element is written, not in what went wrong.
2096
- const report = __velarReport(failure.error, "mount", null);
2097
- try {
2098
- const target = parent ?? (__velarMountedRoot ? null : __velarDomQuerySelector("body"));
2099
- if (target) __velarFatal(target, report.error);
2100
- } catch {}
2101
- return null;
2102
- }
2103
-
2104
- function __velarMount(evaluate, fallbackTarget = null) {
2105
- let values;
2106
- try {
2107
- values = evaluate();
2108
- } catch (failure) {
2109
- const report = __velarReport(failure, "mount", null);
2110
- if (fallbackTarget !== null) {
2111
- try {
2112
- const fallback = __velarDomQuerySelector(fallbackTarget);
2113
- if (fallback) __velarFatal(fallback, report.error);
2114
- } catch {}
2115
- }
2116
- return null;
2117
- }
2118
- const value = values[0];
2119
- const target = values[1];
2120
- const parent = typeof target === "string" ? __velarDomQuerySelector(target) : target;
2121
- // A root whose construction failed while the module evaluated is answered
2122
- // here, ahead of the missing-target question: the construction failure is the
2123
- // cause, and reporting the target instead would name a symptom. The target
2124
- // still decides where the fatal state renders, and a missing one falls back
2125
- // to the document body exactly as it does below.
2126
- if (value && value.__velarModuleFailure) {
2127
- __velarSurfaceModuleFailure(value.__velarModuleFailure, parent || null);
2128
- return null;
2129
- }
2130
- if (!parent) {
2131
- // A missing mount target must keep the no-blank-page promise in every
2132
- // build: the failure is reported through velar/app and the fatal state
2133
- // renders into the document body, since the requested target is exactly
2134
- // what does not exist.
2135
- const report = __velarReport(new Error("VelarScript mount target was not found"), "mount", null);
2136
- try {
2137
- const body = __velarDomQuerySelector("body");
2138
- if (body) __velarFatal(body, report.error);
2139
- } catch {}
2140
- return null;
2141
- }
2142
- try {
2143
- if (value && value.__velarComponent) {
2144
- const result = value.mount(parent);
2145
- if (__velarGraphIsList(globalThis.__velarHotDisposers)) __velarAppendOwned(globalThis.__velarHotDisposers, () => value.destroy());
2146
- __velarMountedRoot = true;
2147
- return result;
2148
- }
2149
- __velarAppend(parent, value);
2150
- __velarMountScope(__velarGlobalScope);
2151
- __velarMountedRoot = true;
2152
- return null;
2153
- } catch (failure) {
2154
- const report = __velarReport(failure, "mount", null);
2155
- __velarFatal(parent, report.error);
2156
- return null;
2157
- }
2158
- }
2159
-
2160
- const __velarSvgNamespace = "http://www.w3.org/2000/svg";
2161
- const __velarXlinkNamespace = "http://www.w3.org/1999/xlink";
2162
- const __velarXmlNamespace = "http://www.w3.org/XML/1998/namespace";
2163
-
2164
- function __velarCreateElement(tag, namespace) {
2165
- return namespace === "svg" || tag === "svg"
2166
- ? __velarDomCreateElementNS(__velarSvgNamespace, tag)
2167
- : __velarDomCreateElement(tag);
2168
- }
2169
-
2170
- function __velarListSnapshot(value, name) {
2171
- value = __velarToRaw(value);
2172
- __velarRuntime.collectionRead(value, __velarWebIterateKey, undefined);
2173
- return __velarDomListSnapshot(value, name);
2174
- }
2175
-
2176
- function __velarAppend(parent, value, state = null) {
2177
- state ??= { active: __velarDomCreateSet(), depth: 0, values: 0, text: 0 };
2178
- if (value == null || value === false || value === true) return;
2179
- state.values += 1;
2180
- if (state.values > 1000000) throw new RangeError("JSX cannot render more than 1000000 values");
2181
- if (typeof value === "string") {
2182
- state.text += value.length;
2183
- if (state.text > 16 * 1024 * 1024) throw new RangeError("JSX text cannot exceed 16 MiB");
2184
- __velarDomAppend(parent, __velarDomCreateTextNode(value));
2185
- return;
2186
- }
2187
- if (typeof value === "number") {
2188
- if (!__velarDomIsFinite(value)) throw new TypeError("JSX numbers must be finite");
2189
- __velarDomAppend(parent, __velarDomCreateTextNode(__velarDomString(value)));
2190
- return;
2191
- }
2192
- if (__velarDomIsNode(value)) { __velarDomAppend(parent, value); return; }
2193
- if (__velarDomIsArray(value)) {
2194
- if (state.depth >= 128) throw new RangeError("JSX Lists cannot exceed 128 nested levels");
2195
- if (__velarDomSetContains(state.active, value)) throw new TypeError("JSX cannot render a cyclic List");
2196
- const values = __velarListSnapshot(value, "JSX children");
2197
- __velarDomSetInsert(state.active, value);
2198
- state.depth += 1;
2199
- try {
2200
- for (let index = 0; index < values.length; index += 1) __velarAppend(parent, values[index], state);
2201
- } finally {
2202
- state.depth -= 1;
2203
- __velarDomSetRemove(state.active, value);
2204
- }
2205
- return;
2206
- }
2207
- throw new TypeError("JSX can render only text, finite numbers, bool, enums, WebNode values, and Lists of those values");
2208
- }
2209
-
2210
- // The rendering region currently being constructed. A 'children' slot is built
2211
- // by the position that shows it and must be destroyed with it, so the slot is
2212
- // owned by this scope rather than by the caller's component scope, which would
2213
- // keep every hidden build's observers alive for the component's whole lifetime.
2214
- let __velarBuildScope = null;
2215
-
2216
- function __velarChildrenNode(build, scope) {
2217
- const owner = __velarBuildScope === null ? scope : __velarBuildScope;
2218
- return __velarInternalRead(() => build(owner));
2219
- }
2220
-
2221
- // The scalar half of __velarAppend, lifted out so a region that can only ever
2222
- // hold one text node can be that text node. The two branches are __velarAppend's
2223
- // own, error text included: the checked type admits an unsound value only where
2224
- // the program lied about it, and such a value must land exactly where it landed
2225
- // before -- rendered if it is text or a finite number, refused with the same
2226
- // message otherwise.
2227
- function __velarTextValue(value) {
2228
- if (typeof value === "string") {
2229
- if (value.length > 16 * 1024 * 1024) throw new RangeError("JSX text cannot exceed 16 MiB");
2230
- return value;
2231
- }
2232
- if (typeof value === "number") {
2233
- if (!__velarDomIsFinite(value)) throw new TypeError("JSX numbers must be finite");
2234
- return __velarDomString(value);
2235
- }
2236
- throw new TypeError("JSX can render only text, finite numbers, bool, enums, WebNode values, and Lists of those values");
2237
- }
2238
-
2239
- // F1: an interpolation whose checked type is 'string' or 'number' renders
2240
- // exactly one text node -- never zero, never markup, never a list. So it needs
2241
- // no comment pair to bracket content that can never grow or vanish, and no
2242
- // child scope to own observers that can never exist: the text node is its own
2243
- // anchor and its own content, created once and updated by assigning its data.
2244
- // That is the same node identity a comment anchor gave, so a keyed row that
2245
- // starts or ends on one still finds its bounds, and a focused sibling is never
2246
- // detached by an update.
2247
- function __velarText(parent, read, scope) {
2248
- let node = null;
2249
- __velarObserver(() => {
2250
- // Read and validate before touching the document: a failed update must
2251
- // leave the last valid text standing, exactly as a failed rebuild leaves
2252
- // the last valid region standing.
2253
- const value = __velarTextValue(read());
2254
- if (node === null) __velarDomAppend(parent, node = __velarDomCreateTextNode(value));
2255
- else __velarDomSetData(node, value);
2256
- }, "dom", scope);
2257
- }
2258
-
2259
- function __velarDynamic(parent, read, scope, rootState = null) {
2260
- const start = __velarDomCreateComment("velar:start");
2261
- const end = __velarDomCreateComment("velar:end");
2262
- __velarDomAppend(parent, start, end);
2263
- let nodes = [];
2264
- let childScope = null;
2265
- __velarAppendOwned(scope.mounts, () => { if (childScope) __velarMountScope(childScope); });
2266
- __velarObserver(() => {
2267
- const nextScope = __velarScope(scope.component);
2268
- const fragment = __velarDomCreateFragment();
2269
- let nextHost = null;
2270
- const previousBuildScope = __velarBuildScope;
2271
- __velarBuildScope = nextScope;
2272
- try {
2273
- __velarAppend(fragment, read(nextScope));
2274
- if (rootState) nextHost = __velarRootHost(fragment, "dynamic component");
2275
- }
2276
- catch (error) { __velarDestroyScope(nextScope); throw error; }
2277
- finally { __velarBuildScope = previousBuildScope; }
2278
- const nextNodes = __velarDomChildNodes(fragment);
2279
- if (childScope) __velarDestroyScope(childScope);
2280
- for (let index = 0; index < nodes.length; index += 1) __velarDomRemove(nodes[index]);
2281
- __velarDomBefore(end, fragment);
2282
- childScope = nextScope;
2283
- nodes = nextNodes;
2284
- if (rootState) {
2285
- rootState.host = nextHost;
2286
- for (const listener of __velarGraphSetItems(rootState.listeners)) listener(nextHost);
2287
- }
2288
- if (scope.mounted) __velarMountScope(nextScope);
2289
- }, "dom", scope);
2290
- __velarAppendOwned(scope.cleanups, () => {
2291
- if (childScope) __velarDestroyScope(childScope);
2292
- for (let index = 0; index < nodes.length; index += 1) __velarDomRemove(nodes[index]);
2293
- nodes = [];
2294
- if (rootState) {
2295
- rootState.host = null;
2296
- for (const listener of __velarGraphSetItems(rootState.listeners)) listener(null);
2297
- }
2298
- });
2299
- }
2300
-
2301
- function __velarDynamicComponent(read, scope) {
2302
- const fragment = __velarDomCreateFragment();
2303
- const rootState = { host: null, listeners: __velarGraphCreateSet() };
2304
- __velarGraphDefine(fragment, "__velarDynamicRoot", { value: rootState });
2305
- __velarDynamic(fragment, read, scope, rootState);
2306
- return fragment;
2307
- }
2308
-
2309
- function __velarKeyed(parent, read, keyOf, render, scope) {
2310
- const start = __velarDomCreateComment("velar:keyed-start");
2311
- const end = __velarDomCreateComment("velar:keyed-end");
2312
- __velarDomAppend(parent, start, end);
2313
- let entries = __velarGraphCreateMap();
2314
- __velarAppendOwned(scope.mounts, () => { for (const entry of __velarGraphMapItems(entries)) __velarMountScope(entry.scope); });
2315
- __velarObserver(() => {
2316
- const source = __velarToRaw(read() ?? []);
2317
- const values = __velarListSnapshot(source, "Keyed JSX");
2318
- const next = __velarGraphCreateMap();
2319
- const created = [];
2320
- try {
2321
- for (let index = 0; index < values.length; index += 1) {
2322
- const rawValue = __velarToRaw(values[index]);
2323
- // The keyed source may be a fresh derived List on every render. A row
2324
- // is observed directly by its child scope, so linking it to that
2325
- // ephemeral container only retains dead Lists and slows later writes.
2326
- const trackedValue = __velarReactive(rawValue);
2327
- const key = __velarKey(keyOf(trackedValue));
2328
- if (__velarGraphMapContains(next, key)) throw new Error("Duplicate JSX key '" + (typeof key === "string" ? key : __velarDomString(key)) + "'");
2329
- let entry = __velarGraphMapRead(entries, key);
2330
- if (entry && !__velarGraphSame(entry.value, rawValue)) entry = undefined;
2331
- if (!entry) {
2332
- const childScope = __velarScope(scope.component);
2333
- const fragment = __velarDomCreateFragment();
2334
- const previousBuildScope = __velarBuildScope;
2335
- __velarBuildScope = childScope;
2336
- try { __velarAppend(fragment, render(trackedValue, childScope)); }
2337
- catch (error) { __velarDestroyScope(childScope); throw error; }
2338
- finally { __velarBuildScope = previousBuildScope; }
2339
- // A row is held by its first and last top-level nodes, never by a
2340
- // snapshot of the list between them: every dynamic construct brackets
2341
- // itself with comments created once, so those two nodes are stable
2342
- // while everything between them is replaced over time. Caching the
2343
- // whole list put destroyed nodes back into the document on a later
2344
- // reorder and stranded the live ones outside their own markers.
2345
- const rowNodes = __velarDomChildNodes(fragment);
2346
- entry = {
2347
- value: rawValue,
2348
- scope: childScope,
2349
- first: rowNodes.length > 0 ? rowNodes[0] : null,
2350
- last: rowNodes.length > 0 ? rowNodes[rowNodes.length - 1] : null,
2351
- fragment,
2352
- };
2353
- created[created.length] = entry;
2354
- }
2355
- __velarGraphMapWrite(next, key, entry);
2356
- }
2357
- } catch (error) {
2358
- for (let index = 0; index < created.length; index += 1) __velarDestroyScope(created[index].scope);
2359
- throw error;
2360
- }
2361
- for (const key of __velarGraphMapKeyItems(entries)) {
2362
- const entry = __velarGraphMapRead(entries, key);
2363
- if (__velarGraphMapRead(next, key) === entry) continue;
2364
- __velarDestroyScope(entry.scope);
2365
- let node = entry.first;
2366
- while (node !== null && node !== end) {
2367
- const following = __velarDomNextSibling(node);
2368
- __velarDomRemove(node);
2369
- if (node === entry.last) break;
2370
- node = following;
2371
- }
2372
- }
2373
- // A row already standing in its final position must not be detached and
2374
- // reattached: that moves focus off a live <input>, ends IME composition,
2375
- // and resets transient subtree state. The cursor walks the surviving nodes
2376
- // in order and only moves a node that is not already where it belongs.
2377
- let cursor = __velarDomNextSibling(start);
2378
- for (const entry of __velarGraphMapItems(next)) {
2379
- if (entry.fragment) {
2380
- __velarDomBefore(cursor === null ? end : cursor, entry.fragment);
2381
- entry.fragment = null;
2382
- if (scope.mounted) __velarMountScope(entry.scope);
2383
- continue;
2384
- }
2385
- let node = entry.first;
2386
- while (node !== null && node !== end) {
2387
- const following = __velarDomNextSibling(node);
2388
- if (node === cursor) cursor = __velarDomNextSibling(cursor);
2389
- else __velarDomBefore(cursor === null ? end : cursor, node);
2390
- if (node === entry.last) break;
2391
- node = following;
2392
- }
2393
- }
2394
- entries = next;
2395
- }, "dom", scope);
2396
- __velarAppendOwned(scope.cleanups, () => {
2397
- for (const entry of __velarGraphMapItems(entries)) __velarDestroyScope(entry.scope);
2398
- __velarGraphMapEmpty(entries);
2399
- });
2400
- }
2401
-
2402
- function __velarStaticAttr(element, name, value) {
2403
- if (value === false || value == null) return;
2404
- __velarSetAttribute(element, name, __velarAttributeValue(value, name));
2405
- }
2406
-
2407
- function __velarAttr(element, name, read, scope) {
2408
- __velarObserver(() => {
2409
- const value = read();
2410
- if (value == null || value === false) __velarRemoveAttribute(element, name);
2411
- else __velarSetAttribute(element, name, __velarAttributeValue(value, name));
2412
- }, "dom", scope);
2413
- }
2414
-
2415
- // The attributes whose value the user agent navigates or fetches. For these the
2416
- // scheme is part of what the value means, so it is checked; every other
2417
- // attribute takes its text unchanged.
2418
- const __velarUrlAttributes = ["href", "src", "action", "formaction", "poster", "data", "xlink:href", "ping", "cite"];
2419
- const __velarUrlSchemes = ["http", "https", "mailto", "tel", "blob"];
2420
- // 'data:' carries its own payload, so it is admitted only for media types the
2421
- // user agent cannot execute. 'image/svg+xml' is deliberately absent: an SVG
2422
- // document can carry script.
2423
- const __velarInertDataTypes = [
2424
- "image/png", "image/jpeg", "image/gif", "image/webp", "image/avif", "image/bmp", "image/x-icon",
2425
- "video/mp4", "video/webm", "video/ogg", "audio/mpeg", "audio/ogg", "audio/wav", "audio/webm",
2426
- "font/woff", "font/woff2", "text/plain",
2427
- ];
2428
-
2429
- // 'javascript:' and 'vbscript:' are code, not locations. A value that arrived as
2430
- // data must never become code because it reached an href, so an unknown scheme
2431
- // is refused rather than passed through.
2432
- function __velarUrlAttributeValue(value, name) {
2433
- let scheme = "";
2434
- for (let index = 0; index < value.length; index += 1) {
2435
- const code = value.charCodeAt(index);
2436
- // The user agent strips ASCII whitespace and control characters before it
2437
- // parses the scheme, so "java\tscript:" reads as "javascript:" to it and
2438
- // has to read that way here too.
2439
- if (code <= 0x20 || code === 0x7f) continue;
2440
- if (code === 58 && scheme.length > 0) {
2441
- const lowered = scheme.toLowerCase();
2442
- if (lowered === "data") {
2443
- const payload = value.slice(index + 1).toLowerCase();
2444
- for (let type = 0; type < __velarInertDataTypes.length; type += 1) {
2445
- if (payload.startsWith(__velarInertDataTypes[type])) return value;
2446
- }
2447
- throw new TypeError("JSX attribute '" + name + "' rejected a 'data:' URL whose media type is not a known inert one");
2448
- }
2449
- if (__velarHasName(__velarUrlSchemes, lowered)) return value;
2450
- throw new TypeError("JSX attribute '" + name + "' rejected the '" + lowered + ":' URL scheme");
2451
- }
2452
- const letter = (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
2453
- if (letter || (scheme.length > 0 && ((code >= 48 && code <= 57) || code === 43 || code === 45 || code === 46))) {
2454
- scheme += value[index];
2455
- continue;
2456
- }
2457
- // Anything else this early means the value names no scheme: it is a
2458
- // relative URL, which is always the application's own origin.
2459
- return value;
2460
- }
2461
- return value;
2462
- }
2463
-
2464
- function __velarAttributeValue(value, name) {
2465
- if (value === true) return "";
2466
- if (typeof value === "number") {
2467
- if (!__velarDomIsFinite(value)) throw new TypeError("JSX attribute '" + name + "' requires a finite number");
2468
- return __velarDomString(value);
2469
- }
2470
- if (typeof value !== "string") throw new TypeError("JSX attribute '" + name + "' requires text, a finite number, bool, an enum, or null");
2471
- if (value.length > 1024 * 1024) throw new RangeError("JSX attribute '" + name + "' cannot exceed 1 MiB");
2472
- if (__velarHasName(__velarUrlAttributes, name)) return __velarUrlAttributeValue(value, name);
2473
- return value;
2474
- }
2475
-
2476
- function __velarKey(value) {
2477
- if (typeof value === "number") {
2478
- if (!__velarDomIsFinite(value)) throw new TypeError("A JSX key number must be finite");
2479
- return value;
2480
- }
2481
- if (typeof value !== "string") throw new TypeError("A JSX key must be a string, string-backed enum, or finite number");
2482
- if (value.length > 65536) throw new RangeError("A JSX key cannot exceed 65536 characters");
2483
- return value;
2484
- }
2485
-
2486
- function __velarSetAttribute(element, name, value) {
2487
- if (name.startsWith("xlink:")) __velarDomSetAttributeNS(element, __velarXlinkNamespace, name, value);
2488
- else if (name.startsWith("xml:")) __velarDomSetAttributeNS(element, __velarXmlNamespace, name, value);
2489
- else __velarDomSetAttribute(element, name, value);
2490
- }
2491
-
2492
- function __velarRemoveAttribute(element, name) {
2493
- if (name.startsWith("xlink:")) __velarDomRemoveAttributeNS(element, __velarXlinkNamespace, name.slice(6));
2494
- else if (name.startsWith("xml:")) __velarDomRemoveAttributeNS(element, __velarXmlNamespace, name.slice(4));
2495
- else __velarDomRemoveAttribute(element, name);
2496
- }
2497
-
2498
- function __velarClass(element, name, read, scope) {
2499
- __velarClassBind(element, () => read() ? name : null, scope);
2500
- }
2501
-
2502
- // The property a token carries. A token is '[target:]conditions:property' and
2503
- // a CSS property name never contains ':', so the last segment is the property.
2504
- function __velarLookProperty(token) {
2505
- return token.slice(token.lastIndexOf(":") + 1);
2506
- }
2507
-
2508
- // The surface a token writes on: its pseudo-element target, if it has one, plus
2509
- // its property. Composition overrides a property on the surface that owns it —
2510
- // '@before: content' and a bare 'content' are two surfaces, not one property
2511
- // written under two conditions.
2512
- function __velarLookSurface(token) {
2513
- const first = token.indexOf(":");
2514
- const last = token.lastIndexOf(":");
2515
- return (first === last ? "" : token.slice(0, first + 1)) + token.slice(last + 1);
2516
- }
2517
-
2518
- // Whether a token declares its property unconditionally: an unconditional
2519
- // declaration spells its condition segment 'base', so the segment in front of
2520
- // the property is what says a token stands on its own.
2521
- function __velarLookUnconditional(token) {
2522
- const last = token.lastIndexOf(":");
2523
- return token.slice(token.lastIndexOf(":", last - 1) + 1, last) === "base";
2524
- }
2525
-
2526
- // Composition is property-level across sources and token-level inside one look
2527
- // block. A later unconditional declaration wins its property outright, so it
2528
- // drops every condition the earlier sources wrote it under: the caller of a
2529
- // component could otherwise not reach a padding the component set behind its
2530
- // own private breakpoint, and 'the caller wins every property both of them set'
2531
- // was true only under the identical condition (LOK-U10). A later conditional
2532
- // declaration refines rather than replaces — it overwrites the identical token
2533
- // and leaves the earlier unconditional value standing, because a caller that
2534
- // writes only 'if @hover: color' never mentioned the resting colour and must
2535
- // not delete it. Declarations written in one block are one source, so a block's
2536
- // own 'if scheme.dark:' and 'if @hover:' still coexist and the cascade decides
2537
- // between them.
2538
- function __velarMergeRules(rules, groups, source, group) {
2539
- const names = __velarGraphOwnNames(source);
2540
- const owned = __velarGraphOwnNames(rules);
2541
- for (let index = 0; index < names.length; index += 1) {
2542
- const descriptor = __velarGraphOwnDescriptor(source, names[index]);
2543
- if (!descriptor || !("value" in descriptor)) continue;
2544
- if (!__velarLookUnconditional(names[index])) continue;
2545
- const surface = __velarLookSurface(names[index]);
2546
- for (let other = 0; other < owned.length; other += 1) {
2547
- const token = owned[other];
2548
- if (groups[token] === group || __velarLookSurface(token) !== surface) continue;
2549
- delete rules[token];
2550
- delete groups[token];
2551
- }
2552
- }
2553
- for (let index = 0; index < names.length; index += 1) {
2554
- const descriptor = __velarGraphOwnDescriptor(source, names[index]);
2555
- if (!descriptor || !("value" in descriptor)) continue;
2556
- if (descriptor.value == null) { delete rules[names[index]]; delete groups[names[index]]; continue; }
2557
- rules[names[index]] = descriptor.value;
2558
- groups[names[index]] = group;
2559
- }
2560
- }
2561
-
2562
- function __velarLook(parts) {
2563
- const rules = __velarGraphCreateRecord();
2564
- const groups = __velarGraphCreateRecord();
2565
- // A built Look is one source. A bare rules record is a run of declarations
2566
- // written in one look block, so consecutive ones share a source and a spread
2567
- // between them opens the next.
2568
- let group = 0;
2569
- let run = 0;
2570
- const add = (part) => {
2571
- if (part == null || part === false) return;
2572
- if (__velarGraphIsList(part)) { for (let index = 0; index < part.length; index += 1) add(part[index]); return; }
2573
- if (part.__velarLook === true) {
2574
- group += 1;
2575
- run = 0;
2576
- __velarMergeRules(rules, groups, part.rules, group);
2577
- return;
2578
- }
2579
- if (part.rules && typeof part.rules === "object") {
2580
- if (run === 0) { group += 1; run = group; }
2581
- __velarMergeRules(rules, groups, part.rules, run);
2582
- return;
2583
- }
2584
- throw new TypeError("look composition accepts only Look, Look?, or lists of Look values");
2585
- };
2586
- add(parts);
2587
- return __velarGraphFreeze({ __velarLook: true, rules: __velarGraphFreeze(rules) });
2588
- }
2589
-
2590
- function __velarKeyframesValue(name) {
2591
- if (typeof name !== "string" || !/^velar-kf-[0-9a-f]{8,32}$/.test(name)) throw new TypeError("Generated keyframes name is invalid");
2592
- return __velarGraphFreeze({ __velarKeyframes: true, name });
2593
- }
2594
-
2595
- function __velarLookVariable(token) {
2596
- return "--velar-look-" + token.replace(/[^A-Za-z0-9_-]+/g, "-");
2597
- }
2598
-
2599
- function __velarLookValue(token, value) {
2600
- if (token.endsWith(":animation")) return __velarAnimationLookValue(value);
2601
- if (typeof value === "number") {
2602
- if (!__velarDomIsFinite(value)) throw new TypeError("Look properties require finite numbers");
2603
- return __velarDomString(value);
2604
- }
2605
- if (typeof value !== "string") throw new TypeError("Look properties require text, finite numbers, typed visual values, or null");
2606
- if (value.length > 1024 * 1024) throw new RangeError("A Look property value cannot exceed 1 MiB");
2607
- if (token.endsWith(":content") && typeof value === "string" && value !== "none" && value !== "normal") return __velarCssString(value);
2608
- // A closed keyword set is the property's whole string vocabulary, so a value
2609
- // the compiler could not read — a prop, a record field, a call result — is
2610
- // checked here instead. Without this a 'display' bound to "grdi" reached the
2611
- // browser as a declaration it silently discards (LOK-U14).
2612
- const keywords = __velarLookKeywords[__velarLookProperty(token)];
2613
- if (keywords !== undefined && !__velarHasName(keywords, value.trim())) {
2614
- let expected = "";
2615
- for (let index = 0; index < keywords.length; index += 1) expected += (expected === "" ? "" : ", ") + keywords[index];
2616
- throw new TypeError("Look property '" + __velarLookProperty(token) + "' does not accept '" + value + "'; use one of " + expected);
2617
- }
2618
- return value;
2619
- }
2620
-
2621
- function __velarAnimationLookValue(value) {
2622
- const parts = [];
2623
- const add = (item) => {
2624
- if (__velarGraphIsList(item)) {
2625
- for (let index = 0; index < item.length; index += 1) add(item[index]);
2626
- return;
2627
- }
2628
- const marker = item && (typeof item === "object" || typeof item === "function")
2629
- ? __velarGraphOwnDescriptor(item, "__velarAnimation") : null;
2630
- const css = item && (typeof item === "object" || typeof item === "function")
2631
- ? __velarGraphOwnDescriptor(item, "css") : null;
2632
- if (!marker || !("value" in marker) || marker.value !== true || !css || !("value" in css) || typeof css.value !== "string") {
2633
- throw new TypeError("Look animation requires Animation or a List of Animation values from animate()");
2634
- }
2635
- __velarAppendOwned(parts, css.value);
2636
- };
2637
- add(value);
2638
- if (parts.length === 0) throw new TypeError("A Look animation list cannot be empty");
2639
- let output = parts[0];
2640
- for (let index = 1; index < parts.length; index += 1) output += ", " + parts[index];
2641
- return output;
2642
- }
2643
-
2644
- const __velarInlineStyleProperties = __velarGraphCreateSet(${JSON.stringify([...LOOK_PROPERTIES].map(cssPropertyName))});
2645
-
2646
- function __velarStyleDeclarations(value) {
2647
- if (!value || typeof value !== "object" || __velarGraphIsList(value)
2648
- || (__velarGraphPrototype(value) !== __velarGraphNativeObject.prototype && __velarGraphPrototype(value) !== null)
2649
- || __velarWebErrorOwnSymbols(value).length > 0) {
2650
- throw new TypeError("style:* requires compiler-owned inline declarations");
2651
- }
2652
- const names = __velarGraphOwnNames(value);
2653
- if (names.length > ${LOOK_PROPERTIES.size}) throw new RangeError("An inline Style has too many properties");
2654
- const output = {};
2655
- for (let index = 0; index < names.length; index += 1) {
2656
- const property = names[index];
2657
- if (!__velarGraphSetContains(__velarInlineStyleProperties, property)) throw new TypeError("Unknown inline Style property '" + property + "'");
2658
- const descriptor = __velarGraphOwnDescriptor(value, property);
2659
- if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) throw new TypeError("Inline Style declarations cannot use accessors");
2660
- __velarGraphDefine(output, property, { value: descriptor.value, enumerable: true, configurable: false, writable: false });
2661
- }
2662
- return __velarGraphFreeze(output);
2663
- }
2664
-
2665
- function __velarInlineStyleState(element) {
2666
- const current = __velarGraphOwnDescriptor(element, "__velarInlineStyleState");
2667
- if (current) {
2668
- if (!("value" in current) || current.enumerable || current.configurable || current.writable
2669
- || !current.value || typeof current.value !== "object") throw new TypeError("Inline Style ownership is invalid");
2670
- return current.value;
2671
- }
2672
- const state = __velarGraphFreeze({ base: __velarGraphCreateMap(), managed: __velarGraphCreateSet() });
2673
- __velarGraphDefine(element, "__velarInlineStyleState", { value: state });
2674
- return state;
2675
- }
2676
-
2677
- function __velarAttachSource(registry, element, source) {
2678
- let sources = __velarGraphWeakMapRead(registry, element);
2679
- if (!sources) { sources = __velarGraphCreateSet(); __velarGraphWeakMapWrite(registry, element, sources); }
2680
- __velarGraphSetInsert(sources, source);
2681
- return sources;
2682
- }
2683
-
2684
- function __velarDetachSource(registry, element, source) {
2685
- const sources = __velarGraphWeakMapRead(registry, element);
2686
- if (!sources) return;
2687
- __velarGraphSetRemove(sources, source);
2688
- if (__velarGraphSetCount(sources) === 0) __velarGraphWeakMapRemove(registry, element);
2689
- }
2690
-
2691
- function __velarApplyStyles(element) {
2692
- const sources = __velarGraphWeakMapRead(__velarRuntime.lookSources, element);
2693
- const merged = __velarGraphCreateMap();
2694
- if (sources) {
2695
- for (const source of __velarGraphSetItems(sources)) {
2696
- if (!source.styles) continue;
2697
- const names = __velarGraphOwnNames(source.styles);
2698
- for (let index = 0; index < names.length; index += 1) {
2699
- __velarGraphMapWrite(merged, names[index], __velarGraphOwnDescriptor(source.styles, names[index]).value);
2700
- }
2701
- }
2702
- }
2703
- const state = __velarInlineStyleState(element);
2704
- const next = __velarGraphCreateSet(__velarGraphMapKeyItems(merged));
2705
- for (const property of __velarGraphSetItems(next)) {
2706
- if (__velarGraphSetContains(state.managed, property)) continue;
2707
- __velarGraphMapWrite(state.base, property, {
2708
- value: __velarDomStyleValue(element, property),
2709
- priority: __velarDomStylePriority(element, property),
2710
- });
2711
- }
2712
- for (const property of __velarGraphSetItems(state.managed)) {
2713
- if (__velarGraphSetContains(next, property)) continue;
2714
- const base = __velarGraphMapRead(state.base, property);
2715
- if (!base || (base.value === "" && base.priority === "")) __velarDomStyleClear(element, property);
2716
- else __velarDomStyleWrite(element, property, base.value, base.priority);
2717
- __velarGraphMapRemove(state.base, property);
2718
- }
2719
- for (const property of __velarGraphSetItems(next)) {
2720
- const value = __velarGraphMapRead(merged, property);
2721
- if (value == null) __velarDomStyleClear(element, property);
2722
- else __velarDomStyleWrite(element, property, __velarLookValue("base:" + property, value));
2723
- }
2724
- __velarGraphSetEmpty(state.managed);
2725
- for (const property of __velarGraphSetItems(next)) __velarGraphSetInsert(state.managed, property);
2726
- }
2727
-
2728
- function __velarStyleBind(element, read, scope) {
2729
- const source = { rules: __velarGraphCreateRecord(), styles: {} };
2730
- __velarAttachSource(__velarRuntime.lookSources, element, source);
2731
- __velarObserver(() => {
2732
- source.styles = __velarStyleDeclarations(read());
2733
- __velarApplyStyles(element);
2734
- }, "dom", scope);
2735
- __velarAppendOwned(scope.cleanups, () => {
2736
- __velarDetachSource(__velarRuntime.lookSources, element, source);
2737
- __velarApplyStyles(element);
2738
- });
2739
- }
2740
-
2741
- function __velarMoveStyleSource(source, previous, next) {
2742
- if (previous) {
2743
- __velarDetachSource(__velarRuntime.lookSources, previous, source);
2744
- __velarApplyStyles(previous);
2745
- }
2746
- if (next) {
2747
- __velarAttachSource(__velarRuntime.lookSources, next, source);
2748
- __velarApplyStyles(next);
2749
- }
2750
- }
2751
-
2752
- // The dynamic-root marker sits on a fragment the emitter created, but the
2753
- // fragment is still a host object: a planted prototype getter would otherwise
2754
- // hand look/class/style application a forged host element.
2755
- function __velarDynamicRootState(root) {
2756
- if (root === null || root === undefined) return null;
2757
- const descriptor = __velarGraphOwnDescriptor(root, "__velarDynamicRoot");
2758
- return descriptor && "value" in descriptor && descriptor.value && typeof descriptor.value === "object"
2759
- ? descriptor.value
2760
- : null;
2761
- }
2762
-
2763
- function __velarStyleBindRoot(root, read, scope) {
2764
- const dynamic = __velarDynamicRootState(root);
2765
- if (!dynamic) {
2766
- __velarStyleBind(__velarRootHost(root, "style"), read, scope);
2767
- return;
2768
- }
2769
- const source = { rules: __velarGraphCreateRecord(), styles: {} };
2770
- let host = null;
2771
- const move = (next) => {
2772
- __velarMoveStyleSource(source, host, next);
2773
- host = next;
2774
- };
2775
- __velarGraphSetInsert(dynamic.listeners, move);
2776
- move(dynamic.host);
2777
- __velarObserver(() => {
2778
- source.styles = __velarStyleDeclarations(read());
2779
- if (host) __velarApplyStyles(host);
2780
- }, "dom", scope);
2781
- __velarAppendOwned(scope.cleanups, () => {
2782
- __velarGraphSetRemove(dynamic.listeners, move);
2783
- move(null);
2784
- });
2785
- }
2786
-
2787
- // Look and class ownership lives in one non-enumerable, non-configurable data
2788
- // property per element, discovered through the captured descriptor ABI exactly
2789
- // like inline style ownership. An ambient expando read would let a hostile
2790
- // prototype hand the framework a forged token set.
2791
- function __velarElementState(element, name, create) {
2792
- const current = __velarGraphOwnDescriptor(element, name);
2793
- if (current) {
2794
- if (!("value" in current) || current.enumerable || current.configurable || current.writable
2795
- || !current.value || typeof current.value !== "object") throw new TypeError("VelarScript element ownership is invalid");
2796
- return current.value;
2797
- }
2798
- const state = create();
2799
- __velarGraphDefine(element, name, { value: state });
2800
- return state;
2801
- }
2802
-
2803
- function __velarApplyLooks(element) {
2804
- const sources = __velarGraphWeakMapRead(__velarRuntime.lookSources, element);
2805
- const merged = __velarGraphCreateRecord();
2806
- const groups = __velarGraphCreateRecord();
2807
- if (sources) {
2808
- // Each attached source is one Look, so a source that sets a property
2809
- // unconditionally drops the property's other conditions from the sources
2810
- // before it: the caller of a component composes after the component's own
2811
- // host look and wins every property both of them set, whatever condition
2812
- // either wrote it under. A source that writes the property only under a
2813
- // condition refines that condition alone — the identical token is
2814
- // overwritten and the earlier unconditional value stays, so the caller does
2815
- // not delete a resting value it never mentioned.
2816
- //
2817
- // A null rule keeps its token: the token drives the generated selector and
2818
- // only the custom property behind it disappears.
2819
- let group = 0;
2820
- for (const source of __velarGraphSetItems(sources)) {
2821
- group += 1;
2822
- const names = __velarGraphOwnNames(source.rules);
2823
- const owned = __velarGraphOwnNames(merged);
2824
- for (let index = 0; index < names.length; index += 1) {
2825
- // A rule the assignment pass below refuses to read must not clear the
2826
- // earlier sources either, or the property disappears with nothing put
2827
- // in its place — the same 'a source deletes a value it never replaces'
2828
- // shape the conditional guard above closes. '__velarMergeRules' spells
2829
- // the test the same way.
2830
- const descriptor = __velarGraphOwnDescriptor(source.rules, names[index]);
2831
- if (!descriptor || !("value" in descriptor)) continue;
2832
- if (!__velarLookUnconditional(names[index])) continue;
2833
- const surface = __velarLookSurface(names[index]);
2834
- for (let other = 0; other < owned.length; other += 1) {
2835
- if (groups[owned[other]] === group || __velarLookSurface(owned[other]) !== surface) continue;
2836
- delete merged[owned[other]];
2837
- delete groups[owned[other]];
2838
- }
2839
- }
2840
- for (let index = 0; index < names.length; index += 1) {
2841
- const descriptor = __velarGraphOwnDescriptor(source.rules, names[index]);
2842
- if (!descriptor || !("value" in descriptor)) continue;
2843
- merged[names[index]] = descriptor.value;
2844
- groups[names[index]] = group;
2845
- }
2846
- }
2847
- }
2848
- // The last value written per token, so a reactive change to one dynamic
2849
- // property costs one DOM write instead of one per token plus a full attribute
2850
- // rewrite (LOK-U15).
2851
- const state = __velarElementState(element, "__velarLookTokens", () => __velarGraphFreeze({
2852
- tokens: __velarGraphCreateSet(), written: { record: __velarGraphCreateRecord(), attribute: undefined },
2853
- }));
2854
- const written = state.written.record;
2855
- const tokens = __velarGraphOwnNames(merged);
2856
- const next = __velarGraphCreateSet(tokens);
2857
- for (const token of __velarGraphSetItems(state.tokens)) {
2858
- if (__velarGraphSetContains(next, token)) continue;
2859
- __velarDomStyleClear(element, __velarLookVariable(token));
2860
- delete written[token];
2861
- }
2862
- let attribute = "";
2863
- for (let index = 0; index < tokens.length; index += 1) {
2864
- const token = tokens[index];
2865
- const value = __velarGraphOwnDescriptor(merged, token)?.value;
2866
- const text = value == null ? null : __velarLookValue(token, value);
2867
- if (!(token in written) || written[token] !== text) {
2868
- if (text === null) __velarDomStyleClear(element, __velarLookVariable(token));
2869
- else __velarDomStyleWrite(element, __velarLookVariable(token), text);
2870
- written[token] = text;
2871
- }
2872
- attribute = attribute === "" ? token : attribute + " " + token;
2873
- }
2874
- const desired = tokens.length === 0 ? null : attribute;
2875
- if (state.written.attribute !== desired) {
2876
- if (desired === null) __velarDomRemoveAttribute(element, "data-velar-look");
2877
- else __velarDomSetAttribute(element, "data-velar-look", desired);
2878
- state.written.attribute = desired;
2879
- }
2880
- __velarGraphSetEmpty(state.tokens);
2881
- for (let index = 0; index < tokens.length; index += 1) __velarGraphSetInsert(state.tokens, tokens[index]);
2882
- }
2883
-
2884
- function __velarLookBind(element, read, scope) {
2885
- const source = { rules: __velarGraphCreateRecord() };
2886
- __velarAttachSource(__velarRuntime.lookSources, element, source);
2887
- __velarObserver(() => {
2888
- source.rules = __velarLook([read()]).rules;
2889
- __velarApplyLooks(element);
2890
- }, "dom", scope);
2891
- __velarAppendOwned(scope.cleanups, () => {
2892
- __velarDetachSource(__velarRuntime.lookSources, element, source);
2893
- __velarApplyLooks(element);
2894
- });
2895
- }
2896
-
2897
- function __velarMoveLookSource(source, previous, next) {
2898
- if (previous) {
2899
- __velarDetachSource(__velarRuntime.lookSources, previous, source);
2900
- __velarApplyLooks(previous);
2901
- }
2902
- if (next) {
2903
- __velarAttachSource(__velarRuntime.lookSources, next, source);
2904
- __velarApplyLooks(next);
2905
- }
2906
- }
2907
-
2908
- function __velarApplyExternalLook(element, value) {
2909
- const source = { rules: __velarLook([value]).rules };
2910
- __velarAttachSource(__velarRuntime.lookSources, element, source);
2911
- __velarApplyLooks(element);
2912
- return () => {
2913
- __velarDetachSource(__velarRuntime.lookSources, element, source);
2914
- __velarApplyLooks(element);
2915
- };
2916
- }
2917
-
2918
- __velarRuntime.installLook(__velarApplyExternalLook);
2919
-
2920
- // One resolution per root, shared by every capability bound to it: look, class
2921
- // and style used to pay a fresh O(subtree) walk each.
2922
- const __velarRootHosts = __velarGraphCreateWeakMap();
2923
-
2924
- function __velarRootHostResolve(root) {
2925
- const elements = [];
2926
- const children = __velarDomChildNodes(root);
2927
- for (let index = 0; index < children.length; index += 1) {
2928
- if (__velarDomNodeType(children[index]) === 1) __velarAppendOwned(elements, children[index]);
2929
- }
2930
- const explicit = [];
2931
- const forwarded = [];
2932
- for (let index = 0; index < elements.length; index += 1) {
2933
- const element = elements[index];
2934
- // A nested component's own, perfectly legal host is that component's, not
2935
- // this one's, at the root level exactly as below it. Every root-level node
2936
- // of a nested component carries the marker and this component's own nodes
2937
- // do not yet — construction marks them after a caller's look binds — so
2938
- // the marker is what separates the two. Reading 'host' first counted a
2939
- // nested component's marked root as a second host of the enclosing one and
2940
- // collapsed the whole region, which is the buried-host defect standing at
2941
- // the root level instead of below it. Such a node is not this component's
2942
- // host but the host this component forwards to when it declares none of
2943
- // its own, so it is collected apart rather than dropped.
2944
- if (__velarDomOwnData(element, "__velarComponentNode") === true) {
2945
- if (__velarDomOwnData(element, "__velarHost") === true) __velarAppendOwned(forwarded, element);
2946
- continue;
2947
- }
2948
- if (__velarDomOwnData(element, "__velarHost") === true) { __velarAppendOwned(explicit, element); continue; }
2949
- // A walk that refuses to enter a marked node stops at a nested component's
2950
- // boundary whatever depth its host sits at; a flat 'querySelectorAll' scan
2951
- // could only skip the marked node itself and still counted a host one level
2952
- // below it.
2953
- const pending = [element];
2954
- for (let cursor = 0; cursor < pending.length; cursor += 1) {
2955
- const nodes = __velarDomChildNodes(pending[cursor]);
2956
- for (let child = 0; child < nodes.length; child += 1) {
2957
- const node = nodes[child];
2958
- if (__velarDomNodeType(node) !== 1) continue;
2959
- if (__velarDomOwnData(node, "__velarComponentNode") === true) continue;
2960
- if (__velarDomOwnData(node, "__velarHost") === true) __velarAppendOwned(explicit, node);
2961
- __velarAppendOwned(pending, node);
2962
- }
2963
- }
2964
- }
2965
- if (explicit.length === 1) return explicit[0];
2966
- if (explicit.length > 1) return "A component can declare only one host element";
2967
- // Nothing of this component's own is marked, so a single nested component
2968
- // root hands its host on. Two of them leave nothing to forward to, and the
2969
- // component has to mark a native element of its own to settle it.
2970
- if (forwarded.length === 1) return forwarded[0];
2971
- if (forwarded.length > 1) return "A component with multiple roots must mark exactly one native element with 'host'";
2972
- if (elements.length === 1) return elements[0];
2973
- return "A component with multiple roots must mark exactly one native element with 'host'";
2974
- }
2975
-
2976
- function __velarRootHost(root, capability) {
2977
- if (root == null) throw new TypeError("A component with multiple roots must mark exactly one native element with 'host'");
2978
- if (__velarDomNodeType(root) === 1) return root;
2979
- let resolved = __velarGraphWeakMapRead(__velarRootHosts, root);
2980
- if (resolved === undefined) {
2981
- resolved = __velarRootHostResolve(root);
2982
- __velarGraphWeakMapWrite(__velarRootHosts, root, resolved);
2983
- }
2984
- if (typeof resolved === "string") throw new TypeError(resolved);
2985
- return resolved;
2986
- }
2987
-
2988
- function __velarLookBindRoot(root, read, scope) {
2989
- const dynamic = __velarDynamicRootState(root);
2990
- if (!dynamic) {
2991
- __velarLookBind(__velarRootHost(root, "look"), read, scope);
2992
- return;
2993
- }
2994
- const source = { rules: __velarGraphCreateRecord() };
2995
- let host = null;
2996
- const move = (next) => {
2997
- __velarMoveLookSource(source, host, next);
2998
- host = next;
2999
- };
3000
- __velarGraphSetInsert(dynamic.listeners, move);
3001
- move(dynamic.host);
3002
- __velarObserver(() => {
3003
- source.rules = __velarLook([read()]).rules;
3004
- if (host) __velarApplyLooks(host);
3005
- }, "dom", scope);
3006
- __velarAppendOwned(scope.cleanups, () => {
3007
- __velarGraphSetRemove(dynamic.listeners, move);
3008
- move(null);
3009
- });
3010
- }
3011
-
3012
- function __velarClassBindRoot(root, read, scope) {
3013
- const dynamic = __velarDynamicRootState(root);
3014
- if (!dynamic) {
3015
- __velarClassBind(__velarRootHost(root, "class"), read, scope);
3016
- return;
3017
- }
3018
- const source = { names: [] };
3019
- let host = null;
3020
- const move = (next) => {
3021
- __velarMoveClassSource(source, host, next);
3022
- host = next;
3023
- };
3024
- __velarGraphSetInsert(dynamic.listeners, move);
3025
- move(dynamic.host);
3026
- __velarObserver(() => {
3027
- source.names = __velarClassNames(read());
3028
- if (host) __velarApplyClasses(host);
3029
- }, "dom", scope);
3030
- __velarAppendOwned(scope.cleanups, () => {
3031
- __velarGraphSetRemove(dynamic.listeners, move);
3032
- move(null);
3033
- });
3034
- }
3035
-
3036
- function __velarClassNames(value, output = []) {
3037
- if (value == null || value === false) return output;
3038
- if (__velarGraphIsList(value)) {
3039
- for (let index = 0; index < value.length; index += 1) __velarClassNames(value[index], output);
3040
- return output;
3041
- }
3042
- if (typeof value !== "string") throw new TypeError("class accepts strings, string?, or lists of strings");
3043
- let name = "";
3044
- for (let index = 0; index < value.length; index += 1) {
3045
- const character = value[index];
3046
- if (character === " " || character === "\t" || character === "\n" || character === "\r" || character === "\f" || character === "\v") {
3047
- if (name !== "") __velarAppendOwned(output, name);
3048
- name = "";
3049
- continue;
3050
- }
3051
- name += character;
3052
- }
3053
- if (name !== "") __velarAppendOwned(output, name);
3054
- return output;
3055
- }
3056
-
3057
- function __velarApplyClasses(element) {
3058
- const sources = __velarGraphWeakMapRead(__velarRuntime.classSources, element);
3059
- const next = __velarGraphCreateSet();
3060
- if (sources) {
3061
- for (const source of __velarGraphSetItems(sources)) {
3062
- for (let index = 0; index < source.names.length; index += 1) __velarGraphSetInsert(next, source.names[index]);
3063
- }
3064
- }
3065
- const state = __velarElementState(element, "__velarClassState", () => __velarGraphFreeze({
3066
- base: __velarGraphCreateSet(__velarDomClassNames(element)),
3067
- managed: __velarGraphCreateSet(),
3068
- }));
3069
- for (const name of __velarGraphSetItems(state.managed)) {
3070
- if (!__velarGraphSetContains(next, name) && !__velarGraphSetContains(state.base, name)) __velarDomClassRemove(element, name);
3071
- }
3072
- for (const name of __velarGraphSetItems(next)) __velarDomClassInsert(element, name);
3073
- __velarGraphSetEmpty(state.managed);
3074
- for (const name of __velarGraphSetItems(next)) __velarGraphSetInsert(state.managed, name);
3075
- }
3076
-
3077
- function __velarMoveClassSource(source, previous, next) {
3078
- if (previous) {
3079
- __velarDetachSource(__velarRuntime.classSources, previous, source);
3080
- __velarApplyClasses(previous);
3081
- }
3082
- if (next) {
3083
- __velarAttachSource(__velarRuntime.classSources, next, source);
3084
- __velarApplyClasses(next);
3085
- }
3086
- }
3087
-
3088
- function __velarClassBind(element, read, scope) {
3089
- const source = { names: [] };
3090
- __velarAttachSource(__velarRuntime.classSources, element, source);
3091
- __velarObserver(() => {
3092
- source.names = __velarClassNames(read());
3093
- __velarApplyClasses(element);
3094
- }, "dom", scope);
3095
- __velarAppendOwned(scope.cleanups, () => {
3096
- __velarDetachSource(__velarRuntime.classSources, element, source);
3097
- __velarApplyClasses(element);
3098
- });
3099
- }
3100
-
3101
- function __velarHtml(element, read, scope) {
3102
- __velarObserver(() => {
3103
- const value = read();
3104
- if (value != null && typeof value !== "string") throw new TypeError("unsafe:html requires string or null");
3105
- if (value?.length > 16 * 1024 * 1024) throw new RangeError("unsafe:html cannot exceed 16 MiB");
3106
- __velarDomSetHtml(element, value ?? "");
3107
- }, "dom", scope);
3108
- }
3109
-
3110
- function __velarOn(element, event, read, scope, modifiers = []) {
3111
- if (typeof __velarInternalRead(read) !== "function") throw new TypeError("Event '" + event + "' requires a function");
3112
- const capture = __velarHasName(modifiers, "capture");
3113
- const once = __velarHasName(modifiers, "once");
3114
- let removed = false;
3115
- const remove = () => {
3116
- if (removed) return;
3117
- removed = true;
3118
- __velarDomRemoveListener(element, event, listener, capture);
3119
- };
3120
- const listener = (value) => {
3121
- try {
3122
- if (__velarHasName(modifiers, "self")) {
3123
- const target = __velarEventField(value, "target", __velarEventTargetGetter);
3124
- if (target === __velarEventMissingField) throw new TypeError("DOM event does not expose a native target");
3125
- if (target !== element) return;
3126
- }
3127
- // 'once' is spent here rather than through the native option, so the
3128
- // documented order -- self, then prevent, then stop, then the handler --
3129
- // holds for it too. The native option removes the registration on the
3130
- // first dispatch that merely reaches the element, which for 'self' is
3131
- // exactly the dispatch the handler must not see: 'on:click.self.once'
3132
- // could then never run at all.
3133
- if (once) remove();
3134
- if (__velarHasName(modifiers, "prevent")) __velarEventCall(value, "preventDefault", __velarEventPreventDefault);
3135
- if (__velarHasName(modifiers, "stop")) __velarEventCall(value, "stopPropagation", __velarEventStopPropagation);
3136
- // The handler expression is re-read per dispatch so handlers routed
3137
- // through live props always see the current value.
3138
- const handler = __velarInternalRead(read);
3139
- if (typeof handler !== "function") throw new TypeError("Event '" + event + "' requires a function");
3140
- const result = __velarUntracked(() => handler(value));
3141
- __velarObservePromise(result, (error) => __velarReportEvent(error, scope, event));
3142
- } catch (error) { __velarReportEvent(error, scope, event); }
3143
- };
3144
- __velarDomAddListener(element, event, listener, { capture });
3145
- __velarAppendOwned(scope.cleanups, remove);
3146
- }
3147
-
3148
- function __velarBindValue(element, state, scope, numeric = false, parse = null) {
3149
- __velarObserver(() => {
3150
- const value = state.get();
3151
- if (value == null) __velarDomSetFieldValue(element, "");
3152
- else if (numeric) {
3153
- if (typeof value !== "number" || !__velarDomIsFinite(value)) throw new TypeError("Numeric bind:value requires a finite number");
3154
- __velarDomSetFieldValue(element, __velarDomString(value));
3155
- } else {
3156
- if (typeof value !== "string") throw new TypeError("bind:value requires text");
3157
- __velarDomSetFieldValue(element, value);
3158
- }
3159
- }, "dom", scope);
3160
- const update = () => state.set(numeric ? __velarDomFieldNumber(element) : parse ? parse(__velarDomFieldValue(element)) : __velarDomFieldValue(element));
3161
- __velarDomAddListener(element, "input", update, false);
3162
- __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "input", update, false));
3163
- }
3164
-
3165
- function __velarBindGroupValues(state, own) {
3166
- const value = __velarInternalRead(() => state.get());
3167
- const values = __velarListSnapshot(value, "bind:group state");
3168
- const output = new __velarDomNativeArray(values.length);
3169
- let count = 0;
3170
- for (let index = 0; index < values.length; index += 1) {
3171
- const item = values[index];
3172
- if (typeof item !== "string") throw new TypeError("bind:group on a checkbox requires List<string> state");
3173
- if (item !== own) { output[count] = item; count += 1; }
3174
- }
3175
- output.length = count;
3176
- return output;
3177
- }
3178
-
3179
- function __velarBindGroup(element, state, scope, multiple = false, parse = null) {
3180
- __velarObserver(() => {
3181
- const own = __velarDomFieldValue(element);
3182
- const value = state.get();
3183
- if (!multiple) {
3184
- if (value != null && typeof value !== "string") throw new TypeError("bind:group requires text state");
3185
- __velarDomSetFieldChecked(element, value === own);
3186
- return;
3187
- }
3188
- const values = __velarListSnapshot(value, "bind:group state");
3189
- let present = false;
3190
- for (let index = 0; index < values.length; index += 1) if (values[index] === own) present = true;
3191
- __velarDomSetFieldChecked(element, present);
3192
- }, "dom", scope);
3193
- const update = () => {
3194
- const own = __velarDomFieldValue(element);
3195
- if (!multiple) {
3196
- if (__velarDomFieldChecked(element)) state.set(parse ? parse(own) : own);
3197
- return;
3198
- }
3199
- const remaining = __velarBindGroupValues(state, own);
3200
- if (__velarDomFieldChecked(element)) remaining[remaining.length] = own;
3201
- state.set(remaining);
3202
- };
3203
- __velarDomAddListener(element, "change", update, false);
3204
- __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "change", update, false));
3205
- }
3206
-
3207
- function __velarBindChecked(element, state, scope) {
3208
- __velarObserver(() => {
3209
- const value = state.get();
3210
- if (typeof value !== "boolean") throw new TypeError("bind:checked requires bool");
3211
- __velarDomSetFieldChecked(element, value);
3212
- }, "dom", scope);
3213
- const update = () => state.set(__velarDomFieldChecked(element));
3214
- __velarDomAddListener(element, "change", update, false);
3215
- __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "change", update, false));
3216
- }
3217
-
3218
- // Prop handles give a component body live reads over its props store. The
3219
- // component function still runs exactly once per instance; only reads race
3220
- // ahead, so state initializers can never re-run on a prop update.
3221
- function __velarPropProvided(props, name) {
3222
- // A children slot is rendered content rather than a value thunk. Asking for
3223
- // its value to decide whether the required slot exists would build the slot
3224
- // once here and again at the JSX position that owns it. Its own property is
3225
- // the presence proof; the first value read remains the one rendering read.
3226
- if (name === "children") return __velarGraphOwnDescriptor(props, name) !== undefined;
3227
- return __velarInternalRead(() => props[name]) !== undefined;
3228
- }
3229
-
3230
- function __velarRequiredProp(props, name, component) {
3231
- if (!__velarPropProvided(props, name)) throw new TypeError("Component " + component + " requires prop " + name);
3232
- return __velarGraphFreeze({
3233
- get() {
3234
- const value = props[name];
3235
- if (value === undefined) throw new TypeError("Component " + component + " requires prop " + name);
3236
- return value;
3237
- },
3238
- });
3239
- }
3240
-
3241
- function __velarProp(props, name, fallback) {
3242
- const fallbackValue = __velarPropProvided(props, name) ? undefined : fallback();
3243
- return __velarGraphFreeze({
3244
- get() {
3245
- const value = props[name];
3246
- return value === undefined ? fallbackValue : value;
3247
- },
3248
- });
3249
- }
3250
-
3251
- function __velarBindComponentRef(instance, setRef) {
3252
- if (setRef === undefined) return instance;
3253
- if (!instance || typeof instance.__bindRef !== "function") throw new TypeError("This component does not expose a Handle");
3254
- instance.__bindRef(setRef);
3255
- return instance;
3256
- }
3257
-
3258
- // Holds every prop's cache open for the length of one construction. The graph
3259
- // records a dependency for whichever observer is running, so forcing the props
3260
- // under this one keeps them clean while the component function runs: a read
3261
- // during construction is served from the value the force produced, and a
3262
- // tracked read still subscribes the observer that made it. Releasing the hold
3263
- // hands each prop over to whatever actually observes it, which is the second
3264
- // half of the rule -- recomputed on demand, cached while observed.
3265
- function __velarConstructionHold() {
3266
- return {
3267
- mode: "computed",
3268
- stopped: false,
3269
- running: false,
3270
- selfInvalidations: 0,
3271
- dependencies: __velarGraphCreateSet(),
3272
- spareDependencies: null,
3273
- notify() {},
3274
- run() {},
3275
- };
3276
- }
3277
-
3278
- // Instantiates a component with a live props store: each prop is a cached
3279
- // derived value the props object exposes as a tracked getter, so a prop
3280
- // expression that nothing reads costs nothing after construction. The component
3281
- // call itself is untracked so construction can never subscribe an enclosing
3282
- // dynamic region to prop reads.
3283
- function __velarInstantiate(component, thunks, children, scope, namespace, setRef) {
3284
- const props = {};
3285
- // 'style:' on a component host is the caller decorating the instance's root,
3286
- // the way it decorates a native element. The slot the compiler inserts for it
3287
- // is not a field the component declares, so it is bound here rather than
3288
- // handed inward -- a component the runtime implements validates its props
3289
- // against the fields it does declare and would refuse an unknown one.
3290
- const styleRead = thunks.__velarStyle;
3291
- const propNames = __velarGraphOwnNames(thunks);
3292
- const accesses = [];
3293
- for (let index = 0; index < propNames.length; index += 1) {
3294
- const name = propNames[index];
3295
- if (name === "__velarStyle") continue;
3296
- // A prop is a derived value, not an eagerly pushed one: an unconditional
3297
- // observer per prop re-ran every prop expression on every dependency
3298
- // change, including the expensive ones behind props the component never
3299
- // reads. The cache is the same one a declared derived value uses.
3300
- const access = __velarComputed(thunks[name]);
3301
- accesses[accesses.length] = access;
3302
- __velarGraphDefine(props, name, { enumerable: true, get: () => access.get() });
3303
- }
3304
- // 'children' follows Vel's ordinary rules: it is rendered content owned by
3305
- // the position that shows it, rebuilt whenever that position renders again.
3306
- // As a one-shot fragment value it could be shown exactly once, and the first
3307
- // time a conditional position hid it the content was destroyed for good.
3308
- if (children !== undefined) __velarGraphDefine(props, "children", { enumerable: true, get: () => __velarChildrenNode(children, scope) });
3309
- const instance = __velarUntracked(() => {
3310
- if (accesses.length === 0) return component(props, namespace);
3311
- // Component JSX evaluates the way the charter says a JavaScript object
3312
- // literal does: every prop expression runs once, in the order the caller
3313
- // wrote it, and only then does the component function run. 'children' is
3314
- // not one of them -- it is rendered content owned by the position that
3315
- // shows it, so a position that never shows it never builds it.
3316
- const hold = __velarConstructionHold();
3317
- try {
3318
- __velarRuntime.runTracked(hold, () => {
3319
- for (let index = 0; index < accesses.length; index += 1) accesses[index].get();
3320
- });
3321
- return component(props, namespace);
3322
- } finally { __velarCleanupObserver(hold); }
3323
- });
3324
- if (styleRead !== undefined) __velarStyleBindRoot(instance.node, styleRead, scope);
3325
- return __velarBindComponentRef(instance, setRef);
3326
- }
3327
-
3328
- // A component element in child position: one stable instance whose prop
3329
- // observers live in a dedicated scope, destroyed only when the position
3330
- // itself unmounts. Construction failures stay contained to the position.
3331
- function __velarChild(component, thunks, children, scope, namespace, setRef) {
3332
- const childScope = __velarScope(scope.component);
3333
- let constructed = false;
3334
- __velarAppendOwned(scope.mounts, () => { if (constructed) __velarMountScope(childScope); });
3335
- __velarAppendOwned(scope.cleanups, () => { if (constructed) __velarDestroyScope(childScope); });
3336
- try {
3337
- const node = __velarUseComponent(__velarInstantiate(component, thunks, children, childScope, namespace, setRef), childScope);
3338
- constructed = true;
3339
- return node;
3340
- } catch (error) {
3341
- __velarDestroyScope(childScope);
3342
- __velarReport(error, "render", scope);
3343
- return __velarDomCreateComment("velar:component-error");
3344
- }
3345
- }
3346
-
3347
- // tick() promises the settled flush, so it drains the reactive queues instead
3348
- // of hopping one microtask and hoping. Each round runs the pending flush and
3349
- // yields, so work an observer queued asynchronously is picked up too; the round
3350
- // count is bounded for the same reason the flush budget is, and the flush's own
3351
- // budget is what ends a runaway cycle.
3352
- function __velarSettledStep() {
3353
- return __velarManagedAsyncCreate((resolve) => __velarEnqueue(resolve));
3354
- }
3355
-
3356
- function __velarSettled(rounds = 10000) {
3357
- return __velarManagedAsyncThen(__velarSettledStep(), () => {
3358
- if (__velarRuntime.flushPending) __velarFlush();
3359
- if (rounds > 1 && (__velarGraphSetCount(__velarRuntime.domQueue)
3360
- || __velarGraphSetCount(__velarRuntime.watchQueue) || __velarRuntime.flushPending)) {
3361
- return __velarSettled(rounds - 1);
3362
- }
3363
- return null;
3364
- });
3365
- }
3366
-
3367
- function __velarTakeUnhandledFailure() {
3368
- for (const failure of __velarGraphSetItems(__velarRuntime.unhandledFailures)) {
3369
- __velarGraphSetRemove(__velarRuntime.unhandledFailures, failure);
3370
- return failure;
3371
- }
3372
- return null;
3373
- }
3374
-
3375
- // In a non-browser host an unhandled report cannot throw from a microtask
3376
- // without ending the whole process, so the runtime parks it. tick() is where
3377
- // an awaiting caller meets the reactive queue, which makes it the owned place
3378
- // for that parked failure to surface: the test that awaited the flush fails
3379
- // with the real error and the process -- the test runner -- continues.
3380
- function __velarTick() {
3381
- return __velarManagedAsyncThen(__velarSettled(), () => {
3382
- const failure = __velarTakeUnhandledFailure();
3383
- if (failure !== null) throw failure;
3384
- return null;
3385
- });
3386
- }
3387
- `.trim();
1304
+ /**
1305
+ * The runtime an emitted Web program carries inside itself: the foundation it
1306
+ * installs, the CSS string serializer, the closed keyword sets of the Look
1307
+ * properties *this* module styles, and the runtime body. Only the keyword table
1308
+ * differs per compilation, which is why it is the one hole
1309
+ * `runtime/manifest.json` records as an assembly (LOK-U13 keeps the serializer
1310
+ * the one css-string.ts publishes rather than a second spelling of it).
1311
+ */
3388
1312
  function webRuntime(foundation, lookKeywords) {
3389
- // `content` is written as a CSS string, which is not a JSON string, so the
3390
- // runtime carries the serializer css-string.ts publishes rather than a second
3391
- // spelling of it (LOK-U13).
3392
- return `${foundation}\n${CSS_STRING_RUNTIME.trim()}\n${lookKeywords}\n${WEB_RUNTIME_BODY}`;
1313
+ return `${foundation}\n${CSS_STRING_RUNTIME_BODY}${lookKeywords}\n${WEB_RUNTIME_BODY}`;
3393
1314
  }
3394
1315
  //# sourceMappingURL=emitter.js.map