Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v8 module: allow TypedArray and DataView #23953

Merged
merged 1 commit into from
Oct 31, 2018
Merged
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
6 changes: 3 additions & 3 deletions doc/api/v8.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Uses a [`DefaultSerializer`][] to serialize `value` into a buffer.
added: v8.0.0
-->

* `buffer` {Buffer|Uint8Array} A buffer returned by [`serialize()`][].
* `buffer` {Buffer|TypedArray|DataView} A buffer returned by [`serialize()`][].

Uses a [`DefaultDeserializer`][] with default options to read a JS value
from a buffer.
Expand Down Expand Up @@ -252,7 +252,7 @@ For use inside of a custom [`serializer._writeHostObject()`][].

#### serializer.writeRawBytes(buffer)

* `buffer` {Buffer|Uint8Array}
* `buffer` {Buffer|TypedArray|DataView}

Write raw bytes into the serializer’s internal buffer. The deserializer
will require a way to compute the length of the buffer.
Expand Down Expand Up @@ -308,7 +308,7 @@ added: v8.0.0

#### new Deserializer(buffer)

* `buffer` {Buffer|Uint8Array} A buffer returned by
* `buffer` {Buffer|TypedArray|DataView} A buffer returned by
[`serializer.releaseBuffer()`][].

Creates a new `Deserializer` object.
Expand Down
8 changes: 4 additions & 4 deletions src/node_serdes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ void SerializerContext::WriteRawBytes(const FunctionCallbackInfo<Value>& args) {
SerializerContext* ctx;
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());

if (!args[0]->IsUint8Array()) {
if (!args[0]->IsArrayBufferView()) {
return node::THROW_ERR_INVALID_ARG_TYPE(
ctx->env(), "source must be a Uint8Array");
ctx->env(), "source must be a TypedArray or a DataView");
}

ctx->serializer_.WriteRawBytes(Buffer::Data(args[0]),
Expand Down Expand Up @@ -317,9 +317,9 @@ MaybeLocal<Object> DeserializerContext::ReadHostObject(Isolate* isolate) {
void DeserializerContext::New(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

if (!args[0]->IsUint8Array()) {
if (!args[0]->IsArrayBufferView()) {
return node::THROW_ERR_INVALID_ARG_TYPE(
env, "buffer must be a Uint8Array");
env, "buffer must be a TypedArray or a DataView");
}

new DeserializerContext(env, args.This(), args[0]);
Expand Down
84 changes: 84 additions & 0 deletions test/parallel/test-v8-serdes.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,47 @@ const deserializerTypeError =
assert.strictEqual(des.readValue().val, hostObject);
}

// This test ensures that `v8.Serializer.writeRawBytes()` support
// `TypedArray` and `DataView`.
{
const text = 'hostObjectTag';
const data = Buffer.from(text);
const arrayBufferViews = common.getArrayBufferViews(data);

// `buf` is one of `TypedArray` or `DataView`.
function testWriteRawBytes(buf) {
let writeHostObjectCalled = false;
const ser = new v8.DefaultSerializer();

ser._writeHostObject = common.mustCall((object) => {
writeHostObjectCalled = true;
ser.writeUint32(buf.byteLength);
ser.writeRawBytes(buf);
});

ser.writeHeader();
ser.writeValue({ val: hostObject });

const des = new v8.DefaultDeserializer(ser.releaseBuffer());
des._readHostObject = common.mustCall(() => {
assert.strictEqual(writeHostObjectCalled, true);
const length = des.readUint32();
const buf = des.readRawBytes(length);
assert.strictEqual(buf.toString(), text);

return hostObject;
});

des.readHeader();

assert.strictEqual(des.readValue().val, hostObject);
}

arrayBufferViews.forEach((buf) => {
testWriteRawBytes(buf);
});
}

{
const ser = new v8.DefaultSerializer();
ser._writeHostObject = common.mustCall((object) => {
Expand Down Expand Up @@ -146,3 +187,46 @@ const deserializerTypeError =
assert.throws(v8.Serializer, serializerTypeError);
assert.throws(v8.Deserializer, deserializerTypeError);
}


// `v8.deserialize()` and `new v8.Deserializer()` should support both
// `TypedArray` and `DataView`.
{
for (const obj of objects) {
const buf = v8.serialize(obj);

for (const arrayBufferView of common.getArrayBufferViews(buf)) {
assert.deepStrictEqual(v8.deserialize(arrayBufferView), obj);
}

for (const arrayBufferView of common.getArrayBufferViews(buf)) {
const deserializer = new v8.DefaultDeserializer(arrayBufferView);
deserializer.readHeader();
const value = deserializer.readValue();
assert.deepStrictEqual(value, obj);

const serializer = new v8.DefaultSerializer();
serializer.writeHeader();
serializer.writeValue(value);
assert.deepStrictEqual(buf, serializer.releaseBuffer());
}
}
}

{
const INVALID_SOURCE = 'INVALID_SOURCE_TYPE';
const serializer = new v8.Serializer();
serializer.writeHeader();
assert.throws(
() => serializer.writeRawBytes(INVALID_SOURCE),
/^TypeError: source must be a TypedArray or a DataView$/,
);
assert.throws(
() => v8.deserialize(INVALID_SOURCE),
/^TypeError: buffer must be a TypedArray or a DataView$/,
);
assert.throws(
() => new v8.Deserializer(INVALID_SOURCE),
/^TypeError: buffer must be a TypedArray or a DataView$/,
);
}