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 <contact@outofplace.space>
This commit is contained in:
Neil
2026-10-26 03:45:15 -07:00
committed by GitHub
co-authored by outof-place
parent 7e573331ee
commit c36378c2b9
2 changed files with 17 additions and 21 deletions
+5
View File
@@ -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') }
}
+12 -21
View File
@@ -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()