From c36378c2b936610a97f897e1933809bb97fb39be Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Mon, 26 Oct 2026 03:45:15 -0700 Subject: [PATCH] fix(build): keep index.js source map aligned with the bootstrap banner (#33899) The main bootstrap banner was prepended to index.js in generateBundle, after Rolldown had already emitted index.js.map, so every main-process crash trace decoded ~200 lines off. Emit it via Rolldown's output.postBanner instead, which shifts the source map natively. Co-authored-by: outof-place --- config/scripts/main-entry-facade.test.ts | 5 ++++ electron.vite.config.ts | 33 +++++++++--------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/config/scripts/main-entry-facade.test.ts b/config/scripts/main-entry-facade.test.ts index 4473e1e8729..bc7da852cb5 100644 --- a/config/scripts/main-entry-facade.test.ts +++ b/config/scripts/main-entry-facade.test.ts @@ -28,6 +28,9 @@ it('keeps main code and asset paths working after a CLI build replaces its publi 'import { writeFileSync } from "node:fs"; import { join } from "node:path"; import { getStatus } from "./controls"; import { createTracker } from "./tracker"; import { getBootLabel } from "./boot-label"; import("./late").then(({ readLabel }) => writeFileSync(join(__dirname, "result.json"), JSON.stringify({ status: getStatus(), tracker: createTracker(), directory: __dirname, label: getBootLabel(), lateLabel: readLabel() })))' ) const options = electronViteConfig.main?.build?.rollupOptions + if (Array.isArray(options?.output)) { + throw new Error('Expected one main-process output') + } await build({ configFile: false, root, @@ -37,6 +40,8 @@ it('keeps main code and asset paths working after a CLI build replaces its publi minify: electronViteConfig.main?.build?.minify, rolldownOptions: { ...options, + // Plugins and the bootstrap banner guard the real main entry, not this fixture. + output: { ...options?.output, postBanner: undefined }, plugins: [], input: { index: join(root, 'main.ts'), controls: join(root, 'controls.ts') } } diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 98bb16bd983..ffdbecb239e 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -2,7 +2,7 @@ import { markdownParserAliases } from './config/build-plugins/markdown-parser-ex import { createRequire } from 'node:module' import { resolve } from 'node:path' import { defineConfig, type UserConfig } from 'electron-vite' -import type { Plugin } from 'vite' +import type { Plugin, Rollup } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' import { createBootstrapFatalExitBanner } from './config/build-plugins/bootstrap-fatal-exit-banner' @@ -180,25 +180,16 @@ function createStartupDiagnosticsBanner(chunkName: string): string { ` } -function createMainBootstrapPlugin() { - return { - name: 'orca-main-bootstrap', - generateBundle(_options, bundle) { - const mainChunk = bundle['index.js'] - if (!mainChunk || mainChunk.type !== 'chunk') { - return - } - if (!mainChunk.moduleIds.some((id) => resolve(id) === MAIN_BUILD_ENTRY_POINTS.index)) { - throw new Error('Main startup must stay in index.js so __dirname resolves app assets') - } - - // Source guards run after Rollup’s require prelude, too late to handle missing bootstrap dependencies. - mainChunk.code = - createBootstrapFatalExitBanner() + - createStartupDiagnosticsBanner(mainChunk.fileName) + - mainChunk.code - } +// postBanner lands after minification and Rolldown shifts index.js.map past it, keeping crash traces on the right line. +function createMainBootstrapPostBanner(chunk: Rollup.RenderedChunk): string { + if (chunk.fileName !== 'index.js') { + return '' } + if (!chunk.moduleIds.some((id) => resolve(id) === MAIN_BUILD_ENTRY_POINTS.index)) { + throw new Error('Main startup must stay in index.js so __dirname resolves app assets') + } + // Source guards run after Rollup’s require prelude, too late to handle missing bootstrap dependencies. + return createBootstrapFatalExitBanner() + createStartupDiagnosticsBanner(chunk.fileName) } // Dev-only unminified main bundle exposes function names in V8 profiles; releases and pnpm build never read this flag. @@ -231,10 +222,10 @@ export const electronViteConfig: UserConfig = { charset: 'ascii', format: 'cjs', entryFileNames: '[name].js', - chunkFileNames: 'chunks/[name]-[hash].js' + chunkFileNames: 'chunks/[name]-[hash].js', + postBanner: createMainBootstrapPostBanner }, plugins: [ - createMainBootstrapPlugin(), createPlainNodeEntryGuardPlugin(), createProcessHostDevRebuildPlugin(), createDarkBuildMarkerPlugin()