@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
package/src/render/slots.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
-
import { basename, join, relative, sep } from 'node:path'
|
|
3
|
-
import { h, type ComponentChildren, type ComponentType } from 'preact'
|
|
4
|
-
import type { RouteParamsSnapshot } from './island-context'
|
|
5
|
-
import { Suspense } from '../api/suspense'
|
|
6
|
-
import type { ClientReference } from '../client/reference'
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
+
import { basename, join, relative, sep } from 'node:path'
|
|
3
|
+
import { h, type ComponentChildren, type ComponentType } from 'preact'
|
|
4
|
+
import type { RouteParamsSnapshot } from './island-context'
|
|
5
|
+
import { Suspense } from '../api/suspense'
|
|
6
|
+
import type { ClientReference } from '../client/reference'
|
|
7
7
|
import {
|
|
8
8
|
consumedSegments,
|
|
9
9
|
isGroupSegment,
|
|
@@ -14,92 +14,87 @@ import {
|
|
|
14
14
|
slotConventionFile,
|
|
15
15
|
slotDirectoriesIn,
|
|
16
16
|
type SegmentMatch,
|
|
17
|
-
} from '../routing/slots'
|
|
18
|
-
import { toPosixPath } from '../utils/fs'
|
|
19
|
-
import type {
|
|
20
|
-
PageProps,
|
|
21
|
-
RouteManifestEntry,
|
|
22
|
-
RouteParamValue,
|
|
23
|
-
ServerComponent,
|
|
24
|
-
} from '../types';
|
|
17
|
+
} from '../routing/slots'
|
|
18
|
+
import { toPosixPath } from '../utils/fs'
|
|
19
|
+
import type { PageProps, RouteManifestEntry, RouteParamValue, ServerComponent } from '../types'
|
|
25
20
|
|
|
26
21
|
interface SlotRenderOptions {
|
|
27
|
-
config: { appPath: string }
|
|
28
|
-
url: URL
|
|
22
|
+
config: { appPath: string }
|
|
23
|
+
url: URL
|
|
29
24
|
nav?: {
|
|
30
|
-
soft?: boolean
|
|
31
|
-
childrenPath?: string
|
|
32
|
-
targetPath?: string
|
|
33
|
-
state?: { childrenSearch?: string; slots?: Record<string, string> }
|
|
34
|
-
}
|
|
35
|
-
route: Pick<RouteManifestEntry, 'clientReferences' | 'slotDirs'
|
|
36
|
-
params?: Record<string, RouteParamValue
|
|
37
|
-
clientComponents?: Map<string, ComponentType<Record<string, unknown
|
|
38
|
-
slotStateOut?: Record<string, string
|
|
39
|
-
moduleLoader?: (file: string) => Promise<Record<string, unknown>> | Record<string, unknown
|
|
25
|
+
soft?: boolean
|
|
26
|
+
childrenPath?: string
|
|
27
|
+
targetPath?: string
|
|
28
|
+
state?: { childrenSearch?: string; slots?: Record<string, string> }
|
|
29
|
+
}
|
|
30
|
+
route: Pick<RouteManifestEntry, 'clientReferences' | 'slotDirs'>
|
|
31
|
+
params?: Record<string, RouteParamValue>
|
|
32
|
+
clientComponents?: Map<string, ComponentType<Record<string, unknown>>>
|
|
33
|
+
slotStateOut?: Record<string, string>
|
|
34
|
+
moduleLoader?: (file: string) => Promise<Record<string, unknown>> | Record<string, unknown>
|
|
40
35
|
}
|
|
41
36
|
|
|
42
37
|
interface ServerVNodeProps extends Record<string, unknown> {
|
|
43
|
-
children?: ComponentChildren
|
|
38
|
+
children?: ComponentChildren
|
|
44
39
|
}
|
|
45
40
|
|
|
46
41
|
interface PageModule {
|
|
47
|
-
default?: ServerComponent<PageProps
|
|
42
|
+
default?: ServerComponent<PageProps>
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
interface LayoutModule {
|
|
51
|
-
default?: ServerComponent<{ children: ComponentChildren }
|
|
46
|
+
default?: ServerComponent<{ children: ComponentChildren }>
|
|
52
47
|
}
|
|
53
48
|
|
|
54
49
|
interface LoadingModule {
|
|
55
|
-
default?: ServerComponent<Record<string, never
|
|
50
|
+
default?: ServerComponent<Record<string, never>>
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
interface SlotRenderDeps<Options extends SlotRenderOptions> {
|
|
59
|
-
importModule: (file: string, options: Options) => Promise<Record<string, unknown
|
|
60
|
-
markServerReference: <T>(component: T) => T
|
|
61
|
-
clientReferenceStub: (reference: ClientReference) => ComponentType<Record<string, unknown
|
|
62
|
-
createPageProps: (options: Options) => PageProps
|
|
54
|
+
importModule: (file: string, options: Options) => Promise<Record<string, unknown>>
|
|
55
|
+
markServerReference: <T>(component: T) => T
|
|
56
|
+
clientReferenceStub: (reference: ClientReference) => ComponentType<Record<string, unknown>>
|
|
57
|
+
createPageProps: (options: Options) => PageProps
|
|
63
58
|
}
|
|
64
59
|
|
|
65
60
|
export interface SlotContext<Options extends SlotRenderOptions = SlotRenderOptions> {
|
|
66
|
-
options: Options
|
|
67
|
-
deps: SlotRenderDeps<Options
|
|
68
|
-
appPath: string
|
|
69
|
-
urlPath: string
|
|
70
|
-
urlSegments: string[]
|
|
61
|
+
options: Options
|
|
62
|
+
deps: SlotRenderDeps<Options>
|
|
63
|
+
appPath: string
|
|
64
|
+
urlPath: string
|
|
65
|
+
urlSegments: string[]
|
|
71
66
|
/** The request's search string (`?a=b` or ''), `_rsc` union query stripped. */
|
|
72
|
-
urlSearch: string
|
|
73
|
-
childrenPath: string
|
|
74
|
-
childrenSegments: string[]
|
|
67
|
+
urlSearch: string
|
|
68
|
+
childrenPath: string
|
|
69
|
+
childrenSegments: string[]
|
|
75
70
|
/** Search string the children tree renders with (host renders inherit it). */
|
|
76
|
-
childrenSearch: string
|
|
77
|
-
soft: boolean
|
|
78
|
-
statePaths: Record<string, string
|
|
79
|
-
stateOut: Record<string, string
|
|
80
|
-
matches: ResolvedSlotMatch[]
|
|
71
|
+
childrenSearch: string
|
|
72
|
+
soft: boolean
|
|
73
|
+
statePaths: Record<string, string>
|
|
74
|
+
stateOut: Record<string, string>
|
|
75
|
+
matches: ResolvedSlotMatch[]
|
|
81
76
|
}
|
|
82
77
|
|
|
83
78
|
export interface ResolvedSlotMatch {
|
|
84
|
-
slotDir: string
|
|
85
|
-
pageFile?: string
|
|
86
|
-
layoutFiles: string[]
|
|
87
|
-
params: Record<string, RouteParamValue
|
|
79
|
+
slotDir: string
|
|
80
|
+
pageFile?: string
|
|
81
|
+
layoutFiles: string[]
|
|
82
|
+
params: Record<string, RouteParamValue>
|
|
88
83
|
}
|
|
89
84
|
|
|
90
85
|
export function createSlotContext<Options extends SlotRenderOptions>(
|
|
91
86
|
options: Options,
|
|
92
87
|
deps: SlotRenderDeps<Options>,
|
|
93
88
|
): SlotContext<Options> {
|
|
94
|
-
const urlPath = trimPathname(options.nav?.targetPath ?? options.url.pathname)
|
|
95
|
-
const childrenPath = trimPathname(options.nav?.childrenPath ?? options.url.pathname)
|
|
96
|
-
const urlSearch = stripRscSearch(options.url.search)
|
|
89
|
+
const urlPath = trimPathname(options.nav?.targetPath ?? options.url.pathname)
|
|
90
|
+
const childrenPath = trimPathname(options.nav?.childrenPath ?? options.url.pathname)
|
|
91
|
+
const urlSearch = stripRscSearch(options.url.search)
|
|
97
92
|
// A host render (children anchored away from the URL) keeps the children
|
|
98
93
|
// tree's own recorded query; a direct render's children query IS the URL's.
|
|
99
94
|
const childrenSearch =
|
|
100
95
|
options.nav?.soft && childrenPath !== trimPathname(options.url.pathname)
|
|
101
96
|
? (options.nav?.state?.childrenSearch ?? '')
|
|
102
|
-
: urlSearch
|
|
97
|
+
: urlSearch
|
|
103
98
|
return {
|
|
104
99
|
options,
|
|
105
100
|
deps,
|
|
@@ -114,30 +109,30 @@ export function createSlotContext<Options extends SlotRenderOptions>(
|
|
|
114
109
|
statePaths: options.nav?.state?.slots ?? {},
|
|
115
110
|
stateOut: options.slotStateOut ?? {},
|
|
116
111
|
matches: [],
|
|
117
|
-
}
|
|
112
|
+
}
|
|
118
113
|
}
|
|
119
114
|
|
|
120
115
|
function trimPathname(pathname: string) {
|
|
121
|
-
return pathname.length > 1 ? pathname.replace(/\/+$/, '') || '/' : pathname
|
|
116
|
+
return pathname.length > 1 ? pathname.replace(/\/+$/, '') || '/' : pathname
|
|
122
117
|
}
|
|
123
118
|
|
|
124
119
|
/** Split a recorded slot source (`pathname` or `pathname?query`) into parts. */
|
|
125
120
|
function sourceParts(source: string): { path: string; search: string } {
|
|
126
|
-
const queryIndex = source.indexOf('?')
|
|
127
|
-
if (queryIndex === -1) return { path: trimPathname(source), search: '' }
|
|
121
|
+
const queryIndex = source.indexOf('?')
|
|
122
|
+
if (queryIndex === -1) return { path: trimPathname(source), search: '' }
|
|
128
123
|
return {
|
|
129
124
|
path: trimPathname(source.slice(0, queryIndex)),
|
|
130
125
|
search: source.slice(queryIndex),
|
|
131
|
-
}
|
|
126
|
+
}
|
|
132
127
|
}
|
|
133
128
|
|
|
134
129
|
/** The router's `_rsc` union query is a CDN cache key, never an app param. */
|
|
135
130
|
function stripRscSearch(search: string): string {
|
|
136
|
-
if (!search.includes('_rsc')) return search
|
|
137
|
-
const params = new URLSearchParams(search)
|
|
138
|
-
params.delete('_rsc')
|
|
139
|
-
const stripped = params.toString()
|
|
140
|
-
return stripped ? `?${stripped}` : ''
|
|
131
|
+
if (!search.includes('_rsc')) return search
|
|
132
|
+
const params = new URLSearchParams(search)
|
|
133
|
+
params.delete('_rsc')
|
|
134
|
+
const stripped = params.toString()
|
|
135
|
+
return stripped ? `?${stripped}` : ''
|
|
141
136
|
}
|
|
142
137
|
|
|
143
138
|
/** Render every `@slot` in `dir` into layout props. */
|
|
@@ -145,26 +140,24 @@ export async function renderDirSlots<Options extends SlotRenderOptions>(
|
|
|
145
140
|
context: SlotContext<Options>,
|
|
146
141
|
dir: string,
|
|
147
142
|
): Promise<Record<string, ComponentChildren>> {
|
|
148
|
-
const slotDirs = slotDirectoriesIn(dir)
|
|
149
|
-
if (slotDirs.length === 0) return {}
|
|
150
|
-
const consumed = consumedSegments(context.appPath, dir)
|
|
143
|
+
const slotDirs = slotDirectoriesIn(dir)
|
|
144
|
+
if (slotDirs.length === 0) return {}
|
|
145
|
+
const consumed = consumedSegments(context.appPath, dir)
|
|
151
146
|
// A `[...catchAll]` layout greedily consumes every remaining URL segment (a catch-all is always the last
|
|
152
147
|
// route segment), so any `@slot` it hosts matches at the index - the empty remaining path. Treat Infinity
|
|
153
148
|
// as "all segments consumed" rather than skipping slot rendering, which would drop the slot entirely on a
|
|
154
149
|
// catch-all route.
|
|
155
|
-
const effectiveConsumed = Number.isFinite(consumed)
|
|
156
|
-
|
|
157
|
-
: context.childrenSegments.length;
|
|
158
|
-
const props: Record<string, ComponentChildren> = {};
|
|
150
|
+
const effectiveConsumed = Number.isFinite(consumed) ? consumed : context.childrenSegments.length
|
|
151
|
+
const props: Record<string, ComponentChildren> = {}
|
|
159
152
|
for (const slotDir of slotDirs) {
|
|
160
|
-
const content = await resolveSlotContent(context, slotDir, effectiveConsumed)
|
|
153
|
+
const content = await resolveSlotContent(context, slotDir, effectiveConsumed)
|
|
161
154
|
// An unmatched slot with no `default.*` stays a bare null: wrapping it in
|
|
162
155
|
// the boundary marker would make it a truthy VNode, and an unmatched
|
|
163
156
|
// `@children` slot must stay falsy so childrenFromSlots can fall back to
|
|
164
157
|
// the segment-matched children tree.
|
|
165
|
-
props[basename(slotDir).slice(1)] = content == null ? null : wrapSlotBoundary(content)
|
|
158
|
+
props[basename(slotDir).slice(1)] = content == null ? null : wrapSlotBoundary(content)
|
|
166
159
|
}
|
|
167
|
-
return props
|
|
160
|
+
return props
|
|
168
161
|
}
|
|
169
162
|
|
|
170
163
|
async function resolveSlotContent<Options extends SlotRenderOptions>(
|
|
@@ -172,7 +165,7 @@ async function resolveSlotContent<Options extends SlotRenderOptions>(
|
|
|
172
165
|
slotDir: string,
|
|
173
166
|
consumed: number,
|
|
174
167
|
): Promise<ComponentChildren> {
|
|
175
|
-
const key = toPosixPath(relative(context.appPath, slotDir))
|
|
168
|
+
const key = toPosixPath(relative(context.appPath, slotDir))
|
|
176
169
|
|
|
177
170
|
// Interceptor targets are absolute paths, so the navigated URL applies to
|
|
178
171
|
// them regardless of the chain's consumed prefix (that mismatch is exactly
|
|
@@ -182,67 +175,67 @@ async function resolveSlotContent<Options extends SlotRenderOptions>(
|
|
|
182
175
|
// not intercept it. Interceptors go before direct matching: an interception
|
|
183
176
|
// route beats a catch-all inside the same slot.
|
|
184
177
|
if (context.soft && context.urlPath !== context.childrenPath) {
|
|
185
|
-
const intercepted = matchSlotInterceptor(context.appPath, slotDir, context.urlPath)
|
|
178
|
+
const intercepted = matchSlotInterceptor(context.appPath, slotDir, context.urlPath)
|
|
186
179
|
if (intercepted) {
|
|
187
|
-
context.stateOut[key] = context.urlPath + context.urlSearch
|
|
188
|
-
return renderSlotMatch(context, slotDir, intercepted, context.urlSearch)
|
|
180
|
+
context.stateOut[key] = context.urlPath + context.urlSearch
|
|
181
|
+
return renderSlotMatch(context, slotDir, intercepted, context.urlSearch)
|
|
189
182
|
}
|
|
190
183
|
}
|
|
191
184
|
|
|
192
185
|
// Each candidate source carries the search string its render uses: a slot
|
|
193
186
|
// re-rendered from a RECORDED source keeps the query it was fetched with
|
|
194
187
|
// (Next's per-segment refetch URL), not the current request's.
|
|
195
|
-
const sources: { path: string; search: string }[] = []
|
|
188
|
+
const sources: { path: string; search: string }[] = []
|
|
196
189
|
const pushSource = (path: string, search: string) => {
|
|
197
|
-
if (!sources.some(source => source.path === path)) sources.push({ path, search })
|
|
198
|
-
}
|
|
199
|
-
const rawStateSource = context.statePaths[key]
|
|
200
|
-
const stateSource = rawStateSource ? sourceParts(rawStateSource) : undefined
|
|
190
|
+
if (!sources.some(source => source.path === path)) sources.push({ path, search })
|
|
191
|
+
}
|
|
192
|
+
const rawStateSource = context.statePaths[key]
|
|
193
|
+
const stateSource = rawStateSource ? sourceParts(rawStateSource) : undefined
|
|
201
194
|
const preserveForInterception =
|
|
202
195
|
context.soft &&
|
|
203
196
|
context.urlPath !== context.childrenPath &&
|
|
204
197
|
context.options.route.slotDirs?.some(dir =>
|
|
205
198
|
Boolean(matchSlotInterceptor(context.appPath, dir, context.urlPath)),
|
|
206
|
-
)
|
|
199
|
+
)
|
|
207
200
|
if (
|
|
208
201
|
preserveForInterception &&
|
|
209
202
|
stateSource &&
|
|
210
203
|
segmentsSharePrefix(pathnameSegments(stateSource.path), context.childrenSegments, consumed)
|
|
211
204
|
) {
|
|
212
|
-
pushSource(stateSource.path, stateSource.search)
|
|
205
|
+
pushSource(stateSource.path, stateSource.search)
|
|
213
206
|
}
|
|
214
207
|
if (segmentsSharePrefix(context.urlSegments, context.childrenSegments, consumed)) {
|
|
215
|
-
pushSource(context.urlPath, context.urlSearch)
|
|
208
|
+
pushSource(context.urlPath, context.urlSearch)
|
|
216
209
|
}
|
|
217
210
|
if (
|
|
218
211
|
context.soft &&
|
|
219
212
|
stateSource &&
|
|
220
213
|
segmentsSharePrefix(pathnameSegments(stateSource.path), context.childrenSegments, consumed)
|
|
221
214
|
) {
|
|
222
|
-
pushSource(stateSource.path, stateSource.search)
|
|
215
|
+
pushSource(stateSource.path, stateSource.search)
|
|
223
216
|
}
|
|
224
217
|
// Host renders (children anchored away from the URL) fall back to the
|
|
225
218
|
// children path itself, so sibling slots keep matching the visible page even
|
|
226
219
|
// without an explicit state entry.
|
|
227
220
|
if (context.childrenPath !== context.urlPath) {
|
|
228
|
-
pushSource(context.childrenPath, context.childrenSearch)
|
|
221
|
+
pushSource(context.childrenPath, context.childrenSearch)
|
|
229
222
|
}
|
|
230
223
|
|
|
231
224
|
for (const source of sources) {
|
|
232
225
|
const intercepted =
|
|
233
226
|
context.soft && source.path !== context.urlPath
|
|
234
227
|
? matchSlotInterceptor(context.appPath, slotDir, source.path)
|
|
235
|
-
: null
|
|
228
|
+
: null
|
|
236
229
|
const match =
|
|
237
|
-
intercepted ?? matchSegments(slotDir, pathnameSegments(source.path).slice(consumed))
|
|
238
|
-
if (!match) continue
|
|
239
|
-
context.stateOut[key] = source.path + source.search
|
|
240
|
-
return renderSlotMatch(context, slotDir, match, source.search)
|
|
230
|
+
intercepted ?? matchSegments(slotDir, pathnameSegments(source.path).slice(consumed))
|
|
231
|
+
if (!match) continue
|
|
232
|
+
context.stateOut[key] = source.path + source.search
|
|
233
|
+
return renderSlotMatch(context, slotDir, match, source.search)
|
|
241
234
|
}
|
|
242
235
|
|
|
243
|
-
const defaultFile = slotConventionFile(slotDir, 'default')
|
|
244
|
-
if (!defaultFile) return null
|
|
245
|
-
return renderSlotComponent(context, defaultFile, {})
|
|
236
|
+
const defaultFile = slotConventionFile(slotDir, 'default')
|
|
237
|
+
if (!defaultFile) return null
|
|
238
|
+
return renderSlotComponent(context, defaultFile, {})
|
|
246
239
|
}
|
|
247
240
|
|
|
248
241
|
/** Render a matched slot page inside its slot-internal layout chain. */
|
|
@@ -255,55 +248,52 @@ async function renderSlotMatch<Options extends SlotRenderOptions>(
|
|
|
255
248
|
// A pageless match renders null children under the matched layout chain.
|
|
256
249
|
let tree: ComponentChildren = match.file
|
|
257
250
|
? await renderSlotComponent(context, match.file, match.params, sourceSearch)
|
|
258
|
-
: null
|
|
251
|
+
: null
|
|
259
252
|
|
|
260
253
|
// Wrap innermost-out: loading.* at the page's own dir suspends the page;
|
|
261
254
|
// each dir's layout receives its own nested slots as props.
|
|
262
|
-
const chain: string[] = [slotDir]
|
|
263
|
-
for (const name of match.dirs) chain.push(join(chain[chain.length - 1]!, name))
|
|
255
|
+
const chain: string[] = [slotDir]
|
|
256
|
+
for (const name of match.dirs) chain.push(join(chain[chain.length - 1]!, name))
|
|
264
257
|
context.matches.push({
|
|
265
258
|
slotDir,
|
|
266
259
|
...(match.file ? { pageFile: match.file } : {}),
|
|
267
260
|
layoutFiles: chain.flatMap(dir => slotConventionFile(dir, 'layout') ?? []),
|
|
268
261
|
params: match.params,
|
|
269
|
-
})
|
|
262
|
+
})
|
|
270
263
|
for (const dir of [...chain].reverse()) {
|
|
271
|
-
const loadingFile = slotConventionFile(dir, 'loading')
|
|
264
|
+
const loadingFile = slotConventionFile(dir, 'loading')
|
|
272
265
|
if (loadingFile) {
|
|
273
266
|
const module = (await context.deps.importModule(
|
|
274
267
|
loadingFile,
|
|
275
268
|
context.options,
|
|
276
|
-
)) as LoadingModule
|
|
277
|
-
const Loading = context.deps.markServerReference(module.default)
|
|
269
|
+
)) as LoadingModule
|
|
270
|
+
const Loading = context.deps.markServerReference(module.default)
|
|
278
271
|
if (Loading) {
|
|
279
272
|
tree = h(
|
|
280
273
|
Suspense,
|
|
281
274
|
{ fallback: h(Loading as ComponentType<Record<string, never>>, {}) },
|
|
282
275
|
tree,
|
|
283
|
-
)
|
|
276
|
+
)
|
|
284
277
|
}
|
|
285
278
|
}
|
|
286
|
-
const layoutFile = slotConventionFile(dir, 'layout')
|
|
287
|
-
if (!layoutFile) continue
|
|
288
|
-
const module = (await context.deps.importModule(layoutFile, context.options)) as LayoutModule
|
|
289
|
-
const Layout = context.deps.markServerReference(module.default)
|
|
290
|
-
if (!Layout) continue
|
|
291
|
-
const nestedSlots = await renderDirSlots(context, dir)
|
|
279
|
+
const layoutFile = slotConventionFile(dir, 'layout')
|
|
280
|
+
if (!layoutFile) continue
|
|
281
|
+
const module = (await context.deps.importModule(layoutFile, context.options)) as LayoutModule
|
|
282
|
+
const Layout = context.deps.markServerReference(module.default)
|
|
283
|
+
if (!Layout) continue
|
|
284
|
+
const nestedSlots = await renderDirSlots(context, dir)
|
|
292
285
|
tree = h(Layout as ComponentType<ServerVNodeProps>, {
|
|
293
286
|
...slotPageProps(context, match.params, sourceSearch),
|
|
294
287
|
...nestedSlots,
|
|
295
288
|
children: tree,
|
|
296
|
-
})
|
|
289
|
+
})
|
|
297
290
|
}
|
|
298
291
|
// Any `'use client'` island rendered anywhere inside this slot subtree must
|
|
299
292
|
// see the slot's own params (its dynamic / catch-all captures) from useParams,
|
|
300
293
|
// not just the global route params. Wrap the subtree in a params scope so the
|
|
301
294
|
// renderer stamps each island it resolves within it (see resolveServerTree's
|
|
302
295
|
// paramsScopeSymbol handling + render/island-context.ts RouteParamsContext).
|
|
303
|
-
return wrapSlotParamsScope(
|
|
304
|
-
{ ...(context.options.params ?? {}), ...match.params },
|
|
305
|
-
tree,
|
|
306
|
-
);
|
|
296
|
+
return wrapSlotParamsScope({ ...(context.options.params ?? {}), ...match.params }, tree)
|
|
307
297
|
}
|
|
308
298
|
|
|
309
299
|
// ---------------------------------------------------------------------------
|
|
@@ -315,18 +305,18 @@ async function renderSlotMatch<Options extends SlotRenderOptions>(
|
|
|
315
305
|
// slot's resolved params. Mirrors the layout-segment scope above.
|
|
316
306
|
// ---------------------------------------------------------------------------
|
|
317
307
|
|
|
318
|
-
export const paramsScopeSymbol = Symbol.for('pnext.paramsScope')
|
|
308
|
+
export const paramsScopeSymbol = Symbol.for('pnext.paramsScope')
|
|
319
309
|
|
|
320
|
-
const PARAMS_SCOPE_PROP = '__pnextParams'
|
|
310
|
+
const PARAMS_SCOPE_PROP = '__pnextParams'
|
|
321
311
|
|
|
322
|
-
const paramsSnapshotStorage = new AsyncLocalStorage<RouteParamsSnapshot>()
|
|
312
|
+
const paramsSnapshotStorage = new AsyncLocalStorage<RouteParamsSnapshot>()
|
|
323
313
|
|
|
324
314
|
type ParamsScopeMarker = ((props: ServerVNodeProps) => ComponentChildren) & {
|
|
325
|
-
[paramsScopeSymbol]?: true
|
|
326
|
-
}
|
|
315
|
+
[paramsScopeSymbol]?: true
|
|
316
|
+
}
|
|
327
317
|
|
|
328
|
-
const ParamsScopeMarker: ParamsScopeMarker = props => props.children
|
|
329
|
-
ParamsScopeMarker[paramsScopeSymbol] = true
|
|
318
|
+
const ParamsScopeMarker: ParamsScopeMarker = props => props.children
|
|
319
|
+
ParamsScopeMarker[paramsScopeSymbol] = true
|
|
330
320
|
|
|
331
321
|
// Parallel-route slot marker (task-boundary scoping). A named `@slot` subtree is wrapped in this marker so
|
|
332
322
|
// the server-tree resolver can arm the build prerender's task boundary ONLY while resolving slot content.
|
|
@@ -334,33 +324,33 @@ ParamsScopeMarker[paramsScopeSymbol] = true;
|
|
|
334
324
|
// to parallel-route slots, the shape it was designed for, and leaves every other <Suspense> baking its task
|
|
335
325
|
// work as before.
|
|
336
326
|
|
|
337
|
-
export const slotBoundarySymbol = Symbol.for('pnext.slotBoundary')
|
|
327
|
+
export const slotBoundarySymbol = Symbol.for('pnext.slotBoundary')
|
|
338
328
|
|
|
339
329
|
type SlotBoundaryMarker = ((props: ServerVNodeProps) => ComponentChildren) & {
|
|
340
|
-
[slotBoundarySymbol]?: true
|
|
341
|
-
}
|
|
330
|
+
[slotBoundarySymbol]?: true
|
|
331
|
+
}
|
|
342
332
|
|
|
343
|
-
const SlotBoundaryMarker: SlotBoundaryMarker = props => props.children
|
|
344
|
-
SlotBoundaryMarker[slotBoundarySymbol] = true
|
|
333
|
+
const SlotBoundaryMarker: SlotBoundaryMarker = props => props.children
|
|
334
|
+
SlotBoundaryMarker[slotBoundarySymbol] = true
|
|
345
335
|
|
|
346
336
|
/** Wrap a named parallel-route slot subtree in the task-boundary marker. */
|
|
347
337
|
export function wrapSlotBoundary(content: ComponentChildren): ComponentChildren {
|
|
348
|
-
return h(SlotBoundaryMarker as ComponentType<ServerVNodeProps>, null, content)
|
|
338
|
+
return h(SlotBoundaryMarker as ComponentType<ServerVNodeProps>, null, content)
|
|
349
339
|
}
|
|
350
340
|
|
|
351
341
|
/** Read the params for the slot scope active in the current async resolution. */
|
|
352
342
|
export function currentParamsSnapshot(): RouteParamsSnapshot | undefined {
|
|
353
|
-
return paramsSnapshotStorage.getStore()
|
|
343
|
+
return paramsSnapshotStorage.getStore()
|
|
354
344
|
}
|
|
355
345
|
|
|
356
346
|
/** Run `fn` with the given slot params installed as the active params scope. */
|
|
357
347
|
export function runInParamsScope<T>(params: RouteParamsSnapshot, fn: () => T): T {
|
|
358
|
-
return paramsSnapshotStorage.run(params, fn)
|
|
348
|
+
return paramsSnapshotStorage.run(params, fn)
|
|
359
349
|
}
|
|
360
350
|
|
|
361
351
|
/** Read the params a params-scope marker VNode carries. */
|
|
362
352
|
export function paramsScopeParams(props: Record<string, unknown>): RouteParamsSnapshot {
|
|
363
|
-
return (props[PARAMS_SCOPE_PROP] as RouteParamsSnapshot | undefined) ?? {}
|
|
353
|
+
return (props[PARAMS_SCOPE_PROP] as RouteParamsSnapshot | undefined) ?? {}
|
|
364
354
|
}
|
|
365
355
|
|
|
366
356
|
function wrapSlotParamsScope(
|
|
@@ -371,7 +361,7 @@ function wrapSlotParamsScope(
|
|
|
371
361
|
ParamsScopeMarker as ComponentType<ServerVNodeProps>,
|
|
372
362
|
{ [PARAMS_SCOPE_PROP]: params },
|
|
373
363
|
tree,
|
|
374
|
-
)
|
|
364
|
+
)
|
|
375
365
|
}
|
|
376
366
|
|
|
377
367
|
async function renderSlotComponent<Options extends SlotRenderOptions>(
|
|
@@ -380,38 +370,38 @@ async function renderSlotComponent<Options extends SlotRenderOptions>(
|
|
|
380
370
|
params: Record<string, RouteParamValue>,
|
|
381
371
|
sourceSearch?: string,
|
|
382
372
|
): Promise<ComponentChildren> {
|
|
383
|
-
const props = slotPageProps(context, params, sourceSearch)
|
|
373
|
+
const props = slotPageProps(context, params, sourceSearch)
|
|
384
374
|
|
|
385
375
|
// A 'use client' page inside a slot renders as an island: the reference
|
|
386
376
|
// stub becomes a hydrated boundary in resolveServerTree. Its promise props
|
|
387
377
|
// (params/searchParams) travel as plain markers the island runtime revives.
|
|
388
378
|
const reference = context.options.route.clientReferences.find(
|
|
389
379
|
item => item.file === file && item.exportName === 'default',
|
|
390
|
-
)
|
|
380
|
+
)
|
|
391
381
|
if (reference) {
|
|
392
382
|
const Component =
|
|
393
383
|
context.options.clientComponents?.get(reference.id) ??
|
|
394
|
-
context.deps.clientReferenceStub(reference)
|
|
384
|
+
context.deps.clientReferenceStub(reference)
|
|
395
385
|
return h(Component, {
|
|
396
386
|
params: promiseMarker(await props.params),
|
|
397
387
|
searchParams: promiseMarker(await props.searchParams),
|
|
398
|
-
})
|
|
388
|
+
})
|
|
399
389
|
}
|
|
400
390
|
|
|
401
|
-
const module = (await context.deps.importModule(file, context.options)) as PageModule
|
|
402
|
-
const Component = context.deps.markServerReference(module.default)
|
|
403
|
-
if (!Component) return null
|
|
404
|
-
return h(Component as ComponentType<PageProps>, props)
|
|
391
|
+
const module = (await context.deps.importModule(file, context.options)) as PageModule
|
|
392
|
+
const Component = context.deps.markServerReference(module.default)
|
|
393
|
+
if (!Component) return null
|
|
394
|
+
return h(Component as ComponentType<PageProps>, props)
|
|
405
395
|
}
|
|
406
396
|
|
|
407
|
-
const PROMISE_MARKER_KEY = '__pnextPromise'
|
|
397
|
+
const PROMISE_MARKER_KEY = '__pnextPromise'
|
|
408
398
|
|
|
409
399
|
export function promiseMarker(value: unknown) {
|
|
410
|
-
return { [PROMISE_MARKER_KEY]: value ?? null }
|
|
400
|
+
return { [PROMISE_MARKER_KEY]: value ?? null }
|
|
411
401
|
}
|
|
412
402
|
|
|
413
403
|
/** The discriminator that makes a placeholder marker rewritable at serve time. */
|
|
414
|
-
const PROMISE_PLACEHOLDER_KEY = '__pnextParams'
|
|
404
|
+
const PROMISE_PLACEHOLDER_KEY = '__pnextParams'
|
|
415
405
|
|
|
416
406
|
/**
|
|
417
407
|
* The wire placeholder for a request-API promise prop that a partial prerender must NOT await (see ppr.ts
|
|
@@ -420,25 +410,25 @@ const PROMISE_PLACEHOLDER_KEY = '__pnextParams';
|
|
|
420
410
|
* `window.__PNEXT_ROUTE__` and `data-pnext-params`, and all three must agree.
|
|
421
411
|
*/
|
|
422
412
|
export function promisePlaceholderMarker(kind: 'params' | 'searchParams') {
|
|
423
|
-
return { [PROMISE_MARKER_KEY]: null, [PROMISE_PLACEHOLDER_KEY]: kind }
|
|
413
|
+
return { [PROMISE_MARKER_KEY]: null, [PROMISE_PLACEHOLDER_KEY]: kind }
|
|
424
414
|
}
|
|
425
415
|
|
|
426
416
|
/** The serialized placeholder the serve-time re-stamp searches for. */
|
|
427
417
|
export function promisePlaceholderJson(kind: 'params' | 'searchParams'): string {
|
|
428
|
-
return `{"${PROMISE_MARKER_KEY}":null,"${PROMISE_PLACEHOLDER_KEY}":"${kind}"}
|
|
418
|
+
return `{"${PROMISE_MARKER_KEY}":null,"${PROMISE_PLACEHOLDER_KEY}":"${kind}"}`
|
|
429
419
|
}
|
|
430
420
|
|
|
431
421
|
/** Revive promise markers into thenables for the SSR pass of an island. */
|
|
432
422
|
export function revivePromiseProps(props: Record<string, unknown>) {
|
|
433
|
-
const out: Record<string, unknown> = {}
|
|
423
|
+
const out: Record<string, unknown> = {}
|
|
434
424
|
for (const [key, value] of Object.entries(props)) {
|
|
435
425
|
if (value && typeof value === 'object' && PROMISE_MARKER_KEY in value) {
|
|
436
|
-
out[key] = Promise.resolve((value as Record<string, unknown>)[PROMISE_MARKER_KEY])
|
|
426
|
+
out[key] = Promise.resolve((value as Record<string, unknown>)[PROMISE_MARKER_KEY])
|
|
437
427
|
} else {
|
|
438
|
-
out[key] = value
|
|
428
|
+
out[key] = value
|
|
439
429
|
}
|
|
440
430
|
}
|
|
441
|
-
return out
|
|
431
|
+
return out
|
|
442
432
|
}
|
|
443
433
|
|
|
444
434
|
function slotPageProps<Options extends SlotRenderOptions>(
|
|
@@ -446,14 +436,14 @@ function slotPageProps<Options extends SlotRenderOptions>(
|
|
|
446
436
|
params: Record<string, RouteParamValue>,
|
|
447
437
|
sourceSearch?: string,
|
|
448
438
|
): PageProps {
|
|
449
|
-
const base = context.deps.createPageProps(context.options)
|
|
439
|
+
const base = context.deps.createPageProps(context.options)
|
|
450
440
|
// What createPageProps already resolves searchParams from: the children
|
|
451
441
|
// tree's recorded query on a host render, the request's otherwise (see
|
|
452
442
|
// childrenSourceSearchParams in renderer.ts).
|
|
453
443
|
const baseSearch =
|
|
454
444
|
context.soft && context.childrenPath !== trimPathname(context.options.url.pathname)
|
|
455
445
|
? context.childrenSearch
|
|
456
|
-
: context.urlSearch
|
|
446
|
+
: context.urlSearch
|
|
457
447
|
return {
|
|
458
448
|
...base,
|
|
459
449
|
params: Promise.resolve({ ...(context.options.params ?? {}), ...params }),
|
|
@@ -463,37 +453,37 @@ function slotPageProps<Options extends SlotRenderOptions>(
|
|
|
463
453
|
...(sourceSearch !== undefined && sourceSearch !== baseSearch
|
|
464
454
|
? { searchParams: fulfilledPromise(searchParamsObject(sourceSearch)) }
|
|
465
455
|
: {}),
|
|
466
|
-
}
|
|
456
|
+
}
|
|
467
457
|
}
|
|
468
458
|
|
|
469
459
|
// Repeated keys collect into arrays (Next's searchParams page-prop shape).
|
|
470
460
|
function searchParamsObject(search: string): Record<string, string | string[]> {
|
|
471
|
-
const result: Record<string, string | string[]> = {}
|
|
461
|
+
const result: Record<string, string | string[]> = {}
|
|
472
462
|
new URLSearchParams(search).forEach((value, key) => {
|
|
473
|
-
if (key === '_rsc') return
|
|
474
|
-
const current = result[key]
|
|
475
|
-
if (current === undefined) result[key] = value
|
|
476
|
-
else if (Array.isArray(current)) current.push(value)
|
|
477
|
-
else result[key] = [current, value]
|
|
478
|
-
})
|
|
479
|
-
return result
|
|
463
|
+
if (key === '_rsc') return
|
|
464
|
+
const current = result[key]
|
|
465
|
+
if (current === undefined) result[key] = value
|
|
466
|
+
else if (Array.isArray(current)) current.push(value)
|
|
467
|
+
else result[key] = [current, value]
|
|
468
|
+
})
|
|
469
|
+
return result
|
|
480
470
|
}
|
|
481
471
|
|
|
482
472
|
// Pre-settled promise (status/value readable synchronously) so preact's use()
|
|
483
473
|
// does not suspend during streaming SSR — mirrors renderer.ts settledPromise
|
|
484
474
|
// (not imported: renderer.ts imports from this module).
|
|
485
475
|
function fulfilledPromise<T>(value: T): Promise<T> {
|
|
486
|
-
const promise = Promise.resolve(value) as Promise<T> & { status?: string; value?: T }
|
|
487
|
-
promise.status = 'fulfilled'
|
|
488
|
-
promise.value = value
|
|
489
|
-
return promise
|
|
476
|
+
const promise = Promise.resolve(value) as Promise<T> & { status?: string; value?: T }
|
|
477
|
+
promise.status = 'fulfilled'
|
|
478
|
+
promise.value = value
|
|
479
|
+
return promise
|
|
490
480
|
}
|
|
491
481
|
|
|
492
482
|
function segmentsSharePrefix(a: string[], b: string[], length: number) {
|
|
493
483
|
for (let index = 0; index < length; index += 1) {
|
|
494
|
-
if (a[index] !== b[index]) return false
|
|
484
|
+
if (a[index] !== b[index]) return false
|
|
495
485
|
}
|
|
496
|
-
return true
|
|
486
|
+
return true
|
|
497
487
|
}
|
|
498
488
|
|
|
499
489
|
// ---------------------------------------------------------------------------
|
|
@@ -508,13 +498,13 @@ function segmentsSharePrefix(a: string[], b: string[], length: number) {
|
|
|
508
498
|
// ---------------------------------------------------------------------------
|
|
509
499
|
|
|
510
500
|
export interface LayoutSegmentScope {
|
|
511
|
-
segments: string[]
|
|
512
|
-
appPath?: string
|
|
513
|
-
layoutDir?: string
|
|
514
|
-
slots?: Record<string, string
|
|
501
|
+
segments: string[]
|
|
502
|
+
appPath?: string
|
|
503
|
+
layoutDir?: string
|
|
504
|
+
slots?: Record<string, string>
|
|
515
505
|
}
|
|
516
506
|
|
|
517
|
-
const layoutSegmentStorage = new AsyncLocalStorage<LayoutSegmentScope>()
|
|
507
|
+
const layoutSegmentStorage = new AsyncLocalStorage<LayoutSegmentScope>()
|
|
518
508
|
|
|
519
509
|
/**
|
|
520
510
|
* Run `fn` inside a layout-segment scope. The synchronous portion of a layout's
|
|
@@ -527,7 +517,7 @@ export function runInLayoutSegmentScope<T>(
|
|
|
527
517
|
fn: () => T,
|
|
528
518
|
scope: Omit<LayoutSegmentScope, 'segments'> = {},
|
|
529
519
|
): T {
|
|
530
|
-
return layoutSegmentStorage.run({ segments, ...scope }, fn)
|
|
520
|
+
return layoutSegmentStorage.run({ segments, ...scope }, fn)
|
|
531
521
|
}
|
|
532
522
|
|
|
533
523
|
/**
|
|
@@ -538,24 +528,23 @@ export function runInLayoutSegmentScope<T>(
|
|
|
538
528
|
* Returns undefined outside any layout scope (e.g. a leaf page island).
|
|
539
529
|
*/
|
|
540
530
|
export function currentLayoutSegmentSnapshot():
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
let depth = 0;
|
|
531
|
+
{ depth: number; segments: string[]; slots: Record<string, string[]> } | undefined {
|
|
532
|
+
const scope = layoutSegmentStorage.getStore()
|
|
533
|
+
if (!scope) return undefined
|
|
534
|
+
const slots: Record<string, string[]> = {}
|
|
535
|
+
let depth = 0
|
|
547
536
|
if (scope.appPath && scope.layoutDir) {
|
|
548
|
-
depth = layoutSegmentDepth(scope.appPath, scope.layoutDir)
|
|
549
|
-
const owner = toPosixPath(relative(scope.appPath, scope.layoutDir))
|
|
550
|
-
const prefix = owner ? `${owner}/@` : '@'
|
|
537
|
+
depth = layoutSegmentDepth(scope.appPath, scope.layoutDir)
|
|
538
|
+
const owner = toPosixPath(relative(scope.appPath, scope.layoutDir))
|
|
539
|
+
const prefix = owner ? `${owner}/@` : '@'
|
|
551
540
|
for (const [dir, path] of Object.entries(scope.slots ?? {})) {
|
|
552
|
-
if (!dir.startsWith(prefix)) continue
|
|
553
|
-
const key = dir.slice(prefix.length)
|
|
554
|
-
if (key.includes('/')) continue
|
|
555
|
-
slots[key] = pathnameSegments(path)
|
|
541
|
+
if (!dir.startsWith(prefix)) continue
|
|
542
|
+
const key = dir.slice(prefix.length)
|
|
543
|
+
if (key.includes('/')) continue
|
|
544
|
+
slots[key] = pathnameSegments(path)
|
|
556
545
|
}
|
|
557
546
|
}
|
|
558
|
-
return { depth, segments: scope.segments, slots }
|
|
547
|
+
return { depth, segments: scope.segments, slots }
|
|
559
548
|
}
|
|
560
549
|
|
|
561
550
|
/**
|
|
@@ -565,18 +554,18 @@ export function currentLayoutSegmentSnapshot():
|
|
|
565
554
|
* hook falls back to the island context instead. Distinguishes the two callers.
|
|
566
555
|
*/
|
|
567
556
|
export function hasLayoutSegmentScope(): boolean {
|
|
568
|
-
return layoutSegmentStorage.getStore() !== undefined
|
|
557
|
+
return layoutSegmentStorage.getStore() !== undefined
|
|
569
558
|
}
|
|
570
559
|
|
|
571
560
|
/** The active layout's "segments below me", or `[]` outside any layout scope. */
|
|
572
561
|
export function currentLayoutSegments(slotKey?: string): string[] {
|
|
573
|
-
const scope = layoutSegmentStorage.getStore()
|
|
574
|
-
if (!scope) return []
|
|
575
|
-
if (!slotKey) return scope.segments
|
|
576
|
-
if (!scope.appPath || !scope.layoutDir) return []
|
|
577
|
-
const owner = toPosixPath(relative(scope.appPath, scope.layoutDir))
|
|
578
|
-
const slotPath = scope.slots?.[owner ? `${owner}/@${slotKey}` : `@${slotKey}`]
|
|
579
|
-
return slotPath ? pathnameSegments(slotPath) : []
|
|
562
|
+
const scope = layoutSegmentStorage.getStore()
|
|
563
|
+
if (!scope) return []
|
|
564
|
+
if (!slotKey) return scope.segments
|
|
565
|
+
if (!scope.appPath || !scope.layoutDir) return []
|
|
566
|
+
const owner = toPosixPath(relative(scope.appPath, scope.layoutDir))
|
|
567
|
+
const slotPath = scope.slots?.[owner ? `${owner}/@${slotKey}` : `@${slotKey}`]
|
|
568
|
+
return slotPath ? pathnameSegments(slotPath) : []
|
|
580
569
|
}
|
|
581
570
|
|
|
582
571
|
/**
|
|
@@ -591,33 +580,33 @@ export function fullLayoutSegments(
|
|
|
591
580
|
leafDir: string,
|
|
592
581
|
params: Record<string, RouteParamValue>,
|
|
593
582
|
): string[] {
|
|
594
|
-
const relativeDir = relative(appPath, leafDir)
|
|
595
|
-
if (relativeDir.startsWith('..')) return []
|
|
596
|
-
const segments: string[] = []
|
|
583
|
+
const relativeDir = relative(appPath, leafDir)
|
|
584
|
+
if (relativeDir.startsWith('..')) return []
|
|
585
|
+
const segments: string[] = []
|
|
597
586
|
for (const name of relativeDir.split(sep).filter(Boolean)) {
|
|
598
|
-
if (isSlotSegment(name)) continue
|
|
587
|
+
if (isSlotSegment(name)) continue
|
|
599
588
|
if (isGroupSegment(name)) {
|
|
600
|
-
segments.push(name)
|
|
601
|
-
continue
|
|
589
|
+
segments.push(name)
|
|
590
|
+
continue
|
|
602
591
|
}
|
|
603
|
-
const optional = /^\[\[\.\.\.([^\]]+)\]\]$/.exec(name)
|
|
604
|
-
const catchAll = optional ?? /^\[\.\.\.([^\]]+)\]$/.exec(name)
|
|
592
|
+
const optional = /^\[\[\.\.\.([^\]]+)\]\]$/.exec(name)
|
|
593
|
+
const catchAll = optional ?? /^\[\.\.\.([^\]]+)\]$/.exec(name)
|
|
605
594
|
if (catchAll?.[1]) {
|
|
606
|
-
const value = params[catchAll[1]]
|
|
607
|
-
const joined = Array.isArray(value) ? value.join('/') : (value ?? '')
|
|
595
|
+
const value = params[catchAll[1]]
|
|
596
|
+
const joined = Array.isArray(value) ? value.join('/') : (value ?? '')
|
|
608
597
|
// An empty optional catch-all contributes no segment at all.
|
|
609
|
-
if (joined) segments.push(joined)
|
|
610
|
-
continue
|
|
598
|
+
if (joined) segments.push(joined)
|
|
599
|
+
continue
|
|
611
600
|
}
|
|
612
|
-
const dynamic = /^\[([^\].]+)\]$/.exec(name)
|
|
601
|
+
const dynamic = /^\[([^\].]+)\]$/.exec(name)
|
|
613
602
|
if (dynamic?.[1]) {
|
|
614
|
-
const value = params[dynamic[1]]
|
|
615
|
-
segments.push(Array.isArray(value) ? value.join('/') : String(value ?? ''))
|
|
616
|
-
continue
|
|
603
|
+
const value = params[dynamic[1]]
|
|
604
|
+
segments.push(Array.isArray(value) ? value.join('/') : String(value ?? ''))
|
|
605
|
+
continue
|
|
617
606
|
}
|
|
618
|
-
segments.push(name)
|
|
607
|
+
segments.push(name)
|
|
619
608
|
}
|
|
620
|
-
return segments
|
|
609
|
+
return segments
|
|
621
610
|
}
|
|
622
611
|
|
|
623
612
|
/**
|
|
@@ -632,33 +621,33 @@ export function layoutParamsForDir(
|
|
|
632
621
|
layoutDir: string,
|
|
633
622
|
params: Record<string, RouteParamValue>,
|
|
634
623
|
): Record<string, RouteParamValue> {
|
|
635
|
-
const relativeDir = relative(appPath, layoutDir)
|
|
636
|
-
if (relativeDir.startsWith('..')) return {}
|
|
637
|
-
const scoped: Record<string, RouteParamValue> = {}
|
|
624
|
+
const relativeDir = relative(appPath, layoutDir)
|
|
625
|
+
if (relativeDir.startsWith('..')) return {}
|
|
626
|
+
const scoped: Record<string, RouteParamValue> = {}
|
|
638
627
|
for (const name of relativeDir.split(sep).filter(Boolean)) {
|
|
639
|
-
if (isSlotSegment(name) || isGroupSegment(name)) continue
|
|
640
|
-
const optional = /^\[\[\.\.\.([^\]]+)\]\]$/.exec(name)
|
|
628
|
+
if (isSlotSegment(name) || isGroupSegment(name)) continue
|
|
629
|
+
const optional = /^\[\[\.\.\.([^\]]+)\]\]$/.exec(name)
|
|
641
630
|
if (optional?.[1]) {
|
|
642
|
-
const value = params[optional[1]]
|
|
631
|
+
const value = params[optional[1]]
|
|
643
632
|
// Empty optional catch-all: omit entirely (no params object for the layout).
|
|
644
633
|
if (value !== undefined && (Array.isArray(value) ? value.length > 0 : value != null)) {
|
|
645
|
-
scoped[optional[1]] = value
|
|
634
|
+
scoped[optional[1]] = value
|
|
646
635
|
}
|
|
647
|
-
continue
|
|
636
|
+
continue
|
|
648
637
|
}
|
|
649
|
-
const catchAll = /^\[\.\.\.([^\]]+)\]$/.exec(name)
|
|
638
|
+
const catchAll = /^\[\.\.\.([^\]]+)\]$/.exec(name)
|
|
650
639
|
if (catchAll?.[1]) {
|
|
651
|
-
const value = params[catchAll[1]]
|
|
652
|
-
if (value !== undefined) scoped[catchAll[1]] = value
|
|
653
|
-
continue
|
|
640
|
+
const value = params[catchAll[1]]
|
|
641
|
+
if (value !== undefined) scoped[catchAll[1]] = value
|
|
642
|
+
continue
|
|
654
643
|
}
|
|
655
|
-
const dynamic = /^\[([^\].]+)\]$/.exec(name)
|
|
644
|
+
const dynamic = /^\[([^\].]+)\]$/.exec(name)
|
|
656
645
|
if (dynamic?.[1]) {
|
|
657
|
-
const value = params[dynamic[1]]
|
|
658
|
-
if (value !== undefined) scoped[dynamic[1]] = value
|
|
646
|
+
const value = params[dynamic[1]]
|
|
647
|
+
if (value !== undefined) scoped[dynamic[1]] = value
|
|
659
648
|
}
|
|
660
649
|
}
|
|
661
|
-
return scoped
|
|
650
|
+
return scoped
|
|
662
651
|
}
|
|
663
652
|
|
|
664
653
|
/**
|
|
@@ -668,12 +657,12 @@ export function layoutParamsForDir(
|
|
|
668
657
|
* present in the full list); slots count as zero.
|
|
669
658
|
*/
|
|
670
659
|
export function layoutSegmentDepth(appPath: string, layoutDir: string): number {
|
|
671
|
-
const relativeDir = relative(appPath, layoutDir)
|
|
672
|
-
if (relativeDir.startsWith('..') || relativeDir === '') return 0
|
|
673
|
-
let depth = 0
|
|
660
|
+
const relativeDir = relative(appPath, layoutDir)
|
|
661
|
+
if (relativeDir.startsWith('..') || relativeDir === '') return 0
|
|
662
|
+
let depth = 0
|
|
674
663
|
for (const name of relativeDir.split(sep).filter(Boolean)) {
|
|
675
|
-
if (isSlotSegment(name)) continue
|
|
676
|
-
depth += 1
|
|
664
|
+
if (isSlotSegment(name)) continue
|
|
665
|
+
depth += 1
|
|
677
666
|
}
|
|
678
|
-
return depth
|
|
667
|
+
return depth
|
|
679
668
|
}
|