@wular/pnext 0.0.3 → 0.0.6
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/README.md +11 -11
- package/bin/pnext +1 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/css.md +13 -9
- package/reference/dev.md +1 -1
- package/reference/metadata.md +7 -7
- package/reference/navigation.md +35 -28
- package/reference/performance.md +70 -70
- package/reference/rendering.md +17 -17
- package/reference/routing.md +17 -17
- package/reference/typegen.md +12 -8
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +113 -109
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +49 -52
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +71 -63
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +88 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +794 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +17 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +1988 -1961
- package/src/{api → client}/router/types.ts +93 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1887
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +69 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2076 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +152 -143
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +442 -186
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +69 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +833 -848
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +952 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +425 -404
- package/src/styles.d.ts +9 -0
- package/src/types.ts +320 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
|
@@ -18,28 +18,28 @@
|
|
|
18
18
|
//
|
|
19
19
|
// Client-escaped errors carry NO digest, matching Next.
|
|
20
20
|
|
|
21
|
-
import { h, options, render } from 'preact'
|
|
22
|
-
import { handleControlFlowError, isControlFlowError } from './control-flow'
|
|
21
|
+
import { h, options, render } from 'preact'
|
|
22
|
+
import { handleControlFlowError, isControlFlowError } from './control-flow'
|
|
23
23
|
import {
|
|
24
24
|
wasErrorHandled,
|
|
25
25
|
type RouteErrorComponent,
|
|
26
26
|
type RouteNotFoundComponent,
|
|
27
|
-
} from './error-boundary'
|
|
27
|
+
} from './error-boundary'
|
|
28
28
|
import {
|
|
29
29
|
escalateToGlobalError,
|
|
30
30
|
mountGlobalError,
|
|
31
31
|
registerGlobalErrorComponent,
|
|
32
32
|
wasReportedUncaught,
|
|
33
33
|
type GlobalErrorComponent,
|
|
34
|
-
} from './global-error'
|
|
35
|
-
import { softRefreshRoute } from './soft-refresh'
|
|
34
|
+
} from './global-error'
|
|
35
|
+
import { softRefreshRoute } from './soft-refresh'
|
|
36
36
|
|
|
37
|
-
export { ClientErrorBoundary, toClientError } from './error-boundary'
|
|
38
|
-
export { markErrorHandled, wasErrorHandled } from './error-boundary'
|
|
39
|
-
export type { RouteErrorComponent } from './error-boundary'
|
|
40
|
-
export { isControlFlowError, handleControlFlowError } from './control-flow'
|
|
41
|
-
export { mountGlobalError } from './global-error'
|
|
42
|
-
export { softRefreshRoute } from './soft-refresh'
|
|
37
|
+
export { ClientErrorBoundary, toClientError } from './error-boundary'
|
|
38
|
+
export { markErrorHandled, wasErrorHandled } from './error-boundary'
|
|
39
|
+
export type { RouteErrorComponent } from './error-boundary'
|
|
40
|
+
export { isControlFlowError, handleControlFlowError } from './control-flow'
|
|
41
|
+
export { mountGlobalError } from './global-error'
|
|
42
|
+
export { softRefreshRoute } from './soft-refresh'
|
|
43
43
|
|
|
44
44
|
export interface InstallOptions {
|
|
45
45
|
/**
|
|
@@ -47,77 +47,77 @@ export interface InstallOptions {
|
|
|
47
47
|
* ClientErrorBoundary (nearest-boundary primary path); retained here so the
|
|
48
48
|
* install signature stays stable and callers can still thread it.
|
|
49
49
|
*/
|
|
50
|
-
errorComponent?: RouteErrorComponent
|
|
51
|
-
notFoundComponent?: RouteNotFoundComponent
|
|
50
|
+
errorComponent?: RouteErrorComponent
|
|
51
|
+
notFoundComponent?: RouteNotFoundComponent
|
|
52
52
|
/** The app's global-error.js component, when available (see gaps: build thread). */
|
|
53
|
-
globalErrorComponent?: GlobalErrorComponent
|
|
53
|
+
globalErrorComponent?: GlobalErrorComponent
|
|
54
54
|
/**
|
|
55
55
|
* Predicate identifying action errors already handled by the action overlay,
|
|
56
56
|
* so this runtime skips them. Defaults to never-skip when omitted.
|
|
57
57
|
*/
|
|
58
|
-
isActionError?: (error: unknown) => boolean
|
|
58
|
+
isActionError?: (error: unknown) => boolean
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
let installed = false
|
|
61
|
+
let installed = false
|
|
62
62
|
|
|
63
63
|
// Set by installClientErrors so ./lazy can replay the errors that escaped
|
|
64
64
|
// before this chunk landed (a throw during hydration or in a first-paint
|
|
65
65
|
// effect) through exactly the same triage.
|
|
66
|
-
let escapedErrorHandler: ((error: unknown) => void) | undefined
|
|
66
|
+
let escapedErrorHandler: ((error: unknown) => void) | undefined
|
|
67
67
|
|
|
68
68
|
/** Replay pre-runtime escapes (./lazy buffers them) through the last resort. */
|
|
69
69
|
export function drainEscapedErrors(errors: unknown[]): void {
|
|
70
|
-
for (const error of errors) escapedErrorHandler?.(error)
|
|
70
|
+
for (const error of errors) escapedErrorHandler?.(error)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
export function installClientErrors(options: InstallOptions = {}): void {
|
|
74
|
-
if ((!process.browser && typeof window === 'undefined') || installed) return
|
|
75
|
-
installed = true
|
|
74
|
+
if ((!process.browser && typeof window === 'undefined') || installed) return
|
|
75
|
+
installed = true
|
|
76
76
|
|
|
77
|
-
const { globalErrorComponent, isActionError } = options
|
|
77
|
+
const { globalErrorComponent, isActionError } = options
|
|
78
78
|
// Register so the in-tree ClientErrorBoundary can escalate a no-error.js route
|
|
79
79
|
// straight to global-error (handles `throw undefined`/`null`, which the window
|
|
80
80
|
// channel would drop).
|
|
81
|
-
registerGlobalErrorComponent(globalErrorComponent)
|
|
81
|
+
registerGlobalErrorComponent(globalErrorComponent)
|
|
82
82
|
|
|
83
83
|
const onError = (error: unknown): void => {
|
|
84
84
|
// Already caught + rendered by a route boundary: the boundary owns it.
|
|
85
|
-
if (wasErrorHandled(error)) return
|
|
85
|
+
if (wasErrorHandled(error)) return
|
|
86
86
|
// Control-flow first: navigate, never render (covers control errors thrown
|
|
87
87
|
// outside any boundary, and boundary-rethrown ones that reach the window).
|
|
88
88
|
if (isControlFlowError(error)) {
|
|
89
|
-
handleControlFlowError(error)
|
|
90
|
-
return
|
|
89
|
+
handleControlFlowError(error)
|
|
90
|
+
return
|
|
91
91
|
}
|
|
92
92
|
// Action errors belong to the action-error overlay.
|
|
93
|
-
if (isActionError?.(error)) return
|
|
93
|
+
if (isActionError?.(error)) return
|
|
94
94
|
|
|
95
95
|
// A genuinely uncaught client error with no route error.js to catch it —
|
|
96
96
|
// the global-error last resort replaces the document. Pass the raw value so
|
|
97
97
|
// a non-Error throw renders unwrapped in global-error.js (`${error}`).
|
|
98
|
-
mountGlobalError(error, globalErrorComponent)
|
|
99
|
-
}
|
|
100
|
-
escapedErrorHandler = onError
|
|
98
|
+
mountGlobalError(error, globalErrorComponent)
|
|
99
|
+
}
|
|
100
|
+
escapedErrorHandler = onError
|
|
101
101
|
|
|
102
102
|
window.addEventListener('error', event => {
|
|
103
103
|
// Ignore ResourceLoad errors (no `error` object) — only script throws carry one.
|
|
104
|
-
if ('error' in event && event.error === undefined) return
|
|
104
|
+
if ('error' in event && event.error === undefined) return
|
|
105
105
|
// Our own synchronous reportUncaught echo: already mounted + reported.
|
|
106
|
-
if (wasReportedUncaught(event.error)) return
|
|
107
|
-
if (event.error !== undefined) onError(event.error)
|
|
108
|
-
})
|
|
106
|
+
if (wasReportedUncaught(event.error)) return
|
|
107
|
+
if (event.error !== undefined) onError(event.error)
|
|
108
|
+
})
|
|
109
109
|
window.addEventListener('unhandledrejection', event => {
|
|
110
110
|
// The escape below already reported this value synchronously; without
|
|
111
111
|
// preventDefault the page would emit a SECOND uncaught-error report.
|
|
112
112
|
if (wasReportedUncaught(event.reason)) {
|
|
113
|
-
event.preventDefault()
|
|
114
|
-
return
|
|
113
|
+
event.preventDefault()
|
|
114
|
+
return
|
|
115
115
|
}
|
|
116
|
-
onError(event.reason)
|
|
117
|
-
})
|
|
116
|
+
onError(event.reason)
|
|
117
|
+
})
|
|
118
118
|
|
|
119
|
-
installRenderEscapeEscalation(globalErrorComponent, isActionError)
|
|
120
|
-
installStreamErrorBoundaries(options.errorComponent, globalErrorComponent)
|
|
119
|
+
installRenderEscapeEscalation(globalErrorComponent, isActionError)
|
|
120
|
+
installStreamErrorBoundaries(options.errorComponent, globalErrorComponent)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// Synchronous global-error escalation for a render throw no boundary held. Preact signals "nothing
|
|
@@ -131,24 +131,24 @@ function installRenderEscapeEscalation(
|
|
|
131
131
|
isActionError?: (error: unknown) => boolean,
|
|
132
132
|
): void {
|
|
133
133
|
// `_catchError` in preact's source; `__e` in its published (mangled) build.
|
|
134
|
-
const hooks = options as unknown as Record<string, unknown
|
|
135
|
-
const key = (['_catchError', '__e'] as const).find(name => typeof hooks[name] === 'function')
|
|
136
|
-
if (!key) return
|
|
137
|
-
const walkBoundaries = hooks[key] as (...args: unknown[]) => unknown
|
|
134
|
+
const hooks = options as unknown as Record<string, unknown>
|
|
135
|
+
const key = (['_catchError', '__e'] as const).find(name => typeof hooks[name] === 'function')
|
|
136
|
+
if (!key) return
|
|
137
|
+
const walkBoundaries = hooks[key] as (...args: unknown[]) => unknown
|
|
138
138
|
hooks[key] = function patchedCatchError(this: unknown, ...args: unknown[]) {
|
|
139
139
|
try {
|
|
140
|
-
return walkBoundaries.apply(this, args)
|
|
140
|
+
return walkBoundaries.apply(this, args)
|
|
141
141
|
} catch (error) {
|
|
142
142
|
// Handled by a boundary, control flow, or an action error: those already
|
|
143
143
|
// have an owner — only a genuinely uncaught error escapes to global-error.
|
|
144
144
|
// escalate (not mount): the error must also report as uncaught in THIS
|
|
145
145
|
// task, not a task later via the natural unhandled rejection.
|
|
146
146
|
if (!wasErrorHandled(error) && !isControlFlowError(error) && !isActionError?.(error)) {
|
|
147
|
-
escalateToGlobalError(error)
|
|
147
|
+
escalateToGlobalError(error)
|
|
148
148
|
}
|
|
149
|
-
throw error
|
|
149
|
+
throw error
|
|
150
150
|
}
|
|
151
|
-
}
|
|
151
|
+
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
// Streamed-Suspense server errors, routed to the route error.js boundary.
|
|
@@ -160,58 +160,57 @@ function installRenderEscapeEscalation(
|
|
|
160
160
|
// here we watch for those markers (initial scan plus a MutationObserver, since stream chunks land after
|
|
161
161
|
// the entry module runs) and mount the route error.js over them. Both callbacks soft-refresh, so a
|
|
162
162
|
// since-recovered server render replaces the boundary with real content.
|
|
163
|
-
const STREAM_ERROR_SELECTOR = 'pnext-error[data-pnext-stream-error][data-pnext-error-message]'
|
|
163
|
+
const STREAM_ERROR_SELECTOR = 'pnext-error[data-pnext-stream-error][data-pnext-error-message]'
|
|
164
164
|
|
|
165
165
|
function installStreamErrorBoundaries(
|
|
166
166
|
errorComponent?: RouteErrorComponent,
|
|
167
167
|
globalErrorComponent?: GlobalErrorComponent,
|
|
168
168
|
): void {
|
|
169
|
-
if (typeof document === 'undefined') return
|
|
169
|
+
if (typeof document === 'undefined') return
|
|
170
170
|
// Announce the runtime so the server's inline stream-error fallback script
|
|
171
171
|
// (renderer streamErrorDocumentScript) defers to this handler.
|
|
172
|
-
(window as unknown as Record<string, unknown>).__PNEXT_STREAM_ERROR_RUNTIME__ = true
|
|
172
|
+
;(window as unknown as Record<string, unknown>).__PNEXT_STREAM_ERROR_RUNTIME__ = true
|
|
173
173
|
|
|
174
174
|
const mountMarker = (marker: Element): void => {
|
|
175
|
-
const message = marker.getAttribute('data-pnext-error-message') ?? ''
|
|
176
|
-
const digest = marker.getAttribute('data-pnext-error-digest') ?? undefined
|
|
177
|
-
const error = new Error(message) as Error & { digest?: string }
|
|
178
|
-
if (digest) error.digest = digest
|
|
175
|
+
const message = marker.getAttribute('data-pnext-error-message') ?? ''
|
|
176
|
+
const digest = marker.getAttribute('data-pnext-error-digest') ?? undefined
|
|
177
|
+
const error = new Error(message) as Error & { digest?: string }
|
|
178
|
+
if (digest) error.digest = digest
|
|
179
179
|
if (!errorComponent) {
|
|
180
180
|
// No route error.js: Next escalates a streamed-Suspense server error to
|
|
181
181
|
// global-error (the built-in "This page couldn't load" document with the
|
|
182
182
|
// ERROR <digest> footer when none exists — default-error-page-ui suite).
|
|
183
|
-
mountGlobalError(error, globalErrorComponent)
|
|
184
|
-
return
|
|
183
|
+
mountGlobalError(error, globalErrorComponent)
|
|
184
|
+
return
|
|
185
185
|
}
|
|
186
|
-
const host = document.createElement('div')
|
|
187
|
-
marker.replaceWith(host)
|
|
188
|
-
const reset = () => softRefreshRoute()
|
|
189
|
-
render(h(errorComponent, { error, reset, unstable_retry: reset }), host)
|
|
190
|
-
}
|
|
186
|
+
const host = document.createElement('div')
|
|
187
|
+
marker.replaceWith(host)
|
|
188
|
+
const reset = () => softRefreshRoute()
|
|
189
|
+
render(h(errorComponent, { error, reset, unstable_retry: reset }), host)
|
|
190
|
+
}
|
|
191
191
|
|
|
192
192
|
const scan = (root: ParentNode): void => {
|
|
193
193
|
for (const marker of Array.from(root.querySelectorAll(STREAM_ERROR_SELECTOR))) {
|
|
194
|
-
mountMarker(marker)
|
|
194
|
+
mountMarker(marker)
|
|
195
195
|
}
|
|
196
|
-
}
|
|
196
|
+
}
|
|
197
197
|
|
|
198
198
|
const observe = () => {
|
|
199
|
-
scan(document)
|
|
199
|
+
scan(document)
|
|
200
200
|
new MutationObserver(mutations => {
|
|
201
201
|
for (const mutation of mutations) {
|
|
202
202
|
for (const node of Array.from(mutation.addedNodes)) {
|
|
203
|
-
if (!(node instanceof Element)) continue
|
|
204
|
-
if (node.matches(STREAM_ERROR_SELECTOR)) mountMarker(node)
|
|
205
|
-
else scan(node)
|
|
203
|
+
if (!(node instanceof Element)) continue
|
|
204
|
+
if (node.matches(STREAM_ERROR_SELECTOR)) mountMarker(node)
|
|
205
|
+
else scan(node)
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
-
}).observe(document.documentElement, { childList: true, subtree: true })
|
|
209
|
-
}
|
|
208
|
+
}).observe(document.documentElement, { childList: true, subtree: true })
|
|
209
|
+
}
|
|
210
210
|
|
|
211
211
|
if (document.readyState === 'loading') {
|
|
212
|
-
document.addEventListener('DOMContentLoaded', observe, { once: true })
|
|
212
|
+
document.addEventListener('DOMContentLoaded', observe, { once: true })
|
|
213
213
|
} else {
|
|
214
|
-
observe()
|
|
214
|
+
observe()
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
|
-
|
|
@@ -6,48 +6,48 @@
|
|
|
6
6
|
// a first-paint effect fires long before the idle tier lands, and Next still shows global-error for
|
|
7
7
|
// it. They buffer the value, pull ./install right away, and hand it over - so a healthy page still
|
|
8
8
|
// never fetches the chunk.
|
|
9
|
-
import { registerDeferredInstall } from '../../../
|
|
10
|
-
import type { InstallOptions } from './install'
|
|
9
|
+
import { registerDeferredInstall } from '../../../client/router'
|
|
10
|
+
import type { InstallOptions } from './install'
|
|
11
11
|
|
|
12
|
-
type ErrorRuntime = typeof import('./install')
|
|
12
|
+
type ErrorRuntime = typeof import('./install')
|
|
13
13
|
|
|
14
14
|
export function installClientErrors(options: InstallOptions = {}): void {
|
|
15
|
-
if (!process.browser && typeof window === 'undefined') return
|
|
15
|
+
if (!process.browser && typeof window === 'undefined') return
|
|
16
16
|
|
|
17
|
-
let runtime: Promise<ErrorRuntime> | undefined
|
|
17
|
+
let runtime: Promise<ErrorRuntime> | undefined
|
|
18
18
|
const load = () =>
|
|
19
19
|
(runtime ??= import('./install').then(module => {
|
|
20
20
|
// Drop the capture listeners before the runtime's own go in, so a later
|
|
21
21
|
// error is triaged once rather than by both paths.
|
|
22
|
-
window.removeEventListener('error', onError)
|
|
23
|
-
window.removeEventListener('unhandledrejection', onRejection)
|
|
24
|
-
module.installClientErrors(options)
|
|
25
|
-
return module
|
|
26
|
-
}))
|
|
22
|
+
window.removeEventListener('error', onError)
|
|
23
|
+
window.removeEventListener('unhandledrejection', onRejection)
|
|
24
|
+
module.installClientErrors(options)
|
|
25
|
+
return module
|
|
26
|
+
}))
|
|
27
27
|
|
|
28
|
-
const escaped: unknown[] = []
|
|
29
|
-
const seen = new WeakSet<object>()
|
|
28
|
+
const escaped: unknown[] = []
|
|
29
|
+
const seen = new WeakSet<object>()
|
|
30
30
|
const capture = (error: unknown) => {
|
|
31
31
|
// The replay itself can throw (control-flow handling, a global-error
|
|
32
32
|
// render), which surfaces as another rejection here. Capturing the same
|
|
33
33
|
// value twice would loop, so object throws are only ever queued once and
|
|
34
34
|
// the chain swallows its own failures.
|
|
35
35
|
if (error !== null && typeof error === 'object') {
|
|
36
|
-
if (seen.has(error)) return
|
|
37
|
-
seen.add(error)
|
|
36
|
+
if (seen.has(error)) return
|
|
37
|
+
seen.add(error)
|
|
38
38
|
}
|
|
39
|
-
escaped.push(error)
|
|
39
|
+
escaped.push(error)
|
|
40
40
|
void load()
|
|
41
41
|
.then(module => module.drainEscapedErrors(escaped.splice(0)))
|
|
42
|
-
.catch(() => undefined)
|
|
43
|
-
}
|
|
42
|
+
.catch(() => undefined)
|
|
43
|
+
}
|
|
44
44
|
// Resource-load failures carry no `error` object; only script throws do.
|
|
45
45
|
const onError = (event: ErrorEvent) => {
|
|
46
|
-
if (event.error !== undefined) capture(event.error)
|
|
47
|
-
}
|
|
48
|
-
const onRejection = (event: PromiseRejectionEvent) => capture(event.reason)
|
|
49
|
-
window.addEventListener('error', onError)
|
|
50
|
-
window.addEventListener('unhandledrejection', onRejection)
|
|
46
|
+
if (event.error !== undefined) capture(event.error)
|
|
47
|
+
}
|
|
48
|
+
const onRejection = (event: PromiseRejectionEvent) => capture(event.reason)
|
|
49
|
+
window.addEventListener('error', onError)
|
|
50
|
+
window.addEventListener('unhandledrejection', onRejection)
|
|
51
51
|
|
|
52
|
-
registerDeferredInstall(load)
|
|
52
|
+
registerDeferredInstall(load)
|
|
53
53
|
}
|
|
@@ -12,26 +12,26 @@
|
|
|
12
12
|
// has no `.then`, so preact proceeds normally into `options._catchError` and the normal boundary walk
|
|
13
13
|
// runs. Boundaries unwrap the tag to recover the original raw value before handing it to the error UI.
|
|
14
14
|
|
|
15
|
-
const RAW_VALUE = Symbol('pnext.primitiveThrowValue')
|
|
15
|
+
const RAW_VALUE = Symbol('pnext.primitiveThrowValue')
|
|
16
16
|
|
|
17
17
|
export interface TaggedPrimitiveThrow extends Error {
|
|
18
|
-
[RAW_VALUE]: unknown
|
|
18
|
+
[RAW_VALUE]: unknown
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function tagPrimitiveThrow(value: unknown): TaggedPrimitiveThrow {
|
|
22
|
-
const message = typeof value === 'string' ? value : String(value)
|
|
23
|
-
const error = new Error(message) as TaggedPrimitiveThrow
|
|
24
|
-
error[RAW_VALUE] = value
|
|
25
|
-
return error
|
|
22
|
+
const message = typeof value === 'string' ? value : String(value)
|
|
23
|
+
const error = new Error(message) as TaggedPrimitiveThrow
|
|
24
|
+
error[RAW_VALUE] = value
|
|
25
|
+
return error
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function isTaggedPrimitiveThrow(error: unknown): error is TaggedPrimitiveThrow {
|
|
29
|
-
return error instanceof Error && RAW_VALUE in error
|
|
29
|
+
return error instanceof Error && RAW_VALUE in error
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/** Unwrap a tagged primitive-throw Error back to the raw value; pass through anything else. */
|
|
33
33
|
export function untagPrimitiveThrow(error: unknown): unknown {
|
|
34
|
-
return isTaggedPrimitiveThrow(error) ? error[RAW_VALUE] : error
|
|
34
|
+
return isTaggedPrimitiveThrow(error) ? error[RAW_VALUE] : error
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -41,13 +41,13 @@ export function untagPrimitiveThrow(error: unknown): unknown {
|
|
|
41
41
|
* the bare one pulling in the full cluster.
|
|
42
42
|
*/
|
|
43
43
|
export function normalizeBoundaryError(error: unknown): unknown {
|
|
44
|
-
const untagged = untagPrimitiveThrow(error)
|
|
45
|
-
if (untagged !== error) return untagged
|
|
44
|
+
const untagged = untagPrimitiveThrow(error)
|
|
45
|
+
if (untagged !== error) return untagged
|
|
46
46
|
if (error instanceof Error) {
|
|
47
|
-
if (error.message === "Cannot read properties of undefined (reading 'then')") return undefined
|
|
48
|
-
if (error.message === "Cannot read properties of null (reading 'then')") return null
|
|
47
|
+
if (error.message === "Cannot read properties of undefined (reading 'then')") return undefined
|
|
48
|
+
if (error.message === "Cannot read properties of null (reading 'then')") return null
|
|
49
49
|
}
|
|
50
|
-
return error
|
|
50
|
+
return error
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -55,7 +55,7 @@ export function normalizeBoundaryError(error: unknown): unknown {
|
|
|
55
55
|
* (`e.then`): null and undefined - the only two JS values where the property access itself throws.
|
|
56
56
|
*/
|
|
57
57
|
function crashesPreactThenCheck(value: unknown): boolean {
|
|
58
|
-
return value === null || value === undefined
|
|
58
|
+
return value === null || value === undefined
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -63,7 +63,7 @@ function crashesPreactThenCheck(value: unknown): boolean {
|
|
|
63
63
|
* check is re-thrown as a tagged Error instead. Safe to call repeatedly on the same component type -
|
|
64
64
|
* the wrapper is cached.
|
|
65
65
|
*/
|
|
66
|
-
const wrapped = new WeakMap<object, unknown>()
|
|
66
|
+
const wrapped = new WeakMap<object, unknown>()
|
|
67
67
|
|
|
68
68
|
// Marks a value this function already produced, so re-wrapping is a no-op. REQUIRED for idempotency
|
|
69
69
|
// across preact's own vnode clone-and-re-render path: a component that re-renders IN PLACE
|
|
@@ -74,69 +74,71 @@ const wrapped = new WeakMap<object, unknown>();
|
|
|
74
74
|
// same component position resolves back to the first, singly-wrapped value. Two different function
|
|
75
75
|
// references at the same tree position make preact treat it as a different component type - a full
|
|
76
76
|
// unmount and remount of that subtree instead of an update.
|
|
77
|
-
const ALREADY_WRAPPED = Symbol('pnext.primitiveThrowWrapped')
|
|
77
|
+
const ALREADY_WRAPPED = Symbol('pnext.primitiveThrowWrapped')
|
|
78
78
|
|
|
79
79
|
function copyMetadata(from: object, to: object): void {
|
|
80
80
|
for (const key of Object.getOwnPropertyNames(from)) {
|
|
81
|
-
if (key === 'length' || key === 'name' || key === 'prototype') continue
|
|
82
|
-
const descriptor = Object.getOwnPropertyDescriptor(from, key)
|
|
83
|
-
if (descriptor) Object.defineProperty(to, key, descriptor)
|
|
81
|
+
if (key === 'length' || key === 'name' || key === 'prototype') continue
|
|
82
|
+
const descriptor = Object.getOwnPropertyDescriptor(from, key)
|
|
83
|
+
if (descriptor) Object.defineProperty(to, key, descriptor)
|
|
84
84
|
}
|
|
85
85
|
for (const symbol of Object.getOwnPropertySymbols(from)) {
|
|
86
|
-
const descriptor = Object.getOwnPropertyDescriptor(from, symbol)
|
|
87
|
-
if (descriptor) Object.defineProperty(to, symbol, descriptor)
|
|
86
|
+
const descriptor = Object.getOwnPropertyDescriptor(from, symbol)
|
|
87
|
+
if (descriptor) Object.defineProperty(to, symbol, descriptor)
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export function wrapComponentForPrimitiveThrows<T extends object>(type: T): T {
|
|
92
|
-
if ((type as { [ALREADY_WRAPPED]?: true })[ALREADY_WRAPPED]) return type
|
|
93
|
-
const cached = wrapped.get(type)
|
|
94
|
-
if (cached) return cached as T
|
|
95
|
-
if (typeof type !== 'function') return type
|
|
92
|
+
if ((type as { [ALREADY_WRAPPED]?: true })[ALREADY_WRAPPED]) return type
|
|
93
|
+
const cached = wrapped.get(type)
|
|
94
|
+
if (cached) return cached as T
|
|
95
|
+
if (typeof type !== 'function') return type
|
|
96
96
|
|
|
97
|
-
const isClassComponent = Boolean((type as { prototype?: { render?: unknown } }).prototype?.render)
|
|
98
|
-
let result: unknown
|
|
97
|
+
const isClassComponent = Boolean((type as { prototype?: { render?: unknown } }).prototype?.render)
|
|
98
|
+
let result: unknown
|
|
99
99
|
|
|
100
100
|
if (isClassComponent) {
|
|
101
101
|
// Class components: preact does `new Type(props, context)` then calls
|
|
102
102
|
// `.render()`. Subclass so `render()` is wrapped; static lifecycle methods
|
|
103
103
|
// (getDerivedStateFromError, etc.) and everything else pass through
|
|
104
104
|
// untouched via normal prototype-chain inheritance.
|
|
105
|
-
const Base = type as unknown as new (...args: unknown[]) => {
|
|
105
|
+
const Base = type as unknown as new (...args: unknown[]) => {
|
|
106
|
+
render(...args: unknown[]): unknown
|
|
107
|
+
}
|
|
106
108
|
class PrimitiveThrowSafe extends Base {
|
|
107
109
|
render(...args: unknown[]) {
|
|
108
110
|
try {
|
|
109
|
-
return super.render(...args)
|
|
111
|
+
return super.render(...args)
|
|
110
112
|
} catch (e) {
|
|
111
|
-
if (crashesPreactThenCheck(e)) throw tagPrimitiveThrow(e)
|
|
112
|
-
throw e
|
|
113
|
+
if (crashesPreactThenCheck(e)) throw tagPrimitiveThrow(e)
|
|
114
|
+
throw e
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
|
-
Object.defineProperty(PrimitiveThrowSafe, 'name', { value: Base.name })
|
|
118
|
+
Object.defineProperty(PrimitiveThrowSafe, 'name', { value: Base.name })
|
|
117
119
|
// Copy static properties AND symbol-keyed metadata (displayName, getDerivedStateFromError,
|
|
118
120
|
// contextType, defaultProps, plus the framework's own client-reference/dynamic-reference/params-
|
|
119
121
|
// scope symbol markers stashed directly on component function objects). resolveServerTree branches
|
|
120
122
|
// on those, so losing them mis-routes a client-reference class through the server-component call
|
|
121
123
|
// path instead of the island path.
|
|
122
|
-
copyMetadata(Base, PrimitiveThrowSafe)
|
|
123
|
-
result = PrimitiveThrowSafe
|
|
124
|
+
copyMetadata(Base, PrimitiveThrowSafe)
|
|
125
|
+
result = PrimitiveThrowSafe
|
|
124
126
|
} else {
|
|
125
|
-
const fn = type as unknown as (...args: unknown[]) => unknown
|
|
127
|
+
const fn = type as unknown as (...args: unknown[]) => unknown
|
|
126
128
|
const wrappedFn = function pnextPrimitiveThrowSafe(this: unknown, ...args: unknown[]) {
|
|
127
129
|
try {
|
|
128
|
-
return fn.apply(this, args)
|
|
130
|
+
return fn.apply(this, args)
|
|
129
131
|
} catch (e) {
|
|
130
|
-
if (crashesPreactThenCheck(e)) throw tagPrimitiveThrow(e)
|
|
131
|
-
throw e
|
|
132
|
+
if (crashesPreactThenCheck(e)) throw tagPrimitiveThrow(e)
|
|
133
|
+
throw e
|
|
132
134
|
}
|
|
133
|
-
}
|
|
134
|
-
Object.defineProperty(wrappedFn, 'name', { value: fn.name })
|
|
135
|
-
copyMetadata(fn, wrappedFn)
|
|
136
|
-
result = wrappedFn
|
|
135
|
+
}
|
|
136
|
+
Object.defineProperty(wrappedFn, 'name', { value: fn.name })
|
|
137
|
+
copyMetadata(fn, wrappedFn)
|
|
138
|
+
result = wrappedFn
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
Object.defineProperty(result as object, ALREADY_WRAPPED, { value: true })
|
|
140
|
-
wrapped.set(type, result)
|
|
141
|
-
return result as T
|
|
141
|
+
Object.defineProperty(result as object, ALREADY_WRAPPED, { value: true })
|
|
142
|
+
wrapped.set(type, result)
|
|
143
|
+
return result as T
|
|
142
144
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { softNavigate } from '../../../
|
|
1
|
+
import { softNavigate } from '../../../client/router'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Soft-refresh the current URL from the server (re-runs the hydrated subtree so a data-dependent
|
|
@@ -7,8 +7,8 @@ import { softNavigate } from '../../../api/router';
|
|
|
7
7
|
* ./install - which rides the deferred tier - into first paint.
|
|
8
8
|
*/
|
|
9
9
|
export function softRefreshRoute(): void {
|
|
10
|
-
if (!process.browser && typeof window === 'undefined') return
|
|
10
|
+
if (!process.browser && typeof window === 'undefined') return
|
|
11
11
|
void softNavigate(location.href, { replace: true, scroll: false, remount: true }).catch(() => {
|
|
12
|
-
location.reload()
|
|
13
|
-
})
|
|
12
|
+
location.reload()
|
|
13
|
+
})
|
|
14
14
|
}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
// Per-link navigation pending state for `useLinkStatus()` (next/link). A single link is "pending" at a
|
|
2
2
|
// time: the last one whose click started an in-flight soft navigation. It clears on completion, and on
|
|
3
3
|
// any navigation started elsewhere - all of which broadcast a location change.
|
|
4
|
-
import { createContext } from 'preact'
|
|
5
|
-
import { softNavigate } from '../../
|
|
6
|
-
import { locationListeners, onNavigationStart } from '../../
|
|
7
|
-
import { patchHistory } from '../../api/client-navigation'
|
|
4
|
+
import { createContext } from 'preact'
|
|
5
|
+
import { softNavigate } from '../../client/router'
|
|
6
|
+
import { locationListeners, onNavigationStart } from '../../client/router/events'
|
|
7
|
+
import { patchHistory } from '../../api/client-navigation'
|
|
8
8
|
|
|
9
9
|
export interface LinkStatus {
|
|
10
|
-
pending: boolean
|
|
10
|
+
pending: boolean
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const LinkStatusContext = createContext<LinkStatus>({ pending: false })
|
|
13
|
+
export const LinkStatusContext = createContext<LinkStatus>({ pending: false })
|
|
14
14
|
|
|
15
|
-
type Listener = () => void
|
|
15
|
+
type Listener = () => void
|
|
16
16
|
|
|
17
|
-
let pendingToken: symbol | null = null
|
|
17
|
+
let pendingToken: symbol | null = null
|
|
18
18
|
// Set right before navigateWithStatus starts its own soft-nav, so the resulting
|
|
19
19
|
// synchronous nav-start is recognized as the link's own, not a supersession.
|
|
20
|
-
let ownNavStart: symbol | null = null
|
|
21
|
-
const listeners = new Set<Listener>()
|
|
22
|
-
let wired = false
|
|
20
|
+
let ownNavStart: symbol | null = null
|
|
21
|
+
const listeners = new Set<Listener>()
|
|
22
|
+
let wired = false
|
|
23
23
|
|
|
24
24
|
function notify() {
|
|
25
|
-
for (const listener of [...listeners]) listener()
|
|
25
|
+
for (const listener of [...listeners]) listener()
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function setPending(token: symbol | null) {
|
|
29
|
-
if (pendingToken === token) return
|
|
30
|
-
pendingToken = token
|
|
31
|
-
notify()
|
|
29
|
+
if (pendingToken === token) return
|
|
30
|
+
pendingToken = token
|
|
31
|
+
notify()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// A different navigation starting (router.push, refresh, another link)
|
|
@@ -36,38 +36,38 @@ function setPending(token: symbol | null) {
|
|
|
36
36
|
// in flight — its synchronous start isn't the pending link's own.
|
|
37
37
|
function onNavStart() {
|
|
38
38
|
if (ownNavStart !== null) {
|
|
39
|
-
ownNavStart = null
|
|
40
|
-
return
|
|
39
|
+
ownNavStart = null
|
|
40
|
+
return
|
|
41
41
|
}
|
|
42
|
-
setPending(null)
|
|
42
|
+
setPending(null)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// A location change ends the pending state: for the pending link's own nav this
|
|
46
46
|
// only fires at completion (its pushState happens after the fetch resolves);
|
|
47
47
|
// for shallow pushState / browser back it fires immediately. Both should clear.
|
|
48
48
|
function onLocationChange() {
|
|
49
|
-
setPending(null)
|
|
49
|
+
setPending(null)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function wire() {
|
|
53
|
-
if (wired || (!process.browser && typeof window === 'undefined')) return
|
|
54
|
-
wired = true
|
|
53
|
+
if (wired || (!process.browser && typeof window === 'undefined')) return
|
|
54
|
+
wired = true
|
|
55
55
|
// Raw window.history.pushState/replaceState (shallow routing) must clear the
|
|
56
56
|
// pending link; the patch broadcasts them through locationListeners.
|
|
57
|
-
patchHistory()
|
|
58
|
-
onNavigationStart(onNavStart)
|
|
59
|
-
locationListeners().add(onLocationChange)
|
|
60
|
-
window.addEventListener('popstate', onLocationChange)
|
|
57
|
+
patchHistory()
|
|
58
|
+
onNavigationStart(onNavStart)
|
|
59
|
+
locationListeners().add(onLocationChange)
|
|
60
|
+
window.addEventListener('popstate', onLocationChange)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export function subscribeLinkStatus(_token: symbol, listener: Listener) {
|
|
64
|
-
wire()
|
|
65
|
-
listeners.add(listener)
|
|
66
|
-
return () => listeners.delete(listener)
|
|
64
|
+
wire()
|
|
65
|
+
listeners.add(listener)
|
|
66
|
+
return () => listeners.delete(listener)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export function linkPending(token: symbol) {
|
|
70
|
-
return pendingToken === token
|
|
70
|
+
return pendingToken === token
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
// Start a soft navigation owned by this link: mark it pending, clear on
|
|
@@ -78,9 +78,9 @@ export function navigateWithStatus(
|
|
|
78
78
|
href: string,
|
|
79
79
|
options: { replace?: boolean; scroll?: boolean },
|
|
80
80
|
) {
|
|
81
|
-
ownNavStart = token
|
|
82
|
-
setPending(token)
|
|
81
|
+
ownNavStart = token
|
|
82
|
+
setPending(token)
|
|
83
83
|
void softNavigate(href, options).finally(() => {
|
|
84
|
-
if (pendingToken === token) setPending(null)
|
|
85
|
-
})
|
|
84
|
+
if (pendingToken === token) setPending(null)
|
|
85
|
+
})
|
|
86
86
|
}
|