mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
make sure ipc with json serialization still works when bun is parent and not the child (#14756)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
@@ -194,21 +194,19 @@ const json = struct {
|
|||||||
// 1 is regular
|
// 1 is regular
|
||||||
// 2 is internal
|
// 2 is internal
|
||||||
|
|
||||||
pub fn decodeIPCMessage(
|
pub fn decodeIPCMessage(data: []const u8, globalThis: *JSC.JSGlobalObject) IPCDecodeError!DecodeIPCMessageResult {
|
||||||
data: []const u8,
|
|
||||||
globalThis: *JSC.JSGlobalObject,
|
|
||||||
) IPCDecodeError!DecodeIPCMessageResult {
|
|
||||||
if (bun.strings.indexOfChar(data, '\n')) |idx| {
|
if (bun.strings.indexOfChar(data, '\n')) |idx| {
|
||||||
var kind = data[0];
|
var kind = data[0];
|
||||||
var json_data = data[1..idx];
|
var json_data = data[0..idx];
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
1, 2 => {},
|
2 => {
|
||||||
|
json_data = data[1..idx];
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
// if the message being recieved is from a node process then it wont have the leading marker byte
|
// assume it's valid json with no header
|
||||||
// assume full message will be json
|
// any error will be thrown by toJSByParseJSON below
|
||||||
kind = 1;
|
kind = 1;
|
||||||
json_data = data[0..idx];
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +228,7 @@ const json = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deserialized = str.toJSByParseJSON(globalThis);
|
const deserialized = str.toJSByParseJSON(globalThis);
|
||||||
|
if (deserialized == .zero) return error.InvalidFormat;
|
||||||
|
|
||||||
return switch (kind) {
|
return switch (kind) {
|
||||||
1 => .{
|
1 => .{
|
||||||
@@ -259,13 +258,12 @@ const json = struct {
|
|||||||
|
|
||||||
const slice = str.slice();
|
const slice = str.slice();
|
||||||
|
|
||||||
try writer.ensureUnusedCapacity(1 + slice.len + 1);
|
try writer.ensureUnusedCapacity(slice.len + 1);
|
||||||
|
|
||||||
writer.writeAssumeCapacity(&.{1});
|
|
||||||
writer.writeAssumeCapacity(slice);
|
writer.writeAssumeCapacity(slice);
|
||||||
writer.writeAssumeCapacity("\n");
|
writer.writeAssumeCapacity("\n");
|
||||||
|
|
||||||
return 1 + slice.len + 1;
|
return slice.len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serializeInternal(_: *IPCData, writer: anytype, global: *JSC.JSGlobalObject, value: JSValue) !usize {
|
pub fn serializeInternal(_: *IPCData, writer: anytype, global: *JSC.JSGlobalObject, value: JSValue) !usize {
|
||||||
@@ -860,7 +858,7 @@ fn NewNamedPipeIPCHandler(comptime Context: type) type {
|
|||||||
// copy the remaining bytes to the start of the buffer
|
// copy the remaining bytes to the start of the buffer
|
||||||
bun.copy(u8, ipc.incoming.ptr[0..slice.len], slice);
|
bun.copy(u8, ipc.incoming.ptr[0..slice.len], slice);
|
||||||
ipc.incoming.len = @truncate(slice.len);
|
ipc.incoming.len = @truncate(slice.len);
|
||||||
log("hit NotEnoughBytes2", .{});
|
log("hit NotEnoughBytes3", .{});
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
error.InvalidFormat => {
|
error.InvalidFormat => {
|
||||||
|
|||||||
7
test/js/bun/spawn/fixtures/ipc-child-bun.js
Normal file
7
test/js/bun/spawn/fixtures/ipc-child-bun.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
console.log("c start");
|
||||||
|
process.on("message", message => {
|
||||||
|
console.log("c", message);
|
||||||
|
process.send(message);
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
console.log("c end");
|
||||||
7
test/js/bun/spawn/fixtures/ipc-child-node.js
Normal file
7
test/js/bun/spawn/fixtures/ipc-child-node.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
console.log("c start");
|
||||||
|
process.on("message", message => {
|
||||||
|
console.log("c", message);
|
||||||
|
process.send(message);
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
console.log("c end");
|
||||||
14
test/js/bun/spawn/fixtures/ipc-parent-bun.js
Normal file
14
test/js/bun/spawn/fixtures/ipc-parent-bun.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const path = require("node:path");
|
||||||
|
|
||||||
|
console.log("p start");
|
||||||
|
const child = Bun.spawn(["node", path.resolve(import.meta.dir, "ipc-child-node.js")], {
|
||||||
|
ipc(message) {
|
||||||
|
console.log("p", message);
|
||||||
|
process.exit(0);
|
||||||
|
},
|
||||||
|
stdio: ["ignore", "inherit", "inherit"],
|
||||||
|
serialization: "json",
|
||||||
|
});
|
||||||
|
|
||||||
|
child.send("I am your father");
|
||||||
|
console.log("p end");
|
||||||
15
test/js/bun/spawn/fixtures/ipc-parent-node.js
Normal file
15
test/js/bun/spawn/fixtures/ipc-parent-node.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const path = require("node:path");
|
||||||
|
const child_process = require("node:child_process");
|
||||||
|
|
||||||
|
console.log("p start");
|
||||||
|
|
||||||
|
const child = child_process.spawn(process.argv[2], [path.resolve(__dirname, "ipc-child-bun.js")], {
|
||||||
|
stdio: ["ignore", "inherit", "inherit", "ipc"],
|
||||||
|
});
|
||||||
|
child.on("message", message => {
|
||||||
|
console.log("p", message);
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.send("I am your father");
|
||||||
|
console.log("p end");
|
||||||
21
test/js/bun/spawn/spawn.ipc.bun-node.test.ts
Normal file
21
test/js/bun/spawn/spawn.ipc.bun-node.test.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { spawn } from "bun";
|
||||||
|
import { test, expect, it } from "bun:test";
|
||||||
|
import { bunExe } from "harness";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
test("ipc with json serialization still works when bun is parent and not the child", async () => {
|
||||||
|
const child = Bun.spawn([bunExe(), path.resolve(import.meta.dir, "fixtures", "ipc-parent-bun.js")], {
|
||||||
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
|
});
|
||||||
|
await child.exited;
|
||||||
|
expect(await new Response(child.stdout).text()).toEqual(
|
||||||
|
`p start
|
||||||
|
p end
|
||||||
|
c start
|
||||||
|
c end
|
||||||
|
c I am your father
|
||||||
|
p I am your father
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
expect(await new Response(child.stderr).text()).toEqual("");
|
||||||
|
});
|
||||||
22
test/js/bun/spawn/spawn.ipc.node-bun.test.ts
Normal file
22
test/js/bun/spawn/spawn.ipc.node-bun.test.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { spawn } from "bun";
|
||||||
|
import { test, expect, it } from "bun:test";
|
||||||
|
import { bunExe, nodeExe } from "harness";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
test("ipc with json serialization still works when bun is not the parent and the child", async () => {
|
||||||
|
// prettier-ignore
|
||||||
|
const child = Bun.spawn(["node", "--no-warnings", path.resolve(import.meta.dir, "fixtures", "ipc-parent-node.js"), bunExe()], {
|
||||||
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
|
});
|
||||||
|
await child.exited;
|
||||||
|
expect(await new Response(child.stderr).text()).toEqual("");
|
||||||
|
expect(await new Response(child.stdout).text()).toEqual(
|
||||||
|
`p start
|
||||||
|
p end
|
||||||
|
c start
|
||||||
|
c end
|
||||||
|
c I am your father
|
||||||
|
p I am your father
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user