Use process shim in WorkerJavaScriptBackend - #37
Open
aron-cf wants to merge 11 commits into
Open
Conversation
commit: |
Several documents still pointed at the pre-rename example directory and source tree. Update the project layout tree to worker-shell and worker-javascript, and repoint the worker backend doc and the package README at examples/worker-shell.
Mirror the worker-shell example with a Durable Object whose Workspace runs an ECMAScript module in a Dynamic Worker through the WorkerJavaScriptBackend. The DO class, HTTP routes, and R2 mount match worker-shell; the difference is the backend and what exec runs. The backend takes only the Loader binding, needs no WorkspaceServiceProxy loopback, and requires waitUntil, so the DO passes ctx.waitUntil.bind(ctx) into the Workspace options. The exec route accepts a module source plus an optional structured input and returns the run's status, streams, and the module's structured value. List the new example in the project layout doc.
The runtime rejected structured input for any command-routed backend, conflating two independent questions: which downstream surface a backend speaks, and whether it accepts a structured input value and returns a structured result. A shell backend that coerced JSON to argv and parsed stdout back to a value could not opt in. Add an optional callable capability to the backend interfaces, default false. The WorkerJavaScriptBackend declares it true. The runtime router now gates input on a callableBackendIds set built from that capability, independent of command-versus-module routing, and reports a clearer "not callable" error.
Explain callable next to the id and type discussion in the package README: a callable backend accepts a structured input value and returns a structured value, the runtime rejects input for a non-callable backend, and the capability is independent of the backend kind.
…cript backend Executions now accept an env map that surfaces inside the module as process.env. The runtime forwards env through the module exec path, the backend passes it as evaluate context alongside the working directory, and the runner installs a process object before importing user code. Only caller-supplied variables are visible; the host process environment is never exposed. The runner replaces globalThis.process, falling back to defineProperty and then to reassigning process.env when the nodejs_compat global resists replacement, so the override holds whether or not the runtime pre-populated the global.
…ript backend Executions accept a stdin value, passed as bytes or a string, that the module reads through process.stdin. The runtime forwards it down the module exec path, the backend normalizes it to bytes, bounds it by a new maxStdinBytes option, and hands it to the runner as evaluate context. The runner shims process.stdin as a non-TTY async iterable that yields the supplied bytes once and then ends, so both for-await and manual iteration read to completion.
…te streams The runner captured console output into a single list tagged with textual level prefixes, which the backend mapped back to stdout or stderr. Replace that with stream-tagged capture: console.log and console.info record to stdout, console.warn and console.error to stderr, and process.stdout.write and process.stderr.write record their raw bytes to the matching stream without an added newline. Console lines carry their own trailing newline, so the backend now emits each captured entry verbatim rather than appending one. The per-stream byte and event ceilings and the truncation marker are preserved.
Add an end-to-end case asserting process.cwd() tracks the exec cwd and that argv and platform carry their inert defaults, pinning the shim surface that the env, stdin, and stdout work left untested.
The host and stub exec paths gained env and stdin, but the client-facing RuntimeExecOptions still omitted them, so callers reaching the runtime through getWorkspace(stub) could not pass either. Add both fields; the client already forwards the whole options object, and env maps and byte stdin survive the capnweb boundary unchanged.
The exec handler now forwards env and stdin from the request body into runtime.exec, so a posted module can read process.env and process.stdin. Document the extended request shape and add a smoke-test recipe that pipes stdin and reads an env value.
Add a section to the JavaScript runtime doc describing the process shim: caller-supplied env exposed through process.env with the host environment hidden, caller-supplied stdin as a non-interactive async-iterable bounded by maxStdinBytes, stdout and stderr capture with console routing, and inert argv, cwd, and platform. List maxStdinBytes among the configurable byte limits. Add a test asserting an oversized stdin fails the run before the loader is invoked.
aron-cf
force-pushed
the
stack/3-process-shim
branch
from
August 1, 2026 17:31
4e782d0 to
9cc0f86
Compare
| function errorJSON(error: unknown, status: number): Response { | ||
| const message = error instanceof Error ? error.message : String(error); | ||
| const code = (error as { code?: string }).code; | ||
| return new Response(JSON.stringify({ error: message, code }), { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Code running in the
worker-javascriptbackend had noprocess. A module could not read an environment variable, consume standard input, or write to standard output and standard error the way ordinary Node-style code expects. This change installs aprocessshim in the runner and threads the pieces it needs through the execution path.The caller supplies
envandstdinon the exec options. These flow through the runtime router and into the runner, which installsglobalThis.processbefore user code runs. Only the values the caller passes are visible throughprocess.env; the host environment is never exposed.process.stdinreads back the caller's bytes as a non-interactive, always-ends stream, bounded by a newmaxStdinBytesceiling.process.cwd()returns the execution's working directory, andprocess.argvandprocess.platformcarry inert defaults.Output is captured with stream identity preserved.
console.logandconsole.infoand directprocess.stdoutwrites route to standard output;console.warn,console.error, andprocess.stderrwrites route to standard error. Each is byte-accurate: a raw write is not given a trailing newline it did not have, and a console line keeps the one it adds. The capture stays bounded by the existing per-stream byte and event ceilings.The client-facing exec options also gained
envandstdin, so callers reaching the runtime through a Workspace stub can pass them; both survive the capnweb boundary unchanged. Theworker-javascriptexample forwardsenvandstdinfrom its exec route, and its README shows a recipe that pipes standard input and reads an environment value.Verify with
npm test --workspace @cloudflare/computer, which exercises the shim end to end against the real Worker Loader, or post a module to the example that readsprocess.envandprocess.stdin.