1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 07:44:48 -05:00

fix(ext/node): worker_threads copies env object (#23536)

Most common argument to `env` option for `worker_threads.Worker` will be
`process.env`.

In Deno `process.env` is a `Proxy` which can't be cloned using
structured clone algorithm.

So to be safe, I'm creating a copy of actual object before it's sent to
the worker thread.

Ref #23522
This commit is contained in:
Bartek Iwańczuk 2024-04-24 17:17:28 +01:00 committed by GitHub
parent 5294885a5a
commit b424959d3e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 2 deletions

View file

@ -29,7 +29,7 @@ import { EventEmitter } from "node:events";
import { BroadcastChannel } from "ext:deno_broadcast_channel/01_broadcast_channel.js";
import process from "node:process";
const { ObjectPrototypeIsPrototypeOf } = primordials;
const { JSONParse, JSONStringify, ObjectPrototypeIsPrototypeOf } = primordials;
const {
Error,
Symbol,
@ -126,10 +126,18 @@ class NodeWorker extends EventEmitter {
}
this.#name = name;
// One of the most common usages will be to pass `process.env` here,
// but because `process.env` is a Proxy in Deno, we need to get a plain
// object out of it - otherwise we'll run in `DataCloneError`s.
// See https://github.com/denoland/deno/issues/23522.
let env_ = undefined;
if (options?.env) {
env_ = JSONParse(JSONStringify(options?.env));
}
const serializedWorkerMetadata = serializeJsMessageData({
workerData: options?.workerData,
environmentData: environmentData,
env: options?.env,
env: env_,
}, options?.transferList ?? []);
const id = op_create_worker(
{

View file

@ -10,6 +10,7 @@ import {
import { fromFileUrl, relative, SEPARATOR } from "@std/path/mod.ts";
import * as workerThreads from "node:worker_threads";
import { EventEmitter, once } from "node:events";
import process from "node:process";
Deno.test("[node/worker_threads] BroadcastChannel is exported", () => {
assertEquals<unknown>(workerThreads.BroadcastChannel, BroadcastChannel);
@ -486,3 +487,31 @@ Deno.test({
await worker.terminate();
},
});
Deno.test({
name: "[node/worker_threads] Worker env using process.env",
async fn() {
const deferred = Promise.withResolvers<void>();
const worker = new workerThreads.Worker(
`
import { parentPort } from "node:worker_threads";
import process from "node:process";
parentPort.postMessage("ok");
`,
{
eval: true,
// Make sure this doesn't throw `DataCloneError`.
// See https://github.com/denoland/deno/issues/23522.
env: process.env,
},
);
worker.on("message", (data) => {
assertEquals(data, "ok");
deferred.resolve();
});
await deferred.promise;
await worker.terminate();
},
});