Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 5 additions & 50 deletions lib/internal/child_process/serialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,14 @@ const {
} = primordials;
const { Buffer } = require('buffer');
const { StringDecoder } = require('string_decoder');
const v8 = require('v8');
const { isArrayBufferView } = require('internal/util/types');
const assert = require('internal/assert');
const { serialize, deserialize } = internalBinding('ipc_serdes');
const { streamBaseState, kLastWriteWasAsync } = internalBinding('stream_wrap');

const kMessageBuffer = Symbol('kMessageBuffer');
const kMessageBufferSize = Symbol('kMessageBufferSize');
const kJSONBuffer = Symbol('kJSONBuffer');
const kStringDecoder = Symbol('kStringDecoder');

// Extend V8's serializer APIs to give more JSON-like behaviour in
// some cases; in particular, for native objects this serializes them the same
// way that JSON does rather than throwing an exception.
const kArrayBufferViewTag = 0;
const kNotArrayBufferViewTag = 1;
class ChildProcessSerializer extends v8.DefaultSerializer {
_writeHostObject(object) {
if (isArrayBufferView(object)) {
this.writeUint32(kArrayBufferViewTag);
return super._writeHostObject(object);
}
this.writeUint32(kNotArrayBufferViewTag);
this.writeValue({ ...object });
}
}

class ChildProcessDeserializer extends v8.DefaultDeserializer {
_readHostObject() {
const tag = this.readUint32();
if (tag === kArrayBufferViewTag)
return super._readHostObject();

assert(tag === kNotArrayBufferViewTag);
return this.readValue();
}
}

// Messages are parsed in either of the following formats:
// - Newline-delimited JSON, or
// - V8-serialized buffers, prefixed with their length as a big endian uint32
Expand Down Expand Up @@ -90,38 +61,22 @@ const advanced = {
channel[kMessageBufferSize],
);

const deserializer = new ChildProcessDeserializer(
TypedArrayPrototypeSubarray(concatenatedBuffer, 4, fullMessageSize),
);
const serializedMessage =
TypedArrayPrototypeSubarray(concatenatedBuffer, 4, fullMessageSize);

messageBufferHead = TypedArrayPrototypeSubarray(concatenatedBuffer, fullMessageSize);
channel[kMessageBufferSize] = messageBufferHead.length;
channel[kMessageBuffer] =
channel[kMessageBufferSize] !== 0 ? [messageBufferHead] : [];

deserializer.readHeader();
yield deserializer.readValue();
yield deserialize(serializedMessage);
}

channel.buffering = channel[kMessageBufferSize] > 0;
},

writeChannelMessage(channel, req, message, handle) {
const ser = new ChildProcessSerializer();
// Add 4 bytes, to later populate with message length
ser.writeRawBytes(Buffer.allocUnsafe(4));
ser.writeHeader();
ser.writeValue(message);

const serializedMessage = ser.releaseBuffer();
const serializedMessageLength = serializedMessage.length - 4;

serializedMessage.set([
serializedMessageLength >> 24 & 0xFF,
serializedMessageLength >> 16 & 0xFF,
serializedMessageLength >> 8 & 0xFF,
serializedMessageLength & 0xFF,
], 0);
const serializedMessage = serialize(message);

const result = channel.writeBuffer(req, serializedMessage, handle);

Expand Down
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
'src/node_http_parser.cc',
'src/node_http2.cc',
'src/node_i18n.cc',
'src/node_ipc_serdes.cc',
'src/node_locks.cc',
'src/node_main_instance.cc',
'src/node_messaging.cc',
Expand Down
1 change: 1 addition & 0 deletions src/node_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
V(http_parser) \
V(inspector) \
V(internal_only_v8) \
V(ipc_serdes) \
V(js_stream) \
V(js_udp_wrap) \
V(locks) \
Expand Down
1 change: 1 addition & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ExternalReferenceRegistry {
V(heap_utils) \
V(http_parser) \
V(internal_only_v8) \
V(ipc_serdes) \
V(locks) \
V(messaging) \
V(mksnapshot) \
Expand Down
Loading
Loading