@wular/pnext 0.0.4 → 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 -1992
- 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 -1897
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +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} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +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 +827 -815
- 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/client/profile.ts
CHANGED
|
@@ -2,37 +2,37 @@
|
|
|
2
2
|
// esbuild / write), off unless PNEXT_CLIENT_PROFILE is set. The bench needs the
|
|
3
3
|
// split to prove where the residual sits; a build must not pay for it.
|
|
4
4
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
5
|
-
const enabled = Boolean(process.env.PNEXT_CLIENT_PROFILE)
|
|
5
|
+
const enabled = Boolean(process.env.PNEXT_CLIENT_PROFILE)
|
|
6
6
|
|
|
7
|
-
const totals = new Map<string, number>()
|
|
8
|
-
const spans = new Map<string, [number, number][]>()
|
|
7
|
+
const totals = new Map<string, number>()
|
|
8
|
+
const spans = new Map<string, [number, number][]>()
|
|
9
9
|
|
|
10
10
|
/** Total wall covered by at least one span (overlaps counted once). */
|
|
11
11
|
function unionMs(intervals: [number, number][]) {
|
|
12
|
-
const sorted = [...intervals].sort((a, b) => a[0] - b[0])
|
|
13
|
-
let total = 0
|
|
14
|
-
let [openStart, openEnd] = sorted[0] ?? [0, 0]
|
|
12
|
+
const sorted = [...intervals].sort((a, b) => a[0] - b[0])
|
|
13
|
+
let total = 0
|
|
14
|
+
let [openStart, openEnd] = sorted[0] ?? [0, 0]
|
|
15
15
|
for (const [start, end] of sorted.slice(1)) {
|
|
16
16
|
if (start > openEnd) {
|
|
17
|
-
total += openEnd - openStart
|
|
18
|
-
[openStart, openEnd] = [start, end]
|
|
17
|
+
total += openEnd - openStart
|
|
18
|
+
;[openStart, openEnd] = [start, end]
|
|
19
19
|
} else if (end > openEnd) {
|
|
20
|
-
openEnd = end
|
|
20
|
+
openEnd = end
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
return total + (openEnd - openStart)
|
|
23
|
+
return total + (openEnd - openStart)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export const clientProfile = {
|
|
27
27
|
enabled,
|
|
28
28
|
/** Time `task` under `phase`. Returns the task's value untouched. */
|
|
29
29
|
time<T>(phase: string, task: () => T): T {
|
|
30
|
-
if (!enabled) return task()
|
|
31
|
-
const start = performance.now()
|
|
30
|
+
if (!enabled) return task()
|
|
31
|
+
const start = performance.now()
|
|
32
32
|
try {
|
|
33
|
-
return task()
|
|
33
|
+
return task()
|
|
34
34
|
} finally {
|
|
35
|
-
totals.set(phase, (totals.get(phase) ?? 0) + (performance.now() - start))
|
|
35
|
+
totals.set(phase, (totals.get(phase) ?? 0) + (performance.now() - start))
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
/**
|
|
@@ -40,36 +40,36 @@ export const clientProfile = {
|
|
|
40
40
|
* the same second many times. Record spans and report the union - the wall the phase occupies.
|
|
41
41
|
*/
|
|
42
42
|
async timeAsync<T>(phase: string, task: () => Promise<T>): Promise<T> {
|
|
43
|
-
if (!enabled) return task()
|
|
44
|
-
const start = performance.now()
|
|
43
|
+
if (!enabled) return task()
|
|
44
|
+
const start = performance.now()
|
|
45
45
|
try {
|
|
46
|
-
return await task()
|
|
46
|
+
return await task()
|
|
47
47
|
} finally {
|
|
48
|
-
(spans.get(phase) ?? spans.set(phase, []).get(phase)!).push([start, performance.now()])
|
|
48
|
+
;(spans.get(phase) ?? spans.set(phase, []).get(phase)!).push([start, performance.now()])
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
count(key: string, by = 1) {
|
|
52
|
-
if (!enabled) return
|
|
53
|
-
totals.set(key, (totals.get(key) ?? 0) + by)
|
|
52
|
+
if (!enabled) return
|
|
53
|
+
totals.set(key, (totals.get(key) ?? 0) + by)
|
|
54
54
|
},
|
|
55
55
|
reset() {
|
|
56
|
-
totals.clear()
|
|
57
|
-
spans.clear()
|
|
56
|
+
totals.clear()
|
|
57
|
+
spans.clear()
|
|
58
58
|
},
|
|
59
59
|
snapshot(): Record<string, number> {
|
|
60
60
|
return {
|
|
61
61
|
...Object.fromEntries(totals),
|
|
62
62
|
...Object.fromEntries([...spans].map(([phase, list]) => [phase, unionMs(list)])),
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
64
|
},
|
|
65
65
|
/** Print the snapshot and clear it, so a second stage starts from zero. */
|
|
66
66
|
report(label: string) {
|
|
67
|
-
if (!enabled) return
|
|
68
|
-
const snap = this.snapshot()
|
|
67
|
+
if (!enabled) return
|
|
68
|
+
const snap = this.snapshot()
|
|
69
69
|
const line = Object.entries(snap)
|
|
70
70
|
.map(([phase, value]) => `${phase} ${value < 100 ? value.toFixed(1) : Math.round(value)}`)
|
|
71
|
-
.join(' · ')
|
|
72
|
-
console.log(`pnext client profile [${label}] ${line}`)
|
|
73
|
-
this.reset()
|
|
71
|
+
.join(' · ')
|
|
72
|
+
console.log(`pnext client profile [${label}] ${line}`)
|
|
73
|
+
this.reset()
|
|
74
74
|
},
|
|
75
|
-
}
|
|
75
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
transform,
|
|
3
|
+
transformSync,
|
|
4
|
+
type TransformOptions,
|
|
5
|
+
type TransformResult,
|
|
6
|
+
} from 'oxc-transform'
|
|
7
|
+
import type { getCompatModeExtensions } from '../extensions'
|
|
3
8
|
|
|
4
9
|
type ReactCompilerOptions = NonNullable<
|
|
5
10
|
ReturnType<ReturnType<typeof getCompatModeExtensions>['reactCompilerOptions']>
|
|
6
|
-
|
|
11
|
+
>
|
|
7
12
|
|
|
8
13
|
// oxc-transform runs the React Compiler (Rust port) plus TypeScript stripping
|
|
9
14
|
// in a single pass, replacing the @babel/core round-trip. JSX is left intact
|
|
@@ -17,7 +22,7 @@ function compilerOptions(options: ReactCompilerOptions): TransformOptions {
|
|
|
17
22
|
panicThreshold: 'critical_errors',
|
|
18
23
|
target: options.target as '17' | '18' | '19',
|
|
19
24
|
},
|
|
20
|
-
}
|
|
25
|
+
}
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
/**
|
|
@@ -35,7 +40,7 @@ export async function transformReactCompiler(
|
|
|
35
40
|
file: string,
|
|
36
41
|
options: ReactCompilerOptions,
|
|
37
42
|
) {
|
|
38
|
-
return reactCompilerResult(await transform(file, source, compilerOptions(options)), source, file)
|
|
43
|
+
return reactCompilerResult(await transform(file, source, compilerOptions(options)), source, file)
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
/** Same pass, for the few callers that cannot await (kept in lock-step above). */
|
|
@@ -44,7 +49,7 @@ export function transformReactCompilerSync(
|
|
|
44
49
|
file: string,
|
|
45
50
|
options: ReactCompilerOptions,
|
|
46
51
|
) {
|
|
47
|
-
return reactCompilerResult(transformSync(file, source, compilerOptions(options)), source, file)
|
|
52
|
+
return reactCompilerResult(transformSync(file, source, compilerOptions(options)), source, file)
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
function reactCompilerResult(result: TransformResult, source: string, file: string) {
|
|
@@ -56,16 +61,16 @@ function reactCompilerResult(result: TransformResult, source: string, file: stri
|
|
|
56
61
|
if (!result.code) {
|
|
57
62
|
// Only genuine transform failures (not React Compiler bailouts) are worth
|
|
58
63
|
// surfacing; esbuild re-parses the fallback source and would flag the rest.
|
|
59
|
-
const failures = result.errors.filter(error => !error.message.startsWith('[ReactCompiler]'))
|
|
64
|
+
const failures = result.errors.filter(error => !error.message.startsWith('[ReactCompiler]'))
|
|
60
65
|
if (failures.length > 0) {
|
|
61
66
|
console.error(
|
|
62
67
|
`React Compiler (oxc) failed for ${file}:\n${failures.map(error => error.message).join('\n')}`,
|
|
63
|
-
)
|
|
68
|
+
)
|
|
64
69
|
}
|
|
65
|
-
return source
|
|
70
|
+
return source
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
return result.code
|
|
73
|
+
return result.code
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
export function stripPureTypeImports(source: string) {
|
|
@@ -78,17 +83,17 @@ export function stripPureTypeImports(source: string) {
|
|
|
78
83
|
.split(',')
|
|
79
84
|
.map(item => item.trim())
|
|
80
85
|
.filter(Boolean)
|
|
81
|
-
.filter(item => !item.startsWith('type '))
|
|
86
|
+
.filter(item => !item.startsWith('type '))
|
|
82
87
|
|
|
83
88
|
return valueSpecifiers.length > 0
|
|
84
89
|
? `import { ${valueSpecifiers.join(', ')} } from ${specifier};`
|
|
85
|
-
: ''
|
|
90
|
+
: ''
|
|
86
91
|
},
|
|
87
|
-
)
|
|
92
|
+
)
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
/** JSX always; a plain .ts/.js only when it looks like it holds a component. */
|
|
91
96
|
export function shouldReactCompile(source: string, file: string) {
|
|
92
|
-
if (/\.[cm]?[jt]sx$/.test(file)) return true
|
|
93
|
-
return /\b(?:use[A-Z][\w$]*|createElement|memo|forwardRef)\b/.test(source)
|
|
97
|
+
if (/\.[cm]?[jt]sx$/.test(file)) return true
|
|
98
|
+
return /\b(?:use[A-Z][\w$]*|createElement|memo|forwardRef)\b/.test(source)
|
|
94
99
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Conservative static scan of a compat app's client graph deciding whether the client bundle can ship
|
|
@@ -41,7 +41,7 @@ const LITE_REACT_NAMES = new Set([
|
|
|
41
41
|
'version',
|
|
42
42
|
'ViewTransition',
|
|
43
43
|
'addTransitionType',
|
|
44
|
-
])
|
|
44
|
+
])
|
|
45
45
|
|
|
46
46
|
// Framework client modules known not to pull preact/compat. Every other bare specifier (npm packages,
|
|
47
47
|
// next/dynamic, next/image, ...) disqualifies the lite tier.
|
|
@@ -53,123 +53,123 @@ const SAFE_BARE_SPECIFIERS = new Set([
|
|
|
53
53
|
'preact/jsx-runtime',
|
|
54
54
|
'react/jsx-runtime',
|
|
55
55
|
'react/jsx-dev-runtime',
|
|
56
|
-
])
|
|
56
|
+
])
|
|
57
57
|
|
|
58
58
|
// Compat-only semantics preact core lacks: React's onChange/onDoubleClick synthetic mapping,
|
|
59
59
|
// default* form props, string refs, legacy class lifecycles - plus async component shapes (they
|
|
60
60
|
// suspend). Matching anywhere in a file (even a comment) just falls back to the full tier.
|
|
61
61
|
const UNSAFE_TOKENS =
|
|
62
|
-
/\bonChange\b|\bonDoubleClick\b|\bdefaultProps\b|\bgetSnapshotBeforeUpdate\b|\bcomponentWillReceiveProps\b|\bUNSAFE_\w+|\bref\s*=\s*["']|async\s+function\s+[A-Z]|(?:const|let|var)\s+[A-Z][\w$]*\s*=\s*async\b|export\s+default\s+async\b
|
|
62
|
+
/\bonChange\b|\bonDoubleClick\b|\bdefaultProps\b|\bgetSnapshotBeforeUpdate\b|\bcomponentWillReceiveProps\b|\bUNSAFE_\w+|\bref\s*=\s*["']|async\s+function\s+[A-Z]|(?:const|let|var)\s+[A-Z][\w$]*\s*=\s*async\b|export\s+default\s+async\b/
|
|
63
63
|
|
|
64
64
|
// defaultValue/defaultChecked are native DOM properties preact core assigns correctly on
|
|
65
65
|
// input/textarea; only <select defaultValue> needs preact/compat's special handling.
|
|
66
66
|
function unsafeDefaultValue(source: string) {
|
|
67
|
-
return source.includes('defaultValue') && source.includes('<select')
|
|
67
|
+
return source.includes('defaultValue') && source.includes('<select')
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
const STATIC_IMPORT = /(?:^|\n)\s*(?:import|export)\s+([^;'"]*?)\s*from\s*(['"])([^'"]+)\2/g
|
|
71
|
-
const BARE_IMPORT = /(?:^|\n)\s*import\s*(['"])([^'"]+)\1/g
|
|
72
|
-
const DYNAMIC_IMPORT = /\bimport\(\s*(['"])([^'"]+)\1/g
|
|
70
|
+
const STATIC_IMPORT = /(?:^|\n)\s*(?:import|export)\s+([^;'"]*?)\s*from\s*(['"])([^'"]+)\2/g
|
|
71
|
+
const BARE_IMPORT = /(?:^|\n)\s*import\s*(['"])([^'"]+)\1/g
|
|
72
|
+
const DYNAMIC_IMPORT = /\bimport\(\s*(['"])([^'"]+)\1/g
|
|
73
73
|
|
|
74
|
-
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']
|
|
75
|
-
const SOURCE_EXTENSION = /\.(?:ts|tsx|js|jsx|mjs|cjs)
|
|
74
|
+
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs']
|
|
75
|
+
const SOURCE_EXTENSION = /\.(?:ts|tsx|js|jsx|mjs|cjs)$/
|
|
76
76
|
|
|
77
77
|
export function clientSuspenseFree(seeds: Iterable<string>): boolean {
|
|
78
|
-
const queue: string[] = []
|
|
79
|
-
const visited = new Set<string>()
|
|
78
|
+
const queue: string[] = []
|
|
79
|
+
const visited = new Set<string>()
|
|
80
80
|
for (const seed of seeds) {
|
|
81
|
-
if (!seed || visited.has(seed)) continue
|
|
82
|
-
visited.add(seed)
|
|
83
|
-
queue.push(seed)
|
|
81
|
+
if (!seed || visited.has(seed)) continue
|
|
82
|
+
visited.add(seed)
|
|
83
|
+
queue.push(seed)
|
|
84
84
|
}
|
|
85
85
|
while (queue.length > 0) {
|
|
86
|
-
const file = queue.pop()
|
|
87
|
-
if (!SOURCE_EXTENSION.test(file) || !existsSync(file)) return false
|
|
88
|
-
let source: string
|
|
86
|
+
const file = queue.pop()!
|
|
87
|
+
if (!SOURCE_EXTENSION.test(file) || !existsSync(file)) return false
|
|
88
|
+
let source: string
|
|
89
89
|
try {
|
|
90
|
-
source = readFileSync(file, 'utf8')
|
|
90
|
+
source = readFileSync(file, 'utf8')
|
|
91
91
|
} catch {
|
|
92
|
-
return false
|
|
92
|
+
return false
|
|
93
93
|
}
|
|
94
|
-
if (UNSAFE_TOKENS.test(source) || unsafeDefaultValue(source)) return false
|
|
94
|
+
if (UNSAFE_TOKENS.test(source) || unsafeDefaultValue(source)) return false
|
|
95
95
|
for (const [clause, specifier] of importsOf(source)) {
|
|
96
96
|
if (specifier === 'react') {
|
|
97
|
-
if (!liteReactClause(clause)) return false
|
|
98
|
-
continue
|
|
97
|
+
if (!liteReactClause(clause)) return false
|
|
98
|
+
continue
|
|
99
99
|
}
|
|
100
|
-
if (SAFE_BARE_SPECIFIERS.has(specifier)) continue
|
|
100
|
+
if (SAFE_BARE_SPECIFIERS.has(specifier)) continue
|
|
101
101
|
if (specifier.startsWith('.')) {
|
|
102
|
-
if (clause !== undefined && typeOnlyClause(clause)) continue
|
|
103
|
-
const resolved = resolveRelative(path.dirname(file), specifier)
|
|
104
|
-
if (resolved === ASSET) continue
|
|
105
|
-
if (!resolved) return false
|
|
102
|
+
if (clause !== undefined && typeOnlyClause(clause)) continue
|
|
103
|
+
const resolved = resolveRelative(path.dirname(file), specifier)
|
|
104
|
+
if (resolved === ASSET) continue
|
|
105
|
+
if (!resolved) return false
|
|
106
106
|
if (!visited.has(resolved)) {
|
|
107
|
-
visited.add(resolved)
|
|
108
|
-
queue.push(resolved)
|
|
107
|
+
visited.add(resolved)
|
|
108
|
+
queue.push(resolved)
|
|
109
109
|
}
|
|
110
|
-
continue
|
|
110
|
+
continue
|
|
111
111
|
}
|
|
112
112
|
// Unknown bare package or framework module that may pull preact/compat.
|
|
113
|
-
if (clause === undefined || !typeOnlyClause(clause)) return false
|
|
113
|
+
if (clause === undefined || !typeOnlyClause(clause)) return false
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
return true
|
|
116
|
+
return true
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
function* importsOf(source: string): Generator<[clause: string | undefined, specifier: string]> {
|
|
120
|
-
for (const match of source.matchAll(STATIC_IMPORT)) yield [match[1], match[3] ?? '']
|
|
121
|
-
for (const match of source.matchAll(BARE_IMPORT)) yield [undefined, match[2] ?? '']
|
|
122
|
-
for (const match of source.matchAll(DYNAMIC_IMPORT)) yield [undefined, match[2] ?? '']
|
|
120
|
+
for (const match of source.matchAll(STATIC_IMPORT)) yield [match[1], match[3] ?? '']
|
|
121
|
+
for (const match of source.matchAll(BARE_IMPORT)) yield [undefined, match[2] ?? '']
|
|
122
|
+
for (const match of source.matchAll(DYNAMIC_IMPORT)) yield [undefined, match[2] ?? '']
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
function typeOnlyClause(clause: string) {
|
|
126
|
-
return /^type\s/.test(clause.trim())
|
|
126
|
+
return /^type\s/.test(clause.trim())
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function liteReactClause(clause: string | undefined): boolean {
|
|
130
|
-
if (clause === undefined) return true
|
|
131
|
-
const trimmed = clause.trim()
|
|
132
|
-
if (typeOnlyClause(trimmed)) return true
|
|
130
|
+
if (clause === undefined) return true
|
|
131
|
+
const trimmed = clause.trim()
|
|
132
|
+
if (typeOnlyClause(trimmed)) return true
|
|
133
133
|
// Default or namespace import: the whole surface is reachable - full tier.
|
|
134
|
-
const braceStart = trimmed.indexOf('{')
|
|
135
|
-
if (braceStart !== 0) return false
|
|
136
|
-
const braceEnd = trimmed.indexOf('}')
|
|
137
|
-
if (braceEnd === -1) return false
|
|
134
|
+
const braceStart = trimmed.indexOf('{')
|
|
135
|
+
if (braceStart !== 0) return false
|
|
136
|
+
const braceEnd = trimmed.indexOf('}')
|
|
137
|
+
if (braceEnd === -1) return false
|
|
138
138
|
for (const entry of trimmed.slice(braceStart + 1, braceEnd).split(',')) {
|
|
139
|
-
const name = entry.trim()
|
|
140
|
-
if (!name || name.startsWith('type ')) continue
|
|
141
|
-
const imported = (name.split(/\s+as\s+/)[0] ?? '').trim()
|
|
142
|
-
if (!LITE_REACT_NAMES.has(imported)) return false
|
|
139
|
+
const name = entry.trim()
|
|
140
|
+
if (!name || name.startsWith('type ')) continue
|
|
141
|
+
const imported = (name.split(/\s+as\s+/)[0] ?? '').trim()
|
|
142
|
+
if (!LITE_REACT_NAMES.has(imported)) return false
|
|
143
143
|
}
|
|
144
|
-
return true
|
|
144
|
+
return true
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const ASSET = Symbol('pnext.compat-surface.asset')
|
|
147
|
+
const ASSET = Symbol('pnext.compat-surface.asset')
|
|
148
148
|
|
|
149
149
|
function resolveRelative(dir: string, specifier: string): string | typeof ASSET | undefined {
|
|
150
|
-
let base = path.resolve(dir, specifier)
|
|
151
|
-
const direct = fileAt(base)
|
|
152
|
-
if (direct) return direct
|
|
150
|
+
let base = path.resolve(dir, specifier)
|
|
151
|
+
const direct = fileAt(base)
|
|
152
|
+
if (direct) return direct
|
|
153
153
|
// NodeNext-style `./x.js` pointing at `./x.ts(x)`.
|
|
154
|
-
if (/\.(?:js|jsx|mjs|cjs)$/.test(base)) base = base.replace(/\.[^.]+$/, '')
|
|
154
|
+
if (/\.(?:js|jsx|mjs|cjs)$/.test(base)) base = base.replace(/\.[^.]+$/, '')
|
|
155
155
|
for (const extension of SOURCE_EXTENSIONS) {
|
|
156
|
-
const candidate = fileAt(base + extension)
|
|
157
|
-
if (candidate) return candidate
|
|
156
|
+
const candidate = fileAt(base + extension)
|
|
157
|
+
if (candidate) return candidate
|
|
158
158
|
}
|
|
159
159
|
for (const extension of SOURCE_EXTENSIONS) {
|
|
160
|
-
const candidate = fileAt(path.join(base, `index${extension}`))
|
|
161
|
-
if (candidate) return candidate
|
|
160
|
+
const candidate = fileAt(path.join(base, `index${extension}`))
|
|
161
|
+
if (candidate) return candidate
|
|
162
162
|
}
|
|
163
|
-
return undefined
|
|
163
|
+
return undefined
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
function fileAt(candidate: string): string | typeof ASSET | undefined {
|
|
167
|
-
if (!existsSync(candidate)) return undefined
|
|
167
|
+
if (!existsSync(candidate)) return undefined
|
|
168
168
|
try {
|
|
169
|
-
if (!statSync(candidate).isFile()) return undefined
|
|
169
|
+
if (!statSync(candidate).isFile()) return undefined
|
|
170
170
|
} catch {
|
|
171
|
-
return undefined
|
|
171
|
+
return undefined
|
|
172
172
|
}
|
|
173
173
|
// Styles/assets never carry react surface.
|
|
174
|
-
return SOURCE_EXTENSION.test(candidate) ? candidate : ASSET
|
|
174
|
+
return SOURCE_EXTENSION.test(candidate) ? candidate : ASSET
|
|
175
175
|
}
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
* boundary from the server graph - the dev module pass and the vendor bundler (a package's own
|
|
5
5
|
* `'use client'` files, reached mid-bundle).
|
|
6
6
|
*/
|
|
7
|
-
import path from 'node:path'
|
|
8
|
-
import { clientReferenceId } from './reference'
|
|
9
|
-
import { pathToFileHref } from '../config'
|
|
10
|
-
import type { ResolvedConfig } from '../config'
|
|
11
|
-
import { resolveImport } from '../resolve/imports'
|
|
12
|
-
import { moduleExportNames, moduleExportStars } from '../resolve/scan-facts'
|
|
13
|
-
import { readText } from '../utils/fs'
|
|
7
|
+
import path from 'node:path'
|
|
8
|
+
import { clientReferenceId } from './reference'
|
|
9
|
+
import { pathToFileHref } from '../config'
|
|
10
|
+
import type { ResolvedConfig } from '../config'
|
|
11
|
+
import { resolveImport } from '../resolve/imports'
|
|
12
|
+
import { moduleExportNames, moduleExportStars } from '../resolve/scan-facts'
|
|
13
|
+
import { readText } from '../utils/fs'
|
|
14
14
|
|
|
15
|
-
export const clientReferenceRuntimeFile = path.resolve(import.meta.dirname, 'reference.ts')
|
|
15
|
+
export const clientReferenceRuntimeFile = path.resolve(import.meta.dirname, 'reference.ts')
|
|
16
16
|
|
|
17
17
|
export interface ClientReferenceModuleOptions {
|
|
18
18
|
/**
|
|
@@ -21,7 +21,7 @@ export interface ClientReferenceModuleOptions {
|
|
|
21
21
|
* reach pnext's own source tree, and the symbol is registry-global, so an
|
|
22
22
|
* inlined lookup is the same symbol the renderer tests for.
|
|
23
23
|
*/
|
|
24
|
-
inlineSymbol?: boolean
|
|
24
|
+
inlineSymbol?: boolean
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export function clientReferenceModuleSource(
|
|
@@ -30,16 +30,16 @@ export function clientReferenceModuleSource(
|
|
|
30
30
|
options: ClientReferenceModuleOptions = {},
|
|
31
31
|
) {
|
|
32
32
|
const reference = (exportName: string) =>
|
|
33
|
-
`createReference({ id: ${JSON.stringify(`c-${clientReferenceId(sourceFile, exportName)}`)}, file: ${JSON.stringify(sourceFile)}, exportName: ${JSON.stringify(exportName)} })
|
|
33
|
+
`createReference({ id: ${JSON.stringify(`c-${clientReferenceId(sourceFile, exportName)}`)}, file: ${JSON.stringify(sourceFile)}, exportName: ${JSON.stringify(exportName)} })`
|
|
34
34
|
const defaultExport = exportNames.includes('default')
|
|
35
35
|
? `export default ${reference('default')};`
|
|
36
|
-
: ''
|
|
36
|
+
: ''
|
|
37
37
|
const namedExports = exportNames
|
|
38
38
|
.filter(name => name !== 'default')
|
|
39
|
-
.map(name => `export const ${name} = ${reference(name)};`)
|
|
39
|
+
.map(name => `export const ${name} = ${reference(name)};`)
|
|
40
40
|
const symbol = options.inlineSymbol
|
|
41
41
|
? `const clientReferenceSymbol = Symbol.for('pnext.clientReference');`
|
|
42
|
-
: `import { clientReferenceSymbol } from ${JSON.stringify(pathToFileHref(clientReferenceRuntimeFile))}
|
|
42
|
+
: `import { clientReferenceSymbol } from ${JSON.stringify(pathToFileHref(clientReferenceRuntimeFile))};`
|
|
43
43
|
|
|
44
44
|
return `${symbol}
|
|
45
45
|
|
|
@@ -53,7 +53,7 @@ function createReference(reference) {
|
|
|
53
53
|
|
|
54
54
|
${defaultExport}
|
|
55
55
|
${namedExports.join('\n')}
|
|
56
|
-
|
|
56
|
+
`
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
@@ -67,32 +67,32 @@ export async function clientReferenceExportNames(
|
|
|
67
67
|
source?: string,
|
|
68
68
|
visited = new Set<string>(),
|
|
69
69
|
): Promise<string[]> {
|
|
70
|
-
const key = path.resolve(file)
|
|
71
|
-
if (visited.has(key)) return []
|
|
72
|
-
visited.add(key)
|
|
73
|
-
const text = source ?? (await readText(file))
|
|
74
|
-
const names = new Set(moduleExportNames(text, file))
|
|
70
|
+
const key = path.resolve(file)
|
|
71
|
+
if (visited.has(key)) return []
|
|
72
|
+
visited.add(key)
|
|
73
|
+
const text = source ?? (await readText(file))
|
|
74
|
+
const names = new Set(moduleExportNames(text, file))
|
|
75
75
|
// A CommonJS-style client module (`exports.X = ...`) has no ESM exports for
|
|
76
76
|
// the transpiler scan; recover the statically visible names so its reference
|
|
77
77
|
// shim exposes them (mirrors the client bundle's CJS-name recovery).
|
|
78
78
|
if (names.size === 0) {
|
|
79
79
|
for (const match of text.matchAll(/\bexports\.([A-Za-z_$][\w$]*)\s*=/g)) {
|
|
80
|
-
if (match[1] !== '__esModule') names.add(match[1]!)
|
|
80
|
+
if (match[1] !== '__esModule') names.add(match[1]!)
|
|
81
81
|
}
|
|
82
|
-
if (/\bmodule\.exports\s*=/.test(text)) names.add('default')
|
|
82
|
+
if (/\bmodule\.exports\s*=/.test(text)) names.add('default')
|
|
83
83
|
}
|
|
84
84
|
// `export * from './x'` re-exports every named export of the target, whose
|
|
85
85
|
// names live in that module — union them recursively (default stays
|
|
86
86
|
// excluded, per ES module star semantics). `export * as ns from` exports
|
|
87
87
|
// only `ns`, which the own-module scan already lists.
|
|
88
88
|
for (const specifier of moduleExportStars(text, file)) {
|
|
89
|
-
const resolved = resolveImport(config.root, file, specifier)
|
|
90
|
-
if (!resolved || !isInside(config.workspaceRoot, resolved)) continue
|
|
89
|
+
const resolved = resolveImport(config.root, file, specifier)
|
|
90
|
+
if (!resolved || !isInside(config.workspaceRoot, resolved)) continue
|
|
91
91
|
for (const name of await clientReferenceExportNames(config, resolved, undefined, visited)) {
|
|
92
|
-
if (name !== 'default') names.add(name)
|
|
92
|
+
if (name !== 'default') names.add(name)
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
return [...names]
|
|
95
|
+
return [...names]
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -104,42 +104,42 @@ export async function clientReferenceExportNames(
|
|
|
104
104
|
*/
|
|
105
105
|
export function hasUseClientDirective(source: string) {
|
|
106
106
|
const isSpace = (index: number) => {
|
|
107
|
-
const code = source.charCodeAt(index)
|
|
108
|
-
return code === 32 || (code >= 9 && code <= 13) || (code > 127 && /\s/.test(source[index]!))
|
|
109
|
-
}
|
|
110
|
-
let i = 0
|
|
107
|
+
const code = source.charCodeAt(index)
|
|
108
|
+
return code === 32 || (code >= 9 && code <= 13) || (code > 127 && /\s/.test(source[index]!))
|
|
109
|
+
}
|
|
110
|
+
let i = 0
|
|
111
111
|
for (;;) {
|
|
112
|
-
while (i < source.length && isSpace(i)) i += 1
|
|
112
|
+
while (i < source.length && isSpace(i)) i += 1
|
|
113
113
|
if (source.startsWith('//', i)) {
|
|
114
|
-
const newline = source.indexOf('\n', i)
|
|
115
|
-
if (newline === -1) return false
|
|
116
|
-
i = newline + 1
|
|
117
|
-
continue
|
|
114
|
+
const newline = source.indexOf('\n', i)
|
|
115
|
+
if (newline === -1) return false
|
|
116
|
+
i = newline + 1
|
|
117
|
+
continue
|
|
118
118
|
}
|
|
119
119
|
if (source.startsWith('/*', i)) {
|
|
120
|
-
const end = source.indexOf('*/', i + 2)
|
|
121
|
-
if (end === -1) return false
|
|
122
|
-
i = end + 2
|
|
123
|
-
continue
|
|
120
|
+
const end = source.indexOf('*/', i + 2)
|
|
121
|
+
if (end === -1) return false
|
|
122
|
+
i = end + 2
|
|
123
|
+
continue
|
|
124
124
|
}
|
|
125
125
|
// Anything that is not a string literal ends the prologue.
|
|
126
|
-
const quote = source[i]
|
|
127
|
-
if (quote !== '"' && quote !== "'") return false
|
|
128
|
-
let end = i + 1
|
|
126
|
+
const quote = source[i]
|
|
127
|
+
if (quote !== '"' && quote !== "'") return false
|
|
128
|
+
let end = i + 1
|
|
129
129
|
while (end < source.length) {
|
|
130
|
-
const char = source[end]
|
|
131
|
-
if (char === quote || char === '\n' || char === '\\') break
|
|
132
|
-
end += 1
|
|
130
|
+
const char = source[end]!
|
|
131
|
+
if (char === quote || char === '\n' || char === '\\') break
|
|
132
|
+
end += 1
|
|
133
133
|
}
|
|
134
|
-
if (source[end] !== quote) return false
|
|
135
|
-
if (source.slice(i + 1, end) === 'use client') return true
|
|
136
|
-
i = end + 1
|
|
137
|
-
while (i < source.length && isSpace(i)) i += 1
|
|
138
|
-
if (source[i] === ';') i += 1
|
|
134
|
+
if (source[end] !== quote) return false
|
|
135
|
+
if (source.slice(i + 1, end) === 'use client') return true
|
|
136
|
+
i = end + 1
|
|
137
|
+
while (i < source.length && isSpace(i)) i += 1
|
|
138
|
+
if (source[i] === ';') i += 1
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
function isInside(root: string, file: string) {
|
|
143
|
-
const relative = path.relative(root, file)
|
|
144
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
143
|
+
const relative = path.relative(root, file)
|
|
144
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
145
145
|
}
|
package/src/client/reference.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
2
|
|
|
3
3
|
export interface ClientReference {
|
|
4
|
-
id: string
|
|
5
|
-
file: string
|
|
6
|
-
exportName: string
|
|
7
|
-
dynamic?: ClientDynamicReference
|
|
8
|
-
cssImports?: string[]
|
|
4
|
+
id: string
|
|
5
|
+
file: string
|
|
6
|
+
exportName: string
|
|
7
|
+
dynamic?: ClientDynamicReference
|
|
8
|
+
cssImports?: string[]
|
|
9
9
|
/**
|
|
10
10
|
* A `'use client'` module imported only for its side effects (a bare
|
|
11
11
|
* `import './client-only'` with no bindings). It is never rendered as a
|
|
@@ -14,21 +14,21 @@ export interface ClientReference {
|
|
|
14
14
|
* client entry (a bare side-effect import) to run its top-level code. It has
|
|
15
15
|
* no SSR component, so it is excluded from every server-side marking pass.
|
|
16
16
|
*/
|
|
17
|
-
sideEffect?: boolean
|
|
17
|
+
sideEffect?: boolean
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface ClientDynamicReference {
|
|
21
|
-
load?: 'render' | 'visible'
|
|
22
|
-
rootMargin?: string
|
|
23
|
-
ssr?: boolean
|
|
24
|
-
threshold?: number | number[]
|
|
21
|
+
load?: 'render' | 'visible'
|
|
22
|
+
rootMargin?: string
|
|
23
|
+
ssr?: boolean
|
|
24
|
+
threshold?: number | number[]
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const clientReferenceSymbol = Symbol.for('pnext.clientReference')
|
|
27
|
+
export const clientReferenceSymbol = Symbol.for('pnext.clientReference')
|
|
28
28
|
|
|
29
29
|
export type ClientComponent = ((props: Record<string, unknown>) => unknown) & {
|
|
30
|
-
[clientReferenceSymbol]?: ClientReference
|
|
31
|
-
}
|
|
30
|
+
[clientReferenceSymbol]?: ClientReference
|
|
31
|
+
}
|
|
32
32
|
|
|
33
33
|
export function clientReferenceId(file: string, exportName: string) {
|
|
34
34
|
return createHash('sha256')
|
|
@@ -36,12 +36,12 @@ export function clientReferenceId(file: string, exportName: string) {
|
|
|
36
36
|
.update('\0')
|
|
37
37
|
.update(exportName)
|
|
38
38
|
.digest('hex')
|
|
39
|
-
.slice(0, 10)
|
|
39
|
+
.slice(0, 10)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export function ssrClientReference(reference: Pick<ClientReference, 'dynamic' | 'sideEffect'>) {
|
|
43
|
-
if (reference.sideEffect) return false
|
|
44
|
-
if (reference.dynamic?.ssr === false) return false
|
|
45
|
-
if (reference.dynamic?.load === 'visible' && reference.dynamic.ssr !== true) return false
|
|
46
|
-
return true
|
|
43
|
+
if (reference.sideEffect) return false
|
|
44
|
+
if (reference.dynamic?.ssr === false) return false
|
|
45
|
+
if (reference.dynamic?.load === 'visible' && reference.dynamic.ssr !== true) return false
|
|
46
|
+
return true
|
|
47
47
|
}
|