@ogygia/core 0.0.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +7 -1
- package/ambient.d.ts +194 -0
- package/dist/ClientBindingStub.svelte +6 -0
- package/dist/ClientBindingStub.svelte.d.ts +26 -0
- package/dist/KeepHost.svelte +19 -0
- package/dist/KeepHost.svelte.d.ts +10 -0
- package/dist/LakeBoundary.svelte +16 -0
- package/dist/LakeBoundary.svelte.d.ts +11 -0
- package/dist/LateIsland.svelte +22 -0
- package/dist/LateIsland.svelte.d.ts +15 -0
- package/dist/LateIslandAwait.svelte +17 -0
- package/dist/LateIslandAwait.svelte.d.ts +15 -0
- package/dist/LiveHost.svelte +19 -0
- package/dist/LiveHost.svelte.d.ts +10 -0
- package/dist/NestedProvider.svelte +13 -0
- package/dist/NestedProvider.svelte.d.ts +8 -0
- package/dist/OgygiaBoundary.svelte +5 -0
- package/dist/OgygiaBoundary.svelte.d.ts +17 -0
- package/dist/PromiseRegion.svelte +40 -0
- package/dist/PromiseRegion.svelte.d.ts +15 -0
- package/dist/PromiseRegionAwait.svelte +27 -0
- package/dist/PromiseRegionAwait.svelte.d.ts +15 -0
- package/dist/Provide.svelte +27 -0
- package/dist/Provide.svelte.d.ts +8 -0
- package/dist/RawHtml.svelte +9 -0
- package/dist/RawHtml.svelte.d.ts +6 -0
- package/dist/Region.svelte +1173 -0
- package/dist/Region.svelte.d.ts +68 -0
- package/dist/SlotBoundary.svelte +13 -0
- package/dist/SlotBoundary.svelte.d.ts +7 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +3 -0
- package/dist/boundary.d.ts +35 -0
- package/dist/boundary.js +127 -0
- package/dist/build-cache.d.ts +13 -0
- package/dist/build-cache.js +77 -0
- package/dist/compiler/blank-styles.d.ts +1 -0
- package/dist/compiler/blank-styles.js +63 -0
- package/dist/compiler/bom.d.ts +2 -0
- package/dist/compiler/bom.js +15 -0
- package/dist/compiler/browser-full.d.ts +8 -0
- package/dist/compiler/browser-full.js +8 -0
- package/dist/compiler/browser.d.ts +11 -0
- package/dist/compiler/browser.js +11 -0
- package/dist/compiler/content/transportables.d.ts +26 -0
- package/dist/compiler/content/transportables.js +219 -0
- package/dist/compiler/ctx.d.ts +185 -0
- package/dist/compiler/ctx.js +203 -0
- package/dist/compiler/debarrel/barrel.d.ts +55 -0
- package/dist/compiler/debarrel/barrel.js +248 -0
- package/dist/compiler/debarrel/options.d.ts +67 -0
- package/dist/compiler/debarrel/options.js +31 -0
- package/dist/compiler/debarrel/parse.d.ts +65 -0
- package/dist/compiler/debarrel/parse.js +256 -0
- package/dist/compiler/debarrel/plugin.d.ts +31 -0
- package/dist/compiler/debarrel/plugin.js +190 -0
- package/dist/compiler/debarrel/rewrite.d.ts +27 -0
- package/dist/compiler/debarrel/rewrite.js +118 -0
- package/dist/compiler/debarrel/svelte.d.ts +13 -0
- package/dist/compiler/debarrel/svelte.js +56 -0
- package/dist/compiler/dev/css-scope.d.ts +16 -0
- package/dist/compiler/dev/css-scope.js +38 -0
- package/dist/compiler/dev/dev-hmr.d.ts +25 -0
- package/dist/compiler/dev/dev-hmr.js +29 -0
- package/dist/compiler/dev/hmr.d.ts +34 -0
- package/dist/compiler/dev/hmr.js +57 -0
- package/dist/compiler/dev/region-bytes.d.ts +34 -0
- package/dist/compiler/dev/region-bytes.js +126 -0
- package/dist/compiler/driver.d.ts +280 -0
- package/dist/compiler/driver.js +1352 -0
- package/dist/compiler/flags.d.ts +16 -0
- package/dist/compiler/flags.js +101 -0
- package/dist/compiler/fouc-css.d.ts +97 -0
- package/dist/compiler/fouc-css.js +335 -0
- package/dist/compiler/free-vars.d.ts +20 -0
- package/dist/compiler/free-vars.js +327 -0
- package/dist/compiler/host.d.ts +65 -0
- package/dist/compiler/host.js +51 -0
- package/dist/compiler/ids.d.ts +84 -0
- package/dist/compiler/ids.js +86 -0
- package/dist/compiler/index.d.ts +11 -0
- package/dist/compiler/index.js +11 -0
- package/dist/compiler/kit.d.ts +129 -0
- package/dist/compiler/kit.js +563 -0
- package/dist/compiler/link/build-output.d.ts +44 -0
- package/dist/compiler/link/build-output.js +147 -0
- package/dist/compiler/link/caps.d.ts +48 -0
- package/dist/compiler/link/caps.js +64 -0
- package/dist/compiler/link/context-detect.d.ts +23 -0
- package/dist/compiler/link/context-detect.js +137 -0
- package/dist/compiler/link/emit-gate.d.ts +11 -0
- package/dist/compiler/link/emit-gate.js +40 -0
- package/dist/compiler/link/entry-shim.d.ts +4 -0
- package/dist/compiler/link/entry-shim.js +29 -0
- package/dist/compiler/link/island-deps.d.ts +142 -0
- package/dist/compiler/link/island-deps.js +525 -0
- package/dist/compiler/link/manifest.d.ts +5 -0
- package/dist/compiler/link/manifest.js +9 -0
- package/dist/compiler/link/page-keys.d.ts +64 -0
- package/dist/compiler/link/page-keys.js +683 -0
- package/dist/compiler/link/registry-stub.d.ts +41 -0
- package/dist/compiler/link/registry-stub.js +212 -0
- package/dist/compiler/link/router-config.d.ts +11 -0
- package/dist/compiler/link/router-config.js +15 -0
- package/dist/compiler/link/router-css.d.ts +22 -0
- package/dist/compiler/link/router-css.js +142 -0
- package/dist/compiler/link/runtime-entry.d.ts +71 -0
- package/dist/compiler/link/runtime-entry.js +132 -0
- package/dist/compiler/link/server-manifest.d.ts +12 -0
- package/dist/compiler/link/server-manifest.js +45 -0
- package/dist/compiler/link/speculation.d.ts +17 -0
- package/dist/compiler/link/speculation.js +36 -0
- package/dist/compiler/link/transport.d.ts +31 -0
- package/dist/compiler/link/transport.js +67 -0
- package/dist/compiler/macros/bake.d.ts +20 -0
- package/dist/compiler/macros/bake.js +317 -0
- package/dist/compiler/macros/browser.d.ts +11 -0
- package/dist/compiler/macros/browser.js +69 -0
- package/dist/compiler/macros/dedent.d.ts +12 -0
- package/dist/compiler/macros/dedent.js +36 -0
- package/dist/compiler/macros/dollar.d.ts +15 -0
- package/dist/compiler/macros/dollar.js +387 -0
- package/dist/compiler/macros/pipeline.d.ts +31 -0
- package/dist/compiler/macros/pipeline.js +106 -0
- package/dist/compiler/macros/source.d.ts +6 -0
- package/dist/compiler/macros/source.js +127 -0
- package/dist/compiler/macros/store.d.ts +17 -0
- package/dist/compiler/macros/store.js +244 -0
- package/dist/compiler/macros/wire.d.ts +14 -0
- package/dist/compiler/macros/wire.js +160 -0
- package/dist/compiler/ownership-stamps.d.ts +6 -0
- package/dist/compiler/ownership-stamps.js +144 -0
- package/dist/compiler/parse/oxc.d.ts +34 -0
- package/dist/compiler/parse/oxc.js +59 -0
- package/dist/compiler/parse/scan.d.ts +43 -0
- package/dist/compiler/parse/scan.js +232 -0
- package/dist/compiler/program.d.ts +140 -0
- package/dist/compiler/program.js +242 -0
- package/dist/compiler/region/emit.d.ts +169 -0
- package/dist/compiler/region/emit.js +286 -0
- package/dist/compiler/region/identity.d.ts +28 -0
- package/dist/compiler/region/identity.js +75 -0
- package/dist/compiler/region/ir.d.ts +65 -0
- package/dist/compiler/region/ir.js +0 -0
- package/dist/compiler/region/transform.d.ts +178 -0
- package/dist/compiler/region/transform.js +1933 -0
- package/dist/compiler/script-request.d.ts +1 -0
- package/dist/compiler/script-request.js +43 -0
- package/dist/context-bridge.d.ts +65 -0
- package/dist/context-bridge.js +217 -0
- package/dist/context-registry.d.ts +40 -0
- package/dist/context-registry.js +15 -0
- package/dist/context.d.ts +72 -0
- package/dist/context.js +158 -0
- package/dist/current-region.d.ts +14 -0
- package/dist/current-region.js +36 -0
- package/dist/document.d.ts +41 -0
- package/dist/document.js +125 -0
- package/dist/entry-hydrate.d.ts +5 -0
- package/dist/entry-hydrate.js +42 -0
- package/dist/escape.d.ts +18 -0
- package/dist/escape.js +37 -0
- package/dist/events/bus.d.ts +33 -0
- package/dist/events/bus.js +153 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.js +4 -0
- package/dist/events/schema.d.ts +389 -0
- package/dist/events/schema.js +23 -0
- package/dist/events/server-registry.d.ts +7 -0
- package/dist/events/server-registry.js +13 -0
- package/dist/events/sinks.d.ts +64 -0
- package/dist/events/sinks.js +85 -0
- package/dist/fn-transport.d.ts +33 -0
- package/dist/fn-transport.js +140 -0
- package/dist/frame.d.ts +20 -0
- package/dist/frame.js +19 -0
- package/dist/holes-record.d.ts +6 -0
- package/dist/holes-record.js +8 -0
- package/dist/hooks.d.ts +43 -0
- package/dist/hooks.js +1191 -0
- package/dist/hydration-info.d.ts +1 -0
- package/dist/hydration-info.js +31 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +17 -0
- package/dist/insights/attr-rules.d.ts +15 -0
- package/dist/insights/attr-rules.js +27 -0
- package/dist/insights/cpu.d.ts +82 -0
- package/dist/insights/cpu.js +177 -0
- package/dist/insights/fp-drift.d.ts +28 -0
- package/dist/insights/fp-drift.js +148 -0
- package/dist/insights/hole-segments.d.ts +26 -0
- package/dist/insights/hole-segments.js +50 -0
- package/dist/insights/html-diff.d.ts +25 -0
- package/dist/insights/html-diff.js +157 -0
- package/dist/insights/hydration-hazards.d.ts +36 -0
- package/dist/insights/hydration-hazards.js +136 -0
- package/dist/insights/hydration-status.d.ts +2 -0
- package/dist/insights/hydration-status.js +0 -0
- package/dist/insights/index.d.ts +14 -0
- package/dist/insights/index.js +12 -0
- package/dist/insights/page-assets.d.ts +211 -0
- package/dist/insights/page-assets.js +608 -0
- package/dist/insights/page-insights.d.ts +749 -0
- package/dist/insights/page-insights.js +2157 -0
- package/dist/insights/session-data.d.ts +108 -0
- package/dist/insights/session-data.js +0 -0
- package/dist/insights/session-insights.d.ts +121 -0
- package/dist/insights/session-insights.js +548 -0
- package/dist/insights/switch.d.ts +53 -0
- package/dist/insights/switch.js +91 -0
- package/dist/insights/testing-version.d.ts +19 -0
- package/dist/insights/testing-version.js +21 -0
- package/dist/insights/third-party.d.ts +75 -0
- package/dist/insights/third-party.js +160 -0
- package/dist/internal-instruments.d.ts +13 -0
- package/dist/internal-instruments.js +12 -0
- package/dist/internal-reconcile.d.ts +3 -0
- package/dist/internal-reconcile.js +3 -0
- package/dist/internal-register.d.ts +7 -0
- package/dist/internal-register.js +7 -0
- package/dist/internal-server.d.ts +7 -0
- package/dist/internal-server.js +7 -0
- package/dist/internal.d.ts +13 -0
- package/dist/internal.js +13 -0
- package/dist/island-graph.d.ts +36 -0
- package/dist/island-graph.js +89 -0
- package/dist/keep-fallback-marker.d.ts +7 -0
- package/dist/keep-fallback-marker.js +9 -0
- package/dist/keep-fallback.d.ts +13 -0
- package/dist/keep-fallback.js +39 -0
- package/dist/kit-paths.d.ts +2 -0
- package/dist/kit-paths.js +39 -0
- package/dist/late-region-registry.d.ts +40 -0
- package/dist/late-region-registry.js +36 -0
- package/dist/live-transport.d.ts +57 -0
- package/dist/live-transport.js +145 -0
- package/dist/markup.d.ts +4 -0
- package/dist/markup.js +4 -0
- package/dist/own-package.d.ts +15 -0
- package/dist/own-package.js +20 -0
- package/dist/page-defer.d.ts +33 -0
- package/dist/page-defer.js +35 -0
- package/dist/page-facts-script.d.ts +7 -0
- package/dist/page-facts-script.js +9 -0
- package/dist/page-seed-registry.d.ts +72 -0
- package/dist/page-seed-registry.js +31 -0
- package/dist/plugin/capability.d.ts +14 -0
- package/dist/plugin/capability.js +44 -0
- package/dist/plugin/client.d.ts +39 -0
- package/dist/plugin/client.js +6 -0
- package/dist/plugin/css.d.ts +3 -0
- package/dist/plugin/css.js +54 -0
- package/dist/plugin/facts.d.ts +42 -0
- package/dist/plugin/facts.js +37 -0
- package/dist/plugin/hooks.d.ts +33 -0
- package/dist/plugin/hooks.js +38 -0
- package/dist/plugin/index.d.ts +127 -0
- package/dist/plugin/index.js +26 -0
- package/dist/plugin/routes.d.ts +32 -0
- package/dist/plugin/routes.js +35 -0
- package/dist/plugin/server.d.ts +27 -0
- package/dist/plugin/server.js +92 -0
- package/dist/plugin/standard-schema.d.ts +27 -0
- package/dist/plugin/standard-schema.js +0 -0
- package/dist/plugin/testing.d.ts +13 -0
- package/dist/plugin/testing.js +54 -0
- package/dist/plugin/utils.d.ts +13 -0
- package/dist/plugin/utils.js +19 -0
- package/dist/portable-form.d.ts +22 -0
- package/dist/portable-form.js +52 -0
- package/dist/preference.d.ts +35 -0
- package/dist/preference.js +84 -0
- package/dist/preload.d.ts +1 -0
- package/dist/preload.js +21 -0
- package/dist/ref-watch.d.ts +31 -0
- package/dist/ref-watch.js +66 -0
- package/dist/ref.d.ts +124 -0
- package/dist/ref.js +272 -0
- package/dist/region-brand.d.ts +8 -0
- package/dist/region-brand.js +10 -0
- package/dist/region-core.d.ts +2 -0
- package/dist/region-core.js +1 -0
- package/dist/region-snippet.d.ts +73 -0
- package/dist/region-snippet.js +351 -0
- package/dist/region.d.ts +127 -0
- package/dist/region.js +162 -0
- package/dist/request-event.d.ts +1 -0
- package/dist/request-event.js +37 -0
- package/dist/router-css.d.ts +39 -0
- package/dist/router-css.js +66 -0
- package/dist/runtime/app-transport.d.ts +2 -0
- package/dist/runtime/app-transport.js +13 -0
- package/dist/runtime/beacon.d.ts +271 -0
- package/dist/runtime/beacon.js +2190 -0
- package/dist/runtime/boot-link.d.ts +1 -0
- package/dist/runtime/boot-link.js +44 -0
- package/dist/runtime/client-hooks.d.ts +5 -0
- package/dist/runtime/client-hooks.js +22 -0
- package/dist/runtime/client-plugins.d.ts +8 -0
- package/dist/runtime/client-plugins.js +34 -0
- package/dist/runtime/concurrency.d.ts +12 -0
- package/dist/runtime/concurrency.js +29 -0
- package/dist/runtime/connected.d.ts +12 -0
- package/dist/runtime/connected.js +16 -0
- package/dist/runtime/context.d.ts +1 -0
- package/dist/runtime/context.js +19 -0
- package/dist/runtime/core.d.ts +15 -0
- package/dist/runtime/core.js +1173 -0
- package/dist/runtime/drift-watch.d.ts +9 -0
- package/dist/runtime/drift-watch.js +60 -0
- package/dist/runtime/entry-locations.d.ts +33 -0
- package/dist/runtime/entry-locations.js +119 -0
- package/dist/runtime/foreign-props.d.ts +8 -0
- package/dist/runtime/foreign-props.js +14 -0
- package/dist/runtime/form-continuity.d.ts +10 -0
- package/dist/runtime/form-continuity.js +107 -0
- package/dist/runtime/frame-nav.d.ts +36 -0
- package/dist/runtime/frame-nav.js +225 -0
- package/dist/runtime/frame-store.d.ts +62 -0
- package/dist/runtime/frame-store.js +214 -0
- package/dist/runtime/frames.d.ts +1 -0
- package/dist/runtime/frames.js +25 -0
- package/dist/runtime/full.d.ts +4 -0
- package/dist/runtime/full.js +32 -0
- package/dist/runtime/hash.d.ts +41 -0
- package/dist/runtime/hash.js +79 -0
- package/dist/runtime/hole-facts.d.ts +8 -0
- package/dist/runtime/hole-facts.js +57 -0
- package/dist/runtime/host-classes.d.ts +24 -0
- package/dist/runtime/host-classes.js +43 -0
- package/dist/runtime/hydrate-core.d.ts +101 -0
- package/dist/runtime/hydrate-core.js +605 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/interaction-replay.d.ts +11 -0
- package/dist/runtime/interaction-replay.js +70 -0
- package/dist/runtime/interaction.d.ts +33 -0
- package/dist/runtime/interaction.js +217 -0
- package/dist/runtime/island-graph-preload.d.ts +13 -0
- package/dist/runtime/island-graph-preload.js +99 -0
- package/dist/runtime/kit-boot.d.ts +29 -0
- package/dist/runtime/kit-boot.js +60 -0
- package/dist/runtime/kit-page-thread.svelte.d.ts +1 -0
- package/dist/runtime/kit-page-thread.svelte.js +116 -0
- package/dist/runtime/lake-anchors.d.ts +13 -0
- package/dist/runtime/lake-anchors.js +19 -0
- package/dist/runtime/lakes.d.ts +15 -0
- package/dist/runtime/lakes.js +212 -0
- package/dist/runtime/live.d.ts +3 -0
- package/dist/runtime/live.js +17 -0
- package/dist/runtime/load-scheduler.d.ts +53 -0
- package/dist/runtime/load-scheduler.js +317 -0
- package/dist/runtime/morph.d.ts +42 -0
- package/dist/runtime/morph.js +671 -0
- package/dist/runtime/nav-handle.d.ts +25 -0
- package/dist/runtime/nav-handle.js +71 -0
- package/dist/runtime/nav-hooks.d.ts +2 -0
- package/dist/runtime/nav-hooks.js +23 -0
- package/dist/runtime/nearest-attr.d.ts +4 -0
- package/dist/runtime/nearest-attr.js +16 -0
- package/dist/runtime/observe.d.ts +27 -0
- package/dist/runtime/observe.js +63 -0
- package/dist/runtime/own-cost.d.ts +9 -0
- package/dist/runtime/own-cost.js +35 -0
- package/dist/runtime/ownership.d.ts +101 -0
- package/dist/runtime/ownership.js +115 -0
- package/dist/runtime/page-cache.d.ts +23 -0
- package/dist/runtime/page-cache.js +74 -0
- package/dist/runtime/page-defer.d.ts +14 -0
- package/dist/runtime/page-defer.js +103 -0
- package/dist/runtime/parse-html.d.ts +40 -0
- package/dist/runtime/parse-html.js +81 -0
- package/dist/runtime/reconcile.d.ts +41 -0
- package/dist/runtime/reconcile.js +194 -0
- package/dist/runtime/region-attrs.d.ts +95 -0
- package/dist/runtime/region-attrs.js +153 -0
- package/dist/runtime/region-endpoint-url.d.ts +76 -0
- package/dist/runtime/region-endpoint-url.js +169 -0
- package/dist/runtime/region-ids.d.ts +8 -0
- package/dist/runtime/region-ids.js +33 -0
- package/dist/runtime/remote-seeds.d.ts +2 -0
- package/dist/runtime/remote-seeds.js +21 -0
- package/dist/runtime/render-blocking.d.ts +2 -0
- package/dist/runtime/render-blocking.js +30 -0
- package/dist/runtime/restore.d.ts +34 -0
- package/dist/runtime/restore.js +390 -0
- package/dist/runtime/router-nav.d.ts +63 -0
- package/dist/runtime/router-nav.js +740 -0
- package/dist/runtime/router.d.ts +201 -0
- package/dist/runtime/router.js +593 -0
- package/dist/runtime/schedule.d.ts +49 -0
- package/dist/runtime/schedule.js +256 -0
- package/dist/runtime/seeds.d.ts +50 -0
- package/dist/runtime/seeds.js +208 -0
- package/dist/runtime/session.d.ts +52 -0
- package/dist/runtime/session.js +130 -0
- package/dist/runtime/sidecar.d.ts +3 -0
- package/dist/runtime/sidecar.js +56 -0
- package/dist/runtime/slots.d.ts +183 -0
- package/dist/runtime/slots.js +44 -0
- package/dist/runtime/spa-cacheable.d.ts +7 -0
- package/dist/runtime/spa-cacheable.js +18 -0
- package/dist/runtime/speculate-hint.d.ts +1 -0
- package/dist/runtime/speculate-hint.js +35 -0
- package/dist/runtime/svelte-warnings.d.ts +28 -0
- package/dist/runtime/svelte-warnings.js +71 -0
- package/dist/runtime/wire-classes.d.ts +3 -0
- package/dist/runtime/wire-classes.js +69 -0
- package/dist/runtime/wire-format.d.ts +7 -0
- package/dist/runtime/wire-format.js +22 -0
- package/dist/script.d.ts +134 -0
- package/dist/script.js +184 -0
- package/dist/seed-refs.d.ts +105 -0
- package/dist/seed-refs.js +487 -0
- package/dist/server/capability-lifetime.d.ts +28 -0
- package/dist/server/capability-lifetime.js +31 -0
- package/dist/server/dead-kit-resolves.d.ts +1 -0
- package/dist/server/dead-kit-resolves.js +39 -0
- package/dist/server/document-assembly.d.ts +30 -0
- package/dist/server/document-assembly.js +26 -0
- package/dist/server/document-tail.d.ts +113 -0
- package/dist/server/document-tail.js +208 -0
- package/dist/server/endpoint.d.ts +51 -0
- package/dist/server/endpoint.js +90 -0
- package/dist/server/entry-location.d.ts +8 -0
- package/dist/server/entry-location.js +29 -0
- package/dist/server/fingerprint.d.ts +1 -0
- package/dist/server/fingerprint.js +25 -0
- package/dist/server/head-presence.d.ts +45 -0
- package/dist/server/head-presence.js +156 -0
- package/dist/server/hmac.d.ts +38 -0
- package/dist/server/hmac.js +89 -0
- package/dist/server/hole-graph.d.ts +7 -0
- package/dist/server/hole-graph.js +71 -0
- package/dist/server/hole-urls.d.ts +3 -0
- package/dist/server/hole-urls.js +76 -0
- package/dist/server/html-scan.d.ts +19 -0
- package/dist/server/html-scan.js +60 -0
- package/dist/server/kit-context.d.ts +78 -0
- package/dist/server/kit-context.js +110 -0
- package/dist/server/late-wire.d.ts +22 -0
- package/dist/server/late-wire.js +28 -0
- package/dist/server/page-facts.d.ts +25 -0
- package/dist/server/page-facts.js +138 -0
- package/dist/server/page-seed.d.ts +33 -0
- package/dist/server/page-seed.js +60 -0
- package/dist/server/page-stream.d.ts +55 -0
- package/dist/server/page-stream.js +121 -0
- package/dist/server/payload.d.ts +6 -0
- package/dist/server/payload.js +22 -0
- package/dist/server/personal-response.d.ts +6 -0
- package/dist/server/personal-response.js +13 -0
- package/dist/server/props-wire.d.ts +56 -0
- package/dist/server/props-wire.js +178 -0
- package/dist/server/rate-limit.d.ts +22 -0
- package/dist/server/rate-limit.js +63 -0
- package/dist/server/region-css.d.ts +5 -0
- package/dist/server/region-css.js +30 -0
- package/dist/server/region-endpoint.d.ts +35 -0
- package/dist/server/region-endpoint.js +142 -0
- package/dist/server/region-props.d.ts +6 -0
- package/dist/server/region-props.js +44 -0
- package/dist/server/remote-seed-gate.d.ts +50 -0
- package/dist/server/remote-seed-gate.js +66 -0
- package/dist/server/render-cache.d.ts +26 -0
- package/dist/server/render-cache.js +51 -0
- package/dist/server/render-page.d.ts +51 -0
- package/dist/server/render-page.js +176 -0
- package/dist/server/render-region-html.d.ts +2 -0
- package/dist/server/render-region-html.js +19 -0
- package/dist/server/request-stats.d.ts +174 -0
- package/dist/server/request-stats.js +54 -0
- package/dist/server/reversible.d.ts +83 -0
- package/dist/server/reversible.js +994 -0
- package/dist/server/seed-shape.d.ts +22 -0
- package/dist/server/seed-shape.js +24 -0
- package/dist/server/shared-cache.d.ts +35 -0
- package/dist/server/shared-cache.js +104 -0
- package/dist/server/signing-key.d.ts +11 -0
- package/dist/server/signing-key.js +47 -0
- package/dist/server/sized-lru.d.ts +20 -0
- package/dist/server/sized-lru.js +68 -0
- package/dist/server/split-regions.d.ts +81 -0
- package/dist/server/split-regions.js +368 -0
- package/dist/server/stream-regions.d.ts +5 -0
- package/dist/server/stream-regions.js +36 -0
- package/dist/shared-state.d.ts +7 -0
- package/dist/shared-state.js +152 -0
- package/dist/shims/app-environment.d.ts +4 -0
- package/dist/shims/app-environment.js +6 -0
- package/dist/shims/app-navigation.d.ts +33 -0
- package/dist/shims/app-navigation.js +119 -0
- package/dist/shims/app-paths.d.ts +6 -0
- package/dist/shims/app-paths.js +18 -0
- package/dist/shims/app-state.svelte.d.ts +23 -0
- package/dist/shims/app-state.svelte.js +50 -0
- package/dist/shims/app-stores.d.ts +21 -0
- package/dist/shims/app-stores.js +54 -0
- package/dist/shims/kit-bridge.d.ts +29 -0
- package/dist/shims/kit-bridge.js +7 -0
- package/dist/shims/kit-remote/client-stub.d.ts +27 -0
- package/dist/shims/kit-remote/client-stub.js +43 -0
- package/dist/shims/kit-remote/paths-internal-stub.d.ts +3 -0
- package/dist/shims/kit-remote/paths-internal-stub.js +5 -0
- package/dist/shims/kit-remote/remote-cache.d.ts +49 -0
- package/dist/shims/kit-remote/remote-cache.js +73 -0
- package/dist/shims/kit-remote/state-stub.d.ts +8 -0
- package/dist/shims/kit-remote/state-stub.js +8 -0
- package/dist/shims/page-store.svelte.d.ts +39 -0
- package/dist/shims/page-store.svelte.js +77 -0
- package/dist/source.d.ts +29 -0
- package/dist/source.js +87 -0
- package/dist/store-transport.d.ts +86 -0
- package/dist/store-transport.js +229 -0
- package/dist/tool-fetches.d.ts +5 -0
- package/dist/tool-fetches.js +41 -0
- package/dist/transport.d.ts +48 -0
- package/dist/transport.js +181 -0
- package/dist/unscoped-css.d.ts +26 -0
- package/dist/unscoped-css.js +53 -0
- package/dist/vite/dev-maps.d.ts +33 -0
- package/dist/vite/dev-maps.js +140 -0
- package/dist/vite/index.d.ts +19 -0
- package/dist/vite/index.js +820 -0
- package/dist/vite/kit-dirs.d.ts +7 -0
- package/dist/vite/kit-dirs.js +67 -0
- package/dist/vite/late-island.d.ts +25 -0
- package/dist/vite/late-island.js +33 -0
- package/dist/vite/module-map.d.ts +8 -0
- package/dist/vite/module-map.js +144 -0
- package/dist/vite/options.d.ts +208 -0
- package/dist/vite/options.js +74 -0
- package/dist/vite/package-files.d.ts +3 -0
- package/dist/vite/package-files.js +84 -0
- package/dist/vite/paths.d.ts +45 -0
- package/dist/vite/paths.js +112 -0
- package/dist/vite/plugin-api.d.ts +166 -0
- package/dist/vite/plugin-api.js +212 -0
- package/dist/vite/profiler-maps.d.ts +23 -0
- package/dist/vite/profiler-maps.js +178 -0
- package/dist/vite/server-sourcemaps.d.ts +8 -0
- package/dist/vite/server-sourcemaps.js +80 -0
- package/dist/vite/sourcemaps.d.ts +18 -0
- package/dist/vite/sourcemaps.js +80 -0
- package/dist/vite/style-preprocess.d.ts +2 -0
- package/dist/vite/style-preprocess.js +96 -0
- package/package.json +180 -6
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
import { analyze_cpu, fn_label, is_trace } from "./cpu.js";
|
|
2
|
+
// src/insights/session-insights.ts
|
|
3
|
+
/**
|
|
4
|
+
* What a recorded session (devtools/session.ts) says — pure, so it tests on plain data. Findings point back
|
|
5
|
+
* at the page: an interaction's target, a shift's element, an island (the tab resolves the refs).
|
|
6
|
+
* The CPU trace, when there is one, names the function behind a slow interaction or a long task
|
|
7
|
+
* (cpu.ts, with each interaction as its own window); long animation frames name the script when
|
|
8
|
+
* the sampler could not run.
|
|
9
|
+
*/
|
|
10
|
+
/** The session on one clock, lane by lane (the Record tab draws it). Capped per lane. */
|
|
11
|
+
function session_timeline(s, names) {
|
|
12
|
+
const z = s.from;
|
|
13
|
+
const cap = (xs) => xs.slice(0, 300);
|
|
14
|
+
const input = [];
|
|
15
|
+
s.clicks.forEach((c, i) => input.push({
|
|
16
|
+
t0: c.t - z,
|
|
17
|
+
t1: c.t - z,
|
|
18
|
+
label: `click ${c.target}`,
|
|
19
|
+
tone: "info",
|
|
20
|
+
ref: {
|
|
21
|
+
kind: "click",
|
|
22
|
+
i
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26
|
+
s.interactions.forEach((x, i) => {
|
|
27
|
+
if (!x.id || seen.has(x.id)) return;
|
|
28
|
+
seen.add(x.id);
|
|
29
|
+
input.push({
|
|
30
|
+
t0: x.t - z,
|
|
31
|
+
t1: x.t - z + x.duration,
|
|
32
|
+
label: `${x.name} ${x.target} — ${Math.round(x.duration)} ms (handlers ${Math.round(x.processing)} ms)`,
|
|
33
|
+
tone: x.duration >= SLOW ? "bad" : x.duration >= SLUGGISH ? "warn" : "ok",
|
|
34
|
+
ref: {
|
|
35
|
+
kind: "interaction",
|
|
36
|
+
i
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
const main = s.longtasks.map((t) => ({
|
|
41
|
+
t0: t.t - z,
|
|
42
|
+
t1: t.t - z + t.ms,
|
|
43
|
+
label: `long task ${Math.round(t.ms)} ms`,
|
|
44
|
+
tone: t.ms >= 200 ? "bad" : "warn"
|
|
45
|
+
}));
|
|
46
|
+
const net = s.requests.map((r) => {
|
|
47
|
+
const ssr = r.server?.find((x) => x.name === "ssr")?.ms;
|
|
48
|
+
const up = r.server?.find((x) => x.name === "net")?.ms ?? 0;
|
|
49
|
+
let path = r.url;
|
|
50
|
+
try {
|
|
51
|
+
path = new URL(r.url).pathname;
|
|
52
|
+
} catch {}
|
|
53
|
+
return {
|
|
54
|
+
t0: r.t - z,
|
|
55
|
+
t1: r.t - z + r.ms,
|
|
56
|
+
label: `${path} — ${Math.round(r.ms)} ms${ssr !== void 0 ? ` (server ${Math.round(ssr)} ms${up ? `, waiting ${Math.round(up)} ms` : ""})` : ""}${r.status && r.status >= 400 ? ` · ${r.status}` : ""}`,
|
|
57
|
+
tone: r.status !== null && r.status >= 400 ? "bad" : r.ms >= 1e3 ? "warn" : "info",
|
|
58
|
+
...ssr !== void 0 ? { server: {
|
|
59
|
+
ms: ssr,
|
|
60
|
+
up
|
|
61
|
+
} } : {}
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
const islands = [];
|
|
65
|
+
for (const p of (s.pages ?? []).slice(1)) islands.push({
|
|
66
|
+
t0: p.t - z,
|
|
67
|
+
t1: p.t - z,
|
|
68
|
+
label: `page load: ${p.url}`,
|
|
69
|
+
tone: "info"
|
|
70
|
+
});
|
|
71
|
+
const hyd = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const e of s.events) if (e.name === "region.hydrate.done" && e.fp) hyd.set(e.fp, e.t);
|
|
73
|
+
for (const e of s.events) {
|
|
74
|
+
const fp = e.fp;
|
|
75
|
+
if (e.name === "wake.fired" && fp) islands.push({
|
|
76
|
+
t0: e.t - z,
|
|
77
|
+
t1: (hyd.get(fp) ?? e.t) - z,
|
|
78
|
+
label: `${names(fp)} woke (${e.when ?? ""})`,
|
|
79
|
+
tone: "ok",
|
|
80
|
+
ref: {
|
|
81
|
+
kind: "island",
|
|
82
|
+
fp
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
else if (e.name === "region.hydrate.failed" && fp) islands.push({
|
|
86
|
+
t0: e.t - z,
|
|
87
|
+
t1: e.t - z,
|
|
88
|
+
label: `${names(fp)} failed to hydrate`,
|
|
89
|
+
tone: "bad",
|
|
90
|
+
ref: {
|
|
91
|
+
kind: "island",
|
|
92
|
+
fp
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
else if (e.name === "nav.finish") islands.push({
|
|
96
|
+
t0: e.t - e.ms - z,
|
|
97
|
+
t1: e.t - z,
|
|
98
|
+
label: `navigation to ${e.to} — ${Math.round(e.ms)} ms`,
|
|
99
|
+
tone: e.ms >= 500 ? "warn" : "info"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const layout = s.shifts.map((x, i) => ({
|
|
103
|
+
t0: x.t - z,
|
|
104
|
+
t1: x.t - z,
|
|
105
|
+
label: `layout shift ${x.value}${x.input ? " (after input)" : ""}${x.fp ? ` in ${names(x.fp)}` : ""}`,
|
|
106
|
+
tone: x.input ? "info" : x.value >= .05 ? "bad" : "warn",
|
|
107
|
+
ref: {
|
|
108
|
+
kind: "shift",
|
|
109
|
+
i
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
const errors = s.errors.map((e) => ({
|
|
113
|
+
t0: e.t - z,
|
|
114
|
+
t1: e.t - z,
|
|
115
|
+
label: e.message,
|
|
116
|
+
tone: "bad"
|
|
117
|
+
}));
|
|
118
|
+
return [
|
|
119
|
+
{
|
|
120
|
+
key: "input",
|
|
121
|
+
label: "input",
|
|
122
|
+
items: cap(input)
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
key: "main",
|
|
126
|
+
label: "main thread",
|
|
127
|
+
items: cap(main)
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
key: "net",
|
|
131
|
+
label: "requests",
|
|
132
|
+
items: cap(net)
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "islands",
|
|
136
|
+
label: "islands · nav",
|
|
137
|
+
items: cap(islands)
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
key: "layout",
|
|
141
|
+
label: "layout",
|
|
142
|
+
items: cap(layout)
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
key: "errors",
|
|
146
|
+
label: "errors",
|
|
147
|
+
items: cap(errors)
|
|
148
|
+
}
|
|
149
|
+
].filter((l) => l.items.length);
|
|
150
|
+
}
|
|
151
|
+
const ms = (n) => n >= 1e3 ? (n / 1e3).toFixed(2) + " s" : Math.round(n) + " ms";
|
|
152
|
+
const kb = (n) => n < 1024 ? n + " B" : n < 1048576 ? (n / 1024).toFixed(1) + " KB" : (n / 1048576).toFixed(1) + " MB";
|
|
153
|
+
const path_of = (u) => {
|
|
154
|
+
try {
|
|
155
|
+
const x = new URL(u);
|
|
156
|
+
return x.pathname + (x.search.length > 1 ? x.search.slice(0, 40) : "");
|
|
157
|
+
} catch {
|
|
158
|
+
return u;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
/** a GET on this page's own origin (the profiler can render only those) */
|
|
162
|
+
function same_origin_get(url, page_url) {
|
|
163
|
+
try {
|
|
164
|
+
return new URL(url).origin === new URL(page_url).origin && !url.includes("/__profiler");
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/** Slow from here (Event Timing duration, ms): Google's INP lines. */
|
|
170
|
+
const SLOW = 200;
|
|
171
|
+
const SLUGGISH = 100;
|
|
172
|
+
function analyze_session(s, names, page_url) {
|
|
173
|
+
const findings = [];
|
|
174
|
+
const name_of = (fp) => fp ? names(fp) : "the page";
|
|
175
|
+
const by_id = /* @__PURE__ */ new Map();
|
|
176
|
+
const longest = /* @__PURE__ */ new Map();
|
|
177
|
+
s.interactions.forEach((x, i) => {
|
|
178
|
+
if (!x.id) return;
|
|
179
|
+
longest.set(x.id, Math.max(longest.get(x.id) ?? 0, x.duration));
|
|
180
|
+
const prev = by_id.get(x.id);
|
|
181
|
+
const p = prev === void 0 ? null : s.interactions[prev];
|
|
182
|
+
if (!p || x.processing > p.processing || x.processing === p.processing && x.duration > p.duration) by_id.set(x.id, i);
|
|
183
|
+
});
|
|
184
|
+
for (const [id, i] of by_id) s.interactions[i] = {
|
|
185
|
+
...s.interactions[i],
|
|
186
|
+
duration: longest.get(id) ?? s.interactions[i].duration
|
|
187
|
+
};
|
|
188
|
+
const chosen = [...by_id.values()];
|
|
189
|
+
let cpu = null;
|
|
190
|
+
if (is_trace(s.cpu)) {
|
|
191
|
+
const windows = chosen.map((i) => ({
|
|
192
|
+
fp: "ix:" + i,
|
|
193
|
+
from: s.interactions[i].t,
|
|
194
|
+
to: s.interactions[i].t + s.interactions[i].duration
|
|
195
|
+
}));
|
|
196
|
+
cpu = analyze_cpu(s.cpu, windows, s.longtasks, page_url);
|
|
197
|
+
}
|
|
198
|
+
const why = (i) => {
|
|
199
|
+
const f = cpu?.islands["ix:" + i]?.top[0];
|
|
200
|
+
if (f && f.self_ms >= 5) return `; mostly ${fn_label(f)}`;
|
|
201
|
+
const x = s.interactions[i];
|
|
202
|
+
const sc = s.frames.find((fr) => fr.t <= x.t + x.duration && fr.t + fr.ms >= x.t && fr.scripts.length)?.scripts.slice().sort((a, b) => b.ms - a.ms)[0];
|
|
203
|
+
return sc && sc.ms >= 5 ? `; mostly ${sc.invoker || sc.fn || "a script"}${sc.source ? ` (${path_of(sc.source).split("/").pop()})` : ""}` : "";
|
|
204
|
+
};
|
|
205
|
+
const slow = chosen.filter((i) => s.interactions[i].duration >= SLUGGISH).sort((a, b) => s.interactions[b].duration - s.interactions[a].duration);
|
|
206
|
+
for (const i of slow.slice(0, 5)) {
|
|
207
|
+
const x = s.interactions[i];
|
|
208
|
+
const part = x.processing >= x.input_delay && x.processing >= x.presentation ? "processing" : x.input_delay >= x.presentation ? "input" : "paint";
|
|
209
|
+
findings.push({
|
|
210
|
+
code: "slow-interaction",
|
|
211
|
+
severity: x.duration >= SLOW ? "warn" : "info",
|
|
212
|
+
message: `${x.name} on ${x.target}${x.fp ? ` in ${name_of(x.fp)}` : ""} took ${ms(x.duration)} to show a result (waiting ${ms(x.input_delay)} · handlers ${ms(x.processing)} · painting ${ms(x.presentation)})${why(i)}.`,
|
|
213
|
+
fix: part === "processing" ? "The handlers are the cost: do less before the next paint (update the screen first, then do the rest in a later task), or move the work off the main thread." : part === "input" ? "The click waited for other work to finish: something else held the main thread when it came (see the long tasks)." : "Rendering the result is the cost: a big DOM change or an expensive style/layout after it. Change less at once.",
|
|
214
|
+
refs: [{
|
|
215
|
+
kind: "interaction",
|
|
216
|
+
i
|
|
217
|
+
}]
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const rage = [];
|
|
221
|
+
for (let a = 0; a < s.clicks.length; a++) {
|
|
222
|
+
let n = 1;
|
|
223
|
+
for (let b = a + 1; b < s.clicks.length && s.clicks[b].t - s.clicks[a].t < 1e3; b++) if (s.clicks[b].target === s.clicks[a].target) n++;
|
|
224
|
+
if (n >= 3 && !rage.some((r) => s.clicks[r].target === s.clicks[a].target)) rage.push(a);
|
|
225
|
+
}
|
|
226
|
+
for (const i of rage) findings.push({
|
|
227
|
+
code: "rage-click",
|
|
228
|
+
severity: "warn",
|
|
229
|
+
message: `${s.clicks[i].target}${s.clicks[i].fp ? ` in ${name_of(s.clicks[i].fp)}` : ""} was clicked 3+ times within a second: to a visitor it looked like nothing happened.`,
|
|
230
|
+
fix: "Show a reaction at once (a pressed state, a spinner), and make sure the click is handled.",
|
|
231
|
+
refs: [{
|
|
232
|
+
kind: "click",
|
|
233
|
+
i
|
|
234
|
+
}]
|
|
235
|
+
});
|
|
236
|
+
const navs = s.events.filter((e) => e.name === "nav.start").map((e) => e.t);
|
|
237
|
+
const raged = new Set(rage.map((r) => s.clicks[r].target));
|
|
238
|
+
const dead = [];
|
|
239
|
+
const late = [];
|
|
240
|
+
s.clicks.forEach((c, i) => {
|
|
241
|
+
if (raged.has(c.target)) return;
|
|
242
|
+
if (!c.clickable) return;
|
|
243
|
+
if (c.fp) {
|
|
244
|
+
const first = s.mut_log.find((m) => m.t >= c.t && m.t <= c.t + 3e3 && m.fp === c.fp);
|
|
245
|
+
if (!first && !navs.some((t) => t >= c.t && t <= c.t + 3e3)) dead.push(i);
|
|
246
|
+
else if (first && first.t - c.t > 500) late.push({
|
|
247
|
+
i,
|
|
248
|
+
after: first.t - c.t
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const until = c.t + 500;
|
|
253
|
+
const others = new Set(s.clicks.filter((o, j) => j !== i && o.t >= c.t && o.t <= until && o.fp).map((o) => o.fp));
|
|
254
|
+
const changed = s.mut_log.some((m) => m.t >= c.t && m.t <= until && !others.has(m.fp));
|
|
255
|
+
const asked = s.requests.some((r) => r.t >= c.t && r.t <= until) && !others.size;
|
|
256
|
+
if (!changed && !asked && !navs.some((t) => t >= c.t && t <= until)) dead.push(i);
|
|
257
|
+
});
|
|
258
|
+
if (late.length) findings.push({
|
|
259
|
+
code: "late-feedback",
|
|
260
|
+
severity: "info",
|
|
261
|
+
message: `${late.length} click${late.length === 1 ? "" : "s"} got no visible answer for a while: ${late.slice(0, 3).map(({ i, after }) => `${s.clicks[i].target}${s.clicks[i].fp ? ` in ${name_of(s.clicks[i].fp)}` : ""} (${ms(after)})`).join(", ")}.`,
|
|
262
|
+
fix: "Show a reaction at once — a pressed or loading state — and then the result.",
|
|
263
|
+
refs: late.slice(0, 6).map(({ i }) => ({
|
|
264
|
+
kind: "click",
|
|
265
|
+
i
|
|
266
|
+
}))
|
|
267
|
+
});
|
|
268
|
+
if (dead.length) findings.push({
|
|
269
|
+
code: "dead-click",
|
|
270
|
+
severity: "info",
|
|
271
|
+
message: `${dead.length} click${dead.length === 1 ? "" : "s"} changed nothing on the page (no DOM change, no request, no navigation): ${[...new Set(dead.map((i) => s.clicks[i].target))].slice(0, 3).join(", ")}.`,
|
|
272
|
+
fix: "If it should do something, its handler is missing (an island that never woke, plain HTML with no JS) or it failed silently.",
|
|
273
|
+
refs: dead.slice(0, 6).map((i) => ({
|
|
274
|
+
kind: "click",
|
|
275
|
+
i
|
|
276
|
+
}))
|
|
277
|
+
});
|
|
278
|
+
const lt_ms = s.longtasks.reduce((a, t) => a + t.ms, 0);
|
|
279
|
+
if (s.longtasks.length) {
|
|
280
|
+
const f = cpu?.outside.top[0];
|
|
281
|
+
findings.push({
|
|
282
|
+
code: "long-tasks",
|
|
283
|
+
severity: lt_ms >= 300 ? "warn" : "info",
|
|
284
|
+
message: `${s.longtasks.length} long task${s.longtasks.length === 1 ? "" : "s"} held the main thread for ${ms(lt_ms)} in all (the longest ${ms(Math.max(...s.longtasks.map((t) => t.ms)))})${f && f.self_ms >= 5 ? `; outside the interactions, mostly ${fn_label(f)}` : ""}.`,
|
|
285
|
+
refs: []
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
const unexpected = s.shifts.map((x, i) => ({
|
|
289
|
+
x,
|
|
290
|
+
i
|
|
291
|
+
})).filter(({ x }) => !x.input);
|
|
292
|
+
const cls = unexpected.reduce((a, { x }) => a + x.value, 0);
|
|
293
|
+
if (cls >= .02) findings.push({
|
|
294
|
+
code: "unexpected-shift",
|
|
295
|
+
severity: cls >= .1 ? "warn" : "info",
|
|
296
|
+
message: `The layout moved by itself (no input) ${unexpected.length} time${unexpected.length === 1 ? "" : "s"}, CLS ${Math.round(cls * 1e3) / 1e3}${unexpected[0]?.x.fp ? `, first in ${name_of(unexpected[0].x.fp)}` : ""}.`,
|
|
297
|
+
fix: "Reserve space for what arrives late (images, holes, islands that grow as they wake).",
|
|
298
|
+
refs: unexpected.slice(0, 6).map(({ i }) => ({
|
|
299
|
+
kind: "shift",
|
|
300
|
+
i
|
|
301
|
+
}))
|
|
302
|
+
});
|
|
303
|
+
const bytes = s.requests.reduce((a, r) => a + r.bytes, 0);
|
|
304
|
+
const failed = s.requests.filter((r) => r.status !== null && r.status >= 400);
|
|
305
|
+
if (failed.length) findings.push({
|
|
306
|
+
code: "failed-requests",
|
|
307
|
+
severity: "warn",
|
|
308
|
+
message: `${failed.length} request${failed.length === 1 ? "" : "s"} failed: ${failed.slice(0, 3).map((r) => `${r.status} ${path_of(r.url)}`).join(", ")}.`,
|
|
309
|
+
refs: []
|
|
310
|
+
});
|
|
311
|
+
const slow_req = s.requests.filter((r) => r.ms >= 1e3).sort((a, b) => b.ms - a.ms);
|
|
312
|
+
if (slow_req.length) findings.push({
|
|
313
|
+
code: "slow-requests",
|
|
314
|
+
severity: "info",
|
|
315
|
+
message: `${slow_req.length} request${slow_req.length === 1 ? "" : "s"} took over a second: ${slow_req.slice(0, 3).map((r) => `${path_of(r.url)} ${ms(r.ms)}`).join(", ")}.`,
|
|
316
|
+
refs: []
|
|
317
|
+
});
|
|
318
|
+
const by_url = /* @__PURE__ */ new Map();
|
|
319
|
+
for (const r of s.requests) if (r.type === "fetch" || r.type === "xmlhttprequest") by_url.set(path_of(r.url), (by_url.get(path_of(r.url)) ?? 0) + 1);
|
|
320
|
+
const repeated = [...by_url].filter(([, n]) => n >= 3).sort((a, b) => b[1] - a[1]);
|
|
321
|
+
if (repeated.length) findings.push({
|
|
322
|
+
code: "repeated-requests",
|
|
323
|
+
severity: "info",
|
|
324
|
+
message: `The same request went out again and again: ${repeated.slice(0, 3).map(([u, n]) => `${u} ×${n}`).join(", ")}.`,
|
|
325
|
+
fix: "Cache the answer, or share one request between the parts that ask.",
|
|
326
|
+
refs: []
|
|
327
|
+
});
|
|
328
|
+
const st = (r, name) => r.server?.find((x) => x.name === name);
|
|
329
|
+
const served = s.requests.filter((r) => st(r, "ssr")).sort((a, b) => (st(b, "ssr")?.ms ?? 0) - (st(a, "ssr")?.ms ?? 0));
|
|
330
|
+
for (const r of served.slice(0, 3)) {
|
|
331
|
+
const ssr = st(r, "ssr").ms;
|
|
332
|
+
if (ssr < 200) break;
|
|
333
|
+
const cpu_ms = st(r, "cpu")?.ms;
|
|
334
|
+
const net = st(r, "net");
|
|
335
|
+
const up = st(r, "up1");
|
|
336
|
+
findings.push({
|
|
337
|
+
code: "server-time",
|
|
338
|
+
severity: ssr >= 500 ? "warn" : "info",
|
|
339
|
+
message: `${path_of(r.url)} took ${ms(r.ms)}: ${ms(ssr)} on the server` + (cpu_ms !== void 0 ? ` (${ms(cpu_ms)} of CPU)` : "") + (net ? `, ${ms(net.ms)} of it waiting on ${net.desc.split("(")[1]?.split(")")[0] ?? "several"} outbound call${net.desc.includes("(1)") ? "" : "s"}${up ? ` — the slowest ${up.desc} ${ms(up.ms)}` : ""}` : "") + `, ${ms(Math.max(0, r.ms - ssr))} on the network.`,
|
|
340
|
+
fix: net && net.ms >= ssr * .5 ? "The server mostly waited: start the calls together, cache the answer, or move the call out of this request." : "Profile it on the server (the button) to see where its time went.",
|
|
341
|
+
refs: (() => {
|
|
342
|
+
const c = s.clicks.filter((x) => x.t <= r.t && r.t - x.t <= 3e3).at(-1);
|
|
343
|
+
return c ? [{
|
|
344
|
+
kind: "click",
|
|
345
|
+
i: s.clicks.indexOf(c)
|
|
346
|
+
}] : [];
|
|
347
|
+
})(),
|
|
348
|
+
...same_origin_get(r.url, page_url) ? { url: r.url } : {}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
const by_island = {};
|
|
352
|
+
const slot = (fp) => by_island[fp] ??= {
|
|
353
|
+
clicks: 0,
|
|
354
|
+
slow: [],
|
|
355
|
+
requests: [],
|
|
356
|
+
mutations: 0
|
|
357
|
+
};
|
|
358
|
+
for (const c of s.clicks) if (c.fp) slot(c.fp).clicks++;
|
|
359
|
+
for (const i of chosen) {
|
|
360
|
+
const x = s.interactions[i];
|
|
361
|
+
if (x.fp && x.duration >= SLUGGISH) slot(x.fp).slow.push({
|
|
362
|
+
target: x.target,
|
|
363
|
+
duration: x.duration,
|
|
364
|
+
processing: x.processing
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
for (const r of s.requests) {
|
|
368
|
+
const c = s.clicks.filter((x) => x.t <= r.t && r.t - x.t <= 3e3).at(-1);
|
|
369
|
+
if (!c?.fp) continue;
|
|
370
|
+
slot(c.fp).requests.push({
|
|
371
|
+
url: path_of(r.url),
|
|
372
|
+
ms: r.ms,
|
|
373
|
+
server_ms: st(r, "ssr")?.ms ?? null,
|
|
374
|
+
net_ms: st(r, "net")?.ms ?? null,
|
|
375
|
+
up: st(r, "up1") ? `${st(r, "up1").desc} ${ms(st(r, "up1").ms)}` : null,
|
|
376
|
+
status: r.status
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
for (const m of s.mutations) if (m.fp && by_island[m.fp]) by_island[m.fp].mutations = m.count;
|
|
380
|
+
const woke = s.events.filter((e) => e.name === "wake.fired");
|
|
381
|
+
if (woke.length) {
|
|
382
|
+
const done = /* @__PURE__ */ new Map();
|
|
383
|
+
for (const e of s.events) if (e.name === "region.hydrate.done" && e.fp) done.set(e.fp, e.ms);
|
|
384
|
+
const list = woke.map((e) => e.fp ? `${name_of(e.fp)}${done.has(e.fp) ? ` (${ms(done.get(e.fp))})` : ""}` : "an island");
|
|
385
|
+
findings.push({
|
|
386
|
+
code: "islands-woke",
|
|
387
|
+
severity: "info",
|
|
388
|
+
message: `${woke.length} island${woke.length === 1 ? "" : "s"} woke during the session: ${[...new Set(list)].slice(0, 5).join(", ")}.`,
|
|
389
|
+
refs: woke.filter((e) => e.fp).slice(0, 6).map((e) => ({
|
|
390
|
+
kind: "island",
|
|
391
|
+
fp: e.fp
|
|
392
|
+
}))
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
for (const e of s.events) if (e.name === "region.hydrate.failed") findings.push({
|
|
396
|
+
code: "hydrate-failed",
|
|
397
|
+
severity: "error",
|
|
398
|
+
message: `${name_of(e.fp ?? null)} failed to hydrate: ${e.message.split("\n")[0].slice(0, 160)}.`,
|
|
399
|
+
refs: e.fp ? [{
|
|
400
|
+
kind: "island",
|
|
401
|
+
fp: e.fp
|
|
402
|
+
}] : []
|
|
403
|
+
});
|
|
404
|
+
else if (e.name === "region.hydrate.recovered") findings.push({
|
|
405
|
+
code: "hydrate-recovered",
|
|
406
|
+
severity: "error",
|
|
407
|
+
message: `${name_of(e.fp ?? null)} threw away its server HTML and rendered again${e.reason ? `: ${e.reason}` : ""}.`,
|
|
408
|
+
refs: e.fp ? [{
|
|
409
|
+
kind: "island",
|
|
410
|
+
fp: e.fp
|
|
411
|
+
}] : []
|
|
412
|
+
});
|
|
413
|
+
else if (e.name === "region.hydrate.healed") findings.push({
|
|
414
|
+
code: "hydrate-healed",
|
|
415
|
+
severity: "warn",
|
|
416
|
+
message: `${name_of(e.fp ?? null)}'s markup was changed by another script before it woke; the runtime put the server markup back${e.reason ? ` (${e.reason})` : ""}.`,
|
|
417
|
+
refs: e.fp ? [{
|
|
418
|
+
kind: "island",
|
|
419
|
+
fp: e.fp
|
|
420
|
+
}] : []
|
|
421
|
+
});
|
|
422
|
+
else if (e.name === "region.hydrate.conflict") findings.push({
|
|
423
|
+
code: "hydrate-conflict",
|
|
424
|
+
severity: "warn",
|
|
425
|
+
message: `${name_of(e.fp ?? null)}: ${e.reason ?? "a web component and Svelte wanted the same nodes"}`,
|
|
426
|
+
refs: e.fp ? [{
|
|
427
|
+
kind: "island",
|
|
428
|
+
fp: e.fp
|
|
429
|
+
}] : []
|
|
430
|
+
});
|
|
431
|
+
else if (e.name === "load.critical" && e.outcome === "cap") findings.push({
|
|
432
|
+
code: "critical-cap",
|
|
433
|
+
severity: "warn",
|
|
434
|
+
message: `The page's critical resource${e.resources === 1 ? "" : "s"} (marked fetchpriority="high") took longer than ${e.waited_ms} ms; ogygia stopped holding its downloads back and let them start.`,
|
|
435
|
+
refs: []
|
|
436
|
+
});
|
|
437
|
+
const held = s.events.filter((e) => e.name === "load.started" && e.class !== "user" && e.waited_ms > 0);
|
|
438
|
+
if (held.length) {
|
|
439
|
+
const most = Math.max(...held.map((e) => e.name === "load.started" ? e.waited_ms : 0));
|
|
440
|
+
findings.push({
|
|
441
|
+
code: "loads-held",
|
|
442
|
+
severity: "info",
|
|
443
|
+
message: `ogygia held ${held.length} download${held.length === 1 ? "" : "s"} back (up to ${most} ms) so the page's critical resources and the visible islands went first.`,
|
|
444
|
+
refs: []
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
const errors = s.events.some((e) => e.name === "region.hydrate.failed") ? s.errors.filter((e) => !e.message.startsWith("console.error: [ogygia] hydration failed")) : s.errors;
|
|
448
|
+
if (errors.length) findings.push({
|
|
449
|
+
code: "errors",
|
|
450
|
+
severity: "error",
|
|
451
|
+
message: `${errors.length} error${errors.length === 1 ? "" : "s"}: ${[...new Set(errors.map((e) => e.message.split("\n")[0].trim()))].slice(0, 3).join(" · ")}.`,
|
|
452
|
+
refs: []
|
|
453
|
+
});
|
|
454
|
+
for (const m of s.mutations.slice(0, 3)) {
|
|
455
|
+
if (m.count < 300) break;
|
|
456
|
+
findings.push({
|
|
457
|
+
code: "dom-churn",
|
|
458
|
+
severity: "info",
|
|
459
|
+
message: `${m.fp ? name_of(m.fp) : "Code outside any island"} changed the DOM ${m.count} times during the session${m.fp ? "" : " (page scripts, a third-party tag)"}.`,
|
|
460
|
+
fix: "Lots of small changes often mean a re-render on every event: batch them, or key the list so unchanged rows stay.",
|
|
461
|
+
refs: m.fp ? [{
|
|
462
|
+
kind: "island",
|
|
463
|
+
fp: m.fp
|
|
464
|
+
}] : []
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
if (s.heap && s.heap.to - s.heap.from >= 5242880) findings.push({
|
|
468
|
+
code: "heap-growth",
|
|
469
|
+
severity: "info",
|
|
470
|
+
message: `The JS heap grew by ${kb(s.heap.to - s.heap.from)} during the session (${kb(s.heap.from)} → ${kb(s.heap.to)}). If it keeps growing across the same actions, something is kept (a listener, a cache, a closed island's state).`,
|
|
471
|
+
refs: []
|
|
472
|
+
});
|
|
473
|
+
for (const e of s.events) {
|
|
474
|
+
if (e.name !== "nav.finish") continue;
|
|
475
|
+
if (e.ms >= 500) findings.push({
|
|
476
|
+
code: "slow-navigation",
|
|
477
|
+
severity: "info",
|
|
478
|
+
message: `The navigation to ${e.to} took ${ms(e.ms)}${e.reconciled ? "" : " (a full swap, not reconciled)"}.`,
|
|
479
|
+
refs: []
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
const order = {
|
|
483
|
+
error: 0,
|
|
484
|
+
warn: 1,
|
|
485
|
+
info: 2
|
|
486
|
+
};
|
|
487
|
+
findings.sort((a, b) => order[a.severity] - order[b.severity]);
|
|
488
|
+
return {
|
|
489
|
+
duration_ms: Math.round(s.to - s.from),
|
|
490
|
+
counts: {
|
|
491
|
+
interactions: chosen.length,
|
|
492
|
+
slow: slow.length,
|
|
493
|
+
longtasks: s.longtasks.length,
|
|
494
|
+
longtask_ms: Math.round(lt_ms),
|
|
495
|
+
requests: s.requests.length,
|
|
496
|
+
request_bytes: bytes,
|
|
497
|
+
errors: s.errors.length,
|
|
498
|
+
shifts: unexpected.length,
|
|
499
|
+
cls: Math.round(cls * 1e3) / 1e3,
|
|
500
|
+
mutations: s.mutations.reduce((a, m) => a + m.count, 0),
|
|
501
|
+
pages: Math.max(1, s.pages?.length ?? 1)
|
|
502
|
+
},
|
|
503
|
+
findings,
|
|
504
|
+
interactions: chosen.map((i) => ({
|
|
505
|
+
i,
|
|
506
|
+
t: s.interactions[i].t,
|
|
507
|
+
name: s.interactions[i].name,
|
|
508
|
+
duration: s.interactions[i].duration,
|
|
509
|
+
target: s.interactions[i].target,
|
|
510
|
+
fp: s.interactions[i].fp
|
|
511
|
+
})).sort((a, b) => b.duration - a.duration).slice(0, 12),
|
|
512
|
+
by_island,
|
|
513
|
+
requests: [...s.requests].filter((r) => r.type === "fetch" || r.type === "xmlhttprequest" || r.server?.length).sort((a, b) => b.ms - a.ms).slice(0, 12).map((r) => ({
|
|
514
|
+
url: path_of(r.url),
|
|
515
|
+
ms: r.ms,
|
|
516
|
+
status: r.status,
|
|
517
|
+
server_ms: st(r, "ssr")?.ms ?? null,
|
|
518
|
+
cpu_ms: st(r, "cpu")?.ms ?? null,
|
|
519
|
+
net_ms: st(r, "net")?.ms ?? null,
|
|
520
|
+
up: st(r, "up1") ? `${st(r, "up1").desc} ${ms(st(r, "up1").ms)}` : null
|
|
521
|
+
})),
|
|
522
|
+
failed: s.requests.filter((r) => r.status !== null && r.status >= 400).map((r) => ({
|
|
523
|
+
url: r.url,
|
|
524
|
+
status: r.status,
|
|
525
|
+
type: r.type,
|
|
526
|
+
t: r.t
|
|
527
|
+
})),
|
|
528
|
+
by_element: Object.values(s.interactions.reduce((acc, x) => {
|
|
529
|
+
const cur = acc[x.target];
|
|
530
|
+
if (!cur || x.duration > cur.duration) acc[x.target] = {
|
|
531
|
+
target: x.target,
|
|
532
|
+
duration: x.duration,
|
|
533
|
+
processing: x.processing,
|
|
534
|
+
t: x.t,
|
|
535
|
+
fp: x.fp
|
|
536
|
+
};
|
|
537
|
+
return acc;
|
|
538
|
+
}, Object.fromEntries(s.clicks.map((c) => [c.target, {
|
|
539
|
+
target: c.target,
|
|
540
|
+
duration: 0,
|
|
541
|
+
processing: 0,
|
|
542
|
+
t: c.t,
|
|
543
|
+
fp: c.fp
|
|
544
|
+
}])))).sort((a, b) => b.duration - a.duration),
|
|
545
|
+
cpu
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
export { analyze_session, session_timeline };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE DEVTOOLS SWITCH — whether devtools is on in this browser, in a BUILD with devtools (a QA or
|
|
3
|
+
* preview deploy; the dev server always has it on). One cookie decides all of it: the launcher shows,
|
|
4
|
+
* the page is measured from the start (runtime/beacon.ts), what islands leave running is watched
|
|
5
|
+
* (leftovers.ts), and the server writes its event side-channel (hooks.ts). Off — the default — a
|
|
6
|
+
* visitor sees nothing and pays nothing.
|
|
7
|
+
*
|
|
8
|
+
* A developer turns it on for their own browser, and it stays on across navigations and reloads:
|
|
9
|
+
* - `?og-devtools=on` / `?og-devtools=off` on any page (the server sets the cookie on that very
|
|
10
|
+
* response, the browser too — a prerendered page has no server — and the address drops the param);
|
|
11
|
+
* - `ogygia.devtools.on()` / `.off()` in the console;
|
|
12
|
+
* - "hide" in the dock turns it off.
|
|
13
|
+
*
|
|
14
|
+
* (The value is not the `1` an earlier launcher set on a plain click: a browser that clicked the old
|
|
15
|
+
* button once stays off until it opts in.)
|
|
16
|
+
*
|
|
17
|
+
* A plain module: the server, the runtime and the launcher all read it.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEVTOOLS_COOKIE = "og_devtools";
|
|
20
|
+
export declare const DEVTOOLS_ON = "on";
|
|
21
|
+
/** The URL param that flips it: `?og-devtools=on` / `?og-devtools=off`. */
|
|
22
|
+
export declare const DEVTOOLS_PARAM = "og-devtools";
|
|
23
|
+
/** What the URL asks for: `true` on, `false` off, `null` nothing (absent or another value). */
|
|
24
|
+
export declare function switch_in_url(url: URL): boolean | null;
|
|
25
|
+
/** The URL without the switch param (the address after it was applied). */
|
|
26
|
+
export declare function without_switch(url: URL): URL;
|
|
27
|
+
/** Is it on in a `Cookie` header / `document.cookie` string. */
|
|
28
|
+
export declare function switch_on_in(cookies: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* LEAN TESTING: `og_testing=lean` (or `?og-testing=lean`) beside the devtools switch — the testing API
|
|
31
|
+
* (`window.__ogygia_testing`) works in full, and nothing else of devtools runs: no launcher, no dock, no
|
|
32
|
+
* watcher of the page's timers, no server event side-channel in the HTML. The page loads what it loads
|
|
33
|
+
* with devtools off, plus the testing engine when a test first asks. An engine that does not know the
|
|
34
|
+
* cookie ignores it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const TESTING_COOKIE = "og_testing";
|
|
37
|
+
export declare const TESTING_LEAN = "lean";
|
|
38
|
+
export declare const TESTING_PARAM = "og-testing";
|
|
39
|
+
/** Is lean testing asked for in a `Cookie` header / `document.cookie` string. */
|
|
40
|
+
export declare function lean_in(cookies: string): boolean;
|
|
41
|
+
/** Lean testing in this browser: the cookie, or the URL param (false off the browser). */
|
|
42
|
+
export declare function testing_lean(): boolean;
|
|
43
|
+
/** The `Set-Cookie`-shaped attributes the switch is written with (browser and server alike). */
|
|
44
|
+
export declare const SWITCH_COOKIE_OPTIONS: {
|
|
45
|
+
path: string;
|
|
46
|
+
maxAge: number;
|
|
47
|
+
sameSite: "lax";
|
|
48
|
+
httpOnly: boolean;
|
|
49
|
+
};
|
|
50
|
+
/** Is it on in this browser (false off the browser, or with cookies blocked). */
|
|
51
|
+
export declare function devtools_switched_on(): boolean;
|
|
52
|
+
/** Turn it on / off in this browser (the cookie; the caller updates what shows). */
|
|
53
|
+
export declare function write_switch(on: boolean): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// src/insights/switch.ts
|
|
2
|
+
/**
|
|
3
|
+
* THE DEVTOOLS SWITCH — whether devtools is on in this browser, in a BUILD with devtools (a QA or
|
|
4
|
+
* preview deploy; the dev server always has it on). One cookie decides all of it: the launcher shows,
|
|
5
|
+
* the page is measured from the start (runtime/beacon.ts), what islands leave running is watched
|
|
6
|
+
* (leftovers.ts), and the server writes its event side-channel (hooks.ts). Off — the default — a
|
|
7
|
+
* visitor sees nothing and pays nothing.
|
|
8
|
+
*
|
|
9
|
+
* A developer turns it on for their own browser, and it stays on across navigations and reloads:
|
|
10
|
+
* - `?og-devtools=on` / `?og-devtools=off` on any page (the server sets the cookie on that very
|
|
11
|
+
* response, the browser too — a prerendered page has no server — and the address drops the param);
|
|
12
|
+
* - `ogygia.devtools.on()` / `.off()` in the console;
|
|
13
|
+
* - "hide" in the dock turns it off.
|
|
14
|
+
*
|
|
15
|
+
* (The value is not the `1` an earlier launcher set on a plain click: a browser that clicked the old
|
|
16
|
+
* button once stays off until it opts in.)
|
|
17
|
+
*
|
|
18
|
+
* A plain module: the server, the runtime and the launcher all read it.
|
|
19
|
+
*/
|
|
20
|
+
const DEVTOOLS_COOKIE = "og_devtools";
|
|
21
|
+
const DEVTOOLS_ON = "on";
|
|
22
|
+
/** The URL param that flips it: `?og-devtools=on` / `?og-devtools=off`. */
|
|
23
|
+
const DEVTOOLS_PARAM = "og-devtools";
|
|
24
|
+
/** 30 days: a developer flips it once per deploy, not per visit. */
|
|
25
|
+
const MAX_AGE = 2592e3;
|
|
26
|
+
/** What the URL asks for: `true` on, `false` off, `null` nothing (absent or another value). */
|
|
27
|
+
function switch_in_url(url) {
|
|
28
|
+
const v = url.searchParams.get(DEVTOOLS_PARAM);
|
|
29
|
+
if (v === null) return null;
|
|
30
|
+
if (v === "on" || v === "1" || v === "true") return true;
|
|
31
|
+
if (v === "off" || v === "0" || v === "false") return false;
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
/** The URL without the switch param (the address after it was applied). */
|
|
35
|
+
function without_switch(url) {
|
|
36
|
+
const u = new URL(url);
|
|
37
|
+
u.searchParams.delete(DEVTOOLS_PARAM);
|
|
38
|
+
return u;
|
|
39
|
+
}
|
|
40
|
+
/** Is it on in a `Cookie` header / `document.cookie` string. */
|
|
41
|
+
function switch_on_in(cookies) {
|
|
42
|
+
const want = "og_devtools=on";
|
|
43
|
+
for (const c of cookies.split(";")) if (c.trim() === want) return true;
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* LEAN TESTING: `og_testing=lean` (or `?og-testing=lean`) beside the devtools switch — the testing API
|
|
48
|
+
* (`window.__ogygia_testing`) works in full, and nothing else of devtools runs: no launcher, no dock, no
|
|
49
|
+
* watcher of the page's timers, no server event side-channel in the HTML. The page loads what it loads
|
|
50
|
+
* with devtools off, plus the testing engine when a test first asks. An engine that does not know the
|
|
51
|
+
* cookie ignores it.
|
|
52
|
+
*/
|
|
53
|
+
const TESTING_COOKIE = "og_testing";
|
|
54
|
+
const TESTING_LEAN = "lean";
|
|
55
|
+
const TESTING_PARAM = "og-testing";
|
|
56
|
+
/** Is lean testing asked for in a `Cookie` header / `document.cookie` string. */
|
|
57
|
+
function lean_in(cookies) {
|
|
58
|
+
const want = "og_testing=lean";
|
|
59
|
+
for (const c of cookies.split(";")) if (c.trim() === want) return true;
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/** Lean testing in this browser: the cookie, or the URL param (false off the browser). */
|
|
63
|
+
function testing_lean() {
|
|
64
|
+
try {
|
|
65
|
+
return lean_in(document.cookie) || new URL(location.href).searchParams.get("og-testing") === "lean";
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** The `Set-Cookie`-shaped attributes the switch is written with (browser and server alike). */
|
|
71
|
+
const SWITCH_COOKIE_OPTIONS = {
|
|
72
|
+
path: "/",
|
|
73
|
+
maxAge: MAX_AGE,
|
|
74
|
+
sameSite: "lax",
|
|
75
|
+
httpOnly: false
|
|
76
|
+
};
|
|
77
|
+
/** Is it on in this browser (false off the browser, or with cookies blocked). */
|
|
78
|
+
function devtools_switched_on() {
|
|
79
|
+
try {
|
|
80
|
+
return switch_on_in(document.cookie);
|
|
81
|
+
} catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Turn it on / off in this browser (the cookie; the caller updates what shows). */
|
|
86
|
+
function write_switch(on) {
|
|
87
|
+
try {
|
|
88
|
+
document.cookie = on ? `${DEVTOOLS_COOKIE}=on; path=/; max-age=${MAX_AGE}; samesite=lax` : `${DEVTOOLS_COOKIE}=; path=/; max-age=0; samesite=lax`;
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
export { DEVTOOLS_COOKIE, DEVTOOLS_ON, DEVTOOLS_PARAM, SWITCH_COOKIE_OPTIONS, TESTING_COOKIE, TESTING_LEAN, TESTING_PARAM, devtools_switched_on, lean_in, switch_in_url, switch_on_in, testing_lean, without_switch, write_switch };
|