diff --git a/packages/next-swc/Cargo.lock b/packages/next-swc/Cargo.lock index 4d438bf6f33d..87e15cb8c10f 100644 --- a/packages/next-swc/Cargo.lock +++ b/packages/next-swc/Cargo.lock @@ -2885,8 +2885,9 @@ dependencies = [ [[package]] name = "tracing-chrome" -version = "0.6.0" -source = "git+https://github.com/kwonoj/tracing-chrome?rev=0dd9d6c9e0f74f43993b58560f4ac0103e058df8#0dd9d6c9e0f74f43993b58560f4ac0103e058df8" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb13184244c7cd22758b79e7c993c515ad67a8e730edcb7e05fe7bcabb283c7" dependencies = [ "json", "tracing", diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index af721400e21f..5f8c323f380e 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -112,7 +112,7 @@ import { TelemetryPlugin } from './webpack/plugins/telemetry-plugin' import { MiddlewareManifest } from './webpack/plugins/middleware-plugin' import { recursiveCopy } from '../lib/recursive-copy' import { recursiveReadDir } from '../lib/recursive-readdir' -import { lockfilePatchPromise } from './swc' +import { lockfilePatchPromise, teardownTraceSubscriber } from './swc' export type SsgRoute = { initialRevalidateSeconds: number | false @@ -2184,6 +2184,7 @@ export default async function build( // Ensure all traces are flushed before finishing the command await flushAllTraces() + teardownTraceSubscriber() } } diff --git a/packages/next/build/output/store.ts b/packages/next/build/output/store.ts index 4c0af9268030..85998dbbd097 100644 --- a/packages/next/build/output/store.ts +++ b/packages/next/build/output/store.ts @@ -2,7 +2,7 @@ import createStore from 'next/dist/compiled/unistore' import stripAnsi from 'next/dist/compiled/strip-ansi' import { flushAllTraces } from '../../trace' import { getUnresolvedModuleFromError } from '../utils' - +import { teardownTraceSubscriber } from '../swc' import * as Log from './log' export type OutputState = @@ -100,6 +100,7 @@ store.subscribe((state) => { // Ensure traces are flushed after each compile in development mode flushAllTraces() + teardownTraceSubscriber() return } @@ -126,6 +127,7 @@ store.subscribe((state) => { Log.warn(state.warnings.join('\n\n')) // Ensure traces are flushed after each compile in development mode flushAllTraces() + teardownTraceSubscriber() return } @@ -141,4 +143,5 @@ store.subscribe((state) => { ) // Ensure traces are flushed after each compile in development mode flushAllTraces() + teardownTraceSubscriber() }) diff --git a/packages/next/build/swc/index.d.ts b/packages/next/build/swc/index.d.ts index 966270bc66ac..564090d59b22 100644 --- a/packages/next/build/swc/index.d.ts +++ b/packages/next/build/swc/index.d.ts @@ -7,3 +7,4 @@ export function bundle(options: any): Promise export function parse(src: string, options: any): any export const lockfilePatchPromise: { cur?: Promise } export function initCustomTraceSubscriber(traceFileName?: string): void +export function teardownTraceSubscriber(): void diff --git a/packages/next/build/swc/index.js b/packages/next/build/swc/index.js index 87a4eb8bd045..f0297bf822f6 100644 --- a/packages/next/build/swc/index.js +++ b/packages/next/build/swc/index.js @@ -12,6 +12,7 @@ const triples = platformArchTriples[PlatformName][ArchName] || [] let nativeBindings let wasmBindings +let swcTraceFlushGuard export const lockfilePatchPromise = {} async function loadBindings() { @@ -314,31 +315,39 @@ export function getBinaryMetadata() { /** * Initialize trace subscriber to emit traces. * - * Returns an internal object to guard async flush emission if subscriber is initialized, caller should manually - * tear it down via `teardownTraceSubscriber`. */ export const initCustomTraceSubscriber = (() => { - let guard - return (filename) => { - if (!guard) { + if (!swcTraceFlushGuard) { // Wasm binary doesn't support trace emission let bindings = loadNative() - guard = bindings.initCustomTraceSubscriber(filename) + swcTraceFlushGuard = bindings.initCustomTraceSubscriber(filename) } - - return guard } })() +/** + * Teardown swc's trace subscriber if there's an initialized flush guard exists. + * + * This is workaround to amend behavior with process.exit + * (https://github.com/vercel/next.js/blob/4db8c49cc31e4fc182391fae6903fb5ef4e8c66e/packages/next/bin/next.ts#L134=) + * seems preventing napi's cleanup hook execution (https://github.com/swc-project/swc/blob/main/crates/node/src/util.rs#L48-L51=), + * + * instead parent process manually drops guard when process gets signal to exit. + */ export const teardownTraceSubscriber = (() => { - let bindings - - return (guard) => { - if (!bindings && !!guard) { - // Wasm binary doesn't support trace emission - bindings = loadNative() - return bindings.teardownTraceSubscriber(guard) + let flushed = false + return () => { + if (!flushed) { + flushed = true + try { + let bindings = loadNative() + if (swcTraceFlushGuard) { + bindings.teardownTraceSubscriber(swcTraceFlushGuard) + } + } catch (e) { + // Suppress exceptions, this fn allows to fail to load native bindings + } } } })() diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 6250095eaf72..08b5aed9e55f 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -87,22 +87,6 @@ const devtoolRevertWarning = execOnce( let loggedSwcDisabled = false let loggedIgnoredCompilerOptions = false -let swcTraceFlushGuard: unknown = null - -/** - * Teardown swc's trace subscriber if there's an initialized flush guard exists. - * - * This is workaround to amend behavior with process.exit - * (https://github.com/vercel/next.js/blob/4db8c49cc31e4fc182391fae6903fb5ef4e8c66e/packages/next/bin/next.ts#L134=) - * seems preventing napi's cleanup hook execution (https://github.com/swc-project/swc/blob/main/crates/node/src/util.rs#L48-L51=), - * - * instead parent process manually drops guard when process gets signal to exit. - */ -process.on('exit', () => { - if (swcTraceFlushGuard) { - require('./swc')?.teardownTraceSubscriber?.(swcTraceFlushGuard) - } -}) function getOptimizedAliases(): { [pkg: string]: string } { const stubWindowFetch = path.join(__dirname, 'polyfills', 'fetch', 'index.js') @@ -451,22 +435,14 @@ export default async function getBaseWebpackConfig( loggedIgnoredCompilerOptions = true } - const getBabelOrSwcLoader = (buildDir: string) => { - if ( - useSWCLoader && - config?.experimental?.swcTraceProfiling && - !swcTraceFlushGuard - ) { + const getBabelOrSwcLoader = () => { + if (useSWCLoader && config?.experimental?.swcTraceProfiling) { // This will init subscribers once only in a single process lifecycle, // even though it can be called multiple times. // Subscriber need to be initialized _before_ any actual swc's call (transform, etcs) // to collect correct trace spans when they are called. - swcTraceFlushGuard = require('./swc')?.initCustomTraceSubscriber?.( - path.join( - buildDir, - config.distDir, - `swc-trace-profile-${Date.now()}.json` - ) + require('./swc')?.initCustomTraceSubscriber?.( + path.join(distDir, `swc-trace-profile-${Date.now()}.json`) ) } @@ -498,7 +474,7 @@ export default async function getBaseWebpackConfig( } const defaultLoaders = { - babel: getBabelOrSwcLoader(false), + babel: getBabelOrSwcLoader(), } const rawPageExtensions = hasServerComponents @@ -1251,7 +1227,7 @@ export default async function getBaseWebpackConfig( { ...codeCondition, issuerLayer: 'middleware', - use: getBabelOrSwcLoader(true), + use: getBabelOrSwcLoader(), }, { ...codeCondition,