Files
orca/src/shared/emoji-shortcode-catalog.lazy.test.ts
Neil 1c4c6b7fec perf(startup): stop queueing window creation behind the proxy apply and i18n (#18436)
* perf(startup): stop queueing window creation behind the proxy apply and i18n

Three independent, measured startup wins, all free:

1. Park the initial Chromium proxy apply on `mainProcessState` instead of
   awaiting it mid-`initializeReadyFoundation`. `setProxy` still starts at the
   identical moment; the default-session request guard (which holds, not
   cancels) is what actually fences fetchers on it, so only window creation
   stops waiting. Runtime launch still awaits it before the desktop relay and
   before every headless-serve fetcher.
2. Run `initializeMainProcessI18nAndMenu` concurrently with
   `initializeMainProcessRuntimeLaunch`. Nothing in window creation reads a
   translated string or the native menu.
3. Load `emojibase-data` in main through `createRequire` on first use instead
   of a static import, keeping 166 KB of JSON off `out/main/index.js` and its
   ~2 ms parse off every launch. The renderer keeps its eager copy unchanged.

out/main/index.js 7,210,071 -> 7,040,147 bytes. No renderer behaviour changes.

* fix(packaging): ship the emoji shortcode dataset main lazily requires

app.asar carries no node_modules, so main's bare requires resolve only out of
Resources/node_modules. emojibase-data is a devDependency and is not in the
packaged runtime allowlist, so the new createRequire in
deferred-emoji-shortcode-dataset.ts threw MODULE_NOT_FOUND in every packaged
build — breaking sanitizeWorktreeName, and with it workspace creation.

Copy the single 166 KB dataset (not the 49 MB package root) into
Resources/node_modules, and gate every createRequire'd bare specifier in
src/main against the packaged resource plan. verifyPackagedMainRuntimeDeps
cannot catch these: the bundler renames the require binding.

* test(proxy): fail CI when a main-process fetcher escapes the default-session guard

The hoist relies on installElectronProxyRequestGuard(session.defaultSession) holding every app-owned request until the persisted proxy lands. Nothing enforced that every fetcher actually lands on defaultSession. Two source-anchored rules do now: no net.fetch/net.request may name a session/partition, and every non-net .fetch( call site is counted against an allowlist.

* test(proxy): close the shorthand and chained-receiver holes in the fetch call-site audit

The audit caught `net.request({ session: x })` and `ident.fetch(`, but not the two
shapes a real regression is just as likely to take: the `{ url, session }` shorthand
that both `net.request` overloads accept, and a receiver with no bare identifier
(`session.fromPartition(...).fetch(`, `ctx.session.fetch(`). Rule 1 now also matches
the shorthand key; rule 2 scans every `.fetch(` and excludes only a literal
`net`/`globalThis`/`global` receiver. Audited counts are unchanged (2/2/1).

* fix(startup): scope the deferred emoji loader to the projects that own it

TS6307: the composite web project lists src/main/ipc/worktree-logic.ts, which
now imports the deferred dataset loader, and the shared lazy test reached into
src/main from a project that has no src/main files. Add the loader to
tsconfig.tc.web.json and move the cross-project case into a src/main test.

Also close the last two review gaps: gate the runtime-RPC startup failure
dialog (the only launch-phase translateMain reader) on a published i18n
barrier so a concurrent i18n phase cannot leave a non-English user with the
English fallback, and let the fetch call-site audit match `net.fetch (url)`.
2026-09-03 21:19:06 -07:00

66 lines
2.8 KiB
TypeScript

import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import emojiShortcodes from 'emojibase-data/en/shortcodes/emojibase.json'
async function importConfiguredCatalog() {
const catalog = await import('./emoji-shortcode-catalog.js')
catalog.setEmojiShortcodeDatasetLoader(() => emojiShortcodes)
return catalog
}
describe('emoji shortcode catalog laziness', () => {
beforeEach(() => {
vi.resetModules()
})
it('does not build the catalog when the shared module is imported', async () => {
const catalog = await importConfiguredCatalog()
expect(catalog.isEmojiShortcodeCatalogBuiltForTest()).toBe(false)
expect(catalog.getStandardEmojiShortcodeEntries().length).toBeGreaterThan(1000)
expect(catalog.isEmojiShortcodeCatalogBuiltForTest()).toBe(true)
})
it('builds on first use and keeps the main process off the eager path', async () => {
const catalog = await importConfiguredCatalog()
expect(catalog.replaceKnownEmojiWithShortcodes('ship \u{1F389}')).toBe('ship party ')
expect(catalog.isEmojiShortcodeCatalogBuiltForTest()).toBe(true)
})
it('leaves the main-process worktree namer importing only the deferred entry points', () => {
// A cross-project import would drag src/main into the shared tsconfig, so assert on source.
const worktreeLogic = readFileSync(join(__dirname, '../main/ipc/worktree-logic.ts'), 'utf8')
const catalogImport = worktreeLogic.match(
/import \{([^}]*)\} from '[^']*emoji-shortcode-catalog'/
)
expect(catalogImport?.[1].split(',').map((name) => name.trim())).toEqual([
'replaceKnownEmojiWithShortcodes',
'setEmojiShortcodeDatasetLoader'
])
})
it('keeps the catalog build out of module scope', () => {
const sharedSource = readFileSync(join(__dirname, 'emoji-shortcode-catalog.ts'), 'utf8')
// A module-scope `const X = <expression over the dataset>` is the regression this guards.
expect(sharedSource).not.toMatch(/^const \w+ = Object\.entries\(/m)
expect(sharedSource).not.toMatch(/^const \w+ = new (?:Map|Intl\.Segmenter)\(/m)
expect(sharedSource).toContain('function loadCatalog()')
})
it('keeps the 166 KB dataset off every module main statically imports', () => {
const sharedSource = readFileSync(join(__dirname, 'emoji-shortcode-catalog.ts'), 'utf8')
const worktreeLogic = readFileSync(join(__dirname, '../main/ipc/worktree-logic.ts'), 'utf8')
// A static `emojibase-data` import anywhere main reaches inlines the dataset into
// out/main/index.js and JSON.parses it on every launch.
const staticDatasetImport = /\bfrom '[^']*emojibase-data[^']*'/
expect(sharedSource).not.toMatch(staticDatasetImport)
expect(worktreeLogic).not.toMatch(staticDatasetImport)
})
})