@askrjs/askr 0.0.48 → 0.0.49
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/dist/benchmark.js +6 -6
- package/dist/benchmark.js.map +1 -1
- package/dist/boot/hydration.js +140 -0
- package/dist/boot/hydration.js.map +1 -0
- package/dist/boot/index.d.ts +3 -56
- package/dist/boot/index.d.ts.map +1 -1
- package/dist/boot/index.js +62 -410
- package/dist/boot/index.js.map +1 -1
- package/dist/boot/root-lifecycle.d.ts +15 -0
- package/dist/boot/root-lifecycle.d.ts.map +1 -0
- package/dist/boot/root-lifecycle.js +205 -0
- package/dist/boot/root-lifecycle.js.map +1 -0
- package/dist/boot/route-startup.js +45 -0
- package/dist/boot/route-startup.js.map +1 -0
- package/dist/boot/types.d.ts +62 -0
- package/dist/boot/types.d.ts.map +1 -0
- package/dist/common/component.d.ts +3 -1
- package/dist/common/component.d.ts.map +1 -1
- package/dist/common/jsx.d.ts +1 -1
- package/dist/common/jsx.d.ts.map +1 -1
- package/dist/common/jsx.js.map +1 -1
- package/dist/common/props.d.ts +1 -1
- package/dist/common/render-context.js +55 -0
- package/dist/common/render-context.js.map +1 -0
- package/dist/common/router.d.ts +5 -1
- package/dist/common/router.d.ts.map +1 -1
- package/dist/common/ssr.d.ts +1 -1
- package/dist/common/ssr.js.map +1 -1
- package/dist/common/vnode.d.ts +5 -4
- package/dist/common/vnode.d.ts.map +1 -1
- package/dist/common/vnode.js.map +1 -1
- package/dist/components/error-boundary.d.ts +1 -1
- package/dist/components/error-boundary.js +2 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/link.js.map +1 -1
- package/dist/control/for.js +2 -1
- package/dist/control/for.js.map +1 -1
- package/dist/data/data-runtime.d.ts +28 -0
- package/dist/data/data-runtime.d.ts.map +1 -0
- package/dist/data/data-runtime.js +114 -0
- package/dist/data/data-runtime.js.map +1 -0
- package/dist/data/index.d.ts +6 -142
- package/dist/data/index.js +5 -539
- package/dist/data/invalidation.d.ts +9 -0
- package/dist/data/invalidation.d.ts.map +1 -0
- package/dist/data/invalidation.js +27 -0
- package/dist/data/invalidation.js.map +1 -0
- package/dist/data/mutation-cell.d.ts +28 -0
- package/dist/data/mutation-cell.d.ts.map +1 -0
- package/dist/data/mutation-cell.js +132 -0
- package/dist/data/mutation-cell.js.map +1 -0
- package/dist/data/query-cell.d.ts +46 -0
- package/dist/data/query-cell.d.ts.map +1 -0
- package/dist/data/query-cell.js +290 -0
- package/dist/data/query-cell.js.map +1 -0
- package/dist/data/query-key.js +42 -0
- package/dist/data/query-key.js.map +1 -0
- package/dist/data/shared.js +20 -0
- package/dist/data/shared.js.map +1 -0
- package/dist/data/types.d.ts +161 -0
- package/dist/data/types.d.ts.map +1 -0
- package/dist/foundations/icon/icon.d.ts.map +1 -1
- package/dist/foundations/icon/icon.js.map +1 -1
- package/dist/foundations/structures/portal.d.ts +1 -1
- package/dist/foundations/structures/portal.d.ts.map +1 -1
- package/dist/foundations/structures/portal.js +2 -1
- package/dist/foundations/structures/portal.js.map +1 -1
- package/dist/fx/fx.d.ts +1 -1
- package/dist/fx/fx.js +5 -4
- package/dist/fx/fx.js.map +1 -1
- package/dist/fx/timing.d.ts.map +1 -1
- package/dist/fx/timing.js +10 -6
- package/dist/fx/timing.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/jsx/index.d.ts +2 -1
- package/dist/jsx/index.js +3 -2
- package/dist/jsx/types.d.ts +2 -0
- package/dist/jsx/types.js +2 -1
- package/dist/jsx-runtime2.d.ts +2 -1
- package/dist/jsx-runtime2.js +3 -2
- package/dist/renderer/attributes.js +231 -0
- package/dist/renderer/attributes.js.map +1 -0
- package/dist/renderer/boundaries.js +266 -0
- package/dist/renderer/boundaries.js.map +1 -0
- package/dist/renderer/child-shape.js +85 -0
- package/dist/renderer/child-shape.js.map +1 -0
- package/dist/renderer/children.js +3 -2
- package/dist/renderer/children.js.map +1 -1
- package/dist/renderer/cleanup.js +2 -1
- package/dist/renderer/cleanup.js.map +1 -1
- package/dist/renderer/component-host-cleanup.js +68 -0
- package/dist/renderer/component-host-cleanup.js.map +1 -0
- package/dist/renderer/component-host-instances.js +65 -0
- package/dist/renderer/component-host-instances.js.map +1 -0
- package/dist/renderer/component-host.js +247 -0
- package/dist/renderer/component-host.js.map +1 -0
- package/dist/renderer/dom-host.js +13 -0
- package/dist/renderer/dom-host.js.map +1 -0
- package/dist/renderer/dom-internal.js +185 -0
- package/dist/renderer/dom-internal.js.map +1 -0
- package/dist/renderer/dom.js +9 -2356
- package/dist/renderer/element-children.js +279 -0
- package/dist/renderer/element-children.js.map +1 -0
- package/dist/renderer/env.js +2 -1
- package/dist/renderer/error-boundary-dom.js +29 -0
- package/dist/renderer/error-boundary-dom.js.map +1 -0
- package/dist/renderer/evaluate-dom-range.js +85 -0
- package/dist/renderer/evaluate-dom-range.js.map +1 -0
- package/dist/renderer/evaluate-reconcile.js +281 -0
- package/dist/renderer/evaluate-reconcile.js.map +1 -0
- package/dist/renderer/evaluate.js +13 -399
- package/dist/renderer/evaluate.js.map +1 -1
- package/dist/renderer/fastpath.js +6 -5
- package/dist/renderer/fastpath.js.map +1 -1
- package/dist/renderer/for-commit-dom-map.js +83 -0
- package/dist/renderer/for-commit-dom-map.js.map +1 -0
- package/dist/renderer/for-commit-removal.js +36 -0
- package/dist/renderer/for-commit-removal.js.map +1 -0
- package/dist/renderer/for-commit-reorder.js +89 -0
- package/dist/renderer/for-commit-reorder.js.map +1 -0
- package/dist/renderer/for-commit.js +6 -188
- package/dist/renderer/for-commit.js.map +1 -1
- package/dist/renderer/index.js +28 -16
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/keyed-children.js +32 -0
- package/dist/renderer/keyed-children.js.map +1 -0
- package/dist/renderer/keyed.js +2 -15
- package/dist/renderer/keyed.js.map +1 -1
- package/dist/renderer/namespaces.js +23 -0
- package/dist/renderer/namespaces.js.map +1 -0
- package/dist/renderer/prop-bindings.js +280 -0
- package/dist/renderer/prop-bindings.js.map +1 -0
- package/dist/renderer/reactive-child-dom.js +133 -0
- package/dist/renderer/reactive-child-dom.js.map +1 -0
- package/dist/renderer/reactive-child-sources.js +184 -0
- package/dist/renderer/reactive-child-sources.js.map +1 -0
- package/dist/renderer/reactive-children.js +294 -0
- package/dist/renderer/reactive-children.js.map +1 -0
- package/dist/renderer/reconcile-commit.js +38 -0
- package/dist/renderer/reconcile-commit.js.map +1 -0
- package/dist/renderer/reconcile-fastpaths.js +106 -0
- package/dist/renderer/reconcile-fastpaths.js.map +1 -0
- package/dist/renderer/reconcile-resolution.js +187 -0
- package/dist/renderer/reconcile-resolution.js.map +1 -0
- package/dist/renderer/reconcile.js +9 -371
- package/dist/renderer/reconcile.js.map +1 -1
- package/dist/renderer/retained-element-rollback.js +276 -0
- package/dist/renderer/retained-element-rollback.js.map +1 -0
- package/dist/renderer/stable-patch.js +82 -0
- package/dist/renderer/stable-patch.js.map +1 -0
- package/dist/renderer/static-reuse.js +96 -0
- package/dist/renderer/static-reuse.js.map +1 -0
- package/dist/renderer/types.js +2 -1
- package/dist/renderer/utils.js +4 -4
- package/dist/renderer/utils.js.map +1 -1
- package/dist/resources/index.d.ts +3 -2
- package/dist/resources/index.js +5 -2
- package/dist/router/access.js +36 -0
- package/dist/router/access.js.map +1 -0
- package/dist/router/activity.d.ts +10 -0
- package/dist/router/activity.d.ts.map +1 -0
- package/dist/router/activity.js +89 -0
- package/dist/router/activity.js.map +1 -0
- package/dist/router/authoring.d.ts +22 -0
- package/dist/router/authoring.d.ts.map +1 -0
- package/dist/router/authoring.js +198 -0
- package/dist/router/authoring.js.map +1 -0
- package/dist/router/index.d.ts +12 -4
- package/dist/router/index.js +10 -3
- package/dist/router/internal-types.d.ts +31 -0
- package/dist/router/internal-types.d.ts.map +1 -0
- package/dist/router/lazy.d.ts +19 -0
- package/dist/router/lazy.d.ts.map +1 -0
- package/dist/router/lazy.js +52 -0
- package/dist/router/lazy.js.map +1 -0
- package/dist/router/manifest.d.ts +10 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/manifest.js +49 -0
- package/dist/router/manifest.js.map +1 -0
- package/dist/router/navigate.d.ts +4 -51
- package/dist/router/navigate.d.ts.map +1 -1
- package/dist/router/navigate.js +16 -459
- package/dist/router/navigate.js.map +1 -1
- package/dist/router/navigation-registry.d.ts +32 -0
- package/dist/router/navigation-registry.d.ts.map +1 -0
- package/dist/router/navigation-registry.js +105 -0
- package/dist/router/navigation-registry.js.map +1 -0
- package/dist/router/navigation-scroll.d.ts +14 -0
- package/dist/router/navigation-scroll.d.ts.map +1 -0
- package/dist/router/navigation-scroll.js +93 -0
- package/dist/router/navigation-scroll.js.map +1 -0
- package/dist/router/navigation-targets.d.ts +31 -0
- package/dist/router/navigation-targets.d.ts.map +1 -0
- package/dist/router/navigation-targets.js +253 -0
- package/dist/router/navigation-targets.js.map +1 -0
- package/dist/router/policy.d.ts +7 -1
- package/dist/router/policy.d.ts.map +1 -1
- package/dist/router/policy.js +27 -9
- package/dist/router/policy.js.map +1 -1
- package/dist/router/rendering.d.ts +10 -0
- package/dist/router/rendering.d.ts.map +1 -0
- package/dist/router/rendering.js +45 -0
- package/dist/router/rendering.js.map +1 -0
- package/dist/router/resolution.d.ts +17 -0
- package/dist/router/resolution.d.ts.map +1 -0
- package/dist/router/resolution.js +253 -0
- package/dist/router/resolution.js.map +1 -0
- package/dist/router/route-query.d.ts +17 -0
- package/dist/router/route-query.d.ts.map +1 -0
- package/dist/router/route-query.js +47 -0
- package/dist/router/route-query.js.map +1 -0
- package/dist/router/route.d.ts +8 -149
- package/dist/router/route.js +8 -854
- package/dist/router/store.d.ts +50 -0
- package/dist/router/store.d.ts.map +1 -0
- package/dist/router/store.js +171 -0
- package/dist/router/store.js.map +1 -0
- package/dist/runtime/access.js +45 -0
- package/dist/runtime/access.js.map +1 -0
- package/dist/runtime/child-scope.d.ts +1 -1
- package/dist/runtime/child-scope.js +4 -1
- package/dist/runtime/child-scope.js.map +1 -1
- package/dist/runtime/component-cleanup.d.ts +16 -0
- package/dist/runtime/component-cleanup.d.ts.map +1 -0
- package/dist/runtime/component-cleanup.js +70 -0
- package/dist/runtime/component-cleanup.js.map +1 -0
- package/dist/runtime/component-commit.js +165 -0
- package/dist/runtime/component-commit.js.map +1 -0
- package/dist/runtime/component-contracts.js +5 -0
- package/dist/runtime/component-facade.d.ts +5 -0
- package/dist/runtime/component-facade.js +4 -0
- package/dist/runtime/component-internal.d.ts +100 -0
- package/dist/runtime/component-internal.d.ts.map +1 -0
- package/dist/runtime/component-internal.js +219 -0
- package/dist/runtime/component-internal.js.map +1 -0
- package/dist/runtime/component-lifecycle.d.ts +49 -0
- package/dist/runtime/component-lifecycle.d.ts.map +1 -0
- package/dist/runtime/component-lifecycle.js +176 -0
- package/dist/runtime/component-lifecycle.js.map +1 -0
- package/dist/runtime/component-scope.d.ts +55 -0
- package/dist/runtime/component-scope.d.ts.map +1 -0
- package/dist/runtime/component-scope.js +154 -0
- package/dist/runtime/component-scope.js.map +1 -0
- package/dist/runtime/component.d.ts +4 -152
- package/dist/runtime/component.js +4 -692
- package/dist/runtime/context.d.ts +1 -1
- package/dist/runtime/context.js +6 -4
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.d.ts +3 -3
- package/dist/runtime/control.js +2 -1
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/derive.d.ts.map +1 -1
- package/dist/runtime/derive.js +6 -5
- package/dist/runtime/derive.js.map +1 -1
- package/dist/runtime/effect.d.ts +1 -1
- package/dist/runtime/effect.d.ts.map +1 -1
- package/dist/runtime/effect.js +2 -2
- package/dist/runtime/effect.js.map +1 -1
- package/dist/runtime/events.js +3 -3
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/fastlane.js +13 -27
- package/dist/runtime/fastlane.js.map +1 -1
- package/dist/runtime/for-bench.d.ts +1 -1
- package/dist/runtime/for-bench.js +1 -4
- package/dist/runtime/for-bench.js.map +1 -1
- package/dist/runtime/for-internal.d.ts +43 -0
- package/dist/runtime/for-internal.d.ts.map +1 -0
- package/dist/runtime/for-internal.js +98 -0
- package/dist/runtime/for-internal.js.map +1 -0
- package/dist/runtime/for-reconcile.d.ts +8 -0
- package/dist/runtime/for-reconcile.d.ts.map +1 -0
- package/dist/runtime/for-reconcile.js +389 -0
- package/dist/runtime/for-reconcile.js.map +1 -0
- package/dist/runtime/for-scopes.d.ts +26 -0
- package/dist/runtime/for-scopes.d.ts.map +1 -0
- package/dist/runtime/for-scopes.js +160 -0
- package/dist/runtime/for-scopes.js.map +1 -0
- package/dist/runtime/for-signals.d.ts +30 -0
- package/dist/runtime/for-signals.d.ts.map +1 -0
- package/dist/runtime/for-signals.js +139 -0
- package/dist/runtime/for-signals.js.map +1 -0
- package/dist/runtime/for.d.ts +4 -66
- package/dist/runtime/for.js +5 -773
- package/dist/runtime/lifecycle-operations.d.ts +31 -0
- package/dist/runtime/lifecycle-operations.d.ts.map +1 -0
- package/dist/runtime/lifecycle-operations.js +195 -0
- package/dist/runtime/lifecycle-operations.js.map +1 -0
- package/dist/runtime/operations.d.ts +3 -40
- package/dist/runtime/operations.js +2 -357
- package/dist/runtime/readable.d.ts +2 -3
- package/dist/runtime/readable.d.ts.map +1 -1
- package/dist/runtime/readable.js +6 -5
- package/dist/runtime/readable.js.map +1 -1
- package/dist/runtime/resource-cell.js +2 -2
- package/dist/runtime/resource-cell.js.map +1 -1
- package/dist/runtime/resource-operation.d.ts +13 -0
- package/dist/runtime/resource-operation.d.ts.map +1 -0
- package/dist/runtime/resource-operation.js +170 -0
- package/dist/runtime/resource-operation.js.map +1 -0
- package/dist/runtime/runtime.d.ts +42 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +59 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +5 -1
- package/dist/runtime/scheduler.d.ts.map +1 -1
- package/dist/runtime/scheduler.js +17 -17
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/selector.js +4 -3
- package/dist/runtime/selector.js.map +1 -1
- package/dist/runtime/snapshot-source.d.ts +1 -1
- package/dist/runtime/snapshot-source.js +1 -1
- package/dist/runtime/state.js +2 -1
- package/dist/runtime/state.js.map +1 -1
- package/dist/ssg/batch-render.js +2 -1
- package/dist/ssg/batch-render.js.map +1 -1
- package/dist/ssg/create-static-gen.d.ts +9 -3
- package/dist/ssg/create-static-gen.d.ts.map +1 -1
- package/dist/ssg/create-static-gen.js +12 -99
- package/dist/ssg/create-static-gen.js.map +1 -1
- package/dist/ssg/generation-plan.js +70 -0
- package/dist/ssg/generation-plan.js.map +1 -0
- package/dist/ssg/incremental-manifest.js +1 -1
- package/dist/ssg/static-routes.js +101 -0
- package/dist/ssg/static-routes.js.map +1 -0
- package/dist/ssg/types.d.ts +15 -7
- package/dist/ssg/types.d.ts.map +1 -1
- package/dist/ssr/boundaries.js +113 -0
- package/dist/ssr/boundaries.js.map +1 -0
- package/dist/ssr/component-runtime.js +111 -0
- package/dist/ssr/component-runtime.js.map +1 -0
- package/dist/ssr/context.d.ts +3 -1
- package/dist/ssr/context.d.ts.map +1 -1
- package/dist/ssr/context.js +9 -2
- package/dist/ssr/context.js.map +1 -1
- package/dist/ssr/errors.d.ts +2 -0
- package/dist/ssr/errors.js +11 -1
- package/dist/ssr/errors.js.map +1 -1
- package/dist/ssr/escape.js +3 -3
- package/dist/ssr/escape.js.map +1 -1
- package/dist/ssr/hydration-data.js +10 -0
- package/dist/ssr/hydration-data.js.map +1 -0
- package/dist/ssr/hydration-verify.d.ts +12 -0
- package/dist/ssr/hydration-verify.d.ts.map +1 -0
- package/dist/ssr/hydration-verify.js +144 -0
- package/dist/ssr/hydration-verify.js.map +1 -0
- package/dist/ssr/index-internal.d.ts +15 -0
- package/dist/ssr/index-internal.d.ts.map +1 -0
- package/dist/ssr/index-internal.js +19 -0
- package/dist/ssr/index-internal.js.map +1 -0
- package/dist/ssr/index.d.ts +5 -57
- package/dist/ssr/index.js +3 -738
- package/dist/ssr/render-keys.js +9 -32
- package/dist/ssr/render-keys.js.map +1 -1
- package/dist/ssr/render-resolved.d.ts +1 -1
- package/dist/ssr/render-resolved.d.ts.map +1 -1
- package/dist/ssr/render-resolved.js +4 -2
- package/dist/ssr/render-resolved.js.map +1 -1
- package/dist/ssr/render-sync.d.ts +21 -0
- package/dist/ssr/render-sync.d.ts.map +1 -0
- package/dist/ssr/render-sync.js +275 -0
- package/dist/ssr/render-sync.js.map +1 -0
- package/dist/ssr/route-policy-resolution.js +77 -0
- package/dist/ssr/route-policy-resolution.js.map +1 -0
- package/dist/ssr/route-render.d.ts +77 -0
- package/dist/ssr/route-render.d.ts.map +1 -0
- package/dist/ssr/route-render.js +119 -0
- package/dist/ssr/route-render.js.map +1 -0
- package/dist/ssr/sink.d.ts +26 -0
- package/dist/ssr/sink.d.ts.map +1 -0
- package/dist/ssr/types.d.ts +1 -0
- package/dist/ssr/types.d.ts.map +1 -1
- package/dist/ssr/verify-hydration.js.map +1 -1
- package/dist/testing/index.d.ts +1 -2
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2 -1
- package/dist/testing/index.js.map +1 -1
- package/package.json +4 -3
- package/dist/data/index.d.ts.map +0 -1
- package/dist/data/index.js.map +0 -1
- package/dist/renderer/dom.js.map +0 -1
- package/dist/router/route.d.ts.map +0 -1
- package/dist/router/route.js.map +0 -1
- package/dist/runtime/component.d.ts.map +0 -1
- package/dist/runtime/component.js.map +0 -1
- package/dist/runtime/for.d.ts.map +0 -1
- package/dist/runtime/for.js.map +0 -1
- package/dist/runtime/operations.d.ts.map +0 -1
- package/dist/runtime/operations.js.map +0 -1
- package/dist/runtime/ssr-bridge.js +0 -24
- package/dist/runtime/ssr-bridge.js.map +0 -1
- package/dist/ssr/index.d.ts.map +0 -1
- package/dist/ssr/index.js.map +0 -1
package/dist/boot/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/boot/index.ts"],"sourcesContent":["/**\n * App bootstrap and mount\n */\n\nimport {\n createComponentInstance,\n mountComponent,\n cleanupComponent,\n type ComponentFunction,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n isDevelopmentEnvironment,\n isProductionEnvironment,\n} from '../common/env';\nimport { logger } from '../dev/logger';\nimport {\n initializeNavigation,\n registerAppInstance,\n unregisterAppInstance,\n} from '../router/navigate';\nimport {\n configureScrollRestoration,\n type ScrollRestorationOptions,\n} from '../router/navigate';\nimport {\n _applyManifest,\n _drainLazy,\n _setActiveRouteAuthOptions,\n _snapshotLazy,\n clearRoutes,\n lockRouteRegistration,\n resolveRouteRequest,\n route as registerRoute,\n setServerLocation,\n} from '../router/route';\nimport { globalScheduler } from '../runtime/scheduler';\nimport { assertExecutionModel } from '../runtime/execution-model';\nimport { setStaticChildSlotsCacheEnabled } from '../renderer/dom';\nimport { isPromiseLike } from '../common/promise';\nimport { SSR_RENDER_DATA_ATTR, type SSRData } from '../common/ssr';\nimport {\n startHydrationRenderPhase,\n stopHydrationRenderPhase,\n} from '../ssr/render-keys';\n\nconst HAS_ROUTES_KEY = Symbol.for('__ASKR_HAS_ROUTES__');\n\nlet componentIdCounter = 0;\n\n// Track instances by root element to support multiple createIsland calls on same root\nconst instancesByRoot = new WeakMap<Element, ComponentInstance>();\n\n// Symbol for storing cleanup on elements\nconst CLEANUP_SYMBOL = Symbol.for('__askrCleanup__');\nconst ROOT_CLEANUP_CALLBACKS_SYMBOL = Symbol.for(\n '__askrRootCleanupCallbacks__'\n);\n\ntype RootCleanupOptions = {\n preserveInstance?: boolean;\n};\n\n// Type for elements that have cleanup functions attached\ninterface ElementWithCleanup extends Element {\n [CLEANUP_SYMBOL]?: (options?: RootCleanupOptions) => void;\n [ROOT_CLEANUP_CALLBACKS_SYMBOL]?: Set<() => void>;\n}\n\nfunction takeHydrationRenderData(rootElement: Element): SSRData | null {\n for (const child of Array.from(rootElement.children)) {\n if (\n child instanceof HTMLScriptElement &&\n child.getAttribute(SSR_RENDER_DATA_ATTR) === 'true'\n ) {\n const raw = child.textContent ?? '';\n child.remove();\n if (!raw) {\n return {};\n }\n\n try {\n return JSON.parse(raw) as SSRData;\n } catch (err) {\n throw new Error(\n '[Askr] Failed to parse embedded SSR render data during hydration.',\n { cause: err }\n );\n }\n }\n }\n\n return null;\n}\n\nfunction clearRootCleanupCallbacks(rootElement: Element): void {\n try {\n delete (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL];\n } catch {\n (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL]?.clear();\n }\n}\n\nfunction registerRootCleanupCallback(\n rootElement: Element,\n callback: () => void\n): () => void {\n const elementWithCleanup = rootElement as ElementWithCleanup;\n const callbacks =\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] ?? new Set();\n callbacks.add(callback);\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] = callbacks;\n\n return () => {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n }\n };\n}\n\nfunction runRootCleanupCallbacks(\n rootElement: Element,\n errors: unknown[]\n): void {\n const callbacks = (rootElement as ElementWithCleanup)[\n ROOT_CLEANUP_CALLBACKS_SYMBOL\n ];\n if (!callbacks || callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n return;\n }\n\n clearRootCleanupCallbacks(rootElement);\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n}\n\nfunction cleanupRootInstance(\n rootElement: Element,\n instance: ComponentInstance,\n options?: RootCleanupOptions\n) {\n // Attempt to remove listeners and cleanup instances under the root.\n // In non-strict mode we preserve previous behavior by swallowing errors\n // (but logging in dev); in strict mode we aggregate and re-throw.\n const errors: unknown[] = [];\n try {\n teardownNodeSubtree(rootElement);\n } catch (e) {\n errors.push(e);\n }\n\n try {\n cleanupComponent(instance);\n } catch (e) {\n errors.push(e);\n }\n\n runRootCleanupCallbacks(rootElement, errors);\n\n if (!options?.preserveInstance) {\n unregisterAppInstance(instance);\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n\n if (errors.length > 0) {\n if (instance.cleanupStrict) {\n throw new AggregateError(errors, `cleanup failed for app root`);\n } else if (isDevelopmentEnvironment()) {\n for (const err of errors) logger.warn('[Askr] cleanup error:', err);\n }\n }\n}\n\nfunction attachCleanupForRoot(\n rootElement: Element,\n instance: ComponentInstance\n) {\n (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL] = (options) => {\n cleanupRootInstance(rootElement, instance, options);\n };\n\n try {\n const descriptor =\n Object.getOwnPropertyDescriptor(rootElement, 'innerHTML') ||\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(rootElement),\n 'innerHTML'\n ) ||\n Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');\n\n if (descriptor && (descriptor.get || descriptor.set)) {\n Object.defineProperty(rootElement, 'innerHTML', {\n get: descriptor.get\n ? function (this: Element) {\n return descriptor.get!.call(this);\n }\n : undefined,\n set: function (this: Element, value: string) {\n if (value === '' && instancesByRoot.get(this) === instance) {\n cleanupRootInstance(rootElement, instance);\n }\n if (descriptor.set) {\n return descriptor.set.call(this, value);\n }\n },\n configurable: true,\n });\n }\n } catch {\n // If Object.defineProperty fails, ignore\n }\n}\n\nimport { Fragment, ELEMENT_TYPE } from '../jsx';\n\nimport { DefaultPortal } from '../foundations/structures/portal';\nimport { disposeDefaultPortalScope } from '../foundations/structures/portal';\n\nfunction mountOrUpdate(\n rootElement: Element,\n componentFn: ComponentFunction,\n options?: { cleanupStrict?: boolean }\n) {\n // Ensure root component always includes a DefaultPortal host by wrapping it.\n const wrappedFn: ComponentFunction = (props, ctx) => {\n const out = componentFn(props, ctx);\n if (isPromiseLike(out)) {\n throw new Error(\n 'Async components are not supported. Components must return synchronously.'\n );\n }\n const portalVNode = {\n $$typeof: ELEMENT_TYPE,\n type: DefaultPortal,\n props: {},\n key: '__default_portal',\n } as unknown;\n return {\n $$typeof: ELEMENT_TYPE,\n type: Fragment,\n props: {\n children:\n out === undefined || out === null\n ? [portalVNode]\n : [out, portalVNode],\n },\n } as unknown as ReturnType<ComponentFunction>;\n };\n // Preserve the original component name for debugging/dev warnings\n Object.defineProperty(wrappedFn, 'name', {\n value: componentFn.name || 'Component',\n });\n\n // Clean up existing cleanup function before mounting new one\n const existingCleanup = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n const reusedExistingInstance = typeof existingCleanup === 'function';\n if (reusedExistingInstance) {\n existingCleanup({ preserveInstance: true });\n }\n\n let instance = instancesByRoot.get(rootElement);\n\n if (instance) {\n const shouldResetHookState = instance.fn.name !== wrappedFn.name;\n\n if (!reusedExistingInstance) {\n removeAllListeners(rootElement);\n try {\n cleanupComponent(instance);\n } catch (e) {\n // If previous cleanup threw in strict mode, log but continue mounting new instance\n if (isDevelopmentEnvironment()) {\n logger.warn('[Askr] prior cleanup threw:', e);\n }\n }\n }\n\n instance.fn = wrappedFn;\n instance.evaluationGeneration++;\n instance.mounted = false;\n instance.expectedStateIndices = [];\n instance.firstRenderComplete = false;\n instance.isRoot = true;\n instance.portalScope = instance;\n\n if (shouldResetHookState) {\n instance.stateValues = [];\n instance.hasPendingUpdate = false;\n instance.notifyUpdate = null;\n instance.stateIndexCheck = -1;\n instance.mountOperations = [];\n instance.commitOperations = [];\n instance.lifecycleSlots = [];\n instance.cleanupFns = [];\n instance._currentRenderToken = undefined;\n instance.lastRenderToken = 0;\n instance._pendingReadSources = undefined;\n instance._lastReadSources = undefined;\n instance._placeholder = undefined;\n instance.errorBoundaryState = undefined;\n instance.devWarningsEmitted = undefined;\n }\n\n // Update strict flag if provided\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n } else {\n const componentId = String(++componentIdCounter);\n instance = createComponentInstance(componentId, wrappedFn, {}, rootElement);\n instancesByRoot.set(rootElement, instance);\n instance.isRoot = true;\n instance.portalScope = instance;\n // Initialize strict flag from options\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n }\n\n attachCleanupForRoot(rootElement, instance);\n registerRootCleanupCallback(rootElement, () => {\n disposeDefaultPortalScope(instance.portalScope ?? instance);\n });\n mountComponent(instance);\n globalScheduler.flush();\n}\n\nfunction bindResolvedRouteHandler(resolved: ResolvedRoute): ComponentFunction {\n return () =>\n resolved.handler(resolved.params) as ReturnType<ComponentFunction>;\n}\n\nfunction bindDeniedStatus(status: number): ComponentFunction {\n return () => ({\n type: 'div',\n props: {\n 'data-route-denied': String(status),\n },\n children: [String(status)],\n });\n}\n\n// New strongly-typed init functions\nimport type {\n Route,\n RouteManifest,\n ResolvedRoute,\n RouteAuthOptions,\n RouteRequestResult,\n} from '../common/router';\nimport {\n installRendererBridge,\n removeAllListeners,\n teardownNodeSubtree,\n} from '../renderer';\ninstallRendererBridge();\n\nexport type IslandConfig = {\n root: Element | string;\n component: ComponentFunction;\n // Optional: surface cleanup errors during teardown for this island\n cleanupStrict?: boolean;\n // Explicitly disallow routes on islands at type level\n routes?: never;\n};\n\nexport type IslandsConfig = {\n islands: IslandConfig[];\n};\n\ntype BootRouteSource =\n | {\n manifest: RouteManifest;\n routes?: Route[];\n }\n | {\n manifest?: RouteManifest;\n routes: Route[];\n };\n\nexport type SPAConfig = BootRouteSource & {\n root: Element | string;\n /**\n * Preferred: pass the route manifest built via `registerRoutes(() => { ... })`.\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n component?: never;\n};\n\nexport type HydrateSPAConfig = BootRouteSource & {\n root: Element | string;\n /** Preferred manifest input — see `SPAConfig.manifest`. */\n auth?: RouteAuthOptions;\n scrollRestoration?: boolean | ScrollRestorationOptions;\n cleanupStrict?: boolean;\n hydrate?: {\n verifyMarkup?: boolean;\n deferUntilIdle?: boolean;\n deferBelowFold?: boolean;\n foldThreshold?: number;\n skipSelectors?: string[];\n };\n};\n\nconst MAX_INITIAL_ROUTE_REDIRECTS = 20;\n\nasync function resolveInitialRoute(\n auth?: RouteAuthOptions\n): Promise<{ path: string; href: string; resolved: RouteRequestResult }> {\n let path = typeof window !== 'undefined' ? window.location.pathname : '/';\n let href =\n typeof window !== 'undefined'\n ? `${window.location.pathname}${window.location.search}${window.location.hash}`\n : path;\n const visited = new Set<string>();\n\n for (\n let redirects = 0;\n redirects <= MAX_INITIAL_ROUTE_REDIRECTS;\n redirects++\n ) {\n if (visited.has(href)) {\n throw new Error(`[Askr] Route redirect cycle detected at ${href}.`);\n }\n visited.add(href);\n\n const resolved = await resolveRouteRequest(href, { auth });\n if (\n typeof window === 'undefined' ||\n !resolved ||\n resolved.kind !== 'redirect'\n ) {\n return { path, href, resolved };\n }\n\n const redirectTarget = new URL(resolved.to, window.location.href);\n const redirectHref = `${redirectTarget.pathname}${redirectTarget.search}${redirectTarget.hash}`;\n window.history.replaceState({ path: redirectHref }, '', redirectHref);\n path = redirectTarget.pathname;\n href = redirectHref;\n }\n\n throw new Error(\n `[Askr] Route redirect limit exceeded (${MAX_INITIAL_ROUTE_REDIRECTS}).`\n );\n}\n\n/**\n * createIsland: Enhances existing DOM (no router, mounts once)\n */\nexport function createIsland(config: IslandConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIsland requires a config object');\n }\n if (typeof config.component !== 'function') {\n throw new Error('createIsland: component must be a function');\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n // Islands must not initialize router or routes\n if ('routes' in config) {\n throw new Error(\n 'createIsland does not accept routes; use createSPA for routed apps'\n );\n }\n\n // Routes are never supported with islands.\n // If routes were registered (even at module load time), fail fast to avoid\n // surprising partial router behavior.\n try {\n const g = globalThis as unknown as Record<string | symbol, unknown>;\n if (g[HAS_ROUTES_KEY]) {\n throw new Error(\n 'Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead.'\n );\n }\n } catch {\n // ignore\n }\n\n mountOrUpdate(rootElement, config.component, {\n cleanupStrict: config.cleanupStrict,\n });\n}\n\n/**\n * createIslands: Enhances one or more existing DOM roots (no router).\n * The only public islands constructor.\n */\nexport function createIslands(config: IslandsConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIslands requires a config object');\n }\n if (!Array.isArray(config.islands) || config.islands.length === 0) {\n throw new Error('createIslands requires a non-empty islands array');\n }\n for (const island of config.islands) {\n createIsland(island);\n }\n}\n\n/**\n * createSPA: Initializes router and mounts the app with the provided route manifest or route table.\n *\n * Preferred usage with manifest:\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n *\n * Legacy usage with plain routes array (still supported):\n * ```ts\n * await createSPA({ root: '#app', routes: getRoutes() });\n * ```\n */\nexport async function createSPA(config: SPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('createSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'createSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n const pendingLazyAtBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n // Preferred path: apply pre-built manifest records directly\n _applyManifest(config.manifest!);\n } else {\n // Legacy path: register plain Route objects (no layout metadata)\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n const routeAuth = config.auth ?? config.manifest?.auth;\n _setActiveRouteAuthOptions(routeAuth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtBoot);\n\n // Lock registration in production to prevent late registration surprises\n if (isProductionEnvironment()) lockRouteRegistration();\n\n // Mount the currently-resolved route handler (if any)\n const { path, resolved } = await resolveInitialRoute(routeAuth);\n\n if (!resolved) {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n if (resolved.kind === 'redirect') {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n return;\n }\n\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler({\n handler: resolved.handler,\n params: resolved.params,\n }),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: routeAuth,\n });\n}\n\n/**\n * Mark elements that should be skipped during hydration\n */\nfunction markSkippedElements(root: Element, skipSelectors: string[]): void {\n if (skipSelectors.length === 0) {\n return;\n }\n\n const uniqueSelectors = Array.from(new Set(skipSelectors));\n const selectorList = uniqueSelectors.join(', ');\n const elements = root.querySelectorAll(selectorList);\n elements.forEach((el) => el.setAttribute('data-skip-hydrate', 'true'));\n}\n\nfunction collectDeferredBelowFoldBoundaries(\n root: Element,\n foldY: number\n): Element[] {\n const boundaries: Element[] = [];\n const stack: Element[] = [];\n\n for (let index = root.children.length - 1; index >= 0; index -= 1) {\n stack.push(root.children[index]);\n }\n\n while (stack.length > 0) {\n const element = stack.pop()!;\n\n if (element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top >= foldY) {\n element.setAttribute('data-skip-hydrate', 'true');\n boundaries.push(element);\n continue;\n }\n\n for (let index = element.children.length - 1; index >= 0; index -= 1) {\n stack.push(element.children[index]);\n }\n }\n\n return boundaries;\n}\n\nfunction activateVisibleDeferredBoundaries(\n boundaries: Element[],\n foldY: number\n): { activated: boolean; remaining: number } {\n let activated = false;\n let remaining = 0;\n\n for (const element of boundaries) {\n if (!element.hasAttribute('data-skip-hydrate')) {\n continue;\n }\n\n const rect = element.getBoundingClientRect();\n if (rect.top < foldY) {\n element.removeAttribute('data-skip-hydrate');\n activated = true;\n } else {\n remaining += 1;\n }\n }\n\n return { activated, remaining };\n}\n\nfunction queueIdleWork(work: () => void): Promise<void> {\n return new Promise((resolve) => {\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(\n () => {\n work();\n resolve();\n },\n { timeout: 2000 }\n );\n return;\n }\n\n setTimeout(() => {\n work();\n resolve();\n }, 0);\n });\n}\n\nfunction flushHydrationActivation(rootElement: Element): void {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) return;\n instance._enqueueRun?.();\n globalScheduler.flush();\n}\n\nfunction shouldVerifyHydrationMarkup(config: HydrateSPAConfig): boolean {\n const explicit = config.hydrate?.verifyMarkup;\n if (typeof explicit === 'boolean') {\n return explicit;\n }\n\n return !isProductionEnvironment();\n}\n\nasync function registerAppNavigation(\n rootElement: Element,\n path: string,\n source?: {\n manifest?: RouteManifest;\n routes?: Route[];\n auth?: RouteAuthOptions;\n }\n) {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) throw new Error('Internal error: app instance missing');\n registerAppInstance(instance as ComponentInstance, path, source);\n initializeNavigation();\n}\n\n/**\n * Apply selective hydration with deferral options\n */\nasync function applySelectiveHydration(\n rootElement: Element,\n resolved: { handler: ComponentFunction; params: Record<string, unknown> },\n path: string,\n cleanupStrict: boolean | undefined,\n hydrateOptions: NonNullable<HydrateSPAConfig['hydrate']>\n): Promise<void> {\n const hasPermanentSkips = (hydrateOptions.skipSelectors?.length ?? 0) > 0;\n const hasBelowFoldDeferral = !!hydrateOptions.deferBelowFold;\n const hasSelectiveBoundaries = hasPermanentSkips || hasBelowFoldDeferral;\n let staticChildSlotsCacheSuspended = false;\n let releaseSelectiveHydrationResources = () => {};\n\n const restoreStaticChildSlotsCache = () => {\n if (!staticChildSlotsCacheSuspended) {\n return;\n }\n\n setStaticChildSlotsCacheEnabled(true);\n staticChildSlotsCacheSuspended = false;\n };\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n\n let deferredBoundaries: Element[] = [];\n if (hydrateOptions.deferBelowFold) {\n setStaticChildSlotsCacheEnabled(false);\n staticChildSlotsCacheSuspended = true;\n const foldY = hydrateOptions.foldThreshold ?? window.innerHeight;\n deferredBoundaries = collectDeferredBelowFoldBoundaries(rootElement, foldY);\n\n let selectiveHydrationResourcesReleased = false;\n let unregisterRootCleanupCallback = () => {};\n\n function handleScroll() {\n const { activated, remaining } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n foldY\n );\n\n if (!activated) {\n return;\n }\n\n flushHydrationActivation(rootElement);\n\n if (remaining === 0) {\n releaseSelectiveHydrationResources();\n }\n }\n\n releaseSelectiveHydrationResources = () => {\n if (selectiveHydrationResourcesReleased) {\n return;\n }\n\n selectiveHydrationResourcesReleased = true;\n unregisterRootCleanupCallback();\n window.removeEventListener('scroll', handleScroll);\n restoreStaticChildSlotsCache();\n };\n\n unregisterRootCleanupCallback = registerRootCleanupCallback(\n rootElement,\n releaseSelectiveHydrationResources\n );\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n }\n\n if (hydrateOptions.deferUntilIdle && !hasSelectiveBoundaries) {\n await queueIdleWork(() => {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n });\n await registerAppNavigation(rootElement, path);\n return;\n }\n\n try {\n mountOrUpdate(\n rootElement,\n (() => resolved.handler(resolved.params)) as ComponentFunction,\n {\n cleanupStrict,\n }\n );\n await registerAppNavigation(rootElement, path);\n } catch (error) {\n releaseSelectiveHydrationResources();\n throw error;\n }\n\n if (hydrateOptions.deferUntilIdle && deferredBoundaries.length > 0) {\n await queueIdleWork(() => {\n try {\n const { activated } = activateVisibleDeferredBoundaries(\n deferredBoundaries,\n Number.POSITIVE_INFINITY\n );\n if (activated) {\n flushHydrationActivation(rootElement);\n }\n } finally {\n releaseSelectiveHydrationResources();\n }\n });\n }\n\n if (deferredBoundaries.length === 0) {\n releaseSelectiveHydrationResources();\n }\n}\n\n/**\n * hydrateSPA: Hydrate server-rendered HTML.\n * Accepts either a `manifest` (preferred) or a legacy `routes` array.\n */\nexport async function hydrateSPA(config: HydrateSPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('hydrateSPA requires a config object');\n }\n\n const hasManifest =\n config.manifest != null && config.manifest.records.length > 0;\n const hasRoutes = Array.isArray(config.routes) && config.routes.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'hydrateSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n const hydrationRenderData = takeHydrationRenderData(rootElement);\n\n const pendingLazyAtHydrationBoot = _snapshotLazy();\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n _applyManifest(config.manifest!);\n } else {\n for (const r of config.routes!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n _setActiveRouteAuthOptions(config.auth ?? config.manifest?.auth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtHydrationBoot);\n\n const {\n path,\n href: currentUrl,\n resolved,\n } = await resolveInitialRoute(config.auth ?? config.manifest?.auth);\n setServerLocation(currentUrl);\n if (isProductionEnvironment()) lockRouteRegistration();\n\n if (!resolved) {\n throw new Error(`hydrateSPA: no route found for current path (${path}).`);\n }\n\n if (resolved.kind === 'redirect') {\n throw new Error(\n `hydrateSPA: unresolved redirect for current path (${path}).`\n );\n }\n\n const hydrationResolved: ResolvedRoute =\n resolved.kind === 'deny'\n ? { handler: bindDeniedStatus(resolved.status), params: {} }\n : { handler: resolved.handler, params: resolved.params };\n\n if (shouldVerifyHydrationMarkup(config)) {\n const legacyRouteTable = hasManifest\n ? config.manifest!.records.map((r) => ({\n path: r.path,\n handler: r.handler,\n namespace: r.options.namespace,\n }))\n : config.routes!;\n\n const { verifyHydrationSyncForUrl } =\n await import('../ssr/verify-hydration');\n if (\n !verifyHydrationSyncForUrl({\n root: rootElement,\n url: currentUrl,\n routes: legacyRouteTable,\n resolved: hydrationResolved,\n options: {\n data: hydrationRenderData ?? undefined,\n },\n })\n ) {\n throw new Error(\n '[Askr] Hydration mismatch detected. Server HTML does not match expected server-render output.'\n );\n }\n }\n\n const hydrateOptions = config.hydrate;\n if (hydrateOptions) {\n if (hydrateOptions.deferUntilIdle || hydrateOptions.deferBelowFold) {\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n await applySelectiveHydration(\n rootElement,\n hydrationResolved,\n path,\n config.cleanupStrict,\n hydrateOptions\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n return;\n }\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n }\n\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler(hydrationResolved),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n await registerAppNavigation(rootElement, path, {\n manifest: config.manifest,\n routes: config.routes,\n auth: config.auth ?? config.manifest?.auth,\n });\n}\n\n/**\n * Cleanup an app mounted on a root element (element or id).\n * Safe to call multiple times — no-op when nothing is mounted.\n */\nexport function cleanupApp(root: Element | string): void {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return;\n\n const cleanupFn = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n try {\n if (typeof cleanupFn === 'function') {\n cleanupFn();\n }\n } finally {\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n}\n\n/**\n * Check whether an app is mounted on the given root\n */\nexport function hasApp(root: Element | string): boolean {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return false;\n return instancesByRoot.has(rootElement);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/boot/index.ts"],"sourcesContent":["/**\n * App bootstrap and mount\n */\n\nimport { isProductionEnvironment } from '../common/env';\nimport type { ResolvedRoute } from '../common/router';\nimport { configureScrollRestoration } from '../router/navigate';\nimport {\n _applyManifest,\n _drainLazy,\n _setActiveRouteAuthOptions,\n _snapshotRouteSourceLazy,\n _snapshotLazy,\n clearRoutes,\n hasRegisteredRoutes,\n lockRouteRegistration,\n route as registerRoute,\n setServerLocation,\n} from '../router/route';\nimport { assertExecutionModel } from '../runtime/execution-model';\nimport {\n startHydrationRenderPhase,\n stopHydrationRenderPhase,\n} from '../common/render-context';\nimport {\n applySelectiveHydration,\n markSkippedElements,\n shouldVerifyHydrationMarkup,\n takeHydrationRenderData,\n} from './hydration';\nimport {\n flushHydrationActivation,\n mountOrUpdate,\n registerAppNavigation,\n registerRootCleanupCallback,\n} from './root-lifecycle';\nimport {\n bindDeniedRouteHandler,\n bindDeniedStatus,\n bindResolvedRouteHandler,\n resolveInitialRoute,\n} from './route-startup';\nimport type {\n HydrateSPAConfig,\n IslandConfig,\n IslandsConfig,\n SPAConfig,\n} from './types';\n\nexport { cleanupApp, hasApp } from './root-lifecycle';\nexport type {\n HydrateSPAConfig,\n IslandConfig,\n IslandsConfig,\n SPAConfig,\n} from './types';\n\n/**\n * createIsland: Enhances existing DOM (no router, mounts once)\n */\nexport function createIsland(config: IslandConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIsland requires a config object');\n }\n if (typeof config.component !== 'function') {\n throw new Error('createIsland: component must be a function');\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n // Islands must not initialize router or routes\n if ('routes' in config) {\n throw new Error(\n 'createIsland does not accept routes; use createSPA for routed apps'\n );\n }\n\n // Routes are never supported with islands.\n // If routes were registered (even at module load time), fail fast to avoid\n // surprising partial router behavior.\n if (hasRegisteredRoutes()) {\n throw new Error(\n 'Routes are not supported with islands. Use createSPA (client) or createSSR (server) instead.'\n );\n }\n\n mountOrUpdate(rootElement, config.component, {\n cleanupStrict: config.cleanupStrict,\n });\n}\n\n/**\n * createIslands: Enhances one or more existing DOM roots (no router).\n * The only public islands constructor.\n */\nexport function createIslands(config: IslandsConfig): void {\n assertExecutionModel('islands');\n if (!config || typeof config !== 'object') {\n throw new Error('createIslands requires a config object');\n }\n if (!Array.isArray(config.islands) || config.islands.length === 0) {\n throw new Error('createIslands requires a non-empty islands array');\n }\n for (const island of config.islands) {\n createIsland(island);\n }\n}\n\n/**\n * createSPA: Initializes router and mounts the app with the provided route manifest or route table.\n *\n * Preferred usage with manifest:\n * ```ts\n * import { getManifest } from '@askrjs/askr/router';\n * await createSPA({ root: '#app', manifest: getManifest() });\n * ```\n *\n * Legacy usage with plain routes array (still supported):\n * ```ts\n * await createSPA({ root: '#app', routes: getRoutes() });\n * ```\n */\nexport async function createSPA(config: SPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('createSPA requires a config object');\n }\n\n const manifest = config.manifest ?? config.registry?.manifest;\n const routeTable = config.routes ?? config.registry?.routes;\n const hasManifest = manifest != null && manifest.records.length > 0;\n const hasRoutes = Array.isArray(routeTable) && routeTable.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'createSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n\n const pendingLazyAtBoot = [\n ..._snapshotLazy(),\n ..._snapshotRouteSourceLazy({ registry: config.registry, manifest }),\n ];\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n // Preferred path: apply pre-built manifest records directly\n _applyManifest(manifest!);\n } else {\n // Legacy path: register plain Route objects (no layout metadata)\n for (const r of routeTable!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n const routeAuth = config.auth ?? manifest?.auth;\n const activeManifest = hasManifest ? manifest : undefined;\n const appRouteSource = {\n manifest: activeManifest,\n routes: hasManifest ? undefined : routeTable,\n auth: routeAuth,\n };\n _setActiveRouteAuthOptions(routeAuth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtBoot);\n\n // Lock registration in production to prevent late registration surprises\n if (isProductionEnvironment()) lockRouteRegistration();\n\n // Mount the currently-resolved route handler (if any)\n const { path, resolved } = await resolveInitialRoute(routeAuth);\n\n if (!resolved) {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n ...appRouteSource,\n });\n return;\n }\n\n if (resolved.kind === 'redirect') {\n mountOrUpdate(rootElement, () => ({ type: 'div', children: [] }), {\n cleanupStrict: config.cleanupStrict,\n });\n\n await registerAppNavigation(rootElement, path, {\n ...appRouteSource,\n });\n return;\n }\n\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler({\n handler: resolved.handler,\n params: resolved.params,\n }),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n\n await registerAppNavigation(rootElement, path, {\n ...appRouteSource,\n });\n}\n\n/**\n * hydrateSPA: Hydrate server-rendered HTML.\n * Accepts either a `manifest` (preferred) or a legacy `routes` array.\n */\nexport async function hydrateSPA(config: HydrateSPAConfig): Promise<void> {\n assertExecutionModel('spa');\n if (!config || typeof config !== 'object') {\n throw new Error('hydrateSPA requires a config object');\n }\n\n const manifest = config.manifest ?? config.registry?.manifest;\n const routeTable = config.routes ?? config.registry?.routes;\n const hasManifest = manifest != null && manifest.records.length > 0;\n const hasRoutes = Array.isArray(routeTable) && routeTable.length > 0;\n\n if (!hasManifest && !hasRoutes) {\n throw new Error(\n 'hydrateSPA requires a route manifest or route table. ' +\n 'Pass `manifest: getManifest()` or `routes: getRoutes()`. ' +\n 'If you are enhancing existing HTML, use createIsland instead.'\n );\n }\n\n const rootElement =\n typeof config.root === 'string'\n ? document.getElementById(config.root)\n : config.root;\n if (!rootElement) throw new Error(`Root element not found: ${config.root}`);\n const hydrationRenderData = takeHydrationRenderData(rootElement);\n\n const pendingLazyAtHydrationBoot = [\n ..._snapshotLazy(),\n ..._snapshotRouteSourceLazy({ registry: config.registry, manifest }),\n ];\n\n configureScrollRestoration(config.scrollRestoration);\n\n clearRoutes();\n\n if (hasManifest) {\n _applyManifest(manifest!);\n } else {\n for (const r of routeTable!) {\n registerRoute(r.path, r.handler as Parameters<typeof registerRoute>[1]);\n }\n }\n\n const routeAuth = config.auth ?? manifest?.auth;\n const activeManifest = hasManifest ? manifest : undefined;\n const appRouteSource = {\n manifest: activeManifest,\n routes: hasManifest ? undefined : routeTable,\n auth: routeAuth,\n };\n _setActiveRouteAuthOptions(routeAuth);\n\n // Drain any lazy() imports so all split chunks are ready before mounting\n await _drainLazy(pendingLazyAtHydrationBoot);\n\n const {\n path,\n href: currentUrl,\n resolved,\n } = await resolveInitialRoute(routeAuth);\n setServerLocation(currentUrl);\n if (isProductionEnvironment()) lockRouteRegistration();\n\n if (!resolved) {\n throw new Error(`hydrateSPA: no route found for current path (${path}).`);\n }\n\n if (resolved.kind === 'redirect') {\n throw new Error(\n `hydrateSPA: unresolved redirect for current path (${path}).`\n );\n }\n\n const hydrationResolved: ResolvedRoute =\n resolved.kind === 'deny'\n ? { handler: bindDeniedRouteHandler(resolved.status), params: {} }\n : { handler: resolved.handler, params: resolved.params };\n\n if (shouldVerifyHydrationMarkup(config)) {\n const legacyRouteTable = hasManifest\n ? manifest!.records.map((r) => ({\n ...r,\n path: r.path,\n handler: r.handler,\n namespace: r.options.namespace,\n }))\n : routeTable!;\n\n const { verifyHydrationSyncForUrl } =\n await import('../ssr/verify-hydration');\n if (\n !verifyHydrationSyncForUrl({\n root: rootElement,\n url: currentUrl,\n routes: legacyRouteTable,\n resolved: hydrationResolved,\n options: {\n data: hydrationRenderData ?? undefined,\n },\n })\n ) {\n throw new Error(\n '[Askr] Hydration mismatch detected. Server HTML does not match expected server-render output.'\n );\n }\n }\n\n const hydrateOptions = config.hydrate;\n if (hydrateOptions) {\n if (hydrateOptions.deferUntilIdle || hydrateOptions.deferBelowFold) {\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n await applySelectiveHydration(\n rootElement,\n hydrationResolved,\n path,\n config.cleanupStrict,\n hydrateOptions,\n appRouteSource,\n {\n mountOrUpdate,\n registerAppNavigation,\n registerRootCleanupCallback,\n flushHydrationActivation,\n }\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n return;\n }\n\n if (hydrateOptions.skipSelectors?.length) {\n markSkippedElements(rootElement, hydrateOptions.skipSelectors);\n }\n }\n\n if (hydrationRenderData) {\n startHydrationRenderPhase(hydrationRenderData);\n }\n try {\n mountOrUpdate(\n rootElement,\n resolved.kind === 'deny'\n ? bindDeniedStatus(resolved.status)\n : bindResolvedRouteHandler(hydrationResolved),\n {\n cleanupStrict: config.cleanupStrict,\n }\n );\n } finally {\n if (hydrationRenderData) {\n stopHydrationRenderPhase();\n }\n }\n await registerAppNavigation(rootElement, path, {\n ...appRouteSource,\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ComponentFunction } from "../common/component.js";
|
|
2
|
+
import { BootAppRouteSource } from "./types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/boot/root-lifecycle.d.ts
|
|
5
|
+
declare function registerRootCleanupCallback(rootElement: Element, callback: () => void): () => void;
|
|
6
|
+
declare function mountOrUpdate(rootElement: Element, componentFn: ComponentFunction, options?: {
|
|
7
|
+
cleanupStrict?: boolean;
|
|
8
|
+
}): void;
|
|
9
|
+
declare function flushHydrationActivation(rootElement: Element): void;
|
|
10
|
+
declare function registerAppNavigation(rootElement: Element, path: string, source?: BootAppRouteSource): Promise<void>;
|
|
11
|
+
declare function cleanupApp(root: Element | string): void;
|
|
12
|
+
declare function hasApp(root: Element | string): boolean;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { cleanupApp, hasApp };
|
|
15
|
+
//# sourceMappingURL=root-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-lifecycle.d.ts","names":[],"sources":["../../src/boot/root-lifecycle.ts"],"mappings":";;;;iBA0DgB,2BAAA,CACd,WAAA,EAAa,OAAO,EACpB,QAAA;AAAA,iBAsHc,aAAA,CACd,WAAA,EAAa,OAAA,EACb,WAAA,EAAa,iBAAiB,EAC9B,OAAA;EAAY,aAAA;AAAA;AAAA,iBAoGE,wBAAA,CAAyB,WAAoB,EAAP,OAAO;AAAA,iBAOvC,qBAAA,CACpB,WAAA,EAAa,OAAA,EACb,IAAA,UACA,MAAA,GAAS,kBAAA,GAAkB,OAAA;AAAA,iBASb,UAAA,CAAW,IAAsB,EAAhB,OAAO;AAAA,iBA0BxB,MAAA,CAAO,IAAsB,EAAhB,OAAO"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { isDevelopmentEnvironment } from "../common/env.js";
|
|
2
|
+
import { logger } from "../dev/logger.js";
|
|
3
|
+
import { flushRuntimeScheduler } from "../runtime/access.js";
|
|
4
|
+
import { ELEMENT_TYPE, Fragment } from "../common/jsx.js";
|
|
5
|
+
import { cleanupComponent } from "../runtime/component-cleanup.js";
|
|
6
|
+
import { isPromiseLike } from "../common/promise.js";
|
|
7
|
+
import { createComponentInstance, mountComponent } from "../runtime/component-internal.js";
|
|
8
|
+
import "../runtime/component.js";
|
|
9
|
+
import { removeAllListeners, teardownNodeSubtree } from "../renderer/cleanup.js";
|
|
10
|
+
import { installRendererBridge } from "../renderer/index.js";
|
|
11
|
+
import { clearRoutes } from "../router/manifest.js";
|
|
12
|
+
import "../router/route.js";
|
|
13
|
+
import { registerAppInstance, unregisterAppInstance } from "../router/navigation-registry.js";
|
|
14
|
+
import { DefaultPortal, disposeDefaultPortalScope } from "../foundations/structures/portal.js";
|
|
15
|
+
import "../jsx/index.js";
|
|
16
|
+
import { initializeNavigation } from "../router/navigate.js";
|
|
17
|
+
//#region src/boot/root-lifecycle.ts
|
|
18
|
+
installRendererBridge();
|
|
19
|
+
let componentIdCounter = 0;
|
|
20
|
+
const instancesByRoot = /* @__PURE__ */ new WeakMap();
|
|
21
|
+
const routedRoots = /* @__PURE__ */ new Set();
|
|
22
|
+
const CLEANUP_SYMBOL = Symbol.for("__askrCleanup__");
|
|
23
|
+
const ROOT_CLEANUP_CALLBACKS_SYMBOL = Symbol.for("__askrRootCleanupCallbacks__");
|
|
24
|
+
function clearRootCleanupCallbacks(rootElement) {
|
|
25
|
+
try {
|
|
26
|
+
delete rootElement[ROOT_CLEANUP_CALLBACKS_SYMBOL];
|
|
27
|
+
} catch {
|
|
28
|
+
rootElement[ROOT_CLEANUP_CALLBACKS_SYMBOL]?.clear();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function registerRootCleanupCallback(rootElement, callback) {
|
|
32
|
+
const elementWithCleanup = rootElement;
|
|
33
|
+
const callbacks = elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] ?? /* @__PURE__ */ new Set();
|
|
34
|
+
callbacks.add(callback);
|
|
35
|
+
elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] = callbacks;
|
|
36
|
+
return () => {
|
|
37
|
+
callbacks.delete(callback);
|
|
38
|
+
if (callbacks.size === 0) clearRootCleanupCallbacks(rootElement);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function runRootCleanupCallbacks(rootElement, errors) {
|
|
42
|
+
const callbacks = rootElement[ROOT_CLEANUP_CALLBACKS_SYMBOL];
|
|
43
|
+
if (!callbacks || callbacks.size === 0) {
|
|
44
|
+
clearRootCleanupCallbacks(rootElement);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
clearRootCleanupCallbacks(rootElement);
|
|
48
|
+
for (const callback of callbacks) try {
|
|
49
|
+
callback();
|
|
50
|
+
} catch (e) {
|
|
51
|
+
errors.push(e);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function cleanupRootInstance(rootElement, instance, options) {
|
|
55
|
+
const errors = [];
|
|
56
|
+
try {
|
|
57
|
+
teardownNodeSubtree(rootElement);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
errors.push(e);
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
cleanupComponent(instance);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
errors.push(e);
|
|
65
|
+
}
|
|
66
|
+
runRootCleanupCallbacks(rootElement, errors);
|
|
67
|
+
if (!options?.preserveInstance) {
|
|
68
|
+
unregisterAppInstance(instance);
|
|
69
|
+
instancesByRoot.delete(rootElement);
|
|
70
|
+
clearRootCleanupCallbacks(rootElement);
|
|
71
|
+
try {
|
|
72
|
+
delete rootElement[CLEANUP_SYMBOL];
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
if (errors.length > 0) {
|
|
76
|
+
if (instance.cleanupStrict) throw new AggregateError(errors, `cleanup failed for app root`);
|
|
77
|
+
else if (isDevelopmentEnvironment()) for (const err of errors) logger.warn("[Askr] cleanup error:", err);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function attachCleanupForRoot(rootElement, instance) {
|
|
81
|
+
rootElement[CLEANUP_SYMBOL] = (options) => {
|
|
82
|
+
cleanupRootInstance(rootElement, instance, options);
|
|
83
|
+
};
|
|
84
|
+
try {
|
|
85
|
+
const descriptor = Object.getOwnPropertyDescriptor(rootElement, "innerHTML") || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(rootElement), "innerHTML") || Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML");
|
|
86
|
+
if (descriptor && (descriptor.get || descriptor.set)) Object.defineProperty(rootElement, "innerHTML", {
|
|
87
|
+
get: descriptor.get ? function() {
|
|
88
|
+
return descriptor.get.call(this);
|
|
89
|
+
} : void 0,
|
|
90
|
+
set: function(value) {
|
|
91
|
+
if (value === "" && instancesByRoot.get(this) === instance) cleanupRootInstance(rootElement, instance);
|
|
92
|
+
if (descriptor.set) return descriptor.set.call(this, value);
|
|
93
|
+
},
|
|
94
|
+
configurable: true
|
|
95
|
+
});
|
|
96
|
+
} catch {}
|
|
97
|
+
}
|
|
98
|
+
function mountOrUpdate(rootElement, componentFn, options) {
|
|
99
|
+
const wrappedFn = (props, ctx) => {
|
|
100
|
+
const out = componentFn(props, ctx);
|
|
101
|
+
if (isPromiseLike(out)) throw new Error("Async components are not supported. Components must return synchronously.");
|
|
102
|
+
const portalVNode = {
|
|
103
|
+
$$typeof: ELEMENT_TYPE,
|
|
104
|
+
type: DefaultPortal,
|
|
105
|
+
props: {},
|
|
106
|
+
key: "__default_portal"
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
$$typeof: ELEMENT_TYPE,
|
|
110
|
+
type: Fragment,
|
|
111
|
+
props: { children: out === void 0 || out === null ? [portalVNode] : [out, portalVNode] }
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
Object.defineProperty(wrappedFn, "name", { value: componentFn.name || "Component" });
|
|
115
|
+
const existingCleanup = rootElement[CLEANUP_SYMBOL];
|
|
116
|
+
const reusedExistingInstance = typeof existingCleanup === "function";
|
|
117
|
+
if (reusedExistingInstance) existingCleanup({ preserveInstance: true });
|
|
118
|
+
let instance = instancesByRoot.get(rootElement);
|
|
119
|
+
if (instance) {
|
|
120
|
+
const shouldResetHookState = instance.fn.name !== wrappedFn.name;
|
|
121
|
+
if (!reusedExistingInstance) {
|
|
122
|
+
removeAllListeners(rootElement);
|
|
123
|
+
try {
|
|
124
|
+
cleanupComponent(instance);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
if (isDevelopmentEnvironment()) logger.warn("[Askr] prior cleanup threw:", e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
instance.fn = wrappedFn;
|
|
130
|
+
instance.evaluationGeneration++;
|
|
131
|
+
instance.mounted = false;
|
|
132
|
+
instance.expectedStateIndices = [];
|
|
133
|
+
instance.firstRenderComplete = false;
|
|
134
|
+
instance.isRoot = true;
|
|
135
|
+
instance.portalScope = instance;
|
|
136
|
+
if (shouldResetHookState) {
|
|
137
|
+
instance.stateValues = [];
|
|
138
|
+
instance.hasPendingUpdate = false;
|
|
139
|
+
instance.notifyUpdate = null;
|
|
140
|
+
instance.stateIndexCheck = -1;
|
|
141
|
+
instance.mountOperations = [];
|
|
142
|
+
instance.commitOperations = [];
|
|
143
|
+
instance.lifecycleSlots = [];
|
|
144
|
+
instance.cleanupFns = [];
|
|
145
|
+
instance._currentRenderToken = void 0;
|
|
146
|
+
instance.lastRenderToken = 0;
|
|
147
|
+
instance._pendingReadSources = void 0;
|
|
148
|
+
instance._lastReadSources = void 0;
|
|
149
|
+
instance._placeholder = void 0;
|
|
150
|
+
instance.errorBoundaryState = void 0;
|
|
151
|
+
instance.devWarningsEmitted = void 0;
|
|
152
|
+
}
|
|
153
|
+
if (options && typeof options.cleanupStrict === "boolean") instance.cleanupStrict = options.cleanupStrict;
|
|
154
|
+
} else {
|
|
155
|
+
instance = createComponentInstance(String(++componentIdCounter), wrappedFn, {}, rootElement);
|
|
156
|
+
instancesByRoot.set(rootElement, instance);
|
|
157
|
+
instance.isRoot = true;
|
|
158
|
+
instance.portalScope = instance;
|
|
159
|
+
if (options && typeof options.cleanupStrict === "boolean") instance.cleanupStrict = options.cleanupStrict;
|
|
160
|
+
}
|
|
161
|
+
attachCleanupForRoot(rootElement, instance);
|
|
162
|
+
registerRootCleanupCallback(rootElement, () => {
|
|
163
|
+
disposeDefaultPortalScope(instance.portalScope ?? instance);
|
|
164
|
+
});
|
|
165
|
+
mountComponent(instance);
|
|
166
|
+
flushRuntimeScheduler();
|
|
167
|
+
}
|
|
168
|
+
function flushHydrationActivation(rootElement) {
|
|
169
|
+
const instance = instancesByRoot.get(rootElement);
|
|
170
|
+
if (!instance) return;
|
|
171
|
+
instance._enqueueRun?.();
|
|
172
|
+
flushRuntimeScheduler();
|
|
173
|
+
}
|
|
174
|
+
async function registerAppNavigation(rootElement, path, source) {
|
|
175
|
+
const instance = instancesByRoot.get(rootElement);
|
|
176
|
+
if (!instance) throw new Error("Internal error: app instance missing");
|
|
177
|
+
routedRoots.add(rootElement);
|
|
178
|
+
registerAppInstance(instance, path, source);
|
|
179
|
+
initializeNavigation();
|
|
180
|
+
}
|
|
181
|
+
function cleanupApp(root) {
|
|
182
|
+
const rootElement = typeof root === "string" ? document.getElementById(root) : root;
|
|
183
|
+
if (!rootElement) return;
|
|
184
|
+
const cleanupFn = rootElement[CLEANUP_SYMBOL];
|
|
185
|
+
try {
|
|
186
|
+
if (typeof cleanupFn === "function") cleanupFn();
|
|
187
|
+
} finally {
|
|
188
|
+
const wasRoutedRoot = routedRoots.delete(rootElement);
|
|
189
|
+
instancesByRoot.delete(rootElement);
|
|
190
|
+
clearRootCleanupCallbacks(rootElement);
|
|
191
|
+
if (wasRoutedRoot && routedRoots.size === 0) clearRoutes();
|
|
192
|
+
try {
|
|
193
|
+
delete rootElement[CLEANUP_SYMBOL];
|
|
194
|
+
} catch {}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function hasApp(root) {
|
|
198
|
+
const rootElement = typeof root === "string" ? document.getElementById(root) : root;
|
|
199
|
+
if (!rootElement) return false;
|
|
200
|
+
return instancesByRoot.has(rootElement);
|
|
201
|
+
}
|
|
202
|
+
//#endregion
|
|
203
|
+
export { cleanupApp, flushHydrationActivation, hasApp, mountOrUpdate, registerAppNavigation, registerRootCleanupCallback };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=root-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-lifecycle.js","names":[],"sources":["../../src/boot/root-lifecycle.ts"],"sourcesContent":["import { isDevelopmentEnvironment } from '../common/env';\nimport { isPromiseLike } from '../common/promise';\nimport { logger } from '../dev/logger';\nimport {\n DefaultPortal,\n disposeDefaultPortalScope,\n} from '../foundations/structures/portal';\nimport { ELEMENT_TYPE, Fragment } from '../jsx';\nimport {\n initializeNavigation,\n registerAppInstance,\n unregisterAppInstance,\n} from '../router/navigate';\nimport { clearRoutes } from '../router/route';\nimport { flushRuntimeScheduler } from '../runtime/access';\nimport {\n cleanupComponent,\n createComponentInstance,\n mountComponent,\n type ComponentFunction,\n type ComponentInstance,\n} from '../runtime/component';\nimport {\n installRendererBridge,\n removeAllListeners,\n teardownNodeSubtree,\n} from '../renderer';\nimport type { BootAppRouteSource } from './types';\n\ninstallRendererBridge();\n\nlet componentIdCounter = 0;\n\nconst instancesByRoot = new WeakMap<Element, ComponentInstance>();\nconst routedRoots = new Set<Element>();\n\nconst CLEANUP_SYMBOL = Symbol.for('__askrCleanup__');\nconst ROOT_CLEANUP_CALLBACKS_SYMBOL = Symbol.for(\n '__askrRootCleanupCallbacks__'\n);\n\ntype RootCleanupOptions = {\n preserveInstance?: boolean;\n};\n\ninterface ElementWithCleanup extends Element {\n [CLEANUP_SYMBOL]?: (options?: RootCleanupOptions) => void;\n [ROOT_CLEANUP_CALLBACKS_SYMBOL]?: Set<() => void>;\n}\n\nfunction clearRootCleanupCallbacks(rootElement: Element): void {\n try {\n delete (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL];\n } catch {\n (rootElement as ElementWithCleanup)[ROOT_CLEANUP_CALLBACKS_SYMBOL]?.clear();\n }\n}\n\nexport function registerRootCleanupCallback(\n rootElement: Element,\n callback: () => void\n): () => void {\n const elementWithCleanup = rootElement as ElementWithCleanup;\n const callbacks =\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] ?? new Set();\n callbacks.add(callback);\n elementWithCleanup[ROOT_CLEANUP_CALLBACKS_SYMBOL] = callbacks;\n\n return () => {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n }\n };\n}\n\nfunction runRootCleanupCallbacks(\n rootElement: Element,\n errors: unknown[]\n): void {\n const callbacks = (rootElement as ElementWithCleanup)[\n ROOT_CLEANUP_CALLBACKS_SYMBOL\n ];\n if (!callbacks || callbacks.size === 0) {\n clearRootCleanupCallbacks(rootElement);\n return;\n }\n\n clearRootCleanupCallbacks(rootElement);\n for (const callback of callbacks) {\n try {\n callback();\n } catch (e) {\n errors.push(e);\n }\n }\n}\n\nfunction cleanupRootInstance(\n rootElement: Element,\n instance: ComponentInstance,\n options?: RootCleanupOptions\n) {\n const errors: unknown[] = [];\n try {\n teardownNodeSubtree(rootElement);\n } catch (e) {\n errors.push(e);\n }\n\n try {\n cleanupComponent(instance);\n } catch (e) {\n errors.push(e);\n }\n\n runRootCleanupCallbacks(rootElement, errors);\n\n if (!options?.preserveInstance) {\n unregisterAppInstance(instance);\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n\n if (errors.length > 0) {\n if (instance.cleanupStrict) {\n throw new AggregateError(errors, `cleanup failed for app root`);\n } else if (isDevelopmentEnvironment()) {\n for (const err of errors) logger.warn('[Askr] cleanup error:', err);\n }\n }\n}\n\nfunction attachCleanupForRoot(\n rootElement: Element,\n instance: ComponentInstance\n) {\n (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL] = (options) => {\n cleanupRootInstance(rootElement, instance, options);\n };\n\n try {\n const descriptor =\n Object.getOwnPropertyDescriptor(rootElement, 'innerHTML') ||\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(rootElement),\n 'innerHTML'\n ) ||\n Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');\n\n if (descriptor && (descriptor.get || descriptor.set)) {\n Object.defineProperty(rootElement, 'innerHTML', {\n get: descriptor.get\n ? function (this: Element) {\n return descriptor.get!.call(this);\n }\n : undefined,\n set: function (this: Element, value: string) {\n if (value === '' && instancesByRoot.get(this) === instance) {\n cleanupRootInstance(rootElement, instance);\n }\n if (descriptor.set) {\n return descriptor.set.call(this, value);\n }\n },\n configurable: true,\n });\n }\n } catch {\n // If Object.defineProperty fails, ignore\n }\n}\n\nexport function mountOrUpdate(\n rootElement: Element,\n componentFn: ComponentFunction,\n options?: { cleanupStrict?: boolean }\n) {\n const wrappedFn: ComponentFunction = (props, ctx) => {\n const out = componentFn(props, ctx);\n if (isPromiseLike(out)) {\n throw new Error(\n 'Async components are not supported. Components must return synchronously.'\n );\n }\n const portalVNode = {\n $$typeof: ELEMENT_TYPE,\n type: DefaultPortal,\n props: {},\n key: '__default_portal',\n } as unknown;\n return {\n $$typeof: ELEMENT_TYPE,\n type: Fragment,\n props: {\n children:\n out === undefined || out === null\n ? [portalVNode]\n : [out, portalVNode],\n },\n } as unknown as ReturnType<ComponentFunction>;\n };\n Object.defineProperty(wrappedFn, 'name', {\n value: componentFn.name || 'Component',\n });\n\n const existingCleanup = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n const reusedExistingInstance = typeof existingCleanup === 'function';\n if (reusedExistingInstance) {\n existingCleanup({ preserveInstance: true });\n }\n\n let instance = instancesByRoot.get(rootElement);\n\n if (instance) {\n const shouldResetHookState = instance.fn.name !== wrappedFn.name;\n\n if (!reusedExistingInstance) {\n removeAllListeners(rootElement);\n try {\n cleanupComponent(instance);\n } catch (e) {\n if (isDevelopmentEnvironment()) {\n logger.warn('[Askr] prior cleanup threw:', e);\n }\n }\n }\n\n instance.fn = wrappedFn;\n instance.evaluationGeneration++;\n instance.mounted = false;\n instance.expectedStateIndices = [];\n instance.firstRenderComplete = false;\n instance.isRoot = true;\n instance.portalScope = instance;\n\n if (shouldResetHookState) {\n instance.stateValues = [];\n instance.hasPendingUpdate = false;\n instance.notifyUpdate = null;\n instance.stateIndexCheck = -1;\n instance.mountOperations = [];\n instance.commitOperations = [];\n instance.lifecycleSlots = [];\n instance.cleanupFns = [];\n instance._currentRenderToken = undefined;\n instance.lastRenderToken = 0;\n instance._pendingReadSources = undefined;\n instance._lastReadSources = undefined;\n instance._placeholder = undefined;\n instance.errorBoundaryState = undefined;\n instance.devWarningsEmitted = undefined;\n }\n\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n } else {\n const componentId = String(++componentIdCounter);\n instance = createComponentInstance(componentId, wrappedFn, {}, rootElement);\n instancesByRoot.set(rootElement, instance);\n instance.isRoot = true;\n instance.portalScope = instance;\n if (options && typeof options.cleanupStrict === 'boolean') {\n instance.cleanupStrict = options.cleanupStrict;\n }\n }\n\n attachCleanupForRoot(rootElement, instance);\n registerRootCleanupCallback(rootElement, () => {\n disposeDefaultPortalScope(instance.portalScope ?? instance);\n });\n mountComponent(instance);\n flushRuntimeScheduler();\n}\n\nexport function flushHydrationActivation(rootElement: Element): void {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) return;\n instance._enqueueRun?.();\n flushRuntimeScheduler();\n}\n\nexport async function registerAppNavigation(\n rootElement: Element,\n path: string,\n source?: BootAppRouteSource\n) {\n const instance = instancesByRoot.get(rootElement);\n if (!instance) throw new Error('Internal error: app instance missing');\n routedRoots.add(rootElement);\n registerAppInstance(instance, path, source);\n initializeNavigation();\n}\n\nexport function cleanupApp(root: Element | string): void {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return;\n\n const cleanupFn = (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n try {\n if (typeof cleanupFn === 'function') {\n cleanupFn();\n }\n } finally {\n const wasRoutedRoot = routedRoots.delete(rootElement);\n instancesByRoot.delete(rootElement);\n clearRootCleanupCallbacks(rootElement);\n if (wasRoutedRoot && routedRoots.size === 0) {\n clearRoutes();\n }\n try {\n delete (rootElement as ElementWithCleanup)[CLEANUP_SYMBOL];\n } catch {\n // Ignore cleanup marker removal failures.\n }\n }\n}\n\nexport function hasApp(root: Element | string): boolean {\n const rootElement =\n typeof root === 'string' ? document.getElementById(root) : root;\n\n if (!rootElement) return false;\n return instancesByRoot.has(rootElement);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { resolveRouteRequest } from "../router/resolution.js";
|
|
2
|
+
import "../router/route.js";
|
|
3
|
+
//#region src/boot/route-startup.ts
|
|
4
|
+
const MAX_INITIAL_ROUTE_REDIRECTS = 20;
|
|
5
|
+
function bindResolvedRouteHandler(resolved) {
|
|
6
|
+
return () => resolved.handler(resolved.params);
|
|
7
|
+
}
|
|
8
|
+
function createDeniedStatusNode(status) {
|
|
9
|
+
return {
|
|
10
|
+
type: "div",
|
|
11
|
+
props: { "data-route-denied": String(status) },
|
|
12
|
+
children: [String(status)]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function bindDeniedStatus(status) {
|
|
16
|
+
return () => createDeniedStatusNode(status);
|
|
17
|
+
}
|
|
18
|
+
function bindDeniedRouteHandler(status) {
|
|
19
|
+
return () => createDeniedStatusNode(status);
|
|
20
|
+
}
|
|
21
|
+
async function resolveInitialRoute(auth) {
|
|
22
|
+
let path = typeof window !== "undefined" ? window.location.pathname : "/";
|
|
23
|
+
let href = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}${window.location.hash}` : path;
|
|
24
|
+
const visited = /* @__PURE__ */ new Set();
|
|
25
|
+
for (let redirects = 0; redirects <= MAX_INITIAL_ROUTE_REDIRECTS; redirects++) {
|
|
26
|
+
if (visited.has(href)) throw new Error(`[Askr] Route redirect cycle detected at ${href}.`);
|
|
27
|
+
visited.add(href);
|
|
28
|
+
const resolved = await resolveRouteRequest(href, { auth });
|
|
29
|
+
if (typeof window === "undefined" || !resolved || resolved.kind !== "redirect") return {
|
|
30
|
+
path,
|
|
31
|
+
href,
|
|
32
|
+
resolved
|
|
33
|
+
};
|
|
34
|
+
const redirectTarget = new URL(resolved.to, window.location.href);
|
|
35
|
+
const redirectHref = `${redirectTarget.pathname}${redirectTarget.search}${redirectTarget.hash}`;
|
|
36
|
+
window.history.replaceState({ path: redirectHref }, "", redirectHref);
|
|
37
|
+
path = redirectTarget.pathname;
|
|
38
|
+
href = redirectHref;
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`[Askr] Route redirect limit exceeded (${MAX_INITIAL_ROUTE_REDIRECTS}).`);
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { bindDeniedRouteHandler, bindDeniedStatus, bindResolvedRouteHandler, resolveInitialRoute };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=route-startup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-startup.js","names":[],"sources":["../../src/boot/route-startup.ts"],"sourcesContent":["import type {\n ResolvedRoute,\n RouteAuthOptions,\n RouteHandler,\n RouteRequestResult,\n} from '../common/router';\nimport { resolveRouteRequest } from '../router/route';\nimport type { ComponentFunction } from '../runtime/component';\n\nconst MAX_INITIAL_ROUTE_REDIRECTS = 20;\n\nexport function bindResolvedRouteHandler(\n resolved: ResolvedRoute\n): ComponentFunction {\n return () =>\n resolved.handler(resolved.params) as ReturnType<ComponentFunction>;\n}\n\nfunction createDeniedStatusNode(status: number) {\n return {\n type: 'div',\n props: {\n 'data-route-denied': String(status),\n },\n children: [String(status)],\n };\n}\n\nexport function bindDeniedStatus(status: number): ComponentFunction {\n return () => createDeniedStatusNode(status);\n}\n\nexport function bindDeniedRouteHandler(status: number): RouteHandler {\n return () => createDeniedStatusNode(status);\n}\n\nexport async function resolveInitialRoute(\n auth?: RouteAuthOptions\n): Promise<{ path: string; href: string; resolved: RouteRequestResult }> {\n let path = typeof window !== 'undefined' ? window.location.pathname : '/';\n let href =\n typeof window !== 'undefined'\n ? `${window.location.pathname}${window.location.search}${window.location.hash}`\n : path;\n const visited = new Set<string>();\n\n for (\n let redirects = 0;\n redirects <= MAX_INITIAL_ROUTE_REDIRECTS;\n redirects++\n ) {\n if (visited.has(href)) {\n throw new Error(`[Askr] Route redirect cycle detected at ${href}.`);\n }\n visited.add(href);\n\n const resolved = await resolveRouteRequest(href, { auth });\n if (\n typeof window === 'undefined' ||\n !resolved ||\n resolved.kind !== 'redirect'\n ) {\n return { path, href, resolved };\n }\n\n const redirectTarget = new URL(resolved.to, window.location.href);\n const redirectHref = `${redirectTarget.pathname}${redirectTarget.search}${redirectTarget.hash}`;\n window.history.replaceState({ path: redirectHref }, '', redirectHref);\n path = redirectTarget.pathname;\n href = redirectHref;\n }\n\n throw new Error(\n `[Askr] Route redirect limit exceeded (${MAX_INITIAL_ROUTE_REDIRECTS}).`\n );\n}\n"],"mappings":";;;AASA,MAAM,8BAA8B;AAEpC,SAAgB,yBACd,UACmB;CACnB,aACE,SAAS,QAAQ,SAAS,MAAM;AACpC;AAEA,SAAS,uBAAuB,QAAgB;CAC9C,OAAO;EACL,MAAM;EACN,OAAO,EACL,qBAAqB,OAAO,MAAM,EACpC;EACA,UAAU,CAAC,OAAO,MAAM,CAAC;CAC3B;AACF;AAEA,SAAgB,iBAAiB,QAAmC;CAClE,aAAa,uBAAuB,MAAM;AAC5C;AAEA,SAAgB,uBAAuB,QAA8B;CACnE,aAAa,uBAAuB,MAAM;AAC5C;AAEA,eAAsB,oBACpB,MACuE;CACvE,IAAI,OAAO,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW;CACtE,IAAI,OACF,OAAO,WAAW,cACd,GAAG,OAAO,SAAS,WAAW,OAAO,SAAS,SAAS,OAAO,SAAS,SACvE;CACN,MAAM,0BAAU,IAAI,IAAY;CAEhC,KACE,IAAI,YAAY,GAChB,aAAa,6BACb,aACA;EACA,IAAI,QAAQ,IAAI,IAAI,GAClB,MAAM,IAAI,MAAM,2CAA2C,KAAK,EAAE;EAEpE,QAAQ,IAAI,IAAI;EAEhB,MAAM,WAAW,MAAM,oBAAoB,MAAM,EAAE,KAAK,CAAC;EACzD,IACE,OAAO,WAAW,eAClB,CAAC,YACD,SAAS,SAAS,YAElB,OAAO;GAAE;GAAM;GAAM;EAAS;EAGhC,MAAM,iBAAiB,IAAI,IAAI,SAAS,IAAI,OAAO,SAAS,IAAI;EAChE,MAAM,eAAe,GAAG,eAAe,WAAW,eAAe,SAAS,eAAe;EACzF,OAAO,QAAQ,aAAa,EAAE,MAAM,aAAa,GAAG,IAAI,YAAY;EACpE,OAAO,eAAe;EACtB,OAAO;CACT;CAEA,MAAM,IAAI,MACR,yCAAyC,4BAA4B,GACvE;AACF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ComponentFunction } from "../common/component.js";
|
|
2
|
+
import { Route, RouteAuthOptions, RouteManifest, RouteRegistry } from "../common/router.js";
|
|
3
|
+
import { ScrollRestorationOptions } from "../router/navigation-scroll.js";
|
|
4
|
+
//#region src/boot/types.d.ts
|
|
5
|
+
type IslandConfig = {
|
|
6
|
+
root: Element | string;
|
|
7
|
+
component: ComponentFunction;
|
|
8
|
+
cleanupStrict?: boolean;
|
|
9
|
+
routes?: never;
|
|
10
|
+
};
|
|
11
|
+
type IslandsConfig = {
|
|
12
|
+
islands: IslandConfig[];
|
|
13
|
+
};
|
|
14
|
+
type BootRouteSource = {
|
|
15
|
+
registry: RouteRegistry;
|
|
16
|
+
manifest?: RouteManifest;
|
|
17
|
+
routes?: Route[];
|
|
18
|
+
} | {
|
|
19
|
+
manifest: RouteManifest;
|
|
20
|
+
registry?: RouteRegistry;
|
|
21
|
+
routes?: Route[];
|
|
22
|
+
} | {
|
|
23
|
+
manifest?: RouteManifest;
|
|
24
|
+
registry?: RouteRegistry;
|
|
25
|
+
routes: Route[];
|
|
26
|
+
};
|
|
27
|
+
type SPAConfig = BootRouteSource & {
|
|
28
|
+
root: Element | string;
|
|
29
|
+
/**
|
|
30
|
+
* Preferred: pass a route registry built via `createRouteRegistry(() => { ... })`.
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { createRouteRegistry } from '@askrjs/askr/router';
|
|
33
|
+
* const registry = createRouteRegistry(() => { ... });
|
|
34
|
+
* await createSPA({ root: '#app', registry });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
auth?: RouteAuthOptions;
|
|
38
|
+
scrollRestoration?: boolean | ScrollRestorationOptions;
|
|
39
|
+
cleanupStrict?: boolean;
|
|
40
|
+
component?: never;
|
|
41
|
+
};
|
|
42
|
+
type HydrateSPAConfig = BootRouteSource & {
|
|
43
|
+
root: Element | string; /** Preferred route input - see `SPAConfig`. */
|
|
44
|
+
auth?: RouteAuthOptions;
|
|
45
|
+
scrollRestoration?: boolean | ScrollRestorationOptions;
|
|
46
|
+
cleanupStrict?: boolean;
|
|
47
|
+
hydrate?: {
|
|
48
|
+
verifyMarkup?: boolean;
|
|
49
|
+
deferUntilIdle?: boolean;
|
|
50
|
+
deferBelowFold?: boolean;
|
|
51
|
+
foldThreshold?: number;
|
|
52
|
+
skipSelectors?: string[];
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
type BootAppRouteSource = {
|
|
56
|
+
manifest?: RouteManifest;
|
|
57
|
+
routes?: readonly Route[];
|
|
58
|
+
auth?: RouteAuthOptions;
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { BootAppRouteSource, HydrateSPAConfig, IslandConfig, IslandsConfig, SPAConfig };
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/boot/types.ts"],"mappings":";;;;KASY,YAAA;EACV,IAAA,EAAM,OAAA;EACN,SAAA,EAAW,iBAAiB;EAE5B,aAAA;EAEA,MAAA;AAAA;AAAA,KAGU,aAAA;EACV,OAAA,EAAS,YAAY;AAAA;AAAA,KAGlB,eAAA;EAEC,QAAA,EAAU,aAAA;EACV,QAAA,GAAW,aAAA;EACX,MAAA,GAAS,KAAA;AAAA;EAGT,QAAA,EAAU,aAAA;EACV,QAAA,GAAW,aAAA;EACX,MAAA,GAAS,KAAA;AAAA;EAGT,QAAA,GAAW,aAAA;EACX,QAAA,GAAW,aAAA;EACX,MAAA,EAAQ,KAAA;AAAA;AAAA,KAGF,SAAA,GAAY,eAAA;EACtB,IAAA,EAAM,OAAA;EAhBQ;;;;;;;;EAyBd,IAAA,GAAO,gBAAA;EACP,iBAAA,aAA8B,wBAAA;EAC9B,aAAA;EACA,SAAA;AAAA;AAAA,KAGU,gBAAA,GAAmB,eAAA;EAC7B,IAAA,EAAM,OAAA,WA9BF;EAgCJ,IAAA,GAAO,gBAAA;EACP,iBAAA,aAA8B,wBAAA;EAC9B,aAAA;EACA,OAAA;IACE,YAAA;IACA,cAAA;IACA,cAAA;IACA,aAAA;IACA,aAAA;EAAA;AAAA;AAAA,KAIQ,kBAAA;EACV,QAAA,GAAW,aAAA;EACX,MAAA,YAAkB,KAAA;EAClB,IAAA,GAAO,gBAAA;AAAA"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Props } from "./props.js";
|
|
2
2
|
import { JSXElement } from "./jsx.js";
|
|
3
|
+
import { SSRContext } from "./ssr.js";
|
|
3
4
|
import { VNode } from "./vnode.js";
|
|
4
5
|
|
|
5
6
|
//#region src/common/component.d.ts
|
|
6
7
|
type ComponentContext = {
|
|
7
8
|
signal: AbortSignal;
|
|
9
|
+
ssr?: SSRContext;
|
|
8
10
|
};
|
|
9
11
|
type ComponentVNode = {
|
|
10
12
|
type: string;
|
|
@@ -13,5 +15,5 @@ type ComponentVNode = {
|
|
|
13
15
|
};
|
|
14
16
|
type ComponentFunction = (props: Props, context?: ComponentContext) => JSXElement | VNode;
|
|
15
17
|
//#endregion
|
|
16
|
-
export { ComponentFunction };
|
|
18
|
+
export { ComponentContext, ComponentFunction, ComponentVNode };
|
|
17
19
|
//# sourceMappingURL=component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","names":[],"sources":["../../src/common/component.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"component.d.ts","names":[],"sources":["../../src/common/component.ts"],"mappings":";;;;;;KASY,gBAAA;EACV,MAAA,EAAQ,WAAA;EACR,GAAA,GAAM,UAAU;AAAA;AAAA,KAMN,cAAA;EACV,IAAA;EACA,KAAA,GAAQ,KAAA;EACR,QAAA,aAAqB,cAAc;AAAA;AAAA,KAGzB,iBAAA,IACV,KAAA,EAAO,KAAA,EACP,OAAA,GAAU,gBAAA,KACP,UAAA,GAAa,KAAA"}
|
package/dist/common/jsx.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface JSXElement {
|
|
|
8
8
|
/** Internal element marker */
|
|
9
9
|
$$typeof: symbol;
|
|
10
10
|
/** Element type: string, component, Fragment, etc */
|
|
11
|
-
type: string | ((props:
|
|
11
|
+
type: string | ((props: never) => unknown) | symbol;
|
|
12
12
|
/** Props bag */
|
|
13
13
|
props: Props;
|
|
14
14
|
/** Optional key (normalized by runtime) */
|
package/dist/common/jsx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx.d.ts","names":[],"sources":["../../src/common/jsx.ts"],"mappings":";;;cAMa,YAAA;AAAA,cACA,QAAA;AAAA,cACA,eAAA;AAAA,UAEI,UAAA;EAHJ;EAKX,QAAA;;EAGA,IAAA,aAAiB,KAAA
|
|
1
|
+
{"version":3,"file":"jsx.d.ts","names":[],"sources":["../../src/common/jsx.ts"],"mappings":";;;cAMa,YAAA;AAAA,cACA,QAAA;AAAA,cACA,eAAA;AAAA,UAEI,UAAA;EAHJ;EAKX,QAAA;;EAGA,IAAA,aAAiB,KAAA;EARgC;EAWjD,KAAA,EAAO,KAAK;EAVmD;EAa/D,GAAA;AAAA"}
|
package/dist/common/jsx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx.js","names":[],"sources":["../../src/common/jsx.ts"],"sourcesContent":["/**\n * Common call contracts: JSX element shape\n */\n\nimport type { Props } from './props';\n\nexport const ELEMENT_TYPE = Symbol.for('askr.element');\nexport const Fragment = Symbol.for('askr.fragment');\nexport const STATIC_CHILDREN = Symbol.for('askr.static-children');\n\nexport interface JSXElement {\n /** Internal element marker */\n $$typeof: symbol;\n\n /** Element type: string, component, Fragment, etc */\n type: string | ((props:
|
|
1
|
+
{"version":3,"file":"jsx.js","names":[],"sources":["../../src/common/jsx.ts"],"sourcesContent":["/**\n * Common call contracts: JSX element shape\n */\n\nimport type { Props } from './props';\n\nexport const ELEMENT_TYPE = Symbol.for('askr.element');\nexport const Fragment = Symbol.for('askr.fragment');\nexport const STATIC_CHILDREN = Symbol.for('askr.static-children');\n\nexport interface JSXElement {\n /** Internal element marker */\n $$typeof: symbol;\n\n /** Element type: string, component, Fragment, etc */\n type: string | ((props: never) => unknown) | symbol;\n\n /** Props bag */\n props: Props;\n\n /** Optional key (normalized by runtime) */\n key?: string | number | null;\n}\n"],"mappings":";AAMA,MAAa,eAAe,OAAO,IAAI,cAAc;AACrD,MAAa,WAAW,OAAO,IAAI,eAAe;AAClD,MAAa,kBAAkB,OAAO,IAAI,sBAAsB"}
|
package/dist/common/props.d.ts
CHANGED
|
@@ -307,5 +307,5 @@ interface ComponentNode {
|
|
|
307
307
|
children?: ComponentNode[];
|
|
308
308
|
}
|
|
309
309
|
//#endregion
|
|
310
|
-
export { IntrinsicFallbackProps, KnownIntrinsicElementProps, Props };
|
|
310
|
+
export { AnchorIntrinsicProps, ButtonIntrinsicProps, ComponentNode, FormIntrinsicProps, ImageIntrinsicProps, InputIntrinsicProps, IntrinsicFallbackProps, IntrinsicProps, KnownIntrinsicElementProps, LabelIntrinsicProps, LayoutIntrinsicProps, ListItemIntrinsicProps, OptionIntrinsicProps, OrderedListIntrinsicProps, OutputIntrinsicProps, Props, SelectIntrinsicProps, SvgCircleIntrinsicProps, SvgGroupIntrinsicProps, SvgIntrinsicProps, SvgPathIntrinsicProps, SvgRectIntrinsicProps, TableCellIntrinsicProps, TableHeaderIntrinsicProps, TextareaIntrinsicProps };
|
|
311
311
|
//# sourceMappingURL=props.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SSRDataMissingError } from "./ssr-errors.js";
|
|
2
|
+
//#region src/common/render-context.ts
|
|
3
|
+
let provider = { getRenderContext() {
|
|
4
|
+
return null;
|
|
5
|
+
} };
|
|
6
|
+
let hydrationRenderData = null;
|
|
7
|
+
let hydrationKeyCounter = 0;
|
|
8
|
+
function configureRenderContextProvider(nextProvider) {
|
|
9
|
+
provider = nextProvider;
|
|
10
|
+
}
|
|
11
|
+
function getActiveRenderContext() {
|
|
12
|
+
return provider.getRenderContext();
|
|
13
|
+
}
|
|
14
|
+
function getCurrentRenderData() {
|
|
15
|
+
return getActiveRenderContext()?.renderData ?? hydrationRenderData;
|
|
16
|
+
}
|
|
17
|
+
function resetRenderKeyCounter() {
|
|
18
|
+
const ctx = getActiveRenderContext();
|
|
19
|
+
if (ctx) ctx.keyCounter = 0;
|
|
20
|
+
}
|
|
21
|
+
function getNextRenderKey() {
|
|
22
|
+
const ctx = getActiveRenderContext();
|
|
23
|
+
if (ctx) return `r:${ctx.keyCounter++}`;
|
|
24
|
+
if (hydrationRenderData) return `r:${hydrationKeyCounter++}`;
|
|
25
|
+
return "r:0";
|
|
26
|
+
}
|
|
27
|
+
function startHydrationRenderPhase(data) {
|
|
28
|
+
hydrationRenderData = data;
|
|
29
|
+
hydrationKeyCounter = 0;
|
|
30
|
+
}
|
|
31
|
+
function stopHydrationRenderPhase() {
|
|
32
|
+
hydrationRenderData = null;
|
|
33
|
+
hydrationKeyCounter = 0;
|
|
34
|
+
}
|
|
35
|
+
function startRenderPhase(data) {
|
|
36
|
+
const ctx = getActiveRenderContext();
|
|
37
|
+
if (ctx) {
|
|
38
|
+
ctx.renderData = data ?? null;
|
|
39
|
+
ctx.keyCounter = 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function stopRenderPhase() {
|
|
43
|
+
const ctx = getActiveRenderContext();
|
|
44
|
+
if (ctx) {
|
|
45
|
+
ctx.renderData = null;
|
|
46
|
+
ctx.keyCounter = 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function throwSSRDataMissing() {
|
|
50
|
+
throw new SSRDataMissingError();
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { configureRenderContextProvider, getActiveRenderContext, getCurrentRenderData, getNextRenderKey, resetRenderKeyCounter, startHydrationRenderPhase, startRenderPhase, stopHydrationRenderPhase, stopRenderPhase, throwSSRDataMissing };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=render-context.js.map
|