diff --git a/src/main/ipc/filesystem-watcher-ignore-real.test.ts b/src/main/ipc/filesystem-watcher-ignore-real.test.ts
index 9656576108f9..aaaeec7a9a67 100644
--- a/src/main/ipc/filesystem-watcher-ignore-real.test.ts
+++ b/src/main/ipc/filesystem-watcher-ignore-real.test.ts
@@ -73,9 +73,9 @@ describe('filesystem watcher native ignores', () => {
sourceFiles.push(join(root, 'source\nnewline.ts'), join(nestedSource, 'source\nnewline.ts'))
}
await writeUntilSeen(sourceFiles)
- // Why: events arrive in order, so once a file written after the storm is seen, any
+ // Why: events arrive in order, so once a file written after the storm is seen at both levels, any
// unignored generated event is already recorded. Replaces a fixed debounce sleep.
- await writeUntilSeen([join(nestedSource, 'sentinel.ts')])
+ await writeUntilSeen([join(root, 'sentinel.ts'), join(nestedSource, 'sentinel.ts')])
expect(errors).toEqual([])
const generatedPaths = new Set(generatedFiles)
diff --git a/src/main/orcad/orcad-serve-parity.integration.test.ts b/src/main/orcad/orcad-serve-parity.integration.test.ts
index 34285f83c35c..f4a6c4494967 100644
--- a/src/main/orcad/orcad-serve-parity.integration.test.ts
+++ b/src/main/orcad/orcad-serve-parity.integration.test.ts
@@ -203,11 +203,14 @@ describe.skipIf(skip)('orca serve on orcad', () => {
const appRoot = profile()
mkdirSync(join(appRoot, 'out', 'web'), { recursive: true })
writeFileSync(join(appRoot, 'out', 'web', WEB_CLIENT_INDEX_FILENAME), '
orca web')
- // The argv `orca serve` builds, but on loopback: a test must not listen on every interface.
- const args = orcadServeArgs({ json: true, port: '0' }, findBundledWebClientRoot(appRoot))
- args.splice(args.indexOf('0.0.0.0'), 1, '127.0.0.1')
+ // The argv `orca serve` builds, but on loopback.
+ const args = orcadServeArgs(
+ { json: true, port: '0' },
+ findBundledWebClientRoot(appRoot),
+ '127.0.0.1'
+ )
try {
- const readiness = await serveOnce(userData, args)
+ const { readiness } = await serveOnce(userData, args)
const webClientUrl: unknown = readiness.pairing?.webClientUrl
expect(webClientUrl).toEqual(expect.stringMatching(/^http:\/\/127\.0\.0\.1:\d+\//u))
const index = await fetch(new URL(`/${WEB_CLIENT_INDEX_FILENAME}`, String(webClientUrl)))
@@ -262,14 +265,30 @@ const running = new Map>()
/** Starts `orca serve --json` on orcad and returns the terminal daemon pid its readiness names. */
async function serveDaemonPid(userData: string): Promise {
- const readiness = await serveOnce(userData, ['--bind', '127.0.0.1', '--port', '0', '--json'])
+ const { readiness, stderr } = await serveOnce(userData, [
+ '--bind',
+ '127.0.0.1',
+ '--port',
+ '0',
+ '--json'
+ ])
const daemon = readiness.health?.terminalDaemon
- expect(daemon?.state).toBe('live')
+ if (daemon?.state !== 'live') {
+ throw new Error(`terminal daemon not live (${String(daemon?.state)}): ${stderr}`)
+ }
return daemon.pid
}
-/** Starts orcad with `args` and returns its parsed readiness line. */
-async function serveOnce(userData: string, args: string[]) {
+type ServeReadiness = {
+ pairing?: { webClientUrl?: unknown }
+ health?: { terminalDaemon?: { state?: string; pid: number } }
+}
+
+/** Starts orcad with `args` and returns its parsed readiness line and stderr so far. */
+async function serveOnce(
+ userData: string,
+ args: string[]
+): Promise<{ readiness: ServeReadiness; stderr: string }> {
const child = spawnProcess({
program: runtime!,
args: [join(slotDir, 'orcad.js'), ...args],
@@ -291,7 +310,8 @@ async function serveOnce(userData: string, args: string[]) {
}
})
})
- return JSON.parse(line)
+ const readiness: ServeReadiness = JSON.parse(line)
+ return { readiness, stderr }
}
/** SIGTERM is serve's graceful stop on POSIX; it leaves the daemon running by design. */
diff --git a/src/main/runtime/construction/runtime-composition-parity.test.ts b/src/main/runtime/construction/runtime-composition-parity.test.ts
index 8bf0fd5f8374..ac04222c6899 100644
--- a/src/main/runtime/construction/runtime-composition-parity.test.ts
+++ b/src/main/runtime/construction/runtime-composition-parity.test.ts
@@ -7,7 +7,7 @@ import { SKILL_INSTALL_CAPABILITY } from '../../../shared/skill-install-capabili
/**
* Electron (`main-process-*`) and orcad (`orcad-entry.ts`) each compose the same runtime, and every
- * dependency is optional, so one root can silently skip a service the other wires (C2: #30120 never
+ * dependency is optional, so one root can silently skip a service the other wires (#30120 never
* gave orcad its web client root). This records what each root's source wires and fails on any
* difference that is not declared below with a reason.
*/
@@ -18,7 +18,7 @@ type DeclaredDifference = {
wiring: string
missingOn: Root
reason: string
- /** Capabilities the missing host still advertises; its methods must refuse accurately (D3). */
+ /** Capabilities the missing host still advertises; its methods must refuse accurately. */
advertisedUnserved?: readonly string[]
}
@@ -148,29 +148,37 @@ const SPREAD_SOURCES: Record = {
const repoRoot = join(__dirname, '../../../..')
const read = (file: string): string => stripComments(readFileSync(join(repoRoot, file), 'utf8'))
+const QUOTES = `'"\``
+
+/** The index of the quote that closes the string opening at `open` (or the end of the source). */
+function stringEnd(source: string, open: number): number {
+ for (let i = open + 1; i < source.length; i++) {
+ if (source[i] === '\\') {
+ i++
+ } else if (source[i] === source[open]) {
+ return i
+ }
+ }
+ return source.length
+}
+
function stripComments(source: string): string {
let out = ''
- let quote: string | null = null
for (let i = 0; i < source.length; i++) {
const char = source[i]
- if (quote) {
- out += char
- if (char === '\\') {
- out += source[++i] ?? ''
- } else if (char === quote) {
- quote = null
- }
+ if (QUOTES.includes(char)) {
+ const end = stringEnd(source, i)
+ out += source.slice(i, end + 1)
+ i = end
} else if (char === '/' && source[i + 1] === '/') {
while (i < source.length && source[i] !== '\n') {
i++
}
out += '\n'
} else if (char === '/' && source[i + 1] === '*') {
- i = source.indexOf('*/', i + 2) + 1
+ const end = source.indexOf('*/', i + 2)
+ i = end === -1 ? source.length : end + 1
} else {
- if (char === "'" || char === '"' || char === '`') {
- quote = char
- }
out += char
}
}
@@ -180,19 +188,10 @@ function stripComments(source: string): string {
/** The inner text of the brace group that opens at `open` (strings are opaque). */
function braceGroup(source: string, open: number): string {
let depth = 0
- let quote: string | null = null
for (let i = open; i < source.length; i++) {
const char = source[i]
- if (quote) {
- if (char === '\\') {
- i++
- } else if (char === quote) {
- quote = null
- }
- continue
- }
- if (char === "'" || char === '"' || char === '`') {
- quote = char
+ if (QUOTES.includes(char)) {
+ i = stringEnd(source, i)
} else if (char === '{') {
depth++
} else if (char === '}' && --depth === 0) {
@@ -218,20 +217,11 @@ function objectLiteralAfter(source: string, anchor: string): string {
function topLevelEntries(inner: string): string[] {
const entries: string[] = []
let depth = 0
- let quote: string | null = null
let start = 0
for (let i = 0; i < inner.length; i++) {
const char = inner[i]
- if (quote) {
- if (char === '\\') {
- i++
- } else if (char === quote) {
- quote = null
- }
- continue
- }
- if (char === "'" || char === '"' || char === '`') {
- quote = char
+ if (QUOTES.includes(char)) {
+ i = stringEnd(inner, i)
} else if ('({['.includes(char)) {
depth++
} else if (')}]'.includes(char)) {
diff --git a/src/shared/orcad-serve-argv.ts b/src/shared/orcad-serve-argv.ts
index 5abf293d1175..4f8fab14aeb9 100644
--- a/src/shared/orcad-serve-argv.ts
+++ b/src/shared/orcad-serve-argv.ts
@@ -31,10 +31,15 @@ export function serveOptionArgs(args: ServeOrcaAppArgs, prefix: '--' | '--serve-
]
}
-export function orcadServeArgs(args: ServeOrcaAppArgs, webClientRoot?: string): string[] {
+/** `bindHost` exists for tests, which must not listen on every interface. */
+export function orcadServeArgs(
+ args: ServeOrcaAppArgs,
+ webClientRoot?: string,
+ bindHost = '0.0.0.0'
+): string[] {
return [
'--bind',
- '0.0.0.0',
+ bindHost,
...serveOptionArgs(args, '--'),
...(webClientRoot ? ['--web-client-root', webClientRoot] : [])
]