diff --git a/compiler/packages/snap/src/runner-watch.ts b/compiler/packages/snap/src/runner-watch.ts index de79655843..cba35bd4e9 100644 --- a/compiler/packages/snap/src/runner-watch.ts +++ b/compiler/packages/snap/src/runner-watch.ts @@ -114,7 +114,6 @@ function subscribeFixtures( onChange: (state: RunnerState) => void ) { // Watch the fixtures directory for changes - /* const fileSubscription = */ watcher.subscribe(FIXTURES_PATH, async (err, _events) => { if (err) { console.error(err); @@ -127,6 +126,7 @@ function subscribeFixtures( const isRealUpdate = performance.now() - state.lastUpdate > 5000; if (isRealUpdate) { // Fixtures changed, re-run tests + state.mode.action = RunnerAction.Test; onChange(state); } }); @@ -136,23 +136,20 @@ function subscribeFilterFile( state: RunnerState, onChange: (state: RunnerState) => void ) { - const filterSubscription = watcher.subscribe( - process.cwd(), - async (err, events) => { - if (err) { - console.error(err); - process.exit(1); - } else if ( - events.findIndex((event) => event.path.includes(FILTER_FILENAME)) !== -1 - ) { - state.filter = await readTestFilter(); - if (state.mode.filter) { - state.mode.action = RunnerAction.Test; - onChange(state); - } + watcher.subscribe(process.cwd(), async (err, events) => { + if (err) { + console.error(err); + process.exit(1); + } else if ( + events.findIndex((event) => event.path.includes(FILTER_FILENAME)) !== -1 + ) { + state.filter = await readTestFilter(); + if (state.mode.filter) { + state.mode.action = RunnerAction.Test; + onChange(state); } } - ); + }); } function subscribeTsc( @@ -172,11 +169,7 @@ function subscribeTsc( state.compilerVersion++; } state.isCompilerBuildValid = isSuccess; - if (state.filter) { - state.mode.action = RunnerAction.Test; - } else { - state.mode.action = RunnerAction.Test; - } + state.mode.action = RunnerAction.Test; onChange(state); } ); @@ -194,6 +187,7 @@ function subscribeKeyEvents( process.exit(0); } else if (key.name === "f") { state.mode.filter = !state.mode.filter; + state.mode.action = RunnerAction.Test; } else { // any other key re-runs tests state.mode.action = RunnerAction.Test; diff --git a/compiler/packages/snap/src/runner.ts b/compiler/packages/snap/src/runner.ts index 8f1ae36d0f..55fcaa66e9 100644 --- a/compiler/packages/snap/src/runner.ts +++ b/compiler/packages/snap/src/runner.ts @@ -6,6 +6,7 @@ */ import { Worker } from "jest-worker"; +import { cpus } from "os"; import process from "process"; import * as readline from "readline"; import ts from "typescript"; @@ -23,6 +24,7 @@ import { import * as runnerWorker from "./runner-worker"; const WORKER_PATH = require.resolve("./runner-worker.js"); +const NUM_WORKERS = cpus().length - 1; readline.emitKeypressEvents(process.stdin); @@ -163,12 +165,40 @@ async function onChange( export async function main(opts: RunnerOptions): Promise { const worker: Worker & typeof runnerWorker = new Worker(WORKER_PATH, { enableWorkerThreads: opts.workerThreads, + numWorkers: NUM_WORKERS, }) as any; worker.getStderr().pipe(process.stderr); worker.getStdout().pipe(process.stdout); if (opts.watch) { makeWatchRunner((state) => onChange(worker, state), opts.filter); + if (opts.filter) { + /** + * Warm up wormers when in watch mode. Loading the Forget babel plugin + * and all of its transitive dependencies takes 1-3s (per worker) on a M1. + * As jest-worker dispatches tasks using a round-robin strategy, we can + * avoid an additional 1-3s wait on the first num_workers runs by warming + * up workers eagerly. + */ + for (let i = 0; i < NUM_WORKERS - 1; i++) { + worker.transformFixture( + { + fixturePath: "tmp", + snapshotPath: "./tmp.expect.md", + inputPath: "./tmp.js", + input: ` + function Foo(props) { + return identity(props); + } + `, + snapshot: null, + }, + 0, + false, + false + ); + } + } } else { // Non-watch mode. For simplicity we re-use the same watchSrc() function. // After the first build completes run tests and exit