Commit 65435199 authored by jbroman's avatar jbroman Committed by Commit bot

ValueSerializer: Add an explicit tag for host objects.

This makes it no longer necessary to ensure that V8 and Blink have non-colliding
tags, which makes it easier for them to evolve independently, and also makes
the wire format more suitable for other V8 embedders, who would not
necessarily be surveyed before V8 introduced a new tag that might collide
with theirs.

BUG=chromium:686159

Review-Url: https://codereview.chromium.org/2709023003
Cr-Commit-Position: refs/heads/master@{#43466}
parent 7f570150
...@@ -27,7 +27,9 @@ namespace internal { ...@@ -27,7 +27,9 @@ namespace internal {
// Version 10: one-byte (Latin-1) strings // Version 10: one-byte (Latin-1) strings
// Version 11: properly separate undefined from the hole in arrays // Version 11: properly separate undefined from the hole in arrays
// Version 12: regexp and string objects share normal string encoding // Version 12: regexp and string objects share normal string encoding
static const uint32_t kLatestVersion = 12; // Version 13: host objects have an explicit tag (rather than handling all
// unknown tags)
static const uint32_t kLatestVersion = 13;
static const int kPretenureThreshold = 100 * KB; static const int kPretenureThreshold = 100 * KB;
...@@ -124,6 +126,9 @@ enum class SerializationTag : uint8_t { ...@@ -124,6 +126,9 @@ enum class SerializationTag : uint8_t {
// wasmWireByteLength:uint32_t, then raw data // wasmWireByteLength:uint32_t, then raw data
// compiledDataLength:uint32_t, then raw data // compiledDataLength:uint32_t, then raw data
kWasmModule = 'W', kWasmModule = 'W',
// The delegate is responsible for processing all following data.
// This "escapes" to whatever wire format the delegate chooses.
kHostObject = '\\',
}; };
namespace { namespace {
...@@ -823,6 +828,7 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { ...@@ -823,6 +828,7 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
} }
Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) { Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
WriteTag(SerializationTag::kHostObject);
if (!delegate_) { if (!delegate_) {
isolate_->Throw(*isolate_->factory()->NewError( isolate_->Throw(*isolate_->factory()->NewError(
isolate_->error_function(), MessageTemplate::kDataCloneError, object)); isolate_->error_function(), MessageTemplate::kDataCloneError, object));
...@@ -1144,11 +1150,16 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() { ...@@ -1144,11 +1150,16 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
} }
case SerializationTag::kWasmModule: case SerializationTag::kWasmModule:
return ReadWasmModule(); return ReadWasmModule();
default: case SerializationTag::kHostObject:
// TODO(jbroman): Introduce an explicit tag for host objects to avoid
// having to treat every unknown tag as a potential host object.
position_--;
return ReadHostObject(); return ReadHostObject();
default:
// Before there was an explicit tag for host objects, all unknown tags
// were delegated to the host.
if (version_ < 13) {
position_--;
return ReadHostObject();
}
return MaybeHandle<Object>();
} }
} }
......
...@@ -2370,8 +2370,9 @@ class ValueSerializerTestWithHostObject : public ValueSerializerTest { ...@@ -2370,8 +2370,9 @@ class ValueSerializerTestWithHostObject : public ValueSerializerTest {
friend class DeserializerDelegate; friend class DeserializerDelegate;
}; };
// This is a tag that's not used in V8. // This is a tag that is used in V8. Using this ensures that we have separate
const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = '+'; // tag namespaces.
const uint8_t ValueSerializerTestWithHostObject::kExampleHostObjectTag = 'T';
TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) { TEST_F(ValueSerializerTestWithHostObject, RoundTripUint32) {
// The host can serialize data as uint32_t. // The host can serialize data as uint32_t.
...@@ -2544,6 +2545,19 @@ TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) { ...@@ -2544,6 +2545,19 @@ TEST_F(ValueSerializerTestWithHostObject, RoundTripSameObject) {
}); });
} }
TEST_F(ValueSerializerTestWithHostObject, DecodeSimpleHostObject) {
EXPECT_CALL(deserializer_delegate_, ReadHostObject(isolate()))
.WillRepeatedly(Invoke([this](Isolate*) {
EXPECT_TRUE(ReadExampleHostObjectTag());
return NewHostObject(deserialization_context(), 0, nullptr);
}));
DecodeTest(
{0xff, 0x0d, 0x5c, kExampleHostObjectTag}, [this](Local<Value> value) {
EXPECT_TRUE(EvaluateScriptForResultBool(
"Object.getPrototypeOf(result) === ExampleHostObject.prototype"));
});
}
class ValueSerializerTestWithHostArrayBufferView class ValueSerializerTestWithHostArrayBufferView
: public ValueSerializerTestWithHostObject { : public ValueSerializerTestWithHostObject {
protected: protected:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment