@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
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// Safe in a pure-core app: the seam only overrides core's generic asset module for recognized image
|
|
9
9
|
// extensions; everything else falls through.
|
|
10
10
|
|
|
11
|
-
import { setAssetExtensions } from '../../extensions'
|
|
12
|
-
import { staticImageModule } from '../next/image/static-metadata'
|
|
11
|
+
import { setAssetExtensions } from '../../extensions'
|
|
12
|
+
import { staticImageModule } from '../next/image/static-metadata'
|
|
13
13
|
|
|
14
14
|
export function registerStaticImageExtensions(): void {
|
|
15
15
|
setAssetExtensions({
|
|
@@ -17,5 +17,5 @@ export function registerStaticImageExtensions(): void {
|
|
|
17
17
|
staticAssetRelativePath: ({ base, hash, ext }) =>
|
|
18
18
|
['_next', 'static', 'media', `${base}.${hash}${ext}`].join('/'),
|
|
19
19
|
staticAssetModule: staticImageModule,
|
|
20
|
-
})
|
|
20
|
+
})
|
|
21
21
|
}
|
|
@@ -8,25 +8,25 @@
|
|
|
8
8
|
// Kept as an explicit registrar rather than nothing, so future misc features that DO need a registry
|
|
9
9
|
// have an owned place to register without touching another file.
|
|
10
10
|
|
|
11
|
-
import type { ResolvedConfig } from '../../config'
|
|
12
|
-
import { taintObjectReference } from '../../utils/serialize'
|
|
13
|
-
import { getNextConfig } from '../next/config-loader'
|
|
11
|
+
import type { ResolvedConfig } from '../../config'
|
|
12
|
+
import { taintObjectReference } from '../../utils/serialize'
|
|
13
|
+
import { getNextConfig } from '../next/config-loader'
|
|
14
14
|
|
|
15
15
|
// Next's `experimental.taint` message for a `process.env` reference reaching a
|
|
16
16
|
// client component (asserted verbatim by test/e2e/app-dir/taint in dev; prod
|
|
17
17
|
// sees the redacted React #441 text via the normal boundary error path).
|
|
18
18
|
const PROCESS_ENV_TAINT_MESSAGE =
|
|
19
|
-
'Do not pass process.env to Client Components since it will leak sensitive data'
|
|
19
|
+
'Do not pass process.env to Client Components since it will leak sensitive data'
|
|
20
20
|
|
|
21
21
|
// Prod redacts every RSC serialization error to React's minified #441 text
|
|
22
22
|
// (test/e2e/app-dir/taint asserts this verbatim for a production build).
|
|
23
23
|
const REDACTED_RSC_ERROR_MESSAGE =
|
|
24
|
-
'Minified React error #441; visit https://react.dev/errors/441 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.'
|
|
24
|
+
'Minified React error #441; visit https://react.dev/errors/441 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.'
|
|
25
25
|
|
|
26
26
|
export function registerMiscExtensions(_config: ResolvedConfig): void {
|
|
27
27
|
// No registry wiring required for the current misc cluster; behavior is
|
|
28
28
|
// activated via direct imports in the action endpoint + client runtime.
|
|
29
|
-
registerTaintedReferences()
|
|
29
|
+
registerTaintedReferences()
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -35,10 +35,10 @@ export function registerMiscExtensions(_config: ResolvedConfig): void {
|
|
|
35
35
|
* IS that object throw.
|
|
36
36
|
*/
|
|
37
37
|
function registerTaintedReferences(): void {
|
|
38
|
-
const experimental = getNextConfig().experimental as { taint?: unknown } | undefined
|
|
39
|
-
if (experimental?.taint !== true) return
|
|
38
|
+
const experimental = getNextConfig().experimental as { taint?: unknown } | undefined
|
|
39
|
+
if (experimental?.taint !== true) return
|
|
40
40
|
taintObjectReference(
|
|
41
41
|
{ dev: PROCESS_ENV_TAINT_MESSAGE, prod: REDACTED_RSC_ERROR_MESSAGE },
|
|
42
42
|
process.env,
|
|
43
|
-
)
|
|
43
|
+
)
|
|
44
44
|
}
|
|
@@ -3,33 +3,33 @@
|
|
|
3
3
|
// `<root>/.next/types/{routes.d.ts,link.d.ts,validator.ts}`. Runs during a build under compat.next;
|
|
4
4
|
// pure-core apps register nothing.
|
|
5
5
|
|
|
6
|
-
import type { ResolvedConfig } from '../../config'
|
|
6
|
+
import type { ResolvedConfig } from '../../config'
|
|
7
7
|
import {
|
|
8
8
|
registerBuildParallelPhases,
|
|
9
9
|
registerBuildSteps,
|
|
10
10
|
type BuildStepContext,
|
|
11
|
-
} from '../../extensions'
|
|
12
|
-
import type { RouteManifestEntry } from '../../types'
|
|
13
|
-
import { nextCompatEnabled } from '../
|
|
14
|
-
import { writeTsconfigDefaults } from '../tsconfig-defaults'
|
|
15
|
-
import { typecheckDisabled, validateTypesOffThread } from '../typecheck'
|
|
16
|
-
import { generateTypedRoutes } from '../typed-routes'
|
|
11
|
+
} from '../../extensions'
|
|
12
|
+
import type { RouteManifestEntry } from '../../types'
|
|
13
|
+
import { nextCompatEnabled } from '../aliases'
|
|
14
|
+
import { writeTsconfigDefaults } from '../tsconfig-defaults'
|
|
15
|
+
import { typecheckDisabled, validateTypesOffThread } from '../typecheck/check'
|
|
16
|
+
import { generateTypedRoutes } from '../typed-routes/generate'
|
|
17
17
|
|
|
18
18
|
export function registerTypedRoutesExtensions(_config: ResolvedConfig): void {
|
|
19
|
-
registerBuildSteps(runTypedRoutesBuildStep)
|
|
19
|
+
registerBuildSteps(runTypedRoutesBuildStep)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async function runTypedRoutesBuildStep(ctx: BuildStepContext): Promise<void> {
|
|
23
|
-
if (!nextCompatEnabled(ctx.config)) return
|
|
24
|
-
await writeTsconfigDefaults(ctx.config)
|
|
25
|
-
await generateTypedRoutes(ctx.config, ctx.routes as RouteManifestEntry[])
|
|
23
|
+
if (!nextCompatEnabled(ctx.config)) return
|
|
24
|
+
await writeTsconfigDefaults(ctx.config)
|
|
25
|
+
await generateTypedRoutes(ctx.config, ctx.routes as RouteManifestEntry[])
|
|
26
26
|
// The typecheck reads only files that already exist on disk, so it runs on a worker thread
|
|
27
27
|
// alongside client bundling and prerendering rather than ahead of them; the CLI awaits it before
|
|
28
28
|
// the summary. A build that disables it reports no line at all.
|
|
29
|
-
if (typecheckDisabled()) return
|
|
30
|
-
const startedAt = performance.now()
|
|
29
|
+
if (typecheckDisabled()) return
|
|
30
|
+
const startedAt = performance.now()
|
|
31
31
|
registerBuildParallelPhases({
|
|
32
32
|
name: 'Typecheck',
|
|
33
33
|
run: validateTypesOffThread(ctx.config).then(() => performance.now() - startedAt),
|
|
34
|
-
})
|
|
34
|
+
})
|
|
35
35
|
}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
// lazy-static MISS responses. Emitting it for pure static HITs needs the route's cacheLife persisted in
|
|
15
15
|
// the build manifest and read by the static-serve path in src/cli/start.ts.
|
|
16
16
|
|
|
17
|
-
import type { ResolvedConfig } from '../../config'
|
|
18
|
-
import { nextCompatEnabled } from '../../compat'
|
|
17
|
+
import type { ResolvedConfig } from '../../config'
|
|
18
|
+
import { nextCompatEnabled } from '../../compat/aliases'
|
|
19
19
|
import {
|
|
20
20
|
onExtensionHostReset,
|
|
21
21
|
registerBuildCompleteHooks,
|
|
@@ -23,32 +23,32 @@ import {
|
|
|
23
23
|
registerResponseFinalizers,
|
|
24
24
|
type ResponseFinalizer,
|
|
25
25
|
type ResponseFinalizerContext,
|
|
26
|
-
} from '../../extensions'
|
|
26
|
+
} from '../../extensions'
|
|
27
27
|
import {
|
|
28
28
|
setUseCacheFillTimeout,
|
|
29
29
|
setUseCacheRootParamNames,
|
|
30
30
|
takeCacheLifeStash,
|
|
31
|
-
} from '../cache/use-cache'
|
|
32
|
-
import { scanRootParams } from '../ppr/root-params-scan'
|
|
31
|
+
} from '../cache/use-cache'
|
|
32
|
+
import { scanRootParams } from '../ppr/root-params-scan'
|
|
33
33
|
import {
|
|
34
34
|
beginPrerenderErrorCollection,
|
|
35
35
|
endPrerenderErrorCollection,
|
|
36
|
-
} from '../cache/build-prerender-errors'
|
|
37
|
-
import { getNextConfig } from '../next/config-loader'
|
|
36
|
+
} from '../cache/build-prerender-errors'
|
|
37
|
+
import { getNextConfig } from '../next/config-loader'
|
|
38
38
|
|
|
39
39
|
// Route kinds a `use cache` page/handler can be served as.
|
|
40
40
|
const CACHEABLE_ROUTE_KINDS = new Set<ResponseFinalizerContext['routeKind']>([
|
|
41
41
|
'html',
|
|
42
42
|
'data',
|
|
43
43
|
'route-handler',
|
|
44
|
-
])
|
|
44
|
+
])
|
|
45
45
|
|
|
46
46
|
const useCacheHeaderFinalizer: ResponseFinalizer = ctx => {
|
|
47
|
-
const life = takeCacheLifeStash()
|
|
48
|
-
if (!life) return
|
|
49
|
-
if (!CACHEABLE_ROUTE_KINDS.has(ctx.routeKind)) return
|
|
47
|
+
const life = takeCacheLifeStash()
|
|
48
|
+
if (!life) return
|
|
49
|
+
if (!CACHEABLE_ROUTE_KINDS.has(ctx.routeKind)) return
|
|
50
50
|
|
|
51
|
-
const { revalidateSeconds, expireSeconds, staleSeconds } = life
|
|
51
|
+
const { revalidateSeconds, expireSeconds, staleSeconds } = life
|
|
52
52
|
|
|
53
53
|
// SWR cache-control: s-maxage = revalidate, stale-while-revalidate =
|
|
54
54
|
// expire − revalidate. Emitted only when a revalidate window is known and no
|
|
@@ -58,8 +58,8 @@ const useCacheHeaderFinalizer: ResponseFinalizer = ctx => {
|
|
|
58
58
|
expireSeconds !== undefined &&
|
|
59
59
|
!ctx.headers.has('cache-control')
|
|
60
60
|
) {
|
|
61
|
-
const swr = Math.max(0, expireSeconds - revalidateSeconds)
|
|
62
|
-
ctx.headers.set('cache-control', `s-maxage=${revalidateSeconds}, stale-while-revalidate=${swr}`)
|
|
61
|
+
const swr = Math.max(0, expireSeconds - revalidateSeconds)
|
|
62
|
+
ctx.headers.set('cache-control', `s-maxage=${revalidateSeconds}, stale-while-revalidate=${swr}`)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// x-nextjs-stale-time drives the client router's cache staleness window.
|
|
@@ -67,24 +67,24 @@ const useCacheHeaderFinalizer: ResponseFinalizer = ctx => {
|
|
|
67
67
|
// mode-derived default, but the live render's own cacheLife is authoritative
|
|
68
68
|
// (the header is internal — never user-supplied — so overwriting is safe).
|
|
69
69
|
if (staleSeconds !== undefined) {
|
|
70
|
-
ctx.headers.set('x-nextjs-stale-time', String(staleSeconds))
|
|
70
|
+
ctx.headers.set('x-nextjs-stale-time', String(staleSeconds))
|
|
71
71
|
}
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
73
|
|
|
74
|
-
let registered = false
|
|
74
|
+
let registered = false
|
|
75
75
|
// Host-scoped guard: a fresh host must be registered into again.
|
|
76
|
-
onExtensionHostReset(() => (registered = false))
|
|
76
|
+
onExtensionHostReset(() => (registered = false))
|
|
77
77
|
|
|
78
78
|
export function registerUseCacheExtensions(config: ResolvedConfig): void {
|
|
79
|
-
if (registered) return
|
|
80
|
-
if (!nextCompatEnabled(config)) return
|
|
81
|
-
registered = true
|
|
82
|
-
registerResponseFinalizers(useCacheHeaderFinalizer)
|
|
79
|
+
if (registered) return
|
|
80
|
+
if (!nextCompatEnabled(config)) return
|
|
81
|
+
registered = true
|
|
82
|
+
registerResponseFinalizers(useCacheHeaderFinalizer)
|
|
83
83
|
|
|
84
84
|
// Seed the root-param NAME set for cache-key participation (Stage B-3): a
|
|
85
85
|
// `use cache` entry's conservative first-call key may only discriminate by
|
|
86
86
|
// root params, so the runtime needs the scanned names at build AND serve.
|
|
87
|
-
setUseCacheRootParamNames(scanRootParams(config.appPath))
|
|
87
|
+
setUseCacheRootParamNames(scanRootParams(config.appPath))
|
|
88
88
|
|
|
89
89
|
// Arm `use cache` build-time validation for this build's prerender pass.
|
|
90
90
|
// Registered as a build STEP so it runs before any page is prerendered; the
|
|
@@ -93,32 +93,32 @@ export function registerUseCacheExtensions(config: ResolvedConfig): void {
|
|
|
93
93
|
registerBuildSteps(ctx => {
|
|
94
94
|
if (nextCompatEnabled(ctx.config)) {
|
|
95
95
|
const config = getNextConfig() as {
|
|
96
|
-
experimental?: { useCacheTimeout?: number }
|
|
97
|
-
staticPageGenerationTimeout?: number
|
|
98
|
-
}
|
|
99
|
-
const configured = config.experimental?.useCacheTimeout
|
|
100
|
-
const staticTimeout = config.staticPageGenerationTimeout
|
|
96
|
+
experimental?: { useCacheTimeout?: number }
|
|
97
|
+
staticPageGenerationTimeout?: number
|
|
98
|
+
}
|
|
99
|
+
const configured = config.experimental?.useCacheTimeout
|
|
100
|
+
const staticTimeout = config.staticPageGenerationTimeout
|
|
101
101
|
// Next clamps the build-time `use cache` fill timeout to just under the
|
|
102
102
|
// page-generation timeout (1s buffer before the build worker kills the
|
|
103
103
|
// page), so a slow fill fails via the clamp rather than the worker.
|
|
104
|
-
const baseMs = typeof configured === 'number' ? configured * 1000 : 50_000
|
|
104
|
+
const baseMs = typeof configured === 'number' ? configured * 1000 : 50_000
|
|
105
105
|
const clampMs =
|
|
106
106
|
typeof staticTimeout === 'number' && staticTimeout > 1
|
|
107
107
|
? (staticTimeout - 1) * 1000
|
|
108
|
-
: undefined
|
|
109
|
-
const fillMs = clampMs !== undefined ? Math.min(baseMs, clampMs) : baseMs
|
|
110
|
-
setUseCacheFillTimeout(fillMs)
|
|
111
|
-
beginPrerenderErrorCollection()
|
|
108
|
+
: undefined
|
|
109
|
+
const fillMs = clampMs !== undefined ? Math.min(baseMs, clampMs) : baseMs
|
|
110
|
+
setUseCacheFillTimeout(fillMs)
|
|
111
|
+
beginPrerenderErrorCollection()
|
|
112
112
|
}
|
|
113
|
-
return Promise.resolve()
|
|
114
|
-
})
|
|
113
|
+
return Promise.resolve()
|
|
114
|
+
})
|
|
115
115
|
|
|
116
116
|
// After prerendering, surface any recorded `use cache` violations. Each is
|
|
117
117
|
// printed with Next's exact error text plus the "Error occurred prerendering
|
|
118
118
|
// page" line the e2e suites grep for, then the build is aborted (exit 1).
|
|
119
119
|
registerBuildCompleteHooks(ctx => {
|
|
120
|
-
const errors = endPrerenderErrorCollection()
|
|
121
|
-
if (!nextCompatEnabled(ctx.config) || errors.length === 0) return Promise.resolve()
|
|
120
|
+
const errors = endPrerenderErrorCollection()
|
|
121
|
+
if (!nextCompatEnabled(ctx.config) || errors.length === 0) return Promise.resolve()
|
|
122
122
|
// Messages were already printed at detection time (see recordPrerenderError);
|
|
123
123
|
// the hook only forces the non-zero exit for builds that otherwise completed
|
|
124
124
|
// (a swallowed hanging timeout or a caught searchParams access).
|
|
@@ -126,6 +126,6 @@ export function registerUseCacheExtensions(config: ResolvedConfig): void {
|
|
|
126
126
|
`pnext build: ${errors.length} "use cache" validation error${
|
|
127
127
|
errors.length === 1 ? '' : 's'
|
|
128
128
|
} (see above)`,
|
|
129
|
-
)
|
|
130
|
-
})
|
|
129
|
+
)
|
|
130
|
+
})
|
|
131
131
|
}
|
|
@@ -7,50 +7,50 @@
|
|
|
7
7
|
// The step is ordered FIRST among build steps (registered before action discovery) so validation fails
|
|
8
8
|
// fast, before any bundling or prerender work. Registration is idempotent and no-op for pure-core apps.
|
|
9
9
|
|
|
10
|
-
import type { ResolvedConfig } from '../../config'
|
|
11
|
-
import { nextCompatEnabled } from '../../compat'
|
|
10
|
+
import type { ResolvedConfig } from '../../config'
|
|
11
|
+
import { nextCompatEnabled } from '../../compat/aliases'
|
|
12
12
|
import {
|
|
13
13
|
onExtensionHostReset,
|
|
14
14
|
registerBuildSteps,
|
|
15
15
|
setBuildCompatExtensions,
|
|
16
16
|
type BuildStep,
|
|
17
|
-
} from '../../extensions'
|
|
18
|
-
import type { RouteManifestEntry } from '../../types'
|
|
19
|
-
import { writeBuildFlags } from '../cache/build-flags'
|
|
20
|
-
import { validateBuild } from '../validation'
|
|
17
|
+
} from '../../extensions'
|
|
18
|
+
import type { RouteManifestEntry } from '../../types'
|
|
19
|
+
import { writeBuildFlags } from '../cache/build-flags'
|
|
20
|
+
import { validateBuild } from '../validation/validate'
|
|
21
21
|
import {
|
|
22
22
|
diagnoseCacheComponentsPrerender,
|
|
23
23
|
diagnosticLeadsWithErrorLine,
|
|
24
24
|
prerenderFailureFooter,
|
|
25
|
-
} from '../validation/prerender-diagnostics'
|
|
25
|
+
} from '../validation/prerender-diagnostics'
|
|
26
26
|
|
|
27
|
-
let registered = false
|
|
27
|
+
let registered = false
|
|
28
28
|
// Host-scoped guard: a fresh host must be registered into again.
|
|
29
|
-
onExtensionHostReset(() => (registered = false))
|
|
29
|
+
onExtensionHostReset(() => (registered = false))
|
|
30
30
|
|
|
31
31
|
export function registerValidationExtensions(config: ResolvedConfig): void {
|
|
32
|
-
if (registered) return
|
|
33
|
-
if (!nextCompatEnabled(config)) return
|
|
34
|
-
registered = true
|
|
32
|
+
if (registered) return
|
|
33
|
+
if (!nextCompatEnabled(config)) return
|
|
34
|
+
registered = true
|
|
35
35
|
|
|
36
36
|
const step: BuildStep = async ctx => {
|
|
37
37
|
// Runtime compat gate: the extension registry is process-global, so once any compat.next build
|
|
38
38
|
// registers this step it stays registered for every later buildProject() in the same process -
|
|
39
39
|
// including pure-core fixtures that legitimately have no root layout. Re-check enablement per build so
|
|
40
40
|
// validation only runs for the app that actually enabled compat.next.
|
|
41
|
-
if (!nextCompatEnabled(ctx.config)) return
|
|
41
|
+
if (!nextCompatEnabled(ctx.config)) return
|
|
42
42
|
await ctx.log.step('validate build', () =>
|
|
43
43
|
Promise.resolve(validateBuild(ctx.config, ctx.routes as RouteManifestEntry[])),
|
|
44
|
-
)
|
|
45
|
-
}
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
46
|
// Gate step: validation diagnostics must beat any error the invalid app would
|
|
47
47
|
// otherwise raise first from bundling or the not-found prerender.
|
|
48
|
-
step.gate = true
|
|
49
|
-
registerBuildSteps(step)
|
|
48
|
+
step.gate = true
|
|
49
|
+
registerBuildSteps(step)
|
|
50
50
|
setBuildCompatExtensions({
|
|
51
51
|
diagnoseCacheComponentsPrerender,
|
|
52
52
|
diagnosticLeadsWithErrorLine,
|
|
53
53
|
prerenderFailureFooter,
|
|
54
54
|
recordBuildFlags: writeBuildFlags,
|
|
55
|
-
})
|
|
55
|
+
})
|
|
56
56
|
}
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
// must be imported from `react` AND used as JSX in the scanned source. Missing a boundary only leaves the
|
|
10
10
|
// route on today's segment-miss path, so false negatives are the safe direction.
|
|
11
11
|
|
|
12
|
-
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
13
|
-
import path from 'node:path'
|
|
12
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
13
|
+
import path from 'node:path'
|
|
14
|
+
import { escapeRegex as escapeRegExp } from '../../utils/code'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* True when the route's PAGE file wraps content in a React `<Suspense>`.
|
|
@@ -22,44 +23,45 @@ import path from 'node:path';
|
|
|
22
23
|
* bound keeps a cyclic re-export from looping) before scanning.
|
|
23
24
|
*/
|
|
24
25
|
export function pageHasInPageSuspense(file: string): boolean {
|
|
25
|
-
return scanSourceOf(file, 2).some(sourceHasInPageSuspense)
|
|
26
|
+
return scanSourceOf(file, 2).some(sourceHasInPageSuspense)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/** `file`'s source plus the sources of its relative re-export targets. */
|
|
29
30
|
function scanSourceOf(file: string, depth: number, seen = new Set<string>()): string[] {
|
|
30
|
-
const resolved = resolveSourceFile(file)
|
|
31
|
-
if (resolved === null || seen.has(resolved)) return []
|
|
32
|
-
seen.add(resolved)
|
|
33
|
-
let source: string
|
|
31
|
+
const resolved = resolveSourceFile(file)
|
|
32
|
+
if (resolved === null || seen.has(resolved)) return []
|
|
33
|
+
seen.add(resolved)
|
|
34
|
+
let source: string
|
|
34
35
|
try {
|
|
35
|
-
source = readFileSync(resolved, 'utf8')
|
|
36
|
+
source = readFileSync(resolved, 'utf8')
|
|
36
37
|
} catch {
|
|
37
|
-
return []
|
|
38
|
+
return []
|
|
38
39
|
}
|
|
39
|
-
const sources = [source]
|
|
40
|
-
if (depth <= 0) return sources
|
|
41
|
-
const pattern =
|
|
42
|
-
|
|
40
|
+
const sources = [source]
|
|
41
|
+
if (depth <= 0) return sources
|
|
42
|
+
const pattern =
|
|
43
|
+
/(?:export|import)\s+(?:\*(?:\s+as\s+[\w$]+)?|\{[^}]*\})\s+from\s*['"](\.[^'"]+)['"]/g
|
|
44
|
+
let match: RegExpExecArray | null
|
|
43
45
|
while ((match = pattern.exec(source)) !== null) {
|
|
44
|
-
const specifier = match[1]
|
|
45
|
-
if (!specifier) continue
|
|
46
|
-
sources.push(...scanSourceOf(path.resolve(path.dirname(resolved), specifier), depth - 1, seen))
|
|
46
|
+
const specifier = match[1]
|
|
47
|
+
if (!specifier) continue
|
|
48
|
+
sources.push(...scanSourceOf(path.resolve(path.dirname(resolved), specifier), depth - 1, seen))
|
|
47
49
|
}
|
|
48
|
-
return sources
|
|
50
|
+
return sources
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/** `file` itself, or the first existing extension/index candidate for it. */
|
|
52
54
|
function resolveSourceFile(file: string): string | null {
|
|
53
|
-
if (existsSync(file) && statSync(file).isFile()) return file
|
|
55
|
+
if (existsSync(file) && statSync(file).isFile()) return file
|
|
54
56
|
for (const extension of SOURCE_EXTENSIONS) {
|
|
55
57
|
for (const candidate of [`${file}${extension}`, path.join(file, `index${extension}`)]) {
|
|
56
|
-
if (existsSync(candidate)) return candidate
|
|
58
|
+
if (existsSync(candidate)) return candidate
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
|
-
return null
|
|
61
|
+
return null
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
const SOURCE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs']
|
|
64
|
+
const SOURCE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs']
|
|
63
65
|
|
|
64
66
|
/**
|
|
65
67
|
* True when `source` imports `Suspense` from React and uses it as a JSX element. Comments are stripped
|
|
@@ -67,47 +69,43 @@ const SOURCE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.cjs'];
|
|
|
67
69
|
* named import and the namespace/default form are recognized.
|
|
68
70
|
*/
|
|
69
71
|
export function sourceHasInPageSuspense(source: string): boolean {
|
|
70
|
-
const stripped = stripComments(source)
|
|
71
|
-
const clauses = reactImportClauses(stripped)
|
|
72
|
-
if (clauses.length === 0) return false
|
|
73
|
-
const named = clauses.some(clause => /\bSuspense\b/.test(clause))
|
|
74
|
-
if (named && /<\s*Suspense[\s/>]/.test(stripped)) return true
|
|
72
|
+
const stripped = stripComments(source)
|
|
73
|
+
const clauses = reactImportClauses(stripped)
|
|
74
|
+
if (clauses.length === 0) return false
|
|
75
|
+
const named = clauses.some(clause => /\bSuspense\b/.test(clause))
|
|
76
|
+
if (named && /<\s*Suspense[\s/>]/.test(stripped)) return true
|
|
75
77
|
// `<React.Suspense>` / `<Foo.Suspense>` needs a default or namespace binding
|
|
76
78
|
// of the react module under that name.
|
|
77
79
|
return namespaceBindings(clauses).some(name =>
|
|
78
80
|
new RegExp(`<\\s*${escapeRegExp(name)}\\.Suspense[\\s/>]`).test(stripped),
|
|
79
|
-
)
|
|
81
|
+
)
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
/** The import clauses of every `... from 'react'` statement in `source`. */
|
|
83
85
|
function reactImportClauses(source: string): string[] {
|
|
84
|
-
const clauses: string[] = []
|
|
85
|
-
const pattern = /import\s+([^'"]*?)\s+from\s*['"]react['"]/g
|
|
86
|
-
let match: RegExpExecArray | null
|
|
87
|
-
while ((match = pattern.exec(source)) !== null) clauses.push(match[1] ?? '')
|
|
86
|
+
const clauses: string[] = []
|
|
87
|
+
const pattern = /import\s+([^'"]*?)\s+from\s*['"]react['"]/g
|
|
88
|
+
let match: RegExpExecArray | null
|
|
89
|
+
while ((match = pattern.exec(source)) !== null) clauses.push(match[1] ?? '')
|
|
88
90
|
// `const React = require('react')` — the CJS form app code still uses.
|
|
89
|
-
const cjs = /(?:const|let|var)\s+([\w$]+)\s*=\s*require\(\s*['"]react['"]\s*\)/g
|
|
90
|
-
while ((match = cjs.exec(source)) !== null) clauses.push(`* as ${match[1] ?? ''}`)
|
|
91
|
-
return clauses
|
|
91
|
+
const cjs = /(?:const|let|var)\s+([\w$]+)\s*=\s*require\(\s*['"]react['"]\s*\)/g
|
|
92
|
+
while ((match = cjs.exec(source)) !== null) clauses.push(`* as ${match[1] ?? ''}`)
|
|
93
|
+
return clauses
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
/** Names bound to the whole react module by an import clause (default/namespace). */
|
|
95
97
|
function namespaceBindings(clauses: readonly string[]): string[] {
|
|
96
|
-
const names: string[] = []
|
|
98
|
+
const names: string[] = []
|
|
97
99
|
for (const clause of clauses) {
|
|
98
|
-
const namespace = /\*\s+as\s+([\w$]+)/.exec(clause)
|
|
99
|
-
if (namespace?.[1]) names.push(namespace[1])
|
|
100
|
+
const namespace = /\*\s+as\s+([\w$]+)/.exec(clause)
|
|
101
|
+
if (namespace?.[1]) names.push(namespace[1])
|
|
100
102
|
// A default binding precedes any `{ ... }` named list.
|
|
101
|
-
const fallback = /^\s*([\w$]+)\s*(?:,|$)/.exec(clause.split('{')[0] ?? '')
|
|
102
|
-
if (fallback?.[1] && fallback[1] !== '*') names.push(fallback[1])
|
|
103
|
+
const fallback = /^\s*([\w$]+)\s*(?:,|$)/.exec(clause.split('{')[0] ?? '')
|
|
104
|
+
if (fallback?.[1] && fallback[1] !== '*') names.push(fallback[1])
|
|
103
105
|
}
|
|
104
|
-
return names
|
|
106
|
+
return names
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
function stripComments(source: string): string {
|
|
108
|
-
return source.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|[^:])\/\/.*$/gm, '$1')
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function escapeRegExp(value: string): string {
|
|
112
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
110
|
+
return source.replace(/\/\*[\s\S]*?\*\//g, '').replace(/(^|[^:])\/\/.*$/gm, '$1')
|
|
113
111
|
}
|