| Index: test/unittests/value-serializer-unittest.cc
|
| diff --git a/test/unittests/value-serializer-unittest.cc b/test/unittests/value-serializer-unittest.cc
|
| index 63b50871ff0b4aba2e16a179a55f7004eedf5507..d45f374c06f26dea4b3ddd88e46ecb7fecdb7f46 100644
|
| --- a/test/unittests/value-serializer-unittest.cc
|
| +++ b/test/unittests/value-serializer-unittest.cc
|
| @@ -707,337 +707,5 @@
|
| });
|
| }
|
|
|
| -TEST_F(ValueSerializerTest, RoundTripArray) {
|
| - // A simple array of integers.
|
| - RoundTripTest("[1, 2, 3, 4, 5]", [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - EXPECT_EQ(5, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool(
|
| - "Object.getPrototypeOf(result) === Array.prototype"));
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("result.toString() === '1,2,3,4,5'"));
|
| - });
|
| - // A long (sparse) array.
|
| - RoundTripTest(
|
| - "(() => { var x = new Array(1000); x[500] = 42; return x; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - EXPECT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[500] === 42"));
|
| - });
|
| - // Duplicate reference.
|
| - RoundTripTest(
|
| - "(() => { var y = {}; return [y, y]; })()", [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result[1]"));
|
| - });
|
| - // Duplicate reference in a sparse array.
|
| - RoundTripTest(
|
| - "(() => { var x = new Array(1000); x[1] = x[500] = {}; return x; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'object'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === result[500]"));
|
| - });
|
| - // Self reference.
|
| - RoundTripTest(
|
| - "(() => { var y = []; y[0] = y; return y; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result"));
|
| - });
|
| - // Self reference in a sparse array.
|
| - RoundTripTest(
|
| - "(() => { var y = new Array(1000); y[519] = y; return y; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[519] === result"));
|
| - });
|
| - // Array with additional properties.
|
| - RoundTripTest(
|
| - "(() => { var y = [1, 2]; y.foo = 'bar'; return y; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.toString() === '1,2'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
|
| - });
|
| - // Sparse array with additional properties.
|
| - RoundTripTest(
|
| - "(() => { var y = new Array(1000); y.foo = 'bar'; return y; })()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool(
|
| - "result.toString() === ','.repeat(999)"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
|
| - });
|
| - // The distinction between holes and undefined elements must be maintained.
|
| - RoundTripTest("[,undefined]", [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[0] === 'undefined'"));
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(0)"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty(1)"));
|
| - });
|
| -}
|
| -
|
| -TEST_F(ValueSerializerTest, DecodeArray) {
|
| - // A simple array of integers.
|
| - DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x41, 0x05, 0x3f, 0x01, 0x49, 0x02,
|
| - 0x3f, 0x01, 0x49, 0x04, 0x3f, 0x01, 0x49, 0x06, 0x3f, 0x01,
|
| - 0x49, 0x08, 0x3f, 0x01, 0x49, 0x0a, 0x24, 0x00, 0x05, 0x00},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - EXPECT_EQ(5, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool(
|
| - "Object.getPrototypeOf(result) === Array.prototype"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool(
|
| - "result.toString() === '1,2,3,4,5'"));
|
| - });
|
| - // A long (sparse) array.
|
| - DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
|
| - 0xe8, 0x07, 0x3f, 0x01, 0x49, 0x54, 0x40, 0x01, 0xe8, 0x07},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - EXPECT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[500] === 42"));
|
| - });
|
| - // Duplicate reference.
|
| - DecodeTest(
|
| - {0xff, 0x09, 0x3f, 0x00, 0x41, 0x02, 0x3f, 0x01, 0x6f, 0x7b, 0x00, 0x3f,
|
| - 0x02, 0x5e, 0x01, 0x24, 0x00, 0x02},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result[1]"));
|
| - });
|
| - // Duplicate reference in a sparse array.
|
| - DecodeTest(
|
| - {0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
|
| - 0x02, 0x3f, 0x01, 0x6f, 0x7b, 0x00, 0x3f, 0x02, 0x49, 0xe8,
|
| - 0x07, 0x3f, 0x02, 0x5e, 0x01, 0x40, 0x02, 0xe8, 0x07, 0x00},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'object'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === result[500]"));
|
| - });
|
| - // Self reference.
|
| - DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x41, 0x01, 0x3f, 0x01, 0x5e, 0x00, 0x24,
|
| - 0x00, 0x01, 0x00},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result"));
|
| - });
|
| - // Self reference in a sparse array.
|
| - DecodeTest(
|
| - {0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
|
| - 0x8e, 0x08, 0x3f, 0x01, 0x5e, 0x00, 0x40, 0x01, 0xe8, 0x07},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[519] === result"));
|
| - });
|
| - // Array with additional properties.
|
| - DecodeTest(
|
| - {0xff, 0x09, 0x3f, 0x00, 0x41, 0x02, 0x3f, 0x01, 0x49, 0x02, 0x3f,
|
| - 0x01, 0x49, 0x04, 0x3f, 0x01, 0x53, 0x03, 0x66, 0x6f, 0x6f, 0x3f,
|
| - 0x01, 0x53, 0x03, 0x62, 0x61, 0x72, 0x24, 0x01, 0x02, 0x00},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.toString() === '1,2'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
|
| - });
|
| - // Sparse array with additional properties.
|
| - DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01,
|
| - 0x53, 0x03, 0x66, 0x6f, 0x6f, 0x3f, 0x01, 0x53, 0x03,
|
| - 0x62, 0x61, 0x72, 0x40, 0x01, 0xe8, 0x07, 0x00},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool(
|
| - "result.toString() === ','.repeat(999)"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
|
| - });
|
| - // The distinction between holes and undefined elements must be maintained.
|
| - // Note that since the previous output from Chrome fails this test, an
|
| - // encoding using the sparse format was constructed instead.
|
| - DecodeTest(
|
| - {0xff, 0x09, 0x61, 0x02, 0x49, 0x02, 0x5f, 0x40, 0x01, 0x02},
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[0] === 'undefined'"));
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(0)"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty(1)"));
|
| - });
|
| -}
|
| -
|
| -TEST_F(ValueSerializerTest, RoundTripArrayWithNonEnumerableElement) {
|
| - // Even though this array looks like [1,5,3], the 5 should be missing from the
|
| - // perspective of structured clone, which only clones properties that were
|
| - // enumerable.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [1,2,3];"
|
| - " Object.defineProperty(x, '1', {enumerable:false, value:5});"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(3, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty('1')"));
|
| - });
|
| -}
|
| -
|
| -TEST_F(ValueSerializerTest, RoundTripArrayWithTrickyGetters) {
|
| - // If an element is deleted before it is serialized, then it's deleted.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() { delete x[1]; }}, 42];"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(1)"));
|
| - });
|
| - // Same for sparse arrays.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() { delete x[1]; }}, 42];"
|
| - " x.length = 1000;"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(
|
| - EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(1)"));
|
| - });
|
| - // If the length is changed, then the resulting array still has the original
|
| - // length, but elements that were not yet serialized are gone.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [1, { get a() { x.length = 0; }}, 3, 4];"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(4, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === 1"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(2)"));
|
| - });
|
| - // Same for sparse arrays.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [1, { get a() { x.length = 0; }}, 3, 4];"
|
| - " x.length = 1000;"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === 1"));
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(2)"));
|
| - });
|
| - // If a getter makes a property non-enumerable, it should still be enumerated
|
| - // as enumeration happens once before getters are invoked.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() {"
|
| - " Object.defineProperty(x, '1', { value: 3, enumerable: false });"
|
| - " }}, 2];"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 3"));
|
| - });
|
| - // Same for sparse arrays.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() {"
|
| - " Object.defineProperty(x, '1', { value: 3, enumerable: false });"
|
| - " }}, 2];"
|
| - " x.length = 1000;"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 3"));
|
| - });
|
| - // Getters on the array itself must also run.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [1, 2, 3];"
|
| - " Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(3, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 4"));
|
| - });
|
| - // Same for sparse arrays.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [1, 2, 3];"
|
| - " Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
|
| - " x.length = 1000;"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 4"));
|
| - });
|
| - // Even with a getter that deletes things, we don't read from the prototype.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() { delete x[1]; } }, 2];"
|
| - " x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(2, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!(1 in result)"));
|
| - });
|
| - // Same for sparse arrays.
|
| - RoundTripTest(
|
| - "(() => {"
|
| - " var x = [{ get a() { delete x[1]; } }, 2];"
|
| - " x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
|
| - " x.length = 1000;"
|
| - " return x;"
|
| - "})()",
|
| - [this](Local<Value> value) {
|
| - ASSERT_TRUE(value->IsArray());
|
| - ASSERT_EQ(1000, Array::Cast(*value)->Length());
|
| - EXPECT_TRUE(EvaluateScriptForResultBool("!(1 in result)"));
|
| - });
|
| -}
|
| -
|
| } // namespace
|
| } // namespace v8
|
|
|