diff --git a/cmd/esbuild/service.go b/cmd/esbuild/service.go index d2a3604ca07..bfb23f17e4e 100644 --- a/cmd/esbuild/service.go +++ b/cmd/esbuild/service.go @@ -14,6 +14,7 @@ import ( "regexp" "runtime/debug" "sync" + "time" "github.com/evanw/esbuild/internal/cli_helpers" "github.com/evanw/esbuild/internal/config" @@ -64,7 +65,9 @@ func runService() { if !ok { break // No more packets } - os.Stdout.Write(packet.bytes) + if _, err := os.Stdout.Write(packet.bytes); err != nil { + os.Exit(1) // I/O error + } // Only signal that this request is done when it has actually been written if packet.refCount != 0 { @@ -76,6 +79,19 @@ func runService() { // The protocol always starts with the version os.Stdout.Write(append(writeUint32(nil, uint32(len(esbuildVersion))), esbuildVersion...)) + // Periodically ping the host even when we're idle. This will catch cases + // where the host has disappeared and will never send us anything else but + // we incorrectly think we are still needed. In that case we will now try + // to write to stdout and fail, and then know that we should exit. + go func() { + for { + time.Sleep(1 * time.Second) + service.sendRequest(map[string]interface{}{ + "command": "ping", + }) + } + }() + for { // Read more data from stdin n, err := os.Stdin.Read(buffer) diff --git a/lib/common.ts b/lib/common.ts index c8b5e2de4ba..60daac92ecd 100644 --- a/lib/common.ts +++ b/lib/common.ts @@ -446,6 +446,7 @@ export function createChannel(streamIn: StreamIn): StreamOut { }; type RequestType = + | protocol.PingRequest | protocol.OnResolveRequest | protocol.OnLoadRequest | protocol.OnRequestRequest @@ -456,6 +457,11 @@ export function createChannel(streamIn: StreamIn): StreamOut { // Catch exceptions in the code below so they get passed to the caller try { switch (request.command) { + case 'ping': { + sendResponse(id, {}); + break; + } + case 'resolve': { let callback = pluginCallbacks.get(request.key); sendResponse(id, await callback!(request) as any); diff --git a/lib/stdio_protocol.ts b/lib/stdio_protocol.ts index 5d920128dbc..7c1651bb645 100644 --- a/lib/stdio_protocol.ts +++ b/lib/stdio_protocol.ts @@ -55,6 +55,10 @@ export interface BuildOutputFile { contents: Uint8Array; } +export interface PingRequest { + command: 'ping'; +} + export interface RebuildRequest { command: 'rebuild'; rebuildID: number; diff --git a/scripts/browser/browser-tests.js b/scripts/browser/browser-tests.js index a7dd5a86611..1dfb53e89c3 100644 --- a/scripts/browser/browser-tests.js +++ b/scripts/browser/browser-tests.js @@ -251,10 +251,9 @@ async function main() { } for (let key in pages) { - promises.push(runPage(key)) + await runPage(key) } - await Promise.all(promises) await browser.close() server.close()