@wular/pnext 0.0.4 → 0.0.7
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 +22 -16
- package/bin/pnext +6 -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 +87 -22
- package/reference/config.md +40 -93
- package/reference/css.md +42 -33
- package/reference/dev.md +26 -33
- package/reference/env.md +18 -20
- package/reference/getting-started.md +132 -0
- package/reference/metadata.md +31 -46
- package/reference/navigation.md +65 -105
- package/reference/performance.md +21 -142
- package/reference/rendering.md +78 -75
- package/reference/routing.md +97 -107
- package/reference/typegen.md +27 -29
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +121 -114
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +52 -53
- 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 +72 -64
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +94 -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 +802 -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 +32 -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 +2022 -1995
- package/src/{api → client}/router/types.ts +98 -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 -1897
- 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 +86 -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 +2087 -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} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- 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 +87 -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 +827 -815
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +954 -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 +428 -406
- package/src/styles.d.ts +9 -0
- package/src/types.ts +324 -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/reference/overview.md +0 -35
- 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
package/src/utils/serialize.ts
CHANGED
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
// as the action wire's $$pnext_date) instead of throwing; the client/server
|
|
4
4
|
// revive the marker back into the original view. assertSerializable accepts
|
|
5
5
|
// them (they are "serializable" via the marker path) rather than rejecting.
|
|
6
|
-
const TYPED_ARRAY_MARKER = '$$pnext_typed_array'
|
|
7
|
-
const ARRAY_BUFFER_MARKER = '$$pnext_array_buffer'
|
|
6
|
+
const TYPED_ARRAY_MARKER = '$$pnext_typed_array'
|
|
7
|
+
const ARRAY_BUFFER_MARKER = '$$pnext_array_buffer'
|
|
8
8
|
// Map/Set are part of React's flight wire vocabulary (client components can receive them as props); pnext
|
|
9
9
|
// does not stream them as distinct RSC row types yet, so they ride as ordinary marker objects, entries
|
|
10
10
|
// encoded recursively like the binary markers above, instead of throwing "must be a plain object". Client
|
|
11
11
|
// code that only round-trips the value sees a marker object rather than a live Map/Set instance - a known
|
|
12
12
|
// gap, not a full flight-protocol Map/Set.
|
|
13
|
-
const MAP_MARKER = '$$pnext_map'
|
|
14
|
-
const SET_MARKER = '$$pnext_set'
|
|
13
|
+
const MAP_MARKER = '$$pnext_map'
|
|
14
|
+
const SET_MARKER = '$$pnext_set'
|
|
15
15
|
// Cyclic props (a client component receiving `obj.self === obj`) are part of React's flight vocabulary:
|
|
16
16
|
// flight emits a BACK-REFERENCE to the row/path the value was first written at rather than expanding it
|
|
17
17
|
// forever. Same idea here, scoped to the ancestor chain: an object that reappears INSIDE ITSELF is written as
|
|
18
18
|
// `{$$pnext_ref: [...path from the props root]}` and the client patches the original object back in,
|
|
19
19
|
// restoring identity. Only true cycles are encoded this way - a value that merely appears twice in different
|
|
20
20
|
// branches is still expanded, so every acyclic payload is byte-identical to what it was before.
|
|
21
|
-
const REF_MARKER = '$$pnext_ref'
|
|
21
|
+
const REF_MARKER = '$$pnext_ref'
|
|
22
22
|
|
|
23
23
|
type TypedArray =
|
|
24
24
|
| Int8Array
|
|
@@ -31,26 +31,26 @@ type TypedArray =
|
|
|
31
31
|
| Float32Array
|
|
32
32
|
| Float64Array
|
|
33
33
|
| BigInt64Array
|
|
34
|
-
| BigUint64Array
|
|
34
|
+
| BigUint64Array
|
|
35
35
|
|
|
36
36
|
function isTypedArray(value: unknown): value is TypedArray {
|
|
37
|
-
return ArrayBuffer.isView(value) && !(value instanceof DataView)
|
|
37
|
+
return ArrayBuffer.isView(value) && !(value instanceof DataView)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function bytesToBase64(bytes: Uint8Array): string {
|
|
41
|
-
if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64')
|
|
42
|
-
let binary = ''
|
|
43
|
-
for (const byte of bytes) binary += String.fromCharCode(byte)
|
|
44
|
-
return btoa(binary)
|
|
41
|
+
if (typeof Buffer !== 'undefined') return Buffer.from(bytes).toString('base64')
|
|
42
|
+
let binary = ''
|
|
43
|
+
for (const byte of bytes) binary += String.fromCharCode(byte)
|
|
44
|
+
return btoa(binary)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function encodeTypedArray(value: TypedArray) {
|
|
48
|
-
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength)
|
|
49
|
-
return { [TYPED_ARRAY_MARKER]: { type: value.constructor.name, data: bytesToBase64(bytes) } }
|
|
48
|
+
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength)
|
|
49
|
+
return { [TYPED_ARRAY_MARKER]: { type: value.constructor.name, data: bytesToBase64(bytes) } }
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function encodeArrayBuffer(value: ArrayBuffer) {
|
|
53
|
-
return { [ARRAY_BUFFER_MARKER]: bytesToBase64(new Uint8Array(value)) }
|
|
53
|
+
return { [ARRAY_BUFFER_MARKER]: bytesToBase64(new Uint8Array(value)) }
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -66,24 +66,20 @@ function encodeBinary(
|
|
|
66
66
|
ancestors = new Map<object, string[]>(),
|
|
67
67
|
path: string[] = [],
|
|
68
68
|
): unknown {
|
|
69
|
-
if (value === null || typeof value !== 'object') return value
|
|
70
|
-
if (isTypedArray(value)) return encodeTypedArray(value)
|
|
71
|
-
if (value instanceof ArrayBuffer) return encodeArrayBuffer(value)
|
|
72
|
-
const ancestorPath = ancestors.get(value)
|
|
73
|
-
if (ancestorPath) return { [REF_MARKER]: ancestorPath }
|
|
74
|
-
ancestors.set(value, path)
|
|
75
|
-
const encoded = encodeContainer(value, ancestors, path)
|
|
76
|
-
ancestors.delete(value)
|
|
77
|
-
return encoded
|
|
69
|
+
if (value === null || typeof value !== 'object') return value
|
|
70
|
+
if (isTypedArray(value)) return encodeTypedArray(value)
|
|
71
|
+
if (value instanceof ArrayBuffer) return encodeArrayBuffer(value)
|
|
72
|
+
const ancestorPath = ancestors.get(value)
|
|
73
|
+
if (ancestorPath) return { [REF_MARKER]: ancestorPath }
|
|
74
|
+
ancestors.set(value, path)
|
|
75
|
+
const encoded = encodeContainer(value, ancestors, path)
|
|
76
|
+
ancestors.delete(value)
|
|
77
|
+
return encoded
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
function encodeContainer(
|
|
81
|
-
value: object,
|
|
82
|
-
ancestors: Map<object, string[]>,
|
|
83
|
-
path: string[],
|
|
84
|
-
): unknown {
|
|
80
|
+
function encodeContainer(value: object, ancestors: Map<object, string[]>, path: string[]): unknown {
|
|
85
81
|
if (Array.isArray(value)) {
|
|
86
|
-
return value.map((item, index) => encodeBinary(item, ancestors, [...path, String(index)]))
|
|
82
|
+
return value.map((item, index) => encodeBinary(item, ancestors, [...path, String(index)]))
|
|
87
83
|
}
|
|
88
84
|
if (value instanceof Map) {
|
|
89
85
|
return {
|
|
@@ -91,22 +87,22 @@ function encodeContainer(
|
|
|
91
87
|
encodeBinary(k, ancestors),
|
|
92
88
|
encodeBinary(v, ancestors),
|
|
93
89
|
]),
|
|
94
|
-
}
|
|
90
|
+
}
|
|
95
91
|
}
|
|
96
92
|
if (value instanceof Set) {
|
|
97
|
-
return { [SET_MARKER]: [...value].map(item => encodeBinary(item, ancestors)) }
|
|
93
|
+
return { [SET_MARKER]: [...value].map(item => encodeBinary(item, ancestors)) }
|
|
98
94
|
}
|
|
99
|
-
if (Object.getPrototypeOf(value) !== Object.prototype) return value
|
|
100
|
-
const out: Record<string, unknown> = {}
|
|
95
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) return value
|
|
96
|
+
const out: Record<string, unknown> = {}
|
|
101
97
|
for (const [key, item] of Object.entries(value)) {
|
|
102
|
-
out[key] = encodeBinary(item, ancestors, [...path, key])
|
|
98
|
+
out[key] = encodeBinary(item, ancestors, [...path, key])
|
|
103
99
|
}
|
|
104
|
-
return out
|
|
100
|
+
return out
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
// Errors reach `error.tsx` as props and ride the same marker convention (the
|
|
108
104
|
// encoder for this one lives on the render side, with the boundary props).
|
|
109
|
-
const ERROR_MARKER = '$$pnextError'
|
|
105
|
+
const ERROR_MARKER = '$$pnextError'
|
|
110
106
|
|
|
111
107
|
/**
|
|
112
108
|
* Revive the wire markers `serializeProps` wrote, IN PLACE:
|
|
@@ -124,22 +120,22 @@ export function reviveSerializedRefs<T>(
|
|
|
124
120
|
root: T,
|
|
125
121
|
extra?: (node: Record<string, unknown>) => unknown,
|
|
126
122
|
): T {
|
|
127
|
-
if (root === null || typeof root !== 'object') return root
|
|
123
|
+
if (root === null || typeof root !== 'object') return root
|
|
128
124
|
const visit = (node: Record<string, unknown>): void => {
|
|
129
125
|
for (const key of Object.keys(node)) {
|
|
130
|
-
const item = node[key]
|
|
131
|
-
if (item === null || typeof item !== 'object' || ArrayBuffer.isView(item)) continue
|
|
132
|
-
const child = item as Record<string, unknown
|
|
133
|
-
const revived = refTarget(root, child) ?? extra?.(child) ?? binaryTarget(child)
|
|
126
|
+
const item = node[key]
|
|
127
|
+
if (item === null || typeof item !== 'object' || ArrayBuffer.isView(item)) continue
|
|
128
|
+
const child = item as Record<string, unknown>
|
|
129
|
+
const revived = refTarget(root, child) ?? extra?.(child) ?? binaryTarget(child)
|
|
134
130
|
if (revived !== undefined) {
|
|
135
|
-
node[key] = revived
|
|
136
|
-
continue
|
|
131
|
+
node[key] = revived
|
|
132
|
+
continue
|
|
137
133
|
}
|
|
138
|
-
visit(child)
|
|
134
|
+
visit(child)
|
|
139
135
|
}
|
|
140
|
-
}
|
|
141
|
-
visit(root as Record<string, unknown>)
|
|
142
|
-
return root
|
|
136
|
+
}
|
|
137
|
+
visit(root as Record<string, unknown>)
|
|
138
|
+
return root
|
|
143
139
|
}
|
|
144
140
|
|
|
145
141
|
/**
|
|
@@ -149,17 +145,17 @@ export function reviveSerializedRefs<T>(
|
|
|
149
145
|
* untouched when compat is off), and only compat entries import this name.
|
|
150
146
|
*/
|
|
151
147
|
export function reviveSerializedErrorRefs<T>(root: T): T {
|
|
152
|
-
return reviveSerializedRefs(root, errorTarget)
|
|
148
|
+
return reviveSerializedRefs(root, errorTarget)
|
|
153
149
|
}
|
|
154
150
|
|
|
155
151
|
function errorTarget(node: Record<string, unknown>): Error | undefined {
|
|
156
|
-
const marker = node[ERROR_MARKER]
|
|
157
|
-
if (marker === null || typeof marker !== 'object') return undefined
|
|
158
|
-
const data = marker as { name?: unknown; message?: unknown; digest?: unknown }
|
|
159
|
-
const error = new Error(typeof data.message === 'string' ? data.message : '')
|
|
160
|
-
if (typeof data.name === 'string') error.name = data.name
|
|
161
|
-
if (typeof data.digest === 'string') (error as Error & { digest?: string }).digest = data.digest
|
|
162
|
-
return error
|
|
152
|
+
const marker = node[ERROR_MARKER]
|
|
153
|
+
if (marker === null || typeof marker !== 'object') return undefined
|
|
154
|
+
const data = marker as { name?: unknown; message?: unknown; digest?: unknown }
|
|
155
|
+
const error = new Error(typeof data.message === 'string' ? data.message : '')
|
|
156
|
+
if (typeof data.name === 'string') error.name = data.name
|
|
157
|
+
if (typeof data.digest === 'string') (error as Error & { digest?: string }).digest = data.digest
|
|
158
|
+
return error
|
|
163
159
|
}
|
|
164
160
|
|
|
165
161
|
// The wire carries the view's constructor NAME. Resolved off the global rather than a name-to-constructor
|
|
@@ -167,48 +163,48 @@ function errorTarget(node: Record<string, unknown>): Error | undefined {
|
|
|
167
163
|
// so any other name - including one that resolves to something else entirely - resolves to undefined and the
|
|
168
164
|
// marker is left alone.
|
|
169
165
|
function typedArrayConstructor(name: string) {
|
|
170
|
-
const constructor = (globalThis as unknown as Record<string, unknown>)[name]
|
|
166
|
+
const constructor = (globalThis as unknown as Record<string, unknown>)[name]
|
|
171
167
|
return typeof constructor === 'function' && 'BYTES_PER_ELEMENT' in constructor
|
|
172
168
|
? (constructor as unknown as new (buffer: ArrayBuffer) => TypedArray)
|
|
173
|
-
: undefined
|
|
169
|
+
: undefined
|
|
174
170
|
}
|
|
175
171
|
|
|
176
172
|
// Decode side is client-only (the encoder is what runs on the server), so no
|
|
177
173
|
// Buffer fast path — `atob` is global in every runtime that reaches this.
|
|
178
174
|
function base64ToBytes(data: string): Uint8Array {
|
|
179
|
-
return Uint8Array.from(atob(data), character => character.charCodeAt(0))
|
|
175
|
+
return Uint8Array.from(atob(data), character => character.charCodeAt(0))
|
|
180
176
|
}
|
|
181
177
|
|
|
182
178
|
function binaryTarget(node: Record<string, unknown>): TypedArray | ArrayBuffer | undefined {
|
|
183
|
-
const buffer = node[ARRAY_BUFFER_MARKER]
|
|
184
|
-
if (typeof buffer === 'string') return base64ToBytes(buffer).buffer as ArrayBuffer
|
|
185
|
-
const typed = node[TYPED_ARRAY_MARKER]
|
|
186
|
-
if (typed === null || typeof typed !== 'object') return undefined
|
|
187
|
-
const { type, data } = typed as { type?: unknown; data?: unknown }
|
|
188
|
-
if (typeof type !== 'string' || typeof data !== 'string') return undefined
|
|
189
|
-
const Constructor = typedArrayConstructor(type)
|
|
190
|
-
return Constructor ? new Constructor(base64ToBytes(data).buffer as ArrayBuffer) : undefined
|
|
179
|
+
const buffer = node[ARRAY_BUFFER_MARKER]
|
|
180
|
+
if (typeof buffer === 'string') return base64ToBytes(buffer).buffer as ArrayBuffer
|
|
181
|
+
const typed = node[TYPED_ARRAY_MARKER]
|
|
182
|
+
if (typed === null || typeof typed !== 'object') return undefined
|
|
183
|
+
const { type, data } = typed as { type?: unknown; data?: unknown }
|
|
184
|
+
if (typeof type !== 'string' || typeof data !== 'string') return undefined
|
|
185
|
+
const Constructor = typedArrayConstructor(type)
|
|
186
|
+
return Constructor ? new Constructor(base64ToBytes(data).buffer as ArrayBuffer) : undefined
|
|
191
187
|
}
|
|
192
188
|
|
|
193
189
|
function refTarget(root: unknown, node: Record<string, unknown>): unknown {
|
|
194
|
-
const path = node[REF_MARKER]
|
|
195
|
-
if (!Array.isArray(path)) return undefined
|
|
196
|
-
let current: unknown = root
|
|
190
|
+
const path = node[REF_MARKER]
|
|
191
|
+
if (!Array.isArray(path)) return undefined
|
|
192
|
+
let current: unknown = root
|
|
197
193
|
for (const key of path) {
|
|
198
|
-
if (current === null || typeof current !== 'object') return undefined
|
|
199
|
-
current = (current as Record<string, unknown>)[String(key)]
|
|
194
|
+
if (current === null || typeof current !== 'object') return undefined
|
|
195
|
+
current = (current as Record<string, unknown>)[String(key)]
|
|
200
196
|
}
|
|
201
|
-
return current
|
|
197
|
+
return current
|
|
202
198
|
}
|
|
203
199
|
|
|
204
200
|
/** A preact vnode: `h` sets `constructor` to undefined on every one it makes. */
|
|
205
201
|
export function isElementLike(value: unknown): boolean {
|
|
206
|
-
if (value === null || typeof value !== 'object') return false
|
|
202
|
+
if (value === null || typeof value !== 'object') return false
|
|
207
203
|
return (
|
|
208
204
|
(value as { constructor?: unknown }).constructor === undefined &&
|
|
209
205
|
'type' in value &&
|
|
210
206
|
'props' in value
|
|
211
|
-
)
|
|
207
|
+
)
|
|
212
208
|
}
|
|
213
209
|
|
|
214
210
|
export function assertSerializable(
|
|
@@ -219,59 +215,59 @@ export function assertSerializable(
|
|
|
219
215
|
// static-slots), so they are serializable there. Server-action args/returns keep throwing.
|
|
220
216
|
allowElements = false,
|
|
221
217
|
) {
|
|
222
|
-
if (value == null) return
|
|
223
|
-
if (allowElements && isElementLike(value)) return
|
|
224
|
-
const type = typeof value
|
|
225
|
-
if (type === 'string' || type === 'number' || type === 'boolean') return
|
|
218
|
+
if (value == null) return
|
|
219
|
+
if (allowElements && isElementLike(value)) return
|
|
220
|
+
const type = typeof value
|
|
221
|
+
if (type === 'string' || type === 'number' || type === 'boolean') return
|
|
226
222
|
if (type === 'function' || type === 'symbol' || type === 'bigint' || type === 'undefined') {
|
|
227
|
-
throw new Error(`${path} is not serializable: ${type}`)
|
|
223
|
+
throw new Error(`${path} is not serializable: ${type}`)
|
|
228
224
|
}
|
|
229
225
|
// Typed arrays / ArrayBuffers are serializable via the binary marker path.
|
|
230
|
-
if (isTypedArray(value) || value instanceof ArrayBuffer) return
|
|
226
|
+
if (isTypedArray(value) || value instanceof ArrayBuffer) return
|
|
231
227
|
if (value instanceof Date || value instanceof URL) {
|
|
232
|
-
throw new Error(`${path} must be a plain JSON value`)
|
|
228
|
+
throw new Error(`${path} must be a plain JSON value`)
|
|
233
229
|
}
|
|
234
|
-
if (typeof value !== 'object') return
|
|
230
|
+
if (typeof value !== 'object') return
|
|
235
231
|
// A value that contains ITSELF is serializable: encodeBinary writes it as a
|
|
236
232
|
// `$$pnext_ref` back-reference (React flight does the same), so stop walking
|
|
237
233
|
// rather than rejecting the props.
|
|
238
|
-
if (seen.has(value)) return
|
|
239
|
-
seen.add(value)
|
|
234
|
+
if (seen.has(value)) return
|
|
235
|
+
seen.add(value)
|
|
240
236
|
|
|
241
237
|
if (Array.isArray(value)) {
|
|
242
238
|
value.forEach((item, index) =>
|
|
243
239
|
assertSerializable(item, `${path}[${index}]`, seen, allowElements),
|
|
244
|
-
)
|
|
245
|
-
return
|
|
240
|
+
)
|
|
241
|
+
return
|
|
246
242
|
}
|
|
247
243
|
|
|
248
|
-
// The slot walk (
|
|
244
|
+
// The slot walk (render/static-slots) never enters Map/Set, so elements inside them must
|
|
249
245
|
// still throw rather than ship mangled.
|
|
250
246
|
if (value instanceof Map) {
|
|
251
|
-
let index = 0
|
|
247
|
+
let index = 0
|
|
252
248
|
for (const [key, item] of value.entries()) {
|
|
253
|
-
assertSerializable(key, `${path}<Map key ${index}>`, seen)
|
|
254
|
-
assertSerializable(item, `${path}<Map value ${index}>`, seen)
|
|
255
|
-
index
|
|
249
|
+
assertSerializable(key, `${path}<Map key ${index}>`, seen)
|
|
250
|
+
assertSerializable(item, `${path}<Map value ${index}>`, seen)
|
|
251
|
+
index++
|
|
256
252
|
}
|
|
257
|
-
return
|
|
253
|
+
return
|
|
258
254
|
}
|
|
259
255
|
|
|
260
256
|
if (value instanceof Set) {
|
|
261
|
-
let index = 0
|
|
257
|
+
let index = 0
|
|
262
258
|
for (const item of value) {
|
|
263
|
-
assertSerializable(item, `${path}<Set item ${index}>`, seen)
|
|
264
|
-
index
|
|
259
|
+
assertSerializable(item, `${path}<Set item ${index}>`, seen)
|
|
260
|
+
index++
|
|
265
261
|
}
|
|
266
|
-
return
|
|
262
|
+
return
|
|
267
263
|
}
|
|
268
264
|
|
|
269
265
|
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
270
|
-
throw new Error(`${path} must be a plain object`)
|
|
266
|
+
throw new Error(`${path} must be a plain object`)
|
|
271
267
|
}
|
|
272
268
|
|
|
273
269
|
for (const [key, item] of Object.entries(value)) {
|
|
274
|
-
assertSerializable(item, `${path}.${key}`, seen, allowElements)
|
|
270
|
+
assertSerializable(item, `${path}.${key}`, seen, allowElements)
|
|
275
271
|
}
|
|
276
272
|
}
|
|
277
273
|
|
|
@@ -291,26 +287,26 @@ export function assertSerializable(
|
|
|
291
287
|
// original) must not split the tainted set.
|
|
292
288
|
// ---------------------------------------------------------------------------
|
|
293
289
|
|
|
294
|
-
const TAINT_REGISTRY_KEY = '__pnext_tainted_values__'
|
|
290
|
+
const TAINT_REGISTRY_KEY = '__pnext_tainted_values__'
|
|
295
291
|
|
|
296
292
|
/** Dev message plus the redacted text prod shows in its place. */
|
|
297
293
|
export interface TaintMessages {
|
|
298
|
-
dev: string
|
|
299
|
-
prod: string
|
|
294
|
+
dev: string
|
|
295
|
+
prod: string
|
|
300
296
|
}
|
|
301
297
|
|
|
302
298
|
function taintRegistry(): Map<object, TaintMessages> {
|
|
303
|
-
const host = globalThis as { [TAINT_REGISTRY_KEY]?: Map<object, TaintMessages> }
|
|
304
|
-
const existing = host[TAINT_REGISTRY_KEY]
|
|
305
|
-
if (existing) return existing
|
|
306
|
-
const created = new Map<object, TaintMessages>()
|
|
307
|
-
host[TAINT_REGISTRY_KEY] = created
|
|
308
|
-
return created
|
|
299
|
+
const host = globalThis as { [TAINT_REGISTRY_KEY]?: Map<object, TaintMessages> }
|
|
300
|
+
const existing = host[TAINT_REGISTRY_KEY]
|
|
301
|
+
if (existing) return existing
|
|
302
|
+
const created = new Map<object, TaintMessages>()
|
|
303
|
+
host[TAINT_REGISTRY_KEY] = created
|
|
304
|
+
return created
|
|
309
305
|
}
|
|
310
306
|
|
|
311
307
|
/** Register `value` as unsafe to pass to a client component. */
|
|
312
308
|
export function taintObjectReference(messages: TaintMessages, value: object): void {
|
|
313
|
-
taintRegistry().set(value, messages)
|
|
309
|
+
taintRegistry().set(value, messages)
|
|
314
310
|
}
|
|
315
311
|
|
|
316
312
|
/**
|
|
@@ -319,60 +315,57 @@ export function taintObjectReference(messages: TaintMessages, value: object): vo
|
|
|
319
315
|
* identity the check relies on).
|
|
320
316
|
*/
|
|
321
317
|
export function assertNotTainted(value: unknown, seen = new Set<unknown>()): void {
|
|
322
|
-
const registry = taintRegistry()
|
|
323
|
-
if (registry.size === 0) return
|
|
324
|
-
if (value === null || typeof value !== 'object') return
|
|
325
|
-
const messages = registry.get(value)
|
|
318
|
+
const registry = taintRegistry()
|
|
319
|
+
if (registry.size === 0) return
|
|
320
|
+
if (value === null || typeof value !== 'object') return
|
|
321
|
+
const messages = registry.get(value)
|
|
326
322
|
if (messages !== undefined) {
|
|
327
323
|
// Next surfaces the explanatory message in dev only; prod renders React's
|
|
328
324
|
// redacted RSC error text in the nearest error boundary.
|
|
329
325
|
throw new Error(
|
|
330
326
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
331
327
|
process.env.NODE_ENV === 'development' ? messages.dev : messages.prod,
|
|
332
|
-
)
|
|
328
|
+
)
|
|
333
329
|
}
|
|
334
|
-
if (seen.has(value)) return
|
|
335
|
-
seen.add(value)
|
|
330
|
+
if (seen.has(value)) return
|
|
331
|
+
seen.add(value)
|
|
336
332
|
if (Array.isArray(value)) {
|
|
337
|
-
for (const item of value) assertNotTainted(item, seen)
|
|
338
|
-
return
|
|
333
|
+
for (const item of value) assertNotTainted(item, seen)
|
|
334
|
+
return
|
|
339
335
|
}
|
|
340
336
|
if (value instanceof Map) {
|
|
341
337
|
for (const [key, item] of value.entries()) {
|
|
342
|
-
assertNotTainted(key, seen)
|
|
343
|
-
assertNotTainted(item, seen)
|
|
338
|
+
assertNotTainted(key, seen)
|
|
339
|
+
assertNotTainted(item, seen)
|
|
344
340
|
}
|
|
345
|
-
return
|
|
341
|
+
return
|
|
346
342
|
}
|
|
347
343
|
if (value instanceof Set) {
|
|
348
|
-
for (const item of value) assertNotTainted(item, seen)
|
|
349
|
-
return
|
|
344
|
+
for (const item of value) assertNotTainted(item, seen)
|
|
345
|
+
return
|
|
350
346
|
}
|
|
351
|
-
const proto = Object.getPrototypeOf(value) as object | null
|
|
352
|
-
if (proto !== Object.prototype && proto !== null) return
|
|
353
|
-
for (const item of Object.values(value)) assertNotTainted(item, seen)
|
|
347
|
+
const proto = Object.getPrototypeOf(value) as object | null
|
|
348
|
+
if (proto !== Object.prototype && proto !== null) return
|
|
349
|
+
for (const item of Object.values(value)) assertNotTainted(item, seen)
|
|
354
350
|
}
|
|
355
351
|
|
|
356
352
|
export function serializeProps(value: unknown, options?: { allowElements?: boolean }) {
|
|
357
|
-
assertNotTainted(value)
|
|
358
|
-
assertSerializable(value, 'props', new Set(), options?.allowElements)
|
|
359
|
-
return JSON.stringify(encodeBinary(value)).replace(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
},
|
|
377
|
-
);
|
|
353
|
+
assertNotTainted(value)
|
|
354
|
+
assertSerializable(value, 'props', new Set(), options?.allowElements)
|
|
355
|
+
return JSON.stringify(encodeBinary(value)).replace(/[<>&\u2028\u2029]/g, char => {
|
|
356
|
+
switch (char) {
|
|
357
|
+
case '<':
|
|
358
|
+
return '\\u003c'
|
|
359
|
+
case '>':
|
|
360
|
+
return '\\u003e'
|
|
361
|
+
case '&':
|
|
362
|
+
return '\\u0026'
|
|
363
|
+
case '\u2028':
|
|
364
|
+
return '\\u2028'
|
|
365
|
+
case '\u2029':
|
|
366
|
+
return '\\u2029'
|
|
367
|
+
default:
|
|
368
|
+
return char
|
|
369
|
+
}
|
|
370
|
+
})
|
|
378
371
|
}
|
package/src/utils/verbose.ts
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { dim } from './ansi'
|
|
1
|
+
import { dim } from './ansi'
|
|
2
2
|
|
|
3
3
|
export interface VerboseLogger {
|
|
4
|
-
readonly enabled: boolean
|
|
5
|
-
log(message: string): void
|
|
6
|
-
step<T>(label: string, task: () => Promise<T>): Promise<T
|
|
4
|
+
readonly enabled: boolean
|
|
5
|
+
log(message: string): void
|
|
6
|
+
step<T>(label: string, task: () => Promise<T>): Promise<T>
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export function createVerboseLogger(enabled: boolean, scope: string): VerboseLogger {
|
|
10
|
-
const prefix = dim(`pnext ${scope}`)
|
|
10
|
+
const prefix = dim(`pnext ${scope}`)
|
|
11
11
|
// Stamp every line with time-since-process-start: once stages run in
|
|
12
12
|
// parallel their lines interleave, and only the stamps say what overlapped.
|
|
13
13
|
const write = (message: string) =>
|
|
14
|
-
console.log(`${prefix} ${dim(`@${(performance.now() / 1000).toFixed(2)}s`)} ${message}`)
|
|
14
|
+
console.log(`${prefix} ${dim(`@${(performance.now() / 1000).toFixed(2)}s`)} ${message}`)
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
enabled,
|
|
18
18
|
log(message) {
|
|
19
|
-
if (enabled) write(message)
|
|
19
|
+
if (enabled) write(message)
|
|
20
20
|
},
|
|
21
21
|
async step(label, task) {
|
|
22
|
-
if (!enabled) return task()
|
|
23
|
-
write(label)
|
|
24
|
-
const start = performance.now()
|
|
22
|
+
if (!enabled) return task()
|
|
23
|
+
write(label)
|
|
24
|
+
const start = performance.now()
|
|
25
25
|
try {
|
|
26
|
-
return await task()
|
|
26
|
+
return await task()
|
|
27
27
|
} finally {
|
|
28
|
-
write(` ${dim(`↳ ${label} ${formatDuration(performance.now() - start)}`)}`)
|
|
28
|
+
write(` ${dim(`↳ ${label} ${formatDuration(performance.now() - start)}`)}`)
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
-
}
|
|
31
|
+
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function formatDuration(durationMs: number) {
|
|
35
|
-
const ms = Math.max(0, durationMs)
|
|
36
|
-
if (ms < 10) return `${ms.toFixed(1)}ms
|
|
37
|
-
if (ms < 1000) return `${Math.round(ms)}ms
|
|
38
|
-
return `${(ms / 1000).toFixed(ms < 10000 ? 2 : 1)}s
|
|
34
|
+
export function formatDuration(durationMs: number) {
|
|
35
|
+
const ms = Math.max(0, durationMs)
|
|
36
|
+
if (ms < 10) return `${ms.toFixed(1)}ms`
|
|
37
|
+
if (ms < 1000) return `${Math.round(ms)}ms`
|
|
38
|
+
return `${(ms / 1000).toFixed(ms < 10000 ? 2 : 1)}s`
|
|
39
39
|
}
|
package/reference/overview.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# pnext
|
|
2
|
-
|
|
3
|
-
pnext is a Preact framework for file-routed applications. It keeps familiar Next-style routing and rendering semantics where they help, and diverges where pnext needs a simpler or smaller model.
|
|
4
|
-
|
|
5
|
-
It renders on the server by default, passes request data through explicit props, provides strong generated route type safety, and ships client JavaScript only for components that opt into running in the browser.
|
|
6
|
-
|
|
7
|
-
## Core Model
|
|
8
|
-
|
|
9
|
-
- Routes live in an `app/` directory.
|
|
10
|
-
- `page.tsx` files define UI routes.
|
|
11
|
-
- `layout.tsx` files export metadata, viewport, and can wrap descendant pages.
|
|
12
|
-
- `route.ts` files define HTTP handlers.
|
|
13
|
-
- `proxy.ts` or `middleware.ts` can run before route matching.
|
|
14
|
-
- `loading.tsx`, `error.tsx`, and `not-found.tsx` define route fallbacks.
|
|
15
|
-
- Pages and layouts are pnext Server Components by default.
|
|
16
|
-
- Server components can be async.
|
|
17
|
-
- Pages without client components emit HTML without pnext client JavaScript.
|
|
18
|
-
- Client Components can be loaded with `dynamic({ load: 'visible' })` and deferred until visible.
|
|
19
|
-
- React compatibility mode supported via `compat.react`.
|
|
20
|
-
- Next compatibility mode supported via `compat.next`.
|
|
21
|
-
- Experimental React Compiler support for React-style Client Components via `compat.reactCompiler`.
|
|
22
|
-
|
|
23
|
-
## References
|
|
24
|
-
|
|
25
|
-
- [Config](./config.md)
|
|
26
|
-
- [Routing](./routing.md)
|
|
27
|
-
- [Metadata](./metadata.md)
|
|
28
|
-
- [Navigation](./navigation.md)
|
|
29
|
-
- [Rendering](./rendering.md)
|
|
30
|
-
- [CSS](./css.md)
|
|
31
|
-
- [Environment Variables](./env.md)
|
|
32
|
-
- [Compatibility](./compat.md)
|
|
33
|
-
- [Typegen](./typegen.md)
|
|
34
|
-
- [Dev Server](./dev.md)
|
|
35
|
-
- [Performance](./performance.md)
|