// Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { readFileSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { Script, constants } from 'node:vm'; import { ipcRenderer } from 'electron'; // This file is in root dir, but the bundled file that we run is in // bundles/preload const srcPath = join(__dirname, 'main.js'); const cachePath = join(__dirname, '..', '..', 'preload.bundle.cache'); let cachedData: Buffer | undefined; try { if (!process.env.GENERATE_PRELOAD_CACHE) { cachedData = readFileSync(cachePath); } } catch (error) { // No cache - no big deal if (error.code !== 'ENOENT') { throw error; } } const source = readFileSync(srcPath, 'utf8'); window.preloadCompileStartTime = Date.now(); // `filename` is used for: // // - Annotating stack traces // - Resolving dynamic `import()` calls // // When it is not an absolute path `import()` is resolved relative to the `cwd`. // // Since filename gets written into the `preload.bundle.cache` we need to use a // path-independent value for reproducibility, and otherwise use full absolute // path in the packaged app. const filename = process.env.GENERATE_PRELOAD_CACHE ? 'bundles/preload/main.js' : srcPath; // Note: we wrap with (function(require, __dirname, exports){}) in // `rolldown.config.ts` to preserve correct offsets in the sourcemap. const script = new Script(source, { filename, lineOffset: 0, cachedData, importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER, }); const { cachedDataRejected } = script; const fn = script.runInThisContext({ displayErrors: true, }); // See `scripts/generate-preload-cache.mjs` if (process.env.GENERATE_PRELOAD_CACHE) { // Use hottest cache possible in CI if (process.env.CI) { fn(require, __dirname, {}); window.startApp(); } writeFileSync(cachePath, script.createCachedData()); ipcRenderer.send('shutdown'); } else { fn(require, __dirname, {}); window.SignalCI?.setPreloadCacheHit( cachedData != null && !cachedDataRejected ); } if (cachedDataRejected) { // oxlint-disable-next-line no-console console.log('preload cache rejected'); } else { // oxlint-disable-next-line no-console console.log('preload cache hit'); }