diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 66aecaf5fcba99..8a1fda1892ca86 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -1541,14 +1541,11 @@ export default abstract class Server< } parsedUrl.pathname = normalizeResult.pathname - for (const key of Object.keys(parsedUrl.query)) { - delete parsedUrl.query[key] - } + // Replace the query object instead of loop-deleting every key. + // Using `delete` on object properties mutates V8 hidden classes, + // which de-optimises inline caches on downstream property accesses. const invokeQuery = getRequestMeta(req, 'invokeQuery') - - if (invokeQuery) { - Object.assign(parsedUrl.query, invokeQuery) - } + parsedUrl.query = invokeQuery ? { ...invokeQuery } : {} finished = await this.normalizeAndAttachMetadata(req, res, parsedUrl) if (finished) return diff --git a/packages/next/src/shared/lib/loadable.shared-runtime.tsx b/packages/next/src/shared/lib/loadable.shared-runtime.tsx index d82563ed97fcf6..c6152e1713c774 100644 --- a/packages/next/src/shared/lib/loadable.shared-runtime.tsx +++ b/packages/next/src/shared/lib/loadable.shared-runtime.tsx @@ -196,7 +196,10 @@ class LoadableSubscription { if (typeof opts.delay === 'number') { if (opts.delay === 0) { this._state.pastDelay = true - } else { + } else if (typeof window !== 'undefined') { + // Skip timers during SSR — the render is synchronous, + // there are no subscribers to notify, and the timers + // would leak in the Node.js process. this._delay = setTimeout(() => { this._update({ pastDelay: true, @@ -205,7 +208,7 @@ class LoadableSubscription { } } - if (typeof opts.timeout === 'number') { + if (typeof opts.timeout === 'number' && typeof window !== 'undefined') { this._timeout = setTimeout(() => { this._update({ timedOut: true }) }, opts.timeout)