@gyral/core 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +129 -0
- package/NOTICE +19 -0
- package/README.md +35 -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 +30 -5
- package/dist/children.js +26 -4
- 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 +31 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +23 -0
- package/dist/compiler/ast.js +149 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +41 -0
- package/dist/compiler/compile.js +148 -0
- package/dist/compiler/compile.js.map +1 -0
- 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 +182 -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 +22 -0
- package/dist/compiler/hooks.js +241 -0
- package/dist/compiler/hooks.js.map +1 -0
- 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 +78 -0
- package/dist/compiler/locate.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +60 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- 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 +41 -0
- package/dist/compiler/scan.js +160 -0
- package/dist/compiler/scan.js.map +1 -0
- 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/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.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 +13 -4
- package/dist/define.js +35 -331
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +13 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +2 -0
- package/dist/devtools-off.js +2 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +4 -0
- package/dist/devtools.js +17 -2
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- 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 +11 -5
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +322 -0
- package/dist/element.js.map +1 -0
- 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 +26 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +16 -0
- package/dist/eslint/index.js +23 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +6 -0
- package/dist/eslint/template-rule.js +76 -0
- package/dist/eslint/template-rule.js.map +1 -0
- 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 +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +13 -12
- package/dist/focus.js +44 -11
- 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/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/host-model.d.ts +77 -0
- package/dist/host-model.js +278 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- 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 +3 -21
- package/dist/hydration.js +14 -63
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +24 -36
- package/dist/index.js +14 -32
- 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 +62 -17
- package/dist/intent.js +193 -100
- 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 +15 -1
- package/dist/internal/interpreter.js +42 -47
- 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/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +4 -53
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +89 -0
- package/dist/prop.js +41 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +57 -21
- package/dist/props.js +157 -34
- 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 +43 -0
- package/dist/scheduler.js +212 -0
- package/dist/scheduler.js.map +1 -0
- 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 +10 -0
- package/dist/server-component.js +133 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +34 -0
- package/dist/server.js +59 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +11 -0
- package/dist/settled.js +62 -0
- package/dist/settled.js.map +1 -0
- 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 -11
- 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.d.ts +6 -3
- package/dist/store-binding.js +7 -8
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +8 -11
- package/dist/store-scope.js +15 -40
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +45 -10
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.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 +5 -7
- package/dist/transitions.js +17 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +142 -49
- 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 +11 -0
- package/dist/view/attributes.js +15 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +26 -0
- package/dist/view/index.js +27 -0
- package/dist/view/index.js.map +1 -0
- 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 +23 -0
- package/dist/view/normalize/check.js +81 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +15 -0
- package/dist/view/normalize/emit.js +165 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +10 -0
- package/dist/view/normalize/id.js +55 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +18 -0
- package/dist/view/normalize/normalize.js +42 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +39 -0
- package/dist/view/normalize/rules.js +120 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- 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/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +55 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +65 -0
- package/dist/view/normalize/tree.js +235 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +146 -0
- package/dist/view/normalize/types.js +29 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/{template-whitespace.js → view/normalize/whitespace.js} +27 -36
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +11 -0
- package/dist/view/prepare.js +63 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +78 -0
- package/dist/view/registry.js +27 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +83 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +286 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +72 -0
- package/dist/view/render/attr-parts.js +262 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +173 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- 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 +5 -0
- package/dist/view/render/hook-part.js +36 -0
- package/dist/view/render/hook-part.js.map +1 -0
- 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 +108 -0
- package/dist/view/render/hooks.js +108 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- 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 +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +55 -0
- package/dist/view/render/mismatch.js.map +1 -0
- 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/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +21 -0
- package/dist/view/render/raw.js +72 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +15 -0
- package/dist/view/render/render.js +65 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- 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 +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +28 -0
- package/dist/view/render/warn.js +114 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +12 -0
- package/dist/view/server/component.js +64 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +48 -0
- package/dist/view/server/index.js +80 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +68 -0
- package/dist/view/server/tags.js +132 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +18 -0
- package/dist/view/server/values.js +94 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +21 -0
- package/dist/view/server/writer.js +170 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +10 -0
- package/dist/view/template-element.js +45 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +29 -0
- package/dist/view/template.js +84 -0
- package/dist/view/template.js.map +1 -0
- 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 +57 -11
- package/dist/vite.js +319 -27
- package/dist/vite.js.map +1 -1
- package/package.json +70 -4
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/lit-html-check.d.ts +0 -6
- package/dist/lit-html-check.js +0 -48
- package/dist/lit-html-check.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.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/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/template-whitespace.d.ts +0 -7
- package/dist/template-whitespace.js.map +0 -1
- package/dist/templates.d.ts +0 -5
- package/dist/templates.js +0 -15
- package/dist/templates.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
package/dist/props.js
CHANGED
|
@@ -1,44 +1,167 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import { DEV, message } from './view/index.js';
|
|
2
|
+
/** `minPrice` → `min-price`. */
|
|
3
|
+
export const kebab = (name) => name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
4
|
+
/** The prop's attribute, or undefined for a property-only prop. */
|
|
5
|
+
export function attributeOf(name, def) {
|
|
6
|
+
if (def.attribute === false)
|
|
7
|
+
return undefined;
|
|
8
|
+
return def.attribute ?? kebab(name);
|
|
9
|
+
}
|
|
10
|
+
const builtIn = {
|
|
11
|
+
string: (v) => typeof v === 'string',
|
|
12
|
+
number: (v) => typeof v === 'number' && !Number.isNaN(v),
|
|
13
|
+
boolean: (v) => typeof v === 'boolean',
|
|
14
|
+
};
|
|
15
|
+
/** Runs the built-in type check and the prop's schema. Schemas must be synchronous. */
|
|
16
|
+
export function checkValue(tag, name, def, value) {
|
|
17
|
+
const typeOk = builtIn[def.kind];
|
|
18
|
+
if (typeOk !== undefined && !typeOk(value)) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
issues: [`expected a ${def.kind}, got ${typeof value}`],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const schema = def.schema;
|
|
25
|
+
if (schema === undefined)
|
|
26
|
+
return { ok: true, value };
|
|
27
|
+
// A type guard (prop.value/prop.json, gyral-c5d.7); ArkType-style callable schemas have ~standard.
|
|
28
|
+
if (!('~standard' in schema)) {
|
|
29
|
+
return schema(value) ? { ok: true, value } : { ok: false, issues: [`failed ${schema.name}`] };
|
|
30
|
+
}
|
|
31
|
+
const result = schema['~standard'].validate(value);
|
|
32
|
+
if (result instanceof Promise) {
|
|
33
|
+
throw new TypeError(message(20, tag, name));
|
|
34
|
+
}
|
|
35
|
+
if (result.issues !== undefined)
|
|
36
|
+
return { ok: false, issues: result.issues.map((i) => i.message) };
|
|
37
|
+
return { ok: true, value: result.value };
|
|
38
|
+
}
|
|
39
|
+
/** Parses an attribute value (`null`: absent) per the builder table; undefined means missing. */
|
|
40
|
+
export function parseAttribute(def, raw) {
|
|
41
|
+
if (def.kind === 'boolean')
|
|
42
|
+
return { ok: true, value: raw !== null };
|
|
43
|
+
if (raw === null)
|
|
44
|
+
return undefined;
|
|
45
|
+
if (def.kind === 'number') {
|
|
46
|
+
const n = raw.trim() === '' ? Number.NaN : Number(raw);
|
|
47
|
+
return Number.isNaN(n)
|
|
48
|
+
? { ok: false, issues: [`"${raw}" is not a number`] }
|
|
49
|
+
: { ok: true, value: n };
|
|
50
|
+
}
|
|
51
|
+
if (def.kind === 'json') {
|
|
52
|
+
try {
|
|
53
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return { ok: false, issues: ['the attribute is not valid JSON'] };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { ok: true, value: raw };
|
|
60
|
+
}
|
|
61
|
+
/** Logs an invalid value; the caller then treats the prop as missing. */
|
|
62
|
+
export function reportInvalid(tag, name, from, issues) {
|
|
63
|
+
console.error(message(21, tag, name, from, issues.join('; ')));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* An attribute's value for prop `name` (view/05-element.md "When props are validated"):
|
|
67
|
+
* parsed per the builder and always validated; invalid or absent values are missing.
|
|
68
|
+
*/
|
|
69
|
+
export function attributeValue(tag, name, def, attr, raw) {
|
|
70
|
+
const parsed = def === undefined ? undefined : parseAttribute(def, raw);
|
|
71
|
+
if (def === undefined || parsed === undefined)
|
|
72
|
+
return undefined;
|
|
73
|
+
const checked = parsed.ok ? checkValue(tag, name, def, parsed.value) : parsed;
|
|
74
|
+
if (checked.ok)
|
|
75
|
+
return checked.value;
|
|
76
|
+
reportInvalid(tag, name, `the attribute ${attr}`, checked.issues);
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A property set's (or seed's) value for prop `name`: validated in development only, where an
|
|
81
|
+
* invalid value is missing and a schema that transforms warns. Production keeps the input
|
|
82
|
+
* without calling this (propFeature, element.ts: gyral-c5d.14).
|
|
83
|
+
*/
|
|
84
|
+
export function propertyValue(tag, name, def, value, from = 'a property') {
|
|
85
|
+
if (!DEV || value === undefined || def === undefined)
|
|
86
|
+
return value;
|
|
87
|
+
const checked = checkValue(tag, name, def, value);
|
|
88
|
+
if (!checked.ok) {
|
|
89
|
+
reportInvalid(tag, name, from, checked.issues);
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
if (!sameData(checked.value, value)) {
|
|
93
|
+
console.warn(`<${tag}> prop "${name}": its schema transformed the value from ${from}. Production ` +
|
|
94
|
+
"doesn't run schemas on property sets; validate, don't transform.");
|
|
95
|
+
}
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
/** Structural equality for plain data (arrays, plain objects), `Object.is` for the rest. */
|
|
99
|
+
export function sameData(a, b) {
|
|
100
|
+
if (Object.is(a, b))
|
|
101
|
+
return true;
|
|
102
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
103
|
+
return false;
|
|
104
|
+
if (Array.isArray(a)) {
|
|
105
|
+
return Array.isArray(b) && a.length === b.length && a.every((x, i) => sameData(x, b[i]));
|
|
106
|
+
}
|
|
107
|
+
if (Object.getPrototypeOf(a) !== Object.prototype ||
|
|
108
|
+
Object.getPrototypeOf(b) !== Object.prototype) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const ka = Object.keys(a);
|
|
112
|
+
return (ka.length === Object.keys(b).length && ka.every((k) => sameData(a[k], b[k])));
|
|
113
|
+
}
|
|
114
|
+
/** The declared props as components see them: `default` fills missing values. */
|
|
115
|
+
export function readProps(values, table) {
|
|
116
|
+
const out = {};
|
|
117
|
+
for (const [name, def] of Object.entries(table)) {
|
|
118
|
+
const value = values[name];
|
|
119
|
+
out[name] = value === undefined ? def.default : value;
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
/** Required props that are still missing (ADR 0007 addendum). */
|
|
124
|
+
export function missingRequired(values, table) {
|
|
125
|
+
return Object.keys(table).filter((name) => table[name]?.required === true && values[name] === undefined);
|
|
126
|
+
}
|
|
127
|
+
/** Warns about required props that are still missing, at first render. */
|
|
128
|
+
export function warnMissing(tag, values, table) {
|
|
129
|
+
const missing = missingRequired(values, table);
|
|
130
|
+
if (missing.length > 0) {
|
|
131
|
+
console.warn(message(22, tag, missing.join(', ')));
|
|
31
132
|
}
|
|
32
133
|
}
|
|
33
134
|
/**
|
|
34
|
-
* Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …)
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* the server's DOM shim doesn't model the full prototype chain.
|
|
135
|
+
* Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …):
|
|
136
|
+
* the accessor replaces the built-in, so setting the prop silently changes what the platform
|
|
137
|
+
* does with it (gyral-czi.33).
|
|
38
138
|
*/
|
|
39
139
|
export function shadowedBuiltins(names) {
|
|
40
140
|
if (typeof HTMLElement === 'undefined')
|
|
41
141
|
return [];
|
|
42
142
|
return names.filter((name) => name in HTMLElement.prototype);
|
|
43
143
|
}
|
|
144
|
+
/** define(): a prop named like a built-in property is an error in development, else a warning. */
|
|
145
|
+
export function checkShadowed(tag, names) {
|
|
146
|
+
const shadowed = shadowedBuiltins(names);
|
|
147
|
+
if (shadowed.length === 0)
|
|
148
|
+
return;
|
|
149
|
+
const text = message(23, tag, shadowed.join(', '));
|
|
150
|
+
if (DEV)
|
|
151
|
+
throw new TypeError(text);
|
|
152
|
+
console.warn(text);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* What the element uses, registered by the prop builders (features.ts). Property sets and seeds
|
|
156
|
+
* go through `propertyValue` in development only: production keeps the value as given, so the
|
|
157
|
+
* property path's schema and guard handling stay out of production bundles (gyral-c5d.14).
|
|
158
|
+
*/
|
|
159
|
+
export const propFeature = {
|
|
160
|
+
attributeOf,
|
|
161
|
+
attributeValue,
|
|
162
|
+
propertyValue: DEV ? propertyValue : undefined,
|
|
163
|
+
warnMissing,
|
|
164
|
+
readProps,
|
|
165
|
+
checkShadowed,
|
|
166
|
+
};
|
|
44
167
|
//# sourceMappingURL=props.js.map
|
package/dist/props.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props.js","sourceRoot":"","sources":["../src/props.ts"],"names":[],"mappings":"AAaA,uFAAuF;AACvF,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,KAAgB;IACvD,MAAM,IAAI,GAAG,EAAS,CAAC;IACvB,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,KAAgB;IACpD,MAAM,IAAI,GAAG,EAAS,CAAC;IACvB,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,IAAI,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjF,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,EAAU,EAAE,KAAgB;IAC1D,MAAM,IAAI,GAAG,EAAS,CAAC;IACvB,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACzB,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;SAC5E,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAI,KAAwB,EAAE,CAAI,EAAE,CAAI;IAC/D,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAE,CAAS,CAAC,IAAI,CAAC,EAAG,CAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,KAAwB,EAAE,MAAW;IAC5E,MAAM,IAAI,GAAG,EAA6B,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAwB;IACvD,IAAI,OAAO,WAAW,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IAClD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["// Prop bookkeeping for define() (ADR 0007): snapshots, defaults, change detection, seed restore.\nimport type { PropertyDeclaration } from 'lit';\n\ntype Bag = Readonly<Record<string, unknown>>;\n\n/** Gyral's view of a declaration: Lit's options plus `required` and `default`. */\nexport interface PropInfo extends PropertyDeclaration {\n readonly required?: boolean;\n readonly default?: unknown;\n}\n\nexport type PropTable = Readonly<Record<string, PropInfo>>;\n\n/** The element's declared props as set on it (no defaults): what a seed must carry. */\nexport function readRawProps(el: object, table: PropTable): Bag {\n const self = el as Bag;\n return Object.fromEntries(Object.keys(table).map((name) => [name, self[name]]));\n}\n\n/** The element's declared props as components see them: `default` fills `undefined`. */\nexport function readProps(el: object, table: PropTable): Bag {\n const self = el as Bag;\n return Object.fromEntries(\n Object.entries(table).map(([name, info]) => {\n const value = self[name];\n return [name, value === undefined && 'default' in info ? info.default : value];\n }),\n );\n}\n\n/** Required props that are still `undefined` (ADR 0007 addendum). */\nexport function missingRequired(el: object, table: PropTable): string[] {\n const self = el as Bag;\n return Object.entries(table)\n .filter(([name, info]) => info.required === true && self[name] === undefined)\n .map(([name]) => name);\n}\n\n/** True when every declared prop is identical (`Object.is`) in both snapshots. */\nexport function sameProps<P>(names: readonly string[], a: P, b: P): boolean {\n return names.every((name) => Object.is((a as Bag)[name], (b as Bag)[name]));\n}\n\n/** Hydration: sets props that only travelled in the seed, unless the page already set them. */\nexport function restoreProps(el: object, names: readonly string[], seeded: Bag): void {\n const self = el as Record<string, unknown>;\n for (const [name, value] of Object.entries(seeded)) {\n if (names.includes(name) && self[name] === undefined) self[name] = value;\n }\n}\n\n/**\n * Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …).\n * Lit's reactive accessor replaces the built-in, so setting the prop silently changes what the\n * platform does with it: a prop named `hidden` hides the element (gyral-czi.33). Browser only:\n * the server's DOM shim doesn't model the full prototype chain.\n */\nexport function shadowedBuiltins(names: readonly string[]): string[] {\n if (typeof HTMLElement === 'undefined') return [];\n return names.filter((name) => name in HTMLElement.prototype);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"props.js","sourceRoot":"","sources":["../src/props.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAM/C,gCAAgC;AAChC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAEpG,mEAAmE;AACnE,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,GAAkB;IAC1D,IAAI,GAAG,CAAC,SAAS,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IAC9C,OAAO,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAMD,MAAM,OAAO,GAAsD;IACjE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ;IACpC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,SAAS;CACvC,CAAC;AAEF,uFAAuF;AACvF,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,IAAY,EAAE,GAAkB,EAAE,KAAc;IACtF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC,cAAc,GAAG,CAAC,IAAI,SAAS,OAAO,KAAK,EAAE,CAAC;SACxD,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAC1B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACrD,mGAAmG;IACnG,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAChG,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;QAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;AAC3C,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,cAAc,CAAC,GAAkB,EAAE,GAAkB;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;IACrE,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACnC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACpB,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,GAAG,mBAAmB,CAAC,EAAE;YACrD,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,EAAE,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,iCAAiC,CAAC,EAAE,CAAC;QACpE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,IAAY,EAAE,IAAY,EAAE,MAAyB;IAC9F,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,IAAY,EACZ,GAA8B,EAC9B,IAAY,EACZ,GAAkB;IAElB,MAAM,MAAM,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACxE,IAAI,GAAG,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9E,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC;IACrC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAClE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,IAAY,EACZ,GAA8B,EAC9B,KAAc,EACd,IAAI,GAAG,YAAY;IAEnB,IAAI,CAAC,GAAG,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACnE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CACV,IAAI,GAAG,WAAW,IAAI,4CAA4C,IAAI,eAAe;YACnF,kEAAkE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,QAAQ,CAAC,CAAU,EAAE,CAAU;IAC7C,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC7F,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC;IACD,IACE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS;QAC7C,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS,EAC7C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,CACL,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAE,CAAS,CAAC,CAAC,CAAC,EAAG,CAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAC/F,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,MAAW,EAAE,KAAgB;IACrD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,eAAe,CAAC,MAAW,EAAE,KAAgB;IAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAC9B,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,CACvE,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,MAAW,EAAE,KAAgB;IACpE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAwB;IACvD,IAAI,OAAO,WAAW,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IAClD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,KAAwB;IACjE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,IAAI,GAAG;QAAE,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW;IACX,cAAc;IACd,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;IAC9C,WAAW;IACX,SAAS;IACT,aAAa;CACd,CAAC","sourcesContent":["// Prop bookkeeping for define() (view/05-element.md \"Props\", ADR 0007): attribute names and\n// parsing, validation through Standard Schema, defaults, change detection, seed restore. The\n// prop builders register `propFeature` (features.ts): components without props don't bundle it.\nimport type { Prop } from './prop.js';\nimport { DEV, message } from './view/index.js';\n\ntype Bag = Readonly<Record<string, unknown>>;\n\nexport type PropTable = Readonly<Record<string, Prop<unknown>>>;\n\n/** `minPrice` → `min-price`. */\nexport const kebab = (name: string): string => name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);\n\n/** The prop's attribute, or undefined for a property-only prop. */\nexport function attributeOf(name: string, def: Prop<unknown>): string | undefined {\n if (def.attribute === false) return undefined;\n return def.attribute ?? kebab(name);\n}\n\nexport type Checked =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly issues: readonly string[] };\n\nconst builtIn: Readonly<Record<string, (v: unknown) => boolean>> = {\n string: (v) => typeof v === 'string',\n number: (v) => typeof v === 'number' && !Number.isNaN(v),\n boolean: (v) => typeof v === 'boolean',\n};\n\n/** Runs the built-in type check and the prop's schema. Schemas must be synchronous. */\nexport function checkValue(tag: string, name: string, def: Prop<unknown>, value: unknown): Checked {\n const typeOk = builtIn[def.kind];\n if (typeOk !== undefined && !typeOk(value)) {\n return {\n ok: false,\n issues: [`expected a ${def.kind}, got ${typeof value}`],\n };\n }\n const schema = def.schema;\n if (schema === undefined) return { ok: true, value };\n // A type guard (prop.value/prop.json, gyral-c5d.7); ArkType-style callable schemas have ~standard.\n if (!('~standard' in schema)) {\n return schema(value) ? { ok: true, value } : { ok: false, issues: [`failed ${schema.name}`] };\n }\n const result = schema['~standard'].validate(value);\n if (result instanceof Promise) {\n throw new TypeError(message(20, tag, name));\n }\n if (result.issues !== undefined)\n return { ok: false, issues: result.issues.map((i) => i.message) };\n return { ok: true, value: result.value };\n}\n\n/** Parses an attribute value (`null`: absent) per the builder table; undefined means missing. */\nexport function parseAttribute(def: Prop<unknown>, raw: string | null): Checked | undefined {\n if (def.kind === 'boolean') return { ok: true, value: raw !== null };\n if (raw === null) return undefined;\n if (def.kind === 'number') {\n const n = raw.trim() === '' ? Number.NaN : Number(raw);\n return Number.isNaN(n)\n ? { ok: false, issues: [`\"${raw}\" is not a number`] }\n : { ok: true, value: n };\n }\n if (def.kind === 'json') {\n try {\n return { ok: true, value: JSON.parse(raw) as unknown };\n } catch {\n return { ok: false, issues: ['the attribute is not valid JSON'] };\n }\n }\n return { ok: true, value: raw };\n}\n\n/** Logs an invalid value; the caller then treats the prop as missing. */\nexport function reportInvalid(tag: string, name: string, from: string, issues: readonly string[]) {\n console.error(message(21, tag, name, from, issues.join('; ')));\n}\n\n/**\n * An attribute's value for prop `name` (view/05-element.md \"When props are validated\"):\n * parsed per the builder and always validated; invalid or absent values are missing.\n */\nexport function attributeValue(\n tag: string,\n name: string,\n def: Prop<unknown> | undefined,\n attr: string,\n raw: string | null,\n): unknown {\n const parsed = def === undefined ? undefined : parseAttribute(def, raw);\n if (def === undefined || parsed === undefined) return undefined;\n const checked = parsed.ok ? checkValue(tag, name, def, parsed.value) : parsed;\n if (checked.ok) return checked.value;\n reportInvalid(tag, name, `the attribute ${attr}`, checked.issues);\n return undefined;\n}\n\n/**\n * A property set's (or seed's) value for prop `name`: validated in development only, where an\n * invalid value is missing and a schema that transforms warns. Production keeps the input\n * without calling this (propFeature, element.ts: gyral-c5d.14).\n */\nexport function propertyValue(\n tag: string,\n name: string,\n def: Prop<unknown> | undefined,\n value: unknown,\n from = 'a property',\n): unknown {\n if (!DEV || value === undefined || def === undefined) return value;\n const checked = checkValue(tag, name, def, value);\n if (!checked.ok) {\n reportInvalid(tag, name, from, checked.issues);\n return undefined;\n }\n if (!sameData(checked.value, value)) {\n console.warn(\n `<${tag}> prop \"${name}\": its schema transformed the value from ${from}. Production ` +\n \"doesn't run schemas on property sets; validate, don't transform.\",\n );\n }\n return value;\n}\n\n/** Structural equality for plain data (arrays, plain objects), `Object.is` for the rest. */\nexport function sameData(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n if (Array.isArray(a)) {\n return Array.isArray(b) && a.length === b.length && a.every((x, i) => sameData(x, b[i]));\n }\n if (\n Object.getPrototypeOf(a) !== Object.prototype ||\n Object.getPrototypeOf(b) !== Object.prototype\n ) {\n return false;\n }\n const ka = Object.keys(a);\n return (\n ka.length === Object.keys(b).length && ka.every((k) => sameData((a as Bag)[k], (b as Bag)[k]))\n );\n}\n\n/** The declared props as components see them: `default` fills missing values. */\nexport function readProps(values: Bag, table: PropTable): Bag {\n const out: Record<string, unknown> = {};\n for (const [name, def] of Object.entries(table)) {\n const value = values[name];\n out[name] = value === undefined ? def.default : value;\n }\n return out;\n}\n\n/** Required props that are still missing (ADR 0007 addendum). */\nexport function missingRequired(values: Bag, table: PropTable): string[] {\n return Object.keys(table).filter(\n (name) => table[name]?.required === true && values[name] === undefined,\n );\n}\n\n/** Warns about required props that are still missing, at first render. */\nexport function warnMissing(tag: string, values: Bag, table: PropTable): void {\n const missing = missingRequired(values, table);\n if (missing.length > 0) {\n console.warn(message(22, tag, missing.join(', ')));\n }\n}\n\n/**\n * Declared props that collide with a built-in element property (`hidden`, `title`, `id`, …):\n * the accessor replaces the built-in, so setting the prop silently changes what the platform\n * does with it (gyral-czi.33).\n */\nexport function shadowedBuiltins(names: readonly string[]): string[] {\n if (typeof HTMLElement === 'undefined') return [];\n return names.filter((name) => name in HTMLElement.prototype);\n}\n\n/** define(): a prop named like a built-in property is an error in development, else a warning. */\nexport function checkShadowed(tag: string, names: readonly string[]): void {\n const shadowed = shadowedBuiltins(names);\n if (shadowed.length === 0) return;\n const text = message(23, tag, shadowed.join(', '));\n if (DEV) throw new TypeError(text);\n console.warn(text);\n}\n\n/**\n * What the element uses, registered by the prop builders (features.ts). Property sets and seeds\n * go through `propertyValue` in development only: production keeps the value as given, so the\n * property path's schema and guard handling stay out of production bundles (gyral-c5d.14).\n */\nexport const propFeature = {\n attributeOf,\n attributeValue,\n propertyValue: DEV ? propertyValue : undefined,\n warnMissing,\n readProps,\n checkShadowed,\n};\n\nexport type PropFeature = typeof propFeature;\n"]}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Driver, RetryPolicy } from './command.js';
|
|
2
|
+
/**
|
|
3
|
+
* The same driver (same name, so substitution by name still works), with `run` retried when it
|
|
4
|
+
* rejects: up to `policy.times` more attempts, after `delayMs` (doubling from it with
|
|
5
|
+
* `backoff: 'exponential'`; a random part of it with `jitter`), and only for failures
|
|
6
|
+
* `retryIf` accepts. An abort (the command switched away, the component disconnected) ends it
|
|
7
|
+
* at once and is never retried. Wrap where the driver is chosen: app setup, a component's
|
|
8
|
+
* `drivers`, or a test fake.
|
|
9
|
+
*
|
|
10
|
+
* const api = retry(makeHttpDriver({ baseUrl: '/api', timeoutMs: 8000 }), {
|
|
11
|
+
* times: 3, delayMs: 300, backoff: 'exponential', jitter: true, retryIf: retryableHttpError,
|
|
12
|
+
* });
|
|
13
|
+
* const feed = retry(subscription('feed', connect), { times: Infinity, delayMs: 1000 });
|
|
14
|
+
*/
|
|
15
|
+
export declare function retry<I, O, E>(driver: Driver<I, O, E>, policy: RetryPolicy<E>): Driver<I, O, E>;
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Waits `ms`, or rejects with the abort reason as soon as `signal` aborts. */
|
|
2
|
+
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
3
|
+
const stop = () => {
|
|
4
|
+
clearTimeout(timer);
|
|
5
|
+
reject(signal.reason);
|
|
6
|
+
};
|
|
7
|
+
const timer = setTimeout(() => {
|
|
8
|
+
signal.removeEventListener('abort', stop);
|
|
9
|
+
resolve();
|
|
10
|
+
}, ms);
|
|
11
|
+
signal.addEventListener('abort', stop, { once: true });
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* The same driver (same name, so substitution by name still works), with `run` retried when it
|
|
15
|
+
* rejects: up to `policy.times` more attempts, after `delayMs` (doubling from it with
|
|
16
|
+
* `backoff: 'exponential'`; a random part of it with `jitter`), and only for failures
|
|
17
|
+
* `retryIf` accepts. An abort (the command switched away, the component disconnected) ends it
|
|
18
|
+
* at once and is never retried. Wrap where the driver is chosen: app setup, a component's
|
|
19
|
+
* `drivers`, or a test fake.
|
|
20
|
+
*
|
|
21
|
+
* const api = retry(makeHttpDriver({ baseUrl: '/api', timeoutMs: 8000 }), {
|
|
22
|
+
* times: 3, delayMs: 300, backoff: 'exponential', jitter: true, retryIf: retryableHttpError,
|
|
23
|
+
* });
|
|
24
|
+
* const feed = retry(subscription('feed', connect), { times: Infinity, delayMs: 1000 });
|
|
25
|
+
*/
|
|
26
|
+
export function retry(driver, policy) {
|
|
27
|
+
const { times, delayMs: base = 0, backoff, jitter, retryIf } = policy;
|
|
28
|
+
return {
|
|
29
|
+
...driver,
|
|
30
|
+
run: async (input, ctx) => {
|
|
31
|
+
for (let attempt = 0;; attempt += 1) {
|
|
32
|
+
try {
|
|
33
|
+
return await driver.run(input, ctx);
|
|
34
|
+
}
|
|
35
|
+
catch (cause) {
|
|
36
|
+
if (ctx.signal.aborted || attempt >= times)
|
|
37
|
+
throw cause;
|
|
38
|
+
// Sound: without `toError` the driver's error type is what it throws.
|
|
39
|
+
if (retryIf?.(driver.toError?.(cause) ?? cause) === false)
|
|
40
|
+
throw cause;
|
|
41
|
+
const delay = backoff === 'exponential' ? base * 2 ** attempt : base;
|
|
42
|
+
await sleep(jitter === true ? Math.random() * delay : delay, ctx.signal);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAIA,+EAA+E;AAC/E,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,MAAmB,EAAiB,EAAE,CAC/D,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,CAAC,MAAM,CAAC,MAAe,CAAC,CAAC;IACjC,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAEL;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,KAAK,CAAU,MAAuB,EAAE,MAAsB;IAC5E,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACtE,OAAO;QACL,GAAG,MAAM;QACT,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACxB,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACrC,IAAI,CAAC;oBACH,OAAO,MAAM,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBACtC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,IAAI,KAAK;wBAAE,MAAM,KAAK,CAAC;oBACxD,sEAAsE;oBACtE,IAAI,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAK,KAAW,CAAC,KAAK,KAAK;wBAAE,MAAM,KAAK,CAAC;oBAC9E,MAAM,KAAK,GAAG,OAAO,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;oBACrE,MAAM,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3E,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// Retries as a driver wrapper (ADR 0022): the interpreter runs a driver once, and apps that\n// never call `retry` don't bundle its delays. A standalone module, like subscription.ts.\nimport type { Driver, RetryPolicy } from './command.js';\n\n/** Waits `ms`, or rejects with the abort reason as soon as `signal` aborts. */\nconst sleep = (ms: number, signal: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n const stop = (): void => {\n clearTimeout(timer);\n reject(signal.reason as Error);\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', stop);\n resolve();\n }, ms);\n signal.addEventListener('abort', stop, { once: true });\n });\n\n/**\n * The same driver (same name, so substitution by name still works), with `run` retried when it\n * rejects: up to `policy.times` more attempts, after `delayMs` (doubling from it with\n * `backoff: 'exponential'`; a random part of it with `jitter`), and only for failures\n * `retryIf` accepts. An abort (the command switched away, the component disconnected) ends it\n * at once and is never retried. Wrap where the driver is chosen: app setup, a component's\n * `drivers`, or a test fake.\n *\n * const api = retry(makeHttpDriver({ baseUrl: '/api', timeoutMs: 8000 }), {\n * times: 3, delayMs: 300, backoff: 'exponential', jitter: true, retryIf: retryableHttpError,\n * });\n * const feed = retry(subscription('feed', connect), { times: Infinity, delayMs: 1000 });\n */\nexport function retry<I, O, E>(driver: Driver<I, O, E>, policy: RetryPolicy<E>): Driver<I, O, E> {\n const { times, delayMs: base = 0, backoff, jitter, retryIf } = policy;\n return {\n ...driver,\n run: async (input, ctx) => {\n for (let attempt = 0; ; attempt += 1) {\n try {\n return await driver.run(input, ctx);\n } catch (cause) {\n if (ctx.signal.aborted || attempt >= times) throw cause;\n // Sound: without `toError` the driver's error type is what it throws.\n if (retryIf?.(driver.toError?.(cause) ?? (cause as E)) === false) throw cause;\n const delay = backoff === 'exponential' ? base * 2 ** attempt : base;\n await sleep(jitter === true ? Math.random() * delay : delay, ctx.signal);\n }\n }\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** One host as the scheduler sees it. define() creates one per element. */
|
|
2
|
+
export interface HostTask {
|
|
3
|
+
/** The component's tag, for errors and the loop guard. */
|
|
4
|
+
readonly tag: string;
|
|
5
|
+
/** Gyral host ancestors in the composed tree, recorded when the host connects. */
|
|
6
|
+
depth: number;
|
|
7
|
+
/** `PropsChanged` (when props changed), then the view and its commit. May throw. */
|
|
8
|
+
readonly render: () => void;
|
|
9
|
+
}
|
|
10
|
+
/** Post-render phases, run in this order once per pass (04 "Post-render queue"). */
|
|
11
|
+
export declare const POST_FOCUS = 0;
|
|
12
|
+
export declare const POST_STATES = 1;
|
|
13
|
+
export declare const POST_HYDRATED = 2;
|
|
14
|
+
export declare const POST_INIT = 3;
|
|
15
|
+
/** A message reached a host or a store (04 "`settled()`": messages restart the quiet window). */
|
|
16
|
+
export declare function noteActivity(): void;
|
|
17
|
+
/** How much activity (messages, marks) the page has seen; only differences matter. */
|
|
18
|
+
export declare const activityCount: () => number;
|
|
19
|
+
/**
|
|
20
|
+
* True when no host is dirty (in either lane), no flush or transition update is pending and
|
|
21
|
+
* nothing is deferred.
|
|
22
|
+
*/
|
|
23
|
+
export declare const isQuiet: () => boolean;
|
|
24
|
+
/** Resolves at the end of the flush that leaves the scheduler quiet. */
|
|
25
|
+
export declare function whenQuiet(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Marks `task` for the next flush: the microtask one, or with `onFrame` the next animation
|
|
28
|
+
* frame's (04 "Frame lane"; the microtask one when the build left the frame lane out). Marking
|
|
29
|
+
* an already-dirty host does nothing; a microtask mark moves a host waiting for the frame into
|
|
30
|
+
* the microtask flush.
|
|
31
|
+
*/
|
|
32
|
+
export declare function markDirty(task: HostTask, onFrame?: boolean): void;
|
|
33
|
+
/** Queues post-render work for the current (or next) flush. */
|
|
34
|
+
export declare function afterRender(phaseOf: number, run: () => void): void;
|
|
35
|
+
/** A message asked for a view transition: the pending flush runs inside one (04). */
|
|
36
|
+
export declare function requestTransition(): void;
|
|
37
|
+
/** Runs `fn` in a microtask that settled() waits for (outputs sent up to a parent). */
|
|
38
|
+
export declare function defer(fn: () => void): void;
|
|
39
|
+
/**
|
|
40
|
+
* Counts `work` (code loading with import(), whose continuation connects hosts) as pending
|
|
41
|
+
* until it settles, so settled() waits for it. `work` must not reject.
|
|
42
|
+
*/
|
|
43
|
+
export declare function hold(work: Promise<void>): void;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// The global scheduler (docs/design-docs/view/04-scheduler.md). Every host's render goes
|
|
2
|
+
// through it: reducers run at once, the render waits for one microtask flush shared by the
|
|
3
|
+
// whole page. A flush renders dirty hosts parents first (smallest depth, then marking order),
|
|
4
|
+
// then their element hooks (children first, view/02 "Commit order"), then runs the post-render queue (focus, custom states, `Hydrated`, deferred init commands),
|
|
5
|
+
// and loops until nothing is dirty. Messages a spec lists in `renderOnFrame` mark their host in
|
|
6
|
+
// the frame lane instead: it renders in the next animation frame (04 "Frame lane",
|
|
7
|
+
// frame-lane.ts). The frame lane and view transitions come through `#spec-features`, present
|
|
8
|
+
// unless a compiled build found no module naming them (gyral-c5d.12). It lives outside view/
|
|
9
|
+
// (view/ never imports it) and drives the renderer through view/index.ts.
|
|
10
|
+
import { fail } from './errors.js';
|
|
11
|
+
import { frameLane, viewTransitions } from '#spec-features';
|
|
12
|
+
import { DEV, flushHooks, message, renderBatch } from './view/index.js';
|
|
13
|
+
/** Post-render phases, run in this order once per pass (04 "Post-render queue"). */
|
|
14
|
+
export const POST_FOCUS = 0;
|
|
15
|
+
export const POST_STATES = 1;
|
|
16
|
+
export const POST_HYDRATED = 2;
|
|
17
|
+
export const POST_INIT = 3;
|
|
18
|
+
/** Loop guard (04 "Loop guard"): renders of one host, and passes, in one flush. */
|
|
19
|
+
const MAX_RENDERS = 10;
|
|
20
|
+
const MAX_PASSES = 100;
|
|
21
|
+
const IDLE = 0;
|
|
22
|
+
const SCHEDULED = 1;
|
|
23
|
+
const TRANSITION = 2;
|
|
24
|
+
const FLUSHING = 3;
|
|
25
|
+
const dirty = new Set();
|
|
26
|
+
let post = [];
|
|
27
|
+
let phase = IDLE;
|
|
28
|
+
let transitionWanted = false;
|
|
29
|
+
/** Deferred callbacks (outputs to parents) and held loads still pending; settled() waits. */
|
|
30
|
+
let deferred = 0;
|
|
31
|
+
let quiet = null;
|
|
32
|
+
/** Messages delivered and hosts marked so far; settled() restarts its quiet window on a change. */
|
|
33
|
+
let activity = 0;
|
|
34
|
+
/** A message reached a host or a store (04 "`settled()`": messages restart the quiet window). */
|
|
35
|
+
export function noteActivity() {
|
|
36
|
+
activity += 1;
|
|
37
|
+
}
|
|
38
|
+
/** How much activity (messages, marks) the page has seen; only differences matter. */
|
|
39
|
+
export const activityCount = () => activity;
|
|
40
|
+
/**
|
|
41
|
+
* True when no host is dirty (in either lane), no flush or transition update is pending and
|
|
42
|
+
* nothing is deferred.
|
|
43
|
+
*/
|
|
44
|
+
export const isQuiet = () => phase === IDLE && dirty.size === 0 && frameLane?.pending() !== true && deferred === 0;
|
|
45
|
+
/** Resolves at the end of the flush that leaves the scheduler quiet. */
|
|
46
|
+
export function whenQuiet() {
|
|
47
|
+
if (isQuiet())
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
if (quiet === null) {
|
|
50
|
+
quiet = Promise.withResolvers();
|
|
51
|
+
}
|
|
52
|
+
return quiet.promise;
|
|
53
|
+
}
|
|
54
|
+
function schedule() {
|
|
55
|
+
if (phase !== IDLE)
|
|
56
|
+
return;
|
|
57
|
+
phase = SCHEDULED;
|
|
58
|
+
queueMicrotask(start);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Marks `task` for the next flush: the microtask one, or with `onFrame` the next animation
|
|
62
|
+
* frame's (04 "Frame lane"; the microtask one when the build left the frame lane out). Marking
|
|
63
|
+
* an already-dirty host does nothing; a microtask mark moves a host waiting for the frame into
|
|
64
|
+
* the microtask flush.
|
|
65
|
+
*/
|
|
66
|
+
export function markDirty(task, onFrame = false) {
|
|
67
|
+
activity += 1;
|
|
68
|
+
if (dirty.has(task))
|
|
69
|
+
return;
|
|
70
|
+
if (onFrame && frameLane !== undefined) {
|
|
71
|
+
frameLane.add(task, markDirty);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
frameLane?.drop(task);
|
|
75
|
+
dirty.add(task);
|
|
76
|
+
schedule();
|
|
77
|
+
}
|
|
78
|
+
/** Queues post-render work for the current (or next) flush. */
|
|
79
|
+
export function afterRender(phaseOf, run) {
|
|
80
|
+
post.push({ phase: phaseOf, run });
|
|
81
|
+
schedule();
|
|
82
|
+
}
|
|
83
|
+
/** A message asked for a view transition: the pending flush runs inside one (04). */
|
|
84
|
+
export function requestTransition() {
|
|
85
|
+
if (phase === IDLE || phase === SCHEDULED)
|
|
86
|
+
transitionWanted = true;
|
|
87
|
+
}
|
|
88
|
+
/** Runs `fn` in a microtask that settled() waits for (outputs sent up to a parent). */
|
|
89
|
+
export function defer(fn) {
|
|
90
|
+
deferred += 1;
|
|
91
|
+
queueMicrotask(() => {
|
|
92
|
+
try {
|
|
93
|
+
fn();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
fail(error, 'command', message(30));
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
deferred -= 1;
|
|
100
|
+
settle();
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Counts `work` (code loading with import(), whose continuation connects hosts) as pending
|
|
106
|
+
* until it settles, so settled() waits for it. `work` must not reject.
|
|
107
|
+
*/
|
|
108
|
+
export function hold(work) {
|
|
109
|
+
deferred += 1;
|
|
110
|
+
void work.finally(() => {
|
|
111
|
+
deferred -= 1;
|
|
112
|
+
settle();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function start() {
|
|
116
|
+
if (transitionWanted) {
|
|
117
|
+
phase = TRANSITION;
|
|
118
|
+
if (viewTransitions?.(flush) === true)
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
flush();
|
|
122
|
+
}
|
|
123
|
+
/** The dirty host with the smallest depth; ties go to the one marked first. */
|
|
124
|
+
function next() {
|
|
125
|
+
let best;
|
|
126
|
+
for (const task of dirty)
|
|
127
|
+
if (best === undefined || task.depth < best.depth)
|
|
128
|
+
best = task;
|
|
129
|
+
return best;
|
|
130
|
+
}
|
|
131
|
+
function renderAll(counts) {
|
|
132
|
+
while (dirty.size > 0) {
|
|
133
|
+
const task = next();
|
|
134
|
+
dirty.delete(task);
|
|
135
|
+
const renders = (counts.get(task) ?? 0) + 1;
|
|
136
|
+
counts.set(task, renders);
|
|
137
|
+
if (renders > MAX_RENDERS)
|
|
138
|
+
throw loopError(counts);
|
|
139
|
+
try {
|
|
140
|
+
task.render();
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
fail(error, 'view', message(31, task.tag), { tag: task.tag });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function runPost() {
|
|
148
|
+
const tasks = post.sort((a, b) => a.phase - b.phase); // stable: queue order within a phase
|
|
149
|
+
post = [];
|
|
150
|
+
for (const task of tasks) {
|
|
151
|
+
try {
|
|
152
|
+
task.run();
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
fail(error, 'view', message(32));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function loopError(counts) {
|
|
160
|
+
const tags = [...new Set([...counts.keys()].map((t) => `<${t.tag}>`))].join(', ');
|
|
161
|
+
return new Error(message(33, tags));
|
|
162
|
+
}
|
|
163
|
+
function flush() {
|
|
164
|
+
phase = FLUSHING;
|
|
165
|
+
const counts = new Map();
|
|
166
|
+
let failure;
|
|
167
|
+
try {
|
|
168
|
+
renderBatch(() => {
|
|
169
|
+
for (let pass = 1;; pass++) {
|
|
170
|
+
renderAll(counts);
|
|
171
|
+
flushHooks(); // every dirty host rendered: element hooks run, children first
|
|
172
|
+
// Client calls can deliver intents: commit their new state before focus/other work.
|
|
173
|
+
if (dirty.size === 0 && post.length > 0)
|
|
174
|
+
runPost();
|
|
175
|
+
if (dirty.size === 0 && post.length === 0)
|
|
176
|
+
return;
|
|
177
|
+
if (pass >= MAX_PASSES)
|
|
178
|
+
throw loopError(counts);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
dirty.clear();
|
|
184
|
+
post = [];
|
|
185
|
+
failure = error instanceof Error ? error : new Error(String(error));
|
|
186
|
+
}
|
|
187
|
+
phase = IDLE;
|
|
188
|
+
transitionWanted = false;
|
|
189
|
+
if (failure === undefined) {
|
|
190
|
+
settle();
|
|
191
|
+
}
|
|
192
|
+
else if (!DEV) {
|
|
193
|
+
fail(failure, 'view', failure.message); // production: report and drop the rest, so the page doesn't freeze
|
|
194
|
+
settle();
|
|
195
|
+
}
|
|
196
|
+
else if (quiet !== null) {
|
|
197
|
+
const waiting = quiet;
|
|
198
|
+
quiet = null;
|
|
199
|
+
waiting.reject(failure);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
throw failure;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function settle() {
|
|
206
|
+
if (quiet === null || !isQuiet())
|
|
207
|
+
return;
|
|
208
|
+
const waiting = quiet;
|
|
209
|
+
quiet = null;
|
|
210
|
+
waiting.resolve();
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["// The global scheduler (docs/design-docs/view/04-scheduler.md). Every host's render goes\n// through it: reducers run at once, the render waits for one microtask flush shared by the\n// whole page. A flush renders dirty hosts parents first (smallest depth, then marking order),\n// then their element hooks (children first, view/02 \"Commit order\"), then runs the post-render queue (focus, custom states, `Hydrated`, deferred init commands),\n// and loops until nothing is dirty. Messages a spec lists in `renderOnFrame` mark their host in\n// the frame lane instead: it renders in the next animation frame (04 \"Frame lane\",\n// frame-lane.ts). The frame lane and view transitions come through `#spec-features`, present\n// unless a compiled build found no module naming them (gyral-c5d.12). It lives outside view/\n// (view/ never imports it) and drives the renderer through view/index.ts.\nimport { fail } from './errors.js';\nimport { frameLane, viewTransitions } from '#spec-features';\nimport { DEV, flushHooks, message, renderBatch } from './view/index.js';\n\n/** One host as the scheduler sees it. define() creates one per element. */\nexport interface HostTask {\n /** The component's tag, for errors and the loop guard. */\n readonly tag: string;\n /** Gyral host ancestors in the composed tree, recorded when the host connects. */\n depth: number;\n /** `PropsChanged` (when props changed), then the view and its commit. May throw. */\n readonly render: () => void;\n}\n\n/** Post-render phases, run in this order once per pass (04 \"Post-render queue\"). */\nexport const POST_FOCUS = 0;\nexport const POST_STATES = 1;\nexport const POST_HYDRATED = 2;\nexport const POST_INIT = 3;\n\ninterface PostTask {\n readonly phase: number;\n readonly run: () => void;\n}\n\n/** Loop guard (04 \"Loop guard\"): renders of one host, and passes, in one flush. */\nconst MAX_RENDERS = 10;\nconst MAX_PASSES = 100;\n\nconst IDLE = 0;\nconst SCHEDULED = 1;\nconst TRANSITION = 2;\nconst FLUSHING = 3;\n\nconst dirty = new Set<HostTask>();\nlet post: PostTask[] = [];\nlet phase = IDLE;\nlet transitionWanted = false;\n/** Deferred callbacks (outputs to parents) and held loads still pending; settled() waits. */\nlet deferred = 0;\nlet quiet: { promise: Promise<void>; resolve: () => void; reject: (e: unknown) => void } | null =\n null;\n/** Messages delivered and hosts marked so far; settled() restarts its quiet window on a change. */\nlet activity = 0;\n\n/** A message reached a host or a store (04 \"`settled()`\": messages restart the quiet window). */\nexport function noteActivity(): void {\n activity += 1;\n}\n\n/** How much activity (messages, marks) the page has seen; only differences matter. */\nexport const activityCount = (): number => activity;\n\n/**\n * True when no host is dirty (in either lane), no flush or transition update is pending and\n * nothing is deferred.\n */\nexport const isQuiet = (): boolean =>\n phase === IDLE && dirty.size === 0 && frameLane?.pending() !== true && deferred === 0;\n\n/** Resolves at the end of the flush that leaves the scheduler quiet. */\nexport function whenQuiet(): Promise<void> {\n if (isQuiet()) return Promise.resolve();\n if (quiet === null) {\n quiet = Promise.withResolvers();\n }\n return quiet.promise;\n}\n\nfunction schedule(): void {\n if (phase !== IDLE) return;\n phase = SCHEDULED;\n queueMicrotask(start);\n}\n\n/**\n * Marks `task` for the next flush: the microtask one, or with `onFrame` the next animation\n * frame's (04 \"Frame lane\"; the microtask one when the build left the frame lane out). Marking\n * an already-dirty host does nothing; a microtask mark moves a host waiting for the frame into\n * the microtask flush.\n */\nexport function markDirty(task: HostTask, onFrame = false): void {\n activity += 1;\n if (dirty.has(task)) return;\n if (onFrame && frameLane !== undefined) {\n frameLane.add(task, markDirty);\n return;\n }\n frameLane?.drop(task);\n dirty.add(task);\n schedule();\n}\n\n/** Queues post-render work for the current (or next) flush. */\nexport function afterRender(phaseOf: number, run: () => void): void {\n post.push({ phase: phaseOf, run });\n schedule();\n}\n\n/** A message asked for a view transition: the pending flush runs inside one (04). */\nexport function requestTransition(): void {\n if (phase === IDLE || phase === SCHEDULED) transitionWanted = true;\n}\n\n/** Runs `fn` in a microtask that settled() waits for (outputs sent up to a parent). */\nexport function defer(fn: () => void): void {\n deferred += 1;\n queueMicrotask(() => {\n try {\n fn();\n } catch (error) {\n fail(error, 'command', message(30));\n } finally {\n deferred -= 1;\n settle();\n }\n });\n}\n\n/**\n * Counts `work` (code loading with import(), whose continuation connects hosts) as pending\n * until it settles, so settled() waits for it. `work` must not reject.\n */\nexport function hold(work: Promise<void>): void {\n deferred += 1;\n void work.finally(() => {\n deferred -= 1;\n settle();\n });\n}\n\nfunction start(): void {\n if (transitionWanted) {\n phase = TRANSITION;\n if (viewTransitions?.(flush) === true) return;\n }\n flush();\n}\n\n/** The dirty host with the smallest depth; ties go to the one marked first. */\nfunction next(): HostTask {\n let best: HostTask | undefined;\n for (const task of dirty) if (best === undefined || task.depth < best.depth) best = task;\n return best as HostTask;\n}\n\nfunction renderAll(counts: Map<HostTask, number>): void {\n while (dirty.size > 0) {\n const task = next();\n dirty.delete(task);\n const renders = (counts.get(task) ?? 0) + 1;\n counts.set(task, renders);\n if (renders > MAX_RENDERS) throw loopError(counts);\n try {\n task.render();\n } catch (error) {\n fail(error, 'view', message(31, task.tag), { tag: task.tag });\n }\n }\n}\n\nfunction runPost(): void {\n const tasks = post.sort((a, b) => a.phase - b.phase); // stable: queue order within a phase\n post = [];\n for (const task of tasks) {\n try {\n task.run();\n } catch (error) {\n fail(error, 'view', message(32));\n }\n }\n}\n\nfunction loopError(counts: Map<HostTask, number>): Error {\n const tags = [...new Set([...counts.keys()].map((t) => `<${t.tag}>`))].join(', ');\n return new Error(message(33, tags));\n}\n\nfunction flush(): void {\n phase = FLUSHING;\n const counts = new Map<HostTask, number>();\n let failure: Error | undefined;\n try {\n renderBatch(() => {\n for (let pass = 1; ; pass++) {\n renderAll(counts);\n flushHooks(); // every dirty host rendered: element hooks run, children first\n // Client calls can deliver intents: commit their new state before focus/other work.\n if (dirty.size === 0 && post.length > 0) runPost();\n if (dirty.size === 0 && post.length === 0) return;\n if (pass >= MAX_PASSES) throw loopError(counts);\n }\n });\n } catch (error) {\n dirty.clear();\n post = [];\n failure = error instanceof Error ? error : new Error(String(error));\n }\n phase = IDLE;\n transitionWanted = false;\n if (failure === undefined) {\n settle();\n } else if (!DEV) {\n fail(failure, 'view', failure.message); // production: report and drop the rest, so the page doesn't freeze\n settle();\n } else if (quiet !== null) {\n const waiting = quiet;\n quiet = null;\n waiting.reject(failure);\n } else {\n throw failure;\n }\n}\n\nfunction settle(): void {\n if (quiet === null || !isQuiet()) return;\n const waiting = quiet;\n quiet = null;\n waiting.resolve();\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// JSON safe to inline in a <script> element. Its own module: head.ts (the head model) and the
|
|
2
|
+
// store seeds both use it, and keeping it out of store-scope.ts stops a bundler from turning
|
|
3
|
+
// the store registry into a shared chunk every page loads (gyral-dyn.35).
|
|
4
|
+
/** JSON for an inline `<script type="application/json">`: `</script>` and friends escaped. */
|
|
5
|
+
export function scriptSafeJson(value) {
|
|
6
|
+
return JSON.stringify(value)
|
|
7
|
+
.replaceAll('<', '\\u003c')
|
|
8
|
+
.replaceAll('>', '\\u003e')
|
|
9
|
+
.replaceAll('&', '\\u0026')
|
|
10
|
+
.replaceAll('
', '\\u2028')
|
|
11
|
+
.replaceAll('
', '\\u2029');
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=script-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-json.js","sourceRoot":"","sources":["../src/script-json.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6FAA6F;AAC7F,0EAA0E;AAE1E,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SAC1B,UAAU,CAAC;CACf,EAAE,SAAS,CAAC;SACR,UAAU,CAAC;CACf,EAAE,SAAS,CAAC,CAAC;AACd,CAAC","sourcesContent":["// JSON safe to inline in a <script> element. Its own module: head.ts (the head model) and the\n// store seeds both use it, and keeping it out of store-scope.ts stops a bundler from turning\n// the store registry into a shared chunk every page loads (gyral-dyn.35).\n\n/** JSON for an inline `<script type=\"application/json\">`: `</script>` and friends escaped. */\nexport function scriptSafeJson(value: unknown): string {\n return JSON.stringify(value)\n .replaceAll('<', '\\\\u003c')\n .replaceAll('>', '\\\\u003e')\n .replaceAll('&', '\\\\u0026')\n .replaceAll('
', '\\\\u2028')\n .replaceAll('
', '\\\\u2029');\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComponentSpec, Tagged } from './types.js';
|
|
2
|
+
import { type ServerComponent } from './view/index.js';
|
|
3
|
+
/** The server registry entry for `spec`. */
|
|
4
|
+
export declare function serverComponent<S, M extends Tagged, P>(tag: string, spec: ComponentSpec<S, M, P>): ServerComponent;
|
|
5
|
+
/**
|
|
6
|
+
* Registers every spec define() recorded outside the browser (and not registered yet) in
|
|
7
|
+
* view/'s server registry. `@gyral/core/internal/server` calls it before each render; client code never
|
|
8
|
+
* imports this module.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerRecordedSpecs(): void;
|