Skip to content

Commit

Permalink
lib: enable TypedArray and DataView for the v8 module
Browse files Browse the repository at this point in the history
This commit allow passing `TypedArray` and `DataView` to:
- v8.deserialize()
- new v8.Deserializer()
- v8.serializer.writeRawBytes()

PR-URL: #23953
Refs: #1826
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Refael Ackermann <refack@gmail.com>
  • Loading branch information
oyyd authored and targos committed Nov 2, 2018
1 parent 063b40e commit 55adc25
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 7 deletions.
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$/,
);
}

0 comments on commit 55adc25

Please sign in to comment.