@gyral/core 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/NOTICE +19 -0
- package/README.md +36 -8
- package/dist/call.d.ts +32 -0
- package/dist/call.js +63 -0
- package/dist/call.js.map +1 -0
- package/dist/children.d.ts +25 -3
- package/dist/children.js +18 -1
- package/dist/children.js.map +1 -1
- package/dist/cli/gyral-types.d.ts +2 -0
- package/dist/cli/gyral-types.js +23 -0
- package/dist/cli/gyral-types.js.map +1 -0
- package/dist/command.d.ts +54 -12
- package/dist/command.js +25 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +2 -0
- package/dist/compiler/ast.js +5 -1
- package/dist/compiler/ast.js.map +1 -1
- package/dist/compiler/compile.d.ts +5 -2
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/component-entries.d.ts +7 -0
- package/dist/compiler/component-entries.js +42 -0
- package/dist/compiler/component-entries.js.map +1 -0
- package/dist/compiler/components.d.ts +4 -0
- package/dist/compiler/components.js +190 -0
- package/dist/compiler/components.js.map +1 -0
- package/dist/compiler/facts.d.ts +31 -0
- package/dist/compiler/facts.js +285 -0
- package/dist/compiler/facts.js.map +1 -0
- package/dist/compiler/features.d.ts +34 -0
- package/dist/compiler/features.js +158 -0
- package/dist/compiler/features.js.map +1 -0
- package/dist/compiler/hooks.d.ts +4 -0
- package/dist/compiler/hooks.js +144 -89
- package/dist/compiler/hooks.js.map +1 -1
- package/dist/compiler/loader-source.d.ts +14 -0
- package/dist/compiler/loader-source.js +86 -0
- package/dist/compiler/loader-source.js.map +1 -0
- package/dist/compiler/locate.d.ts +14 -0
- package/dist/compiler/locate.js +90 -0
- package/dist/compiler/locate.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +1 -1
- package/dist/compiler/parse5-check.js +8 -3
- package/dist/compiler/parse5-check.js.map +1 -1
- package/dist/compiler/prop-schemas.d.ts +4 -0
- package/dist/compiler/prop-schemas.js +108 -0
- package/dist/compiler/prop-schemas.js.map +1 -0
- package/dist/compiler/scan.d.ts +13 -3
- package/dist/compiler/scan.js +21 -13
- package/dist/compiler/scan.js.map +1 -1
- package/dist/compiler/scope.d.ts +8 -0
- package/dist/compiler/scope.js +116 -0
- package/dist/compiler/scope.js.map +1 -0
- package/dist/compiler/tag-map.d.ts +41 -0
- package/dist/compiler/tag-map.js +126 -0
- package/dist/compiler/tag-map.js.map +1 -0
- package/dist/components-ready.d.ts +7 -0
- package/dist/components-ready.js +19 -0
- package/dist/components-ready.js.map +1 -0
- package/dist/define.d.ts +12 -4
- package/dist/define.js +8 -12
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +8 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +3 -0
- package/dist/devtools.js +14 -0
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-internals.d.ts +1 -0
- package/dist/element-internals.js +11 -0
- package/dist/element-internals.js.map +1 -0
- package/dist/element-types.d.ts +7 -4
- package/dist/element-types.js.map +1 -1
- package/dist/element.js +80 -27
- package/dist/element.js.map +1 -1
- package/dist/error-view.d.ts +10 -0
- package/dist/error-view.js +30 -0
- package/dist/error-view.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/errors.json +289 -0
- package/dist/eslint/imports.d.ts +2 -0
- package/dist/eslint/imports.js +2 -2
- package/dist/eslint/imports.js.map +1 -1
- package/dist/eslint/index.d.ts +2 -1
- package/dist/eslint/index.js +11 -3
- package/dist/eslint/index.js.map +1 -1
- package/dist/eslint/template-rule.d.ts +1 -0
- package/dist/eslint/template-rule.js +15 -5
- package/dist/eslint/template-rule.js.map +1 -1
- package/dist/eslint/unused-intent-rule.d.ts +2 -0
- package/dist/eslint/unused-intent-rule.js +186 -0
- package/dist/eslint/unused-intent-rule.js.map +1 -0
- package/dist/features.d.ts +2 -2
- package/dist/features.js.map +1 -1
- package/dist/focus.d.ts +6 -0
- package/dist/focus.js +32 -2
- package/dist/focus.js.map +1 -1
- package/dist/form-associated.d.ts +46 -0
- package/dist/form-associated.js +77 -0
- package/dist/form-associated.js.map +1 -0
- package/dist/forms.d.ts +42 -30
- package/dist/forms.js +85 -41
- package/dist/forms.js.map +1 -1
- package/dist/frame-lane.d.ts +11 -0
- package/dist/frame-lane.js +28 -0
- package/dist/frame-lane.js.map +1 -0
- package/dist/head.d.ts +61 -0
- package/dist/head.js +85 -0
- package/dist/head.js.map +1 -0
- package/dist/host-model.d.ts +34 -5
- package/dist/host-model.js +146 -23
- package/dist/host-model.js.map +1 -1
- package/dist/hydration-client.js +2 -2
- package/dist/hydration-client.js.map +1 -1
- package/dist/hydration-loader.d.ts +13 -0
- package/dist/hydration-loader.js +58 -0
- package/dist/hydration-loader.js.map +1 -0
- package/dist/hydration-off.d.ts +8 -0
- package/dist/hydration-off.js +25 -0
- package/dist/hydration-off.js.map +1 -0
- package/dist/hydration.d.ts +0 -12
- package/dist/hydration.js +3 -52
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +21 -24
- package/dist/index.js +10 -19
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-types.d.ts +97 -0
- package/dist/indexeddb-types.js +2 -0
- package/dist/indexeddb-types.js.map +1 -0
- package/dist/indexeddb.d.ts +5 -0
- package/dist/indexeddb.js +118 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/intent.d.ts +42 -20
- package/dist/intent.js +145 -107
- package/dist/intent.js.map +1 -1
- package/dist/internal/indexeddb-open.d.ts +8 -0
- package/dist/internal/indexeddb-open.js +96 -0
- package/dist/internal/indexeddb-open.js.map +1 -0
- package/dist/internal/indexeddb-transaction.d.ts +4 -0
- package/dist/internal/indexeddb-transaction.js +134 -0
- package/dist/internal/indexeddb-transaction.js.map +1 -0
- package/dist/internal/interpreter.d.ts +12 -4
- package/dist/internal/interpreter.js +36 -48
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/internal/token.d.ts +1 -0
- package/dist/internal/token.js +7 -0
- package/dist/internal/token.js.map +1 -0
- package/dist/internal.d.ts +20 -0
- package/dist/internal.js +22 -0
- package/dist/internal.js.map +1 -0
- package/dist/invoker-fallback-used.d.ts +4 -0
- package/dist/invoker-fallback-used.js +10 -0
- package/dist/invoker-fallback-used.js.map +1 -0
- package/dist/invoker-fallback.d.ts +4 -0
- package/dist/invoker-fallback.js +15 -0
- package/dist/invoker-fallback.js.map +1 -0
- package/dist/light-dom.d.ts +1 -1
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +30 -7
- package/dist/prop.js +19 -0
- package/dist/prop.js.map +1 -1
- package/dist/props.d.ts +8 -3
- package/dist/props.js +22 -15
- package/dist/props.js.map +1 -1
- package/dist/retry.d.ts +15 -0
- package/dist/retry.js +48 -0
- package/dist/retry.js.map +1 -0
- package/dist/scheduler.d.ts +7 -3
- package/dist/scheduler.js +38 -56
- package/dist/scheduler.js.map +1 -1
- package/dist/script-json.d.ts +2 -0
- package/dist/script-json.js +13 -0
- package/dist/script-json.js.map +1 -0
- package/dist/server-component.d.ts +1 -1
- package/dist/server-component.js +45 -14
- package/dist/server-component.js.map +1 -1
- package/dist/server.d.ts +9 -3
- package/dist/server.js +12 -3
- package/dist/server.js.map +1 -1
- package/dist/settled.d.ts +4 -3
- package/dist/settled.js +48 -26
- package/dist/settled.js.map +1 -1
- package/dist/spec-features-used.d.ts +21 -0
- package/dist/spec-features-used.js +50 -0
- package/dist/spec-features-used.js.map +1 -0
- package/dist/spec-features.d.ts +28 -0
- package/dist/spec-features.js +42 -0
- package/dist/spec-features.js.map +1 -0
- package/dist/states.d.ts +3 -5
- package/dist/states.js +22 -8
- package/dist/states.js.map +1 -1
- package/dist/storage.d.ts +69 -0
- package/dist/storage.js +158 -0
- package/dist/storage.js.map +1 -0
- package/dist/store-binding.js +2 -2
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +2 -4
- package/dist/store-scope.js +6 -16
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +2 -6
- package/dist/store.js +36 -8
- package/dist/store.js.map +1 -1
- package/dist/subscription.d.ts +35 -0
- package/dist/subscription.js +74 -0
- package/dist/subscription.js.map +1 -0
- package/dist/subscriptions.d.ts +26 -0
- package/dist/subscriptions.js +98 -0
- package/dist/subscriptions.js.map +1 -0
- package/dist/transitions.d.ts +4 -5
- package/dist/transitions.js +10 -4
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +141 -32
- package/dist/types.js.map +1 -1
- package/dist/use-dialogs.d.ts +2 -0
- package/dist/use-dialogs.js +9 -0
- package/dist/use-dialogs.js.map +1 -0
- package/dist/use-disposal.d.ts +2 -0
- package/dist/use-disposal.js +9 -0
- package/dist/use-disposal.js.map +1 -0
- package/dist/use-error-view.d.ts +2 -0
- package/dist/use-error-view.js +9 -0
- package/dist/use-error-view.js.map +1 -0
- package/dist/use-errored.d.ts +2 -0
- package/dist/use-errored.js +9 -0
- package/dist/use-errored.js.map +1 -0
- package/dist/use-form-associated.d.ts +2 -0
- package/dist/use-form-associated.js +7 -0
- package/dist/use-form-associated.js.map +1 -0
- package/dist/use-frame-lane.d.ts +2 -0
- package/dist/use-frame-lane.js +10 -0
- package/dist/use-frame-lane.js.map +1 -0
- package/dist/use-invokers.d.ts +2 -0
- package/dist/use-invokers.js +10 -0
- package/dist/use-invokers.js.map +1 -0
- package/dist/use-states.d.ts +2 -0
- package/dist/use-states.js +10 -0
- package/dist/use-states.js.map +1 -0
- package/dist/use-subscriptions.d.ts +2 -0
- package/dist/use-subscriptions.js +10 -0
- package/dist/use-subscriptions.js.map +1 -0
- package/dist/use-transitions.d.ts +2 -0
- package/dist/use-transitions.js +10 -0
- package/dist/use-transitions.js.map +1 -0
- package/dist/view/attributes.d.ts +5 -0
- package/dist/view/attributes.js +5 -0
- package/dist/view/attributes.js.map +1 -1
- package/dist/view/compiled.d.ts +1 -1
- package/dist/view/compiled.js +1 -1
- package/dist/view/compiled.js.map +1 -1
- package/dist/view/index.d.ts +9 -4
- package/dist/view/index.js +9 -3
- package/dist/view/index.js.map +1 -1
- package/dist/view/loc.d.ts +9 -0
- package/dist/view/loc.js +50 -0
- package/dist/view/loc.js.map +1 -0
- package/dist/view/message.d.ts +17 -0
- package/dist/view/message.js +40 -0
- package/dist/view/message.js.map +1 -0
- package/dist/view/messages.d.ts +43 -0
- package/dist/view/messages.js +84 -0
- package/dist/view/messages.js.map +1 -0
- package/dist/view/normalize/check.d.ts +5 -2
- package/dist/view/normalize/check.js +6 -3
- package/dist/view/normalize/check.js.map +1 -1
- package/dist/view/normalize/emit.d.ts +2 -0
- package/dist/view/normalize/emit.js +40 -11
- package/dist/view/normalize/emit.js.map +1 -1
- package/dist/view/normalize/errors.js +1 -1
- package/dist/view/normalize/errors.js.map +1 -1
- package/dist/view/normalize/id.d.ts +5 -2
- package/dist/view/normalize/id.js +9 -2
- package/dist/view/normalize/id.js.map +1 -1
- package/dist/view/normalize/normalize.d.ts +7 -4
- package/dist/view/normalize/normalize.js +15 -9
- package/dist/view/normalize/normalize.js.map +1 -1
- package/dist/view/normalize/rules.d.ts +9 -0
- package/dist/view/normalize/rules.js +35 -5
- package/dist/view/normalize/rules.js.map +1 -1
- package/dist/view/normalize/svg.d.ts +14 -0
- package/dist/view/normalize/svg.js +40 -0
- package/dist/view/normalize/svg.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +5 -1
- package/dist/view/normalize/tokens.js.map +1 -1
- package/dist/view/normalize/tree.d.ts +8 -2
- package/dist/view/normalize/tree.js +58 -13
- package/dist/view/normalize/tree.js.map +1 -1
- package/dist/view/normalize/types.d.ts +24 -4
- package/dist/view/normalize/types.js +4 -1
- package/dist/view/normalize/types.js.map +1 -1
- package/dist/view/normalize/whitespace.js +4 -3
- package/dist/view/normalize/whitespace.js.map +1 -1
- package/dist/view/prepare-stub.js +2 -2
- package/dist/view/prepare-stub.js.map +1 -1
- package/dist/view/prepare.d.ts +5 -2
- package/dist/view/prepare.js +9 -3
- package/dist/view/prepare.js.map +1 -1
- package/dist/view/registry.d.ts +15 -0
- package/dist/view/registry.js +10 -2
- package/dist/view/registry.js.map +1 -1
- package/dist/view/render/adopt-attr.js +7 -1
- package/dist/view/render/adopt-attr.js.map +1 -1
- package/dist/view/render/adopt.js +21 -4
- package/dist/view/render/adopt.js.map +1 -1
- package/dist/view/render/attr-parts.d.ts +12 -1
- package/dist/view/render/attr-parts.js +38 -5
- package/dist/view/render/attr-parts.js.map +1 -1
- package/dist/view/render/child-part.js +5 -2
- package/dist/view/render/child-part.js.map +1 -1
- package/dist/view/render/dispose.d.ts +3 -0
- package/dist/view/render/dispose.js +76 -0
- package/dist/view/render/dispose.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -1
- package/dist/view/render/hook-part.js +21 -5
- package/dist/view/render/hook-part.js.map +1 -1
- package/dist/view/render/hook-run.d.ts +2 -0
- package/dist/view/render/hook-run.js +72 -0
- package/dist/view/render/hook-run.js.map +1 -0
- package/dist/view/render/hooks.d.ts +74 -6
- package/dist/view/render/hooks.js +79 -17
- package/dist/view/render/hooks.js.map +1 -1
- package/dist/view/render/hydrate.js +2 -2
- package/dist/view/render/hydrate.js.map +1 -1
- package/dist/view/render/keyed.d.ts +6 -0
- package/dist/view/render/keyed.js +15 -0
- package/dist/view/render/keyed.js.map +1 -0
- package/dist/view/render/list.d.ts +1 -1
- package/dist/view/render/list.js.map +1 -1
- package/dist/view/render/mismatch.js +5 -3
- package/dist/view/render/mismatch.js.map +1 -1
- package/dist/view/render/modal.d.ts +3 -0
- package/dist/view/render/modal.js +39 -0
- package/dist/view/render/modal.js.map +1 -0
- package/dist/view/render/raw.d.ts +4 -1
- package/dist/view/render/raw.js +6 -2
- package/dist/view/render/raw.js.map +1 -1
- package/dist/view/render/render.d.ts +4 -1
- package/dist/view/render/render.js +17 -12
- package/dist/view/render/render.js.map +1 -1
- package/dist/view/render/toggles.d.ts +6 -0
- package/dist/view/render/toggles.js +6 -0
- package/dist/view/render/toggles.js.map +1 -0
- package/dist/view/render/values.d.ts +1 -1
- package/dist/view/render/values.js.map +1 -1
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +45 -0
- package/dist/view/render/warn.js.map +1 -1
- package/dist/view/server/component.d.ts +6 -3
- package/dist/view/server/component.js +29 -7
- package/dist/view/server/component.js.map +1 -1
- package/dist/view/server/index.d.ts +20 -0
- package/dist/view/server/index.js +12 -4
- package/dist/view/server/index.js.map +1 -1
- package/dist/view/server/tags.d.ts +13 -2
- package/dist/view/server/tags.js +13 -2
- package/dist/view/server/tags.js.map +1 -1
- package/dist/view/server/values.d.ts +2 -0
- package/dist/view/server/values.js +8 -0
- package/dist/view/server/values.js.map +1 -1
- package/dist/view/server/writer.d.ts +9 -4
- package/dist/view/server/writer.js +33 -18
- package/dist/view/server/writer.js.map +1 -1
- package/dist/view/template-element.d.ts +7 -0
- package/dist/view/template-element.js +25 -5
- package/dist/view/template-element.js.map +1 -1
- package/dist/view/template.d.ts +9 -2
- package/dist/view/template.js +61 -8
- package/dist/view/template.js.map +1 -1
- package/dist/view/trusted-html.d.ts +6 -0
- package/dist/view/trusted-html.js +34 -0
- package/dist/view/trusted-html.js.map +1 -0
- package/dist/vite.d.ts +38 -31
- package/dist/vite.js +206 -31
- package/dist/vite.js.map +1 -1
- package/package.json +34 -3
- package/dist/hooks/labelled-by.d.ts +0 -13
- package/dist/hooks/labelled-by.js +0 -51
- package/dist/hooks/labelled-by.js.map +0 -1
- package/dist/random.d.ts +0 -13
- package/dist/random.js +0 -19
- package/dist/random.js.map +0 -1
package/dist/element.js
CHANGED
|
@@ -3,26 +3,36 @@
|
|
|
3
3
|
// through the global scheduler (view/04-scheduler.md); intents are delegated listeners on the
|
|
4
4
|
// root (ADR 0001). The model side (state, commands, stores) is host-model.ts.
|
|
5
5
|
import { DEVTOOLS_ENABLED, devConnect, devHydrated } from '#devtools';
|
|
6
|
+
import { fail } from './errors.js';
|
|
6
7
|
import { HostModel } from './host-model.js';
|
|
7
|
-
import { hydrationCode, takeSeed, whenHydrationLoads } from '
|
|
8
|
+
import { hydrationCode, takeSeed, whenHydrationLoads } from '#hydration-loader';
|
|
8
9
|
import { DEFAULT_EVENTS, eventsOf, handleIntent, hostDepth, intentNames, listenForIntents, } from './intent.js';
|
|
9
10
|
import { isLight } from './light-dom.js';
|
|
10
11
|
import { features } from './features.js';
|
|
11
12
|
import { afterRender, markDirty, POST_HYDRATED, POST_INIT, POST_STATES, } from './scheduler.js';
|
|
12
|
-
import {
|
|
13
|
-
import { render, sheetsFor } from './view/index.js';
|
|
13
|
+
import { checkSpecFeatures, customStates, errorView, formAssociation } from '#spec-features';
|
|
14
|
+
import { DEV, ERROR_ATTRIBUTE, message, onHookFailure, render, sheetsFor, suspendHooks, } from './view/index.js';
|
|
14
15
|
const DEFER = 'defer-hydration';
|
|
16
|
+
// A hook that throws is reported for the host owning the render root (ADR 0024).
|
|
17
|
+
onHookFailure((error, root) => {
|
|
18
|
+
const host = root instanceof ShadowRoot ? root.host : root;
|
|
19
|
+
fail(error, 'hook', message(75, host.localName), { host, tag: host.localName });
|
|
20
|
+
});
|
|
15
21
|
/** The element class for `spec` (not yet registered); define() types it for the spec. */
|
|
16
22
|
export function elementClass(tag, spec) {
|
|
17
23
|
const table = (spec.props ?? {});
|
|
18
24
|
const names = Object.keys(table);
|
|
19
25
|
// Registered by the prop builders (features.ts): set whenever a component declares props.
|
|
20
26
|
const props = features.props;
|
|
27
|
+
/** Property sets and seeds: checked in development, kept as given in production (05). */
|
|
28
|
+
const checked = (props) => props.propertyValue;
|
|
21
29
|
const attrs = new Map();
|
|
22
30
|
const light = isLight(spec);
|
|
23
31
|
let sheets;
|
|
24
|
-
const parsers = spec.intent;
|
|
32
|
+
const parsers = (spec.intent ?? {});
|
|
25
33
|
const model = spec;
|
|
34
|
+
if (DEV)
|
|
35
|
+
checkSpecFeatures(tag, spec);
|
|
26
36
|
class Element extends HTMLElement {
|
|
27
37
|
static { this.spec = spec; }
|
|
28
38
|
static { this.tagName = tag; }
|
|
@@ -42,7 +52,7 @@ export function elementClass(tag, spec) {
|
|
|
42
52
|
return this.#values[name];
|
|
43
53
|
},
|
|
44
54
|
set(value) {
|
|
45
|
-
this.#write(name, props
|
|
55
|
+
this.#write(name, DEV ? checked(props)(tag, name, table[name], value) : value);
|
|
46
56
|
},
|
|
47
57
|
});
|
|
48
58
|
}
|
|
@@ -57,7 +67,6 @@ export function elementClass(tag, spec) {
|
|
|
57
67
|
#hydrating = false;
|
|
58
68
|
/** init's commands for a server-rendered host: started after its first render. */
|
|
59
69
|
#afterInit = [];
|
|
60
|
-
#states;
|
|
61
70
|
#task = {
|
|
62
71
|
tag,
|
|
63
72
|
depth: 0,
|
|
@@ -88,6 +97,7 @@ export function elementClass(tag, spec) {
|
|
|
88
97
|
Reflect.deleteProperty(this, name);
|
|
89
98
|
self[name] = value;
|
|
90
99
|
}
|
|
100
|
+
formAssociation?.create(this, this.#model, spec.formAssociated);
|
|
91
101
|
}
|
|
92
102
|
get state() {
|
|
93
103
|
return this.#state();
|
|
@@ -114,6 +124,9 @@ export function elementClass(tag, spec) {
|
|
|
114
124
|
}
|
|
115
125
|
disconnectedCallback() {
|
|
116
126
|
this.#model.disconnect();
|
|
127
|
+
// Element hooks' dispose; they run client again after the render on reconnect (02).
|
|
128
|
+
if (suspendHooks(this.#root))
|
|
129
|
+
this.#stale = true;
|
|
117
130
|
if (DEVTOOLS_ENABLED)
|
|
118
131
|
devConnect(this, tag, false);
|
|
119
132
|
}
|
|
@@ -128,7 +141,8 @@ export function elementClass(tag, spec) {
|
|
|
128
141
|
this.#write(prop, props.attributeValue(tag, prop, table[prop], name, raw));
|
|
129
142
|
}
|
|
130
143
|
#write(name, value) {
|
|
131
|
-
|
|
144
|
+
// The prop's `equals` (prop.ts): `Object.is`, the same JSON for prop.json, or the option.
|
|
145
|
+
if (table[name]?.equals(this.#values[name], value))
|
|
132
146
|
return;
|
|
133
147
|
this.#values[name] = value;
|
|
134
148
|
if (this.#model.ready)
|
|
@@ -145,7 +159,7 @@ export function elementClass(tag, spec) {
|
|
|
145
159
|
const def = table[name];
|
|
146
160
|
if (def === undefined || this.#values[name] !== undefined)
|
|
147
161
|
continue;
|
|
148
|
-
this.#values[name] = props
|
|
162
|
+
this.#values[name] = DEV ? checked(props)(tag, name, def, value, 'the seed') : value;
|
|
149
163
|
}
|
|
150
164
|
this.#afterInit = this.#model.resume(seed);
|
|
151
165
|
this.#serverRendered = true;
|
|
@@ -169,21 +183,27 @@ export function elementClass(tag, spec) {
|
|
|
169
183
|
this.#start();
|
|
170
184
|
}
|
|
171
185
|
#start() {
|
|
172
|
-
|
|
186
|
+
// `shadow: { delegatesFocus }` (05 "Focus"); `true` and `undefined` spread nothing.
|
|
187
|
+
const root = light
|
|
188
|
+
? this
|
|
189
|
+
: (this.shadowRoot ??
|
|
190
|
+
this.attachShadow({ ...spec.shadow, mode: 'open' }));
|
|
173
191
|
this.#root = root;
|
|
174
192
|
this.#hydrating = this.#serverRendered && hydrationCode != null && root.hasChildNodes();
|
|
175
193
|
sheets ??= light ? [] : sheetsFor(spec.styles);
|
|
176
194
|
// Rendering fresh: a shadow root without a seed (hand-written DSD) or a server-rendered
|
|
177
195
|
// host whose hydration code failed to load starts empty.
|
|
196
|
+
// A host that failed on the server (ADR 0024) starts fresh: its content is a fallback.
|
|
197
|
+
const failedOnServer = this.hasAttribute(ERROR_ATTRIBUTE);
|
|
198
|
+
if (failedOnServer)
|
|
199
|
+
this.removeAttribute(ERROR_ATTRIBUTE);
|
|
178
200
|
if (!this.#hydrating) {
|
|
179
|
-
if (!light || this.#serverRendered)
|
|
201
|
+
if (!light || this.#serverRendered || failedOnServer)
|
|
180
202
|
root.replaceChildren();
|
|
181
203
|
if (!light)
|
|
182
204
|
root.adoptedStyleSheets = sheets;
|
|
183
205
|
}
|
|
184
206
|
this.#listen(DEFAULT_EVENTS);
|
|
185
|
-
if (spec.events !== undefined)
|
|
186
|
-
this.#listen(spec.events);
|
|
187
207
|
this.#state(); // init, unless resumed from a seed
|
|
188
208
|
this.#connect();
|
|
189
209
|
}
|
|
@@ -212,15 +232,36 @@ export function elementClass(tag, spec) {
|
|
|
212
232
|
}
|
|
213
233
|
this.#stale = false;
|
|
214
234
|
this.#model.syncProps(names);
|
|
215
|
-
const
|
|
216
|
-
if (
|
|
217
|
-
|
|
218
|
-
this.#
|
|
235
|
+
const failure = this.#model.failure;
|
|
236
|
+
if (failure !== undefined) {
|
|
237
|
+
// init threw (ADR 0024): the error view, once; nothing else runs for this host.
|
|
238
|
+
if (!this.#rendered)
|
|
239
|
+
this.#fallback(root, failure, undefined);
|
|
240
|
+
this.#rendered = true;
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const view = spec.view(this.state, intentNames, this.#model.ctx());
|
|
245
|
+
if (this.#hydrating) {
|
|
246
|
+
hydrationCode?.hydrateRoot(this, tag, view, root, light ? undefined : sheets, this.#seen);
|
|
247
|
+
this.#hydrating = false;
|
|
248
|
+
}
|
|
249
|
+
else
|
|
250
|
+
render(view, root, this.#seen);
|
|
251
|
+
formAssociation?.sync(this, this.state, this.#model.ctx(), root);
|
|
252
|
+
}
|
|
253
|
+
catch (cause) {
|
|
254
|
+
const error = this.#model.fail(cause, 'view', message(31, tag));
|
|
255
|
+
this.#fallback(root, error, this.state);
|
|
256
|
+
return; // the first-render steps wait for a render that succeeds
|
|
257
|
+
}
|
|
258
|
+
const states = spec.states;
|
|
259
|
+
const sync = customStates;
|
|
260
|
+
if (states !== undefined && sync !== undefined) {
|
|
261
|
+
afterRender(POST_STATES, () => {
|
|
262
|
+
sync(this, states(this.state));
|
|
263
|
+
});
|
|
219
264
|
}
|
|
220
|
-
else
|
|
221
|
-
render(view, root, this.#seen);
|
|
222
|
-
if (spec.states !== undefined)
|
|
223
|
-
afterRender(POST_STATES, this.#syncStates);
|
|
224
265
|
if (this.#rendered)
|
|
225
266
|
return;
|
|
226
267
|
this.#rendered = true;
|
|
@@ -239,13 +280,24 @@ export function elementClass(tag, spec) {
|
|
|
239
280
|
this.#model.run(commands);
|
|
240
281
|
});
|
|
241
282
|
}
|
|
283
|
+
if (spec.subscriptions !== undefined) {
|
|
284
|
+
afterRender(POST_INIT, () => {
|
|
285
|
+
this.#model.subscribe();
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Renders `spec.error` (ADR 0024). Without one the root keeps what it shows; a fallback that
|
|
291
|
+
* throws too is reported and changes nothing.
|
|
292
|
+
*/
|
|
293
|
+
#fallback(root, error, state) {
|
|
294
|
+
if (spec.error === undefined || errorView === undefined)
|
|
295
|
+
return;
|
|
296
|
+
const view = (failure, at) => spec.error?.(failure, at);
|
|
297
|
+
if (errorView(view, root, error, state, this.#hydrating, this.#seen, this, tag)) {
|
|
298
|
+
this.#hydrating = false;
|
|
299
|
+
}
|
|
242
300
|
}
|
|
243
|
-
#syncStates = () => {
|
|
244
|
-
// ElementInternals is attached lazily, once, when the first states sync needs it (05).
|
|
245
|
-
this.#states ??= stateSync(this.attachInternals());
|
|
246
|
-
if (this.#states !== false && spec.states !== undefined)
|
|
247
|
-
this.#states(spec.states(this.state));
|
|
248
|
-
};
|
|
249
301
|
/** Intent event types this host's root listens for (view/05-element.md "Intent events"). */
|
|
250
302
|
#listening = new Set();
|
|
251
303
|
#listen(types) {
|
|
@@ -258,12 +310,13 @@ export function elementClass(tag, spec) {
|
|
|
258
310
|
#onEvent = (event) => {
|
|
259
311
|
if (this.#root === undefined)
|
|
260
312
|
return;
|
|
261
|
-
handleIntent(event, this.#root, parsers, tag, (msg) => {
|
|
313
|
+
handleIntent(event, this.#root, parsers, tag, this.#model, (msg) => {
|
|
262
314
|
if (msg !== undefined && this.isConnected)
|
|
263
315
|
this.#model.dispatch(msg);
|
|
264
316
|
});
|
|
265
317
|
};
|
|
266
318
|
}
|
|
319
|
+
formAssociation?.install(Element, spec.formAssociated !== undefined);
|
|
267
320
|
return Element;
|
|
268
321
|
}
|
|
269
322
|
//# sourceMappingURL=element.js.map
|
package/dist/element.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,6FAA6F;AAC7F,8FAA8F;AAC9F,8EAA8E;AAC9E,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAqB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,WAAW,EACX,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,WAAW,EACX,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,GAEZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAe,MAAM,iBAAiB,CAAC;AAEjE,MAAM,KAAK,GAAG,iBAAiB,CAAC;AAGhC,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,IAA4B;IAE5B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAc,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,0FAA0F;IAC1F,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAoB,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,MAAmC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,MAA+D,CAAC;IACrF,MAAM,KAAK,GAAG,IAA8C,CAAC;IAE7D,MAAM,OAAQ,SAAQ,WAAW;iBACf,SAAI,GAAG,IAAI,CAAC;iBACZ,YAAO,GAAG,GAAG,CAAC;QAC9B,MAAM,KAAK,kBAAkB;YAC3B,OAAO,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;QAED;YACE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxB,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC1E,IAAI,IAAI,KAAK,SAAS;oBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC9C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE;oBAC1C,YAAY,EAAE,IAAI;oBAClB,UAAU,EAAE,IAAI;oBAChB,GAAG;wBACD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAC5B,CAAC;oBACD,GAAG,CAAgB,KAAc;wBAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;oBACxE,CAAC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAMD,OAAO,GAAQ,EAAE,CAAC;QAClB,KAAK,CAAuC;QAC5C,SAAS,GAAG,KAAK,CAAC;QAClB,iEAAiE;QACjE,MAAM,GAAG,KAAK,CAAC;QACf,eAAe,GAAG,KAAK,CAAC;QACxB,0FAA0F;QAC1F,UAAU,GAAG,KAAK,CAAC;QACnB,kFAAkF;QAClF,UAAU,GAA4B,EAAE,CAAC;QACzC,OAAO,CAAgC;QACvC,KAAK,GAAa;YAChB,GAAG;YACH,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,GAAG,EAAE;gBACX,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,CAAC;SACF,CAAC;QACF,MAAM,GAAG,IAAI,SAAS,CACpB;YACE,EAAE,EAAE,IAAI;YACR,GAAG;YACH,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;YACtB,UAAU,EAAE,CAAC,OAAO,EAAE,EAAE;gBACtB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;SACF,EACD,KAAK,CACN,CAAC;QAEF;YACE,KAAK,EAAE,CAAC;YACR,MAAM,IAAI,GAAG,IAAsB,CAAC;YACpC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;YAC/B,mFAAmF;YACnF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;oBAAE,SAAS;gBACzC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzB,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACrB,CAAC;QACH,CAAC;QAED,IAAI,KAAK;YACP,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,MAAM;YACJ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACxF,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,GAAM;YACT,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,iBAAiB;YACf,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;QAED,2FAA2F;QAC3F,qBAAqB;YACnB,uBAAuB;QACzB,CAAC;QAED,oBAAoB;YAClB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACzB,IAAI,gBAAgB;gBAAE,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,wBAAwB,CAAC,IAAY,EAAE,IAAmB,EAAE,GAAkB;YAC5E,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;oBAAE,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChF,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,IAAI,KAAK,SAAS;gBACpB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,CAAC,IAAY,EAAE,KAAc;YACjC,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;gBAAE,OAAO;YACjD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YAC3B,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK;gBAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5C,CAAC;QAED,yFAAyF;QACzF,OAAO;YACL,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK;gBAAE,OAAO;YAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO;YAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxB,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS;oBAAE,SAAS;gBACpE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;YAC9E,CAAC;YACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED;;;;WAIG;QACH,MAAM;YACJ,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,aAAa,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,EAAE,CAAC;gBACnE,kBAAkB,CAAC,GAAG,EAAE;oBACtB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;wBAAE,IAAI,CAAC,MAAM,EAAE,CAAC;gBAClE,CAAC,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,KAAK,IAAI,aAAa,KAAK,IAAI;gBAAE,aAAa,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;;gBAC3E,IAAI,CAAC,MAAM,EAAE,CAAC;QACrB,CAAC;QAED,MAAM;YACJ,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;YACrF,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;YAClB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,eAAe,IAAI,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxF,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,wFAAwF;YACxF,yDAAyD;YACzD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe;oBAAE,IAAI,CAAC,eAAe,EAAE,CAAC;gBAC3D,IAAI,CAAC,KAAK;oBAAG,IAAmB,CAAC,kBAAkB,GAAG,MAAM,CAAC;YAC/D,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzD,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,mCAAmC;YAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;QAED,QAAQ;YACN,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,gBAAgB;gBAAE,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO;gBAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QACpE,CAAC;QAED,WAAW,CAAC,OAAO,GAAG,KAAK;YACzB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO;YACrC,IAAI,IAAI,CAAC,WAAW;gBAAE,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;;gBAChD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAC1B,CAAC;QAED,6FAA6F;QAC7F,OAAO;YACL,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;YACxB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC5C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,WAA6B,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;YACrF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,aAAa,EAAE,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC1F,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YAC1B,CAAC;;gBAAM,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBAAE,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1E,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO;YAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,gBAAgB;gBAAE,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YACnE,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACvC,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,CAAC,eAAe,EAAY,CAAC;gBACjF,WAAW,CAAC,aAAa,EAAE,GAAG,EAAE;oBAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC5B,CAAC,CAAC,CAAC;YACL,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;YACjC,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;YACrB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE;oBAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC5B,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,WAAW,GAAG,GAAS,EAAE;YACvB,uFAAuF;YACvF,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;gBACrD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC;QAEF,4FAA4F;QAC5F,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QAE/B,OAAO,CAAC,KAAwB;YAC9B,gBAAgB,CAAC,IAAI,CAAC,KAAa,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9E,CAAC;QAED,wFAAwF;QACxF,KAAK,GAAG,CAAC,MAAc,EAAQ,EAAE;YAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC;QAEF,QAAQ,GAAG,CAAC,KAAY,EAAQ,EAAE;YAChC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO;YACrC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;gBACpD,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW;oBAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACvE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;;IAEJ,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["// The element define() creates (docs/design-docs/view/05-element.md): a plain HTMLElement\n// subclass. Declared props are prototype accessors over Standard Schema builders; renders go\n// through the global scheduler (view/04-scheduler.md); intents are delegated listeners on the\n// root (ADR 0001). The model side (state, commands, stores) is host-model.ts.\nimport { DEVTOOLS_ENABLED, devConnect, devHydrated } from '#devtools';\nimport type { DriverOverrides } from './command.js';\nimport type { GyralElement } from './element-types.js';\nimport { HostModel, type ModelCommand } from './host-model.js';\nimport { hydrationCode, takeSeed, whenHydrationLoads } from './hydration.js';\nimport {\n DEFAULT_EVENTS,\n eventsOf,\n handleIntent,\n hostDepth,\n intentNames,\n listenForIntents,\n} from './intent.js';\nimport { isLight } from './light-dom.js';\nimport { features } from './features.js';\nimport type { PropFeature, PropTable } from './props.js';\nimport {\n afterRender,\n markDirty,\n POST_HYDRATED,\n POST_INIT,\n POST_STATES,\n type HostTask,\n} from './scheduler.js';\nimport { stateSync, type StateSync } from './states.js';\nimport type { StoreOverrides } from './store.js';\nimport type { ComponentSpec, IntentNames, IntentParser, Tagged } from './types.js';\nimport { render, sheetsFor, type Markup } from './view/index.js';\n\nconst DEFER = 'defer-hydration';\n\ntype Bag = Record<string, unknown>;\n/** The element class for `spec` (not yet registered); define() types it for the spec. */\nexport function elementClass<S, M extends Tagged, P>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): CustomElementConstructor {\n const table = (spec.props ?? {}) as PropTable;\n const names = Object.keys(table);\n // Registered by the prop builders (features.ts): set whenever a component declares props.\n const props = features.props as PropFeature;\n const attrs = new Map<string, string>();\n const light = isLight(spec);\n let sheets: CSSStyleSheet[] | undefined;\n const parsers = spec.intent as Readonly<Record<string, IntentParser<M> | undefined>>;\n const model = spec as unknown as ComponentSpec<S, Tagged, P>;\n\n class Element extends HTMLElement implements GyralElement<S, M> {\n static readonly spec = spec;\n static readonly tagName = tag;\n static get observedAttributes(): string[] {\n return [...attrs.keys(), DEFER];\n }\n\n static {\n for (const name of names) {\n const def = table[name];\n const attr = def === undefined ? undefined : props.attributeOf(name, def);\n if (attr !== undefined) attrs.set(attr, name);\n Object.defineProperty(this.prototype, name, {\n configurable: true,\n enumerable: true,\n get(this: Element): unknown {\n return this.#values[name];\n },\n set(this: Element, value: unknown) {\n this.#write(name, props.propertyValue(tag, name, table[name], value));\n },\n });\n }\n }\n\n declare drivers: DriverOverrides;\n declare stores: StoreOverrides;\n declare initialMessages: readonly Tagged[];\n\n #values: Bag = {};\n #root: ShadowRoot | HTMLElement | undefined;\n #rendered = false;\n /** Something changed while disconnected: render on reconnect. */\n #stale = false;\n #serverRendered = false;\n /** The first render adopts the server's DOM (07): resumed from a seed, root not empty. */\n #hydrating = false;\n /** init's commands for a server-rendered host: started after its first render. */\n #afterInit: readonly ModelCommand[] = [];\n #states: StateSync | false | undefined;\n #task: HostTask = {\n tag,\n depth: 0,\n render: () => {\n this.#render();\n },\n };\n #model = new HostModel<S, P>(\n {\n el: this,\n tag,\n props: () => (names.length > 0 ? props.readProps(this.#values, table) : {}),\n root: () => this.#root,\n invalidate: (onFrame) => {\n this.#invalidate(onFrame);\n },\n },\n model,\n );\n\n constructor() {\n super();\n const self = this as unknown as Bag;\n self['drivers'] ??= {};\n self['stores'] ??= {};\n self['initialMessages'] ??= [];\n // Upgrade capture: a property set before the class was defined hides the accessor.\n for (const name of names) {\n if (!Object.hasOwn(this, name)) continue;\n const value = self[name];\n Reflect.deleteProperty(this, name);\n self[name] = value;\n }\n }\n\n get state(): S {\n return this.#state();\n }\n\n #state(): S {\n if (!this.#model.ready && names.length > 0) props.warnMissing(tag, this.#values, table);\n return this.#model.state(this.initialMessages);\n }\n\n send(msg: M): void {\n this.#model.dispatch(msg);\n }\n\n connectedCallback(): void {\n if (this.#root !== undefined) {\n this.#connect();\n return;\n }\n this.#resume();\n this.#begin();\n }\n\n /** `moveBefore()` keeps everything: no disconnect, no re-resolution (view/03-lists.md). */\n connectedMoveCallback(): void {\n // Intentionally empty.\n }\n\n disconnectedCallback(): void {\n this.#model.disconnect();\n if (DEVTOOLS_ENABLED) devConnect(this, tag, false);\n }\n\n attributeChangedCallback(name: string, _old: string | null, raw: string | null): void {\n if (name === DEFER) {\n if (raw === null && this.isConnected && this.#root === undefined) this.#begin();\n return;\n }\n const prop = attrs.get(name);\n if (prop !== undefined)\n this.#write(prop, props.attributeValue(tag, prop, table[prop], name, raw));\n }\n\n #write(name: string, value: unknown): void {\n if (Object.is(this.#values[name], value)) return;\n this.#values[name] = value;\n if (this.#model.ready) this.#invalidate();\n }\n\n /** Hydration seeds (ADR 0012): the server's state and the props no attribute carried. */\n #resume(): void {\n if (this.#model.ready) return;\n const seed = takeSeed(this);\n if (seed === undefined) return;\n for (const [name, value] of Object.entries(seed.props)) {\n const def = table[name];\n if (def === undefined || this.#values[name] !== undefined) continue;\n this.#values[name] = props.propertyValue(tag, name, def, value, 'the seed');\n }\n this.#afterInit = this.#model.resume(seed);\n this.#serverRendered = true;\n }\n\n /**\n * Starts the host, or waits: for the hydration code (a server-rendered host or an island,\n * view/07-hydration.md \"Loading\"), then for an island's trigger (released by\n * attributeChangedCallback).\n */\n #begin(): void {\n const defer = this.hasAttribute(DEFER);\n if (hydrationCode === undefined && (this.#serverRendered || defer)) {\n whenHydrationLoads(() => {\n if (this.isConnected && this.#root === undefined) this.#begin();\n });\n } else if (defer && hydrationCode !== null) hydrationCode?.scheduleIsland(this);\n else this.#start();\n }\n\n #start(): void {\n const root = light ? this : (this.shadowRoot ?? this.attachShadow({ mode: 'open' }));\n this.#root = root;\n this.#hydrating = this.#serverRendered && hydrationCode != null && root.hasChildNodes();\n sheets ??= light ? [] : sheetsFor(spec.styles);\n // Rendering fresh: a shadow root without a seed (hand-written DSD) or a server-rendered\n // host whose hydration code failed to load starts empty.\n if (!this.#hydrating) {\n if (!light || this.#serverRendered) root.replaceChildren();\n if (!light) (root as ShadowRoot).adoptedStyleSheets = sheets;\n }\n this.#listen(DEFAULT_EVENTS);\n if (spec.events !== undefined) this.#listen(spec.events);\n this.#state(); // init, unless resumed from a seed\n this.#connect();\n }\n\n #connect(): void {\n this.#task.depth = hostDepth(this);\n const rebound = this.#model.connect();\n if (DEVTOOLS_ENABLED) devConnect(this, tag, true);\n if (!this.#rendered || this.#stale || rebound) this.#invalidate();\n }\n\n #invalidate(onFrame = false): void {\n if (this.#root === undefined) return;\n if (this.isConnected) markDirty(this.#task, onFrame);\n else this.#stale = true;\n }\n\n /** One render (the scheduler calls it): PropsChanged first, then the view and its commit. */\n #render(): void {\n const root = this.#root;\n if (root === undefined || !this.isConnected) {\n this.#stale = true;\n return;\n }\n this.#stale = false;\n this.#model.syncProps(names);\n const view = spec.view(this.state, intentNames as IntentNames<M>, this.#model.ctx());\n if (this.#hydrating) {\n hydrationCode?.hydrateRoot(this, tag, view, root, light ? undefined : sheets, this.#seen);\n this.#hydrating = false;\n } else render(view, root, this.#seen);\n if (spec.states !== undefined) afterRender(POST_STATES, this.#syncStates);\n if (this.#rendered) return;\n this.#rendered = true;\n if (DEVTOOLS_ENABLED) devHydrated(this, tag, this.#serverRendered);\n if (this.#model.hasReducer('Hydrated')) {\n const msg = { _tag: 'Hydrated', serverRendered: this.#serverRendered } as Tagged;\n afterRender(POST_HYDRATED, () => {\n this.#model.dispatch(msg);\n });\n }\n const commands = this.#afterInit;\n this.#afterInit = [];\n if (commands.length > 0) {\n afterRender(POST_INIT, () => {\n this.#model.run(commands);\n });\n }\n }\n\n #syncStates = (): void => {\n // ElementInternals is attached lazily, once, when the first states sync needs it (05).\n this.#states ??= stateSync(this.attachInternals());\n if (this.#states !== false && spec.states !== undefined)\n this.#states(spec.states(this.state));\n };\n\n /** Intent event types this host's root listens for (view/05-element.md \"Intent events\"). */\n #listening = new Set<string>();\n\n #listen(types: readonly string[]): void {\n listenForIntents(this.#root as Node, this.#listening, types, this.#onEvent);\n }\n\n /** Told about each template a render instantiates: listen for what its markup names. */\n #seen = (markup: Markup): void => {\n this.#listen(eventsOf(markup));\n };\n\n #onEvent = (event: Event): void => {\n if (this.#root === undefined) return;\n handleIntent(event, this.#root, parsers, tag, (msg) => {\n if (msg !== undefined && this.isConnected) this.#model.dispatch(msg);\n });\n };\n }\n return Element;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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","sourcesContent":["// The element define() creates (docs/design-docs/view/05-element.md): a plain HTMLElement\n// subclass. Declared props are prototype accessors over Standard Schema builders; renders go\n// through the global scheduler (view/04-scheduler.md); intents are delegated listeners on the\n// root (ADR 0001). The model side (state, commands, stores) is host-model.ts.\nimport { DEVTOOLS_ENABLED, devConnect, devHydrated } from '#devtools';\nimport type { DriverOverrides } from './command.js';\nimport type { GyralElement } from './element-types.js';\nimport { fail, type GyralError } from './errors.js';\nimport { HostModel, type ModelCommand } from './host-model.js';\nimport { hydrationCode, takeSeed, whenHydrationLoads } from '#hydration-loader';\nimport {\n DEFAULT_EVENTS,\n eventsOf,\n handleIntent,\n hostDepth,\n intentNames,\n listenForIntents,\n} from './intent.js';\nimport { isLight } from './light-dom.js';\nimport { features } from './features.js';\nimport type { PropFeature, PropTable, propertyValue } from './props.js';\nimport {\n afterRender,\n markDirty,\n POST_HYDRATED,\n POST_INIT,\n POST_STATES,\n type HostTask,\n} from './scheduler.js';\nimport { checkSpecFeatures, customStates, errorView, formAssociation } from '#spec-features';\nimport type { StoreOverrides } from './store.js';\nimport type { ComponentSpec, IntentNames, IntentParser, Tagged } from './types.js';\nimport {\n DEV,\n ERROR_ATTRIBUTE,\n message,\n onHookFailure,\n render,\n sheetsFor,\n suspendHooks,\n type Markup,\n} from './view/index.js';\n\nconst DEFER = 'defer-hydration';\n\n// A hook that throws is reported for the host owning the render root (ADR 0024).\nonHookFailure((error, root) => {\n const host = root instanceof ShadowRoot ? root.host : (root as Element);\n fail(error, 'hook', message(75, host.localName), { host, tag: host.localName });\n});\n\ntype Bag = Record<string, unknown>;\n/** The element class for `spec` (not yet registered); define() types it for the spec. */\nexport function elementClass<S, M extends Tagged, P>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): CustomElementConstructor {\n const table = (spec.props ?? {}) as PropTable;\n const names = Object.keys(table);\n // Registered by the prop builders (features.ts): set whenever a component declares props.\n const props = features.props as PropFeature;\n /** Property sets and seeds: checked in development, kept as given in production (05). */\n const checked = (props: PropFeature): typeof propertyValue =>\n props.propertyValue as typeof propertyValue;\n const attrs = new Map<string, string>();\n const light = isLight(spec);\n let sheets: CSSStyleSheet[] | undefined;\n const parsers = (spec.intent ?? {}) as Readonly<\n Record<string, IntentParser<M> | true | undefined>\n >;\n const model = spec as unknown as ComponentSpec<S, Tagged, P>;\n if (DEV) checkSpecFeatures(tag, spec);\n\n class Element extends HTMLElement implements GyralElement<S, M> {\n static readonly spec = spec;\n static readonly tagName = tag;\n static get observedAttributes(): string[] {\n return [...attrs.keys(), DEFER];\n }\n\n static {\n for (const name of names) {\n const def = table[name];\n const attr = def === undefined ? undefined : props.attributeOf(name, def);\n if (attr !== undefined) attrs.set(attr, name);\n Object.defineProperty(this.prototype, name, {\n configurable: true,\n enumerable: true,\n get(this: Element): unknown {\n return this.#values[name];\n },\n set(this: Element, value: unknown) {\n this.#write(name, DEV ? checked(props)(tag, name, table[name], value) : value);\n },\n });\n }\n }\n\n declare drivers: DriverOverrides;\n declare stores: StoreOverrides;\n declare initialMessages: readonly Tagged[];\n\n #values: Bag = {};\n #root: ShadowRoot | HTMLElement | undefined;\n #rendered = false;\n /** Something changed while disconnected: render on reconnect. */\n #stale = false;\n #serverRendered = false;\n /** The first render adopts the server's DOM (07): resumed from a seed, root not empty. */\n #hydrating = false;\n /** init's commands for a server-rendered host: started after its first render. */\n #afterInit: readonly ModelCommand[] = [];\n #task: HostTask = {\n tag,\n depth: 0,\n render: () => {\n this.#render();\n },\n };\n #model = new HostModel<S, P>(\n {\n el: this,\n tag,\n props: () => (names.length > 0 ? props.readProps(this.#values, table) : {}),\n root: () => this.#root,\n invalidate: (onFrame) => {\n this.#invalidate(onFrame);\n },\n },\n model,\n );\n\n constructor() {\n super();\n const self = this as unknown as Bag;\n self['drivers'] ??= {};\n self['stores'] ??= {};\n self['initialMessages'] ??= [];\n // Upgrade capture: a property set before the class was defined hides the accessor.\n for (const name of names) {\n if (!Object.hasOwn(this, name)) continue;\n const value = self[name];\n Reflect.deleteProperty(this, name);\n self[name] = value;\n }\n formAssociation?.create(this, this.#model, spec.formAssociated);\n }\n\n get state(): S {\n return this.#state();\n }\n\n #state(): S {\n if (!this.#model.ready && names.length > 0) props.warnMissing(tag, this.#values, table);\n return this.#model.state(this.initialMessages);\n }\n\n send(msg: M): void {\n this.#model.dispatch(msg);\n }\n\n connectedCallback(): void {\n if (this.#root !== undefined) {\n this.#connect();\n return;\n }\n this.#resume();\n this.#begin();\n }\n\n /** `moveBefore()` keeps everything: no disconnect, no re-resolution (view/03-lists.md). */\n connectedMoveCallback(): void {\n // Intentionally empty.\n }\n\n disconnectedCallback(): void {\n this.#model.disconnect();\n // Element hooks' dispose; they run client again after the render on reconnect (02).\n if (suspendHooks(this.#root)) this.#stale = true;\n if (DEVTOOLS_ENABLED) devConnect(this, tag, false);\n }\n\n attributeChangedCallback(name: string, _old: string | null, raw: string | null): void {\n if (name === DEFER) {\n if (raw === null && this.isConnected && this.#root === undefined) this.#begin();\n return;\n }\n const prop = attrs.get(name);\n if (prop !== undefined)\n this.#write(prop, props.attributeValue(tag, prop, table[prop], name, raw));\n }\n\n #write(name: string, value: unknown): void {\n // The prop's `equals` (prop.ts): `Object.is`, the same JSON for prop.json, or the option.\n if (table[name]?.equals(this.#values[name], value)) return;\n this.#values[name] = value;\n if (this.#model.ready) this.#invalidate();\n }\n\n /** Hydration seeds (ADR 0012): the server's state and the props no attribute carried. */\n #resume(): void {\n if (this.#model.ready) return;\n const seed = takeSeed(this);\n if (seed === undefined) return;\n for (const [name, value] of Object.entries(seed.props)) {\n const def = table[name];\n if (def === undefined || this.#values[name] !== undefined) continue;\n this.#values[name] = DEV ? checked(props)(tag, name, def, value, 'the seed') : value;\n }\n this.#afterInit = this.#model.resume(seed);\n this.#serverRendered = true;\n }\n\n /**\n * Starts the host, or waits: for the hydration code (a server-rendered host or an island,\n * view/07-hydration.md \"Loading\"), then for an island's trigger (released by\n * attributeChangedCallback).\n */\n #begin(): void {\n const defer = this.hasAttribute(DEFER);\n if (hydrationCode === undefined && (this.#serverRendered || defer)) {\n whenHydrationLoads(() => {\n if (this.isConnected && this.#root === undefined) this.#begin();\n });\n } else if (defer && hydrationCode !== null) hydrationCode?.scheduleIsland(this);\n else this.#start();\n }\n\n #start(): void {\n // `shadow: { delegatesFocus }` (05 \"Focus\"); `true` and `undefined` spread nothing.\n const root = light\n ? this\n : (this.shadowRoot ??\n this.attachShadow({ ...(spec.shadow as object | undefined), mode: 'open' }));\n this.#root = root;\n this.#hydrating = this.#serverRendered && hydrationCode != null && root.hasChildNodes();\n sheets ??= light ? [] : sheetsFor(spec.styles);\n // Rendering fresh: a shadow root without a seed (hand-written DSD) or a server-rendered\n // host whose hydration code failed to load starts empty.\n // A host that failed on the server (ADR 0024) starts fresh: its content is a fallback.\n const failedOnServer = this.hasAttribute(ERROR_ATTRIBUTE);\n if (failedOnServer) this.removeAttribute(ERROR_ATTRIBUTE);\n if (!this.#hydrating) {\n if (!light || this.#serverRendered || failedOnServer) root.replaceChildren();\n if (!light) (root as ShadowRoot).adoptedStyleSheets = sheets;\n }\n this.#listen(DEFAULT_EVENTS);\n this.#state(); // init, unless resumed from a seed\n this.#connect();\n }\n\n #connect(): void {\n this.#task.depth = hostDepth(this);\n const rebound = this.#model.connect();\n if (DEVTOOLS_ENABLED) devConnect(this, tag, true);\n if (!this.#rendered || this.#stale || rebound) this.#invalidate();\n }\n\n #invalidate(onFrame = false): void {\n if (this.#root === undefined) return;\n if (this.isConnected) markDirty(this.#task, onFrame);\n else this.#stale = true;\n }\n\n /** One render (the scheduler calls it): PropsChanged first, then the view and its commit. */\n #render(): void {\n const root = this.#root;\n if (root === undefined || !this.isConnected) {\n this.#stale = true;\n return;\n }\n this.#stale = false;\n this.#model.syncProps(names);\n const failure = this.#model.failure;\n if (failure !== undefined) {\n // init threw (ADR 0024): the error view, once; nothing else runs for this host.\n if (!this.#rendered) this.#fallback(root, failure, undefined);\n this.#rendered = true;\n return;\n }\n try {\n const view = spec.view(this.state, intentNames as IntentNames<string>, this.#model.ctx());\n if (this.#hydrating) {\n hydrationCode?.hydrateRoot(this, tag, view, root, light ? undefined : sheets, this.#seen);\n this.#hydrating = false;\n } else render(view, root, this.#seen);\n formAssociation?.sync(this, this.state, this.#model.ctx(), root);\n } catch (cause) {\n const error = this.#model.fail(cause, 'view', message(31, tag));\n this.#fallback(root, error, this.state);\n return; // the first-render steps wait for a render that succeeds\n }\n const states = spec.states;\n const sync = customStates;\n if (states !== undefined && sync !== undefined) {\n afterRender(POST_STATES, () => {\n sync(this, states(this.state));\n });\n }\n if (this.#rendered) return;\n this.#rendered = true;\n if (DEVTOOLS_ENABLED) devHydrated(this, tag, this.#serverRendered);\n if (this.#model.hasReducer('Hydrated')) {\n const msg = { _tag: 'Hydrated', serverRendered: this.#serverRendered } as Tagged;\n afterRender(POST_HYDRATED, () => {\n this.#model.dispatch(msg);\n });\n }\n const commands = this.#afterInit;\n this.#afterInit = [];\n if (commands.length > 0) {\n afterRender(POST_INIT, () => {\n this.#model.run(commands);\n });\n }\n if (spec.subscriptions !== undefined) {\n afterRender(POST_INIT, () => {\n this.#model.subscribe();\n });\n }\n }\n\n /**\n * Renders `spec.error` (ADR 0024). Without one the root keeps what it shows; a fallback that\n * throws too is reported and changes nothing.\n */\n #fallback(root: ShadowRoot | HTMLElement, error: GyralError, state: S | undefined): void {\n if (spec.error === undefined || errorView === undefined) return;\n const view = (failure: GyralError, at: never): unknown => spec.error?.(failure, at);\n if (errorView(view, root, error, state, this.#hydrating, this.#seen, this, tag)) {\n this.#hydrating = false;\n }\n }\n\n /** Intent event types this host's root listens for (view/05-element.md \"Intent events\"). */\n #listening = new Set<string>();\n\n #listen(types: readonly string[]): void {\n listenForIntents(this.#root as Node, this.#listening, types, this.#onEvent);\n }\n\n /** Told about each template a render instantiates: listen for what its markup names. */\n #seen = (markup: Markup): void => {\n this.#listen(eventsOf(markup));\n };\n\n #onEvent = (event: Event): void => {\n if (this.#root === undefined) return;\n handleIntent(event, this.#root, parsers, tag, this.#model, (msg) => {\n if (msg !== undefined && this.isConnected) this.#model.dispatch(msg);\n });\n };\n }\n formAssociation?.install(Element, spec.formAssociated !== undefined);\n return Element;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ErrorPhase, type GyralError } from './errors.js';
|
|
2
|
+
import type { Tagged } from './types.js';
|
|
3
|
+
import { type SeenMarkup } from './view/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Renders a component's `error` view into `root`; true when it rendered (a hydrating root is
|
|
6
|
+
* cleared first). A view that throws too is reported and changes nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderErrorView(view: (error: GyralError, state: never) => unknown, root: ShadowRoot | HTMLElement, error: GyralError, state: unknown, hydrating: boolean, seen: SeenMarkup, host: HTMLElement, tag: string): boolean;
|
|
9
|
+
/** Sends `Errored` to a component whose `update` handles it (a failed update, parse or command). */
|
|
10
|
+
export declare function sendErrored(dispatch: (msg: Tagged) => unknown, phase: ErrorPhase, error: GyralError): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Optional error handling a component asks for by name (ADR 0024, gyral-1zd.17): the `error`
|
|
2
|
+
// fallback view and the `Errored` framework message. Reached through `#spec-features`, so a
|
|
3
|
+
// compiled build bundles each only when some module names `error` or `Errored`
|
|
4
|
+
// (compiler/features.ts); the reporting channel itself (errors.ts) is in every app.
|
|
5
|
+
import { fail } from './errors.js';
|
|
6
|
+
import { message, render } from './view/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Renders a component's `error` view into `root`; true when it rendered (a hydrating root is
|
|
9
|
+
* cleared first). A view that throws too is reported and changes nothing.
|
|
10
|
+
*/
|
|
11
|
+
export function renderErrorView(view, root, error, state, hydrating, seen, host, tag) {
|
|
12
|
+
try {
|
|
13
|
+
const value = view(error, state);
|
|
14
|
+
if (hydrating)
|
|
15
|
+
root.replaceChildren();
|
|
16
|
+
render(value, root, seen);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch (cause) {
|
|
20
|
+
fail(cause, 'view', message(31, tag), { host, tag });
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Sends `Errored` to a component whose `update` handles it (a failed update, parse or command). */
|
|
25
|
+
export function sendErrored(dispatch, phase, error) {
|
|
26
|
+
if (phase === 'update' || phase === 'parse' || phase === 'command') {
|
|
27
|
+
dispatch({ _tag: 'Errored', phase, error });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=error-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-view.js","sourceRoot":"","sources":["../src/error-view.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,4FAA4F;AAC5F,+EAA+E;AAC/E,oFAAoF;AACpF,OAAO,EAAE,IAAI,EAAoC,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAoC,MAAM,iBAAiB,CAAC;AAEpF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAkD,EAClD,IAA8B,EAC9B,KAAiB,EACjB,KAAc,EACd,SAAkB,EAClB,IAAgB,EAChB,IAAiB,EACjB,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAc,CAAe,CAAC;QACxD,IAAI,SAAS;YAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACrD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CACzB,QAAkC,EAClC,KAAiB,EACjB,KAAiB;IAEjB,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACnE,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAY,CAAC,CAAC;IACxD,CAAC;AACH,CAAC","sourcesContent":["// Optional error handling a component asks for by name (ADR 0024, gyral-1zd.17): the `error`\n// fallback view and the `Errored` framework message. Reached through `#spec-features`, so a\n// compiled build bundles each only when some module names `error` or `Errored`\n// (compiler/features.ts); the reporting channel itself (errors.ts) is in every app.\nimport { fail, type ErrorPhase, type GyralError } from './errors.js';\nimport type { Tagged } from './types.js';\nimport { message, render, type ChildValue, type SeenMarkup } from './view/index.js';\n\n/**\n * Renders a component's `error` view into `root`; true when it rendered (a hydrating root is\n * cleared first). A view that throws too is reported and changes nothing.\n */\nexport function renderErrorView(\n view: (error: GyralError, state: never) => unknown,\n root: ShadowRoot | HTMLElement,\n error: GyralError,\n state: unknown,\n hydrating: boolean,\n seen: SeenMarkup,\n host: HTMLElement,\n tag: string,\n): boolean {\n try {\n const value = view(error, state as never) as ChildValue;\n if (hydrating) root.replaceChildren();\n render(value, root, seen);\n return true;\n } catch (cause) {\n fail(cause, 'view', message(31, tag), { host, tag });\n return false;\n }\n}\n\n/** Sends `Errored` to a component whose `update` handles it (a failed update, parse or command). */\nexport function sendErrored(\n dispatch: (msg: Tagged) => unknown,\n phase: ErrorPhase,\n error: GyralError,\n): void {\n if (phase === 'update' || phase === 'parse' || phase === 'command') {\n dispatch({ _tag: 'Errored', phase, error } as Tagged);\n }\n}\n"]}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Where a failure happened. */
|
|
2
|
+
export type ErrorPhase = 'init' | 'update' | 'view' | 'parse' | 'command' | 'hook' | 'store' | 'subscribe';
|
|
3
|
+
/** A failure Gyral caught, with its context; `cause` is what was thrown. */
|
|
4
|
+
export declare class GyralError extends Error {
|
|
5
|
+
readonly name = "GyralError";
|
|
6
|
+
/** The failing host's tag; `undefined` for a store or work not tied to one component. */
|
|
7
|
+
readonly component: string | undefined;
|
|
8
|
+
readonly phase: ErrorPhase;
|
|
9
|
+
/** The message tag being reduced, the intent name, or the driver's name. */
|
|
10
|
+
readonly msg: string | undefined;
|
|
11
|
+
constructor(phase: ErrorPhase, text: string, cause: unknown, component?: string, msg?: string);
|
|
12
|
+
}
|
|
13
|
+
/** Where a failure happened, for `fail()`. */
|
|
14
|
+
export interface FailureSite {
|
|
15
|
+
/** The failing host: it gets the boundary event. */
|
|
16
|
+
readonly host?: Element | undefined;
|
|
17
|
+
readonly tag?: string | undefined;
|
|
18
|
+
readonly msg?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Reports `cause` (ADR 0024 "Recommendation"); returns the GyralError it reported. */
|
|
21
|
+
export declare function fail(cause: unknown, phase: ErrorPhase, text: string, site?: FailureSite): GyralError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Errors (ADR 0024): one reporting channel. Every failure Gyral catches becomes a `GyralError`
|
|
2
|
+
// carrying the component, the phase and the message, and goes through `fail()`: the devtools
|
|
3
|
+
// timeline, then a bubbling, composed, cancelable `ErrorEvent('error')` on the failing host
|
|
4
|
+
// (a parent claims it with `preventDefault()`), then `reportError()` unless it was claimed, so
|
|
5
|
+
// `window` `error` listeners and monitoring tools see it. The boundary event stops at the
|
|
6
|
+
// document, so `window` gets each failure once, from `reportError`.
|
|
7
|
+
import { DEVTOOLS_ENABLED, devError } from '#devtools';
|
|
8
|
+
/** A failure Gyral caught, with its context; `cause` is what was thrown. */
|
|
9
|
+
export class GyralError extends Error {
|
|
10
|
+
constructor(phase, text, cause, component, msg) {
|
|
11
|
+
super(text, { cause });
|
|
12
|
+
this.name = 'GyralError';
|
|
13
|
+
this.phase = phase;
|
|
14
|
+
this.component = component;
|
|
15
|
+
this.msg = msg;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let stopping = false;
|
|
19
|
+
/** Reports `cause` (ADR 0024 "Recommendation"); returns the GyralError it reported. */
|
|
20
|
+
export function fail(cause, phase, text, site = {}) {
|
|
21
|
+
const { host, tag, msg } = site;
|
|
22
|
+
const error = cause instanceof GyralError ? cause : new GyralError(phase, text, cause, tag, msg);
|
|
23
|
+
if (DEVTOOLS_ENABLED)
|
|
24
|
+
devError(host, error);
|
|
25
|
+
let claimed = false;
|
|
26
|
+
if (host?.isConnected === true) {
|
|
27
|
+
if (!stopping) {
|
|
28
|
+
// The boundary event ends at the document: `window` hears the failure from reportError.
|
|
29
|
+
stopping = true;
|
|
30
|
+
document.addEventListener('error', (event) => {
|
|
31
|
+
if (event.error instanceof GyralError)
|
|
32
|
+
event.stopPropagation();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
claimed = !host.dispatchEvent(new ErrorEvent('error', {
|
|
36
|
+
error,
|
|
37
|
+
message: error.message,
|
|
38
|
+
bubbles: true,
|
|
39
|
+
composed: true,
|
|
40
|
+
cancelable: true,
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
if (!claimed)
|
|
44
|
+
reportError(error); // Baseline widely available since 2024-09 (ADR 0024)
|
|
45
|
+
return error;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,6FAA6F;AAC7F,4FAA4F;AAC5F,+FAA+F;AAC/F,0FAA0F;AAC1F,oEAAoE;AACpE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAMvD,4EAA4E;AAC5E,MAAM,OAAO,UAAW,SAAQ,KAAK;IAQnC,YAAY,KAAiB,EAAE,IAAY,EAAE,KAAc,EAAE,SAAkB,EAAE,GAAY;QAC3F,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QARP,SAAI,GAAG,YAAY,CAAC;QASpC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF;AAUD,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,uFAAuF;AACvF,MAAM,UAAU,IAAI,CAClB,KAAc,EACd,KAAiB,EACjB,IAAY,EACZ,OAAoB,EAAE;IAEtB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACjG,IAAI,gBAAgB;QAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,wFAAwF;YACxF,QAAQ,GAAG,IAAI,CAAC;YAChB,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC3C,IAAI,KAAK,CAAC,KAAK,YAAY,UAAU;oBAAE,KAAK,CAAC,eAAe,EAAE,CAAC;YACjE,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,CAAC,aAAa,CAC3B,IAAI,UAAU,CAAC,OAAO,EAAE;YACtB,KAAK;YACL,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CACH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,qDAAqD;IACvF,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["// Errors (ADR 0024): one reporting channel. Every failure Gyral catches becomes a `GyralError`\n// carrying the component, the phase and the message, and goes through `fail()`: the devtools\n// timeline, then a bubbling, composed, cancelable `ErrorEvent('error')` on the failing host\n// (a parent claims it with `preventDefault()`), then `reportError()` unless it was claimed, so\n// `window` `error` listeners and monitoring tools see it. The boundary event stops at the\n// document, so `window` gets each failure once, from `reportError`.\nimport { DEVTOOLS_ENABLED, devError } from '#devtools';\n\n/** Where a failure happened. */\nexport type ErrorPhase =\n 'init' | 'update' | 'view' | 'parse' | 'command' | 'hook' | 'store' | 'subscribe';\n\n/** A failure Gyral caught, with its context; `cause` is what was thrown. */\nexport class GyralError extends Error {\n override readonly name = 'GyralError';\n /** The failing host's tag; `undefined` for a store or work not tied to one component. */\n readonly component: string | undefined;\n readonly phase: ErrorPhase;\n /** The message tag being reduced, the intent name, or the driver's name. */\n readonly msg: string | undefined;\n\n constructor(phase: ErrorPhase, text: string, cause: unknown, component?: string, msg?: string) {\n super(text, { cause });\n this.phase = phase;\n this.component = component;\n this.msg = msg;\n }\n}\n\n/** Where a failure happened, for `fail()`. */\nexport interface FailureSite {\n /** The failing host: it gets the boundary event. */\n readonly host?: Element | undefined;\n readonly tag?: string | undefined;\n readonly msg?: string | undefined;\n}\n\nlet stopping = false;\n\n/** Reports `cause` (ADR 0024 \"Recommendation\"); returns the GyralError it reported. */\nexport function fail(\n cause: unknown,\n phase: ErrorPhase,\n text: string,\n site: FailureSite = {},\n): GyralError {\n const { host, tag, msg } = site;\n const error = cause instanceof GyralError ? cause : new GyralError(phase, text, cause, tag, msg);\n if (DEVTOOLS_ENABLED) devError(host, error);\n let claimed = false;\n if (host?.isConnected === true) {\n if (!stopping) {\n // The boundary event ends at the document: `window` hears the failure from reportError.\n stopping = true;\n document.addEventListener('error', (event) => {\n if (event.error instanceof GyralError) event.stopPropagation();\n });\n }\n claimed = !host.dispatchEvent(\n new ErrorEvent('error', {\n error,\n message: error.message,\n bubbles: true,\n composed: true,\n cancelable: true,\n }),\n );\n }\n if (!claimed) reportError(error); // Baseline widely available since 2024-09 (ADR 0024)\n return error;\n}\n"]}
|