OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "include/v8.h" | 10 #include "include/v8.h" |
(...skipping 1304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 DecodeTest( | 1315 DecodeTest( |
1316 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x53, 0x01, 0x61, | 1316 {0xff, 0x09, 0x3f, 0x00, 0x6f, 0x3f, 0x01, 0x53, 0x01, 0x61, |
1317 0x3f, 0x01, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x3f, 0x02, | 1317 0x3f, 0x01, 0x52, 0x03, 0x66, 0x6f, 0x6f, 0x03, 0x3f, 0x02, |
1318 0x53, 0x01, 0x62, 0x3f, 0x02, 0x5e, 0x01, 0x7b, 0x02, 0x00}, | 1318 0x53, 0x01, 0x62, 0x3f, 0x02, 0x5e, 0x01, 0x7b, 0x02, 0x00}, |
1319 [this](Local<Value> value) { | 1319 [this](Local<Value> value) { |
1320 EXPECT_TRUE(EvaluateScriptForResultBool("result.a instanceof RegExp")); | 1320 EXPECT_TRUE(EvaluateScriptForResultBool("result.a instanceof RegExp")); |
1321 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b")); | 1321 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === result.b")); |
1322 }); | 1322 }); |
1323 } | 1323 } |
1324 | 1324 |
| 1325 TEST_F(ValueSerializerTest, RoundTripMap) { |
| 1326 RoundTripTest( |
| 1327 "(() => { var m = new Map(); m.set(42, 'foo'); return m; })()", |
| 1328 [this](Local<Value> value) { |
| 1329 ASSERT_TRUE(value->IsMap()); |
| 1330 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1331 "Object.getPrototypeOf(result) === Map.prototype")); |
| 1332 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1333 EXPECT_TRUE(EvaluateScriptForResultBool("result.get(42) === 'foo'")); |
| 1334 }); |
| 1335 RoundTripTest("(() => { var m = new Map(); m.set(m, m); return m; })()", |
| 1336 [this](Local<Value> value) { |
| 1337 ASSERT_TRUE(value->IsMap()); |
| 1338 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1339 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1340 "result.get(result) === result")); |
| 1341 }); |
| 1342 // Iteration order must be preserved. |
| 1343 RoundTripTest( |
| 1344 "(() => {" |
| 1345 " var m = new Map();" |
| 1346 " m.set(1, 0); m.set('a', 0); m.set(3, 0); m.set(2, 0);" |
| 1347 " return m;" |
| 1348 "})()", |
| 1349 [this](Local<Value> value) { |
| 1350 ASSERT_TRUE(value->IsMap()); |
| 1351 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1352 "Array.from(result.keys()).toString() === '1,a,3,2'")); |
| 1353 }); |
| 1354 } |
| 1355 |
| 1356 TEST_F(ValueSerializerTest, DecodeMap) { |
| 1357 DecodeTest( |
| 1358 {0xff, 0x09, 0x3f, 0x00, 0x3b, 0x3f, 0x01, 0x49, 0x54, 0x3f, 0x01, 0x53, |
| 1359 0x03, 0x66, 0x6f, 0x6f, 0x3a, 0x02}, |
| 1360 [this](Local<Value> value) { |
| 1361 ASSERT_TRUE(value->IsMap()); |
| 1362 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1363 "Object.getPrototypeOf(result) === Map.prototype")); |
| 1364 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1365 EXPECT_TRUE(EvaluateScriptForResultBool("result.get(42) === 'foo'")); |
| 1366 }); |
| 1367 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x3b, 0x3f, 0x01, 0x5e, 0x00, 0x3f, 0x01, |
| 1368 0x5e, 0x00, 0x3a, 0x02, 0x00}, |
| 1369 [this](Local<Value> value) { |
| 1370 ASSERT_TRUE(value->IsMap()); |
| 1371 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1372 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1373 "result.get(result) === result")); |
| 1374 }); |
| 1375 // Iteration order must be preserved. |
| 1376 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x3b, 0x3f, 0x01, 0x49, 0x02, 0x3f, |
| 1377 0x01, 0x49, 0x00, 0x3f, 0x01, 0x53, 0x01, 0x61, 0x3f, 0x01, |
| 1378 0x49, 0x00, 0x3f, 0x01, 0x49, 0x06, 0x3f, 0x01, 0x49, 0x00, |
| 1379 0x3f, 0x01, 0x49, 0x04, 0x3f, 0x01, 0x49, 0x00, 0x3a, 0x08}, |
| 1380 [this](Local<Value> value) { |
| 1381 ASSERT_TRUE(value->IsMap()); |
| 1382 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1383 "Array.from(result.keys()).toString() === '1,a,3,2'")); |
| 1384 }); |
| 1385 } |
| 1386 |
| 1387 TEST_F(ValueSerializerTest, RoundTripMapWithTrickyGetters) { |
| 1388 // Even if an entry is removed or reassigned, the original key/value pair is |
| 1389 // used. |
| 1390 RoundTripTest( |
| 1391 "(() => {" |
| 1392 " var m = new Map();" |
| 1393 " m.set(0, { get a() {" |
| 1394 " m.delete(1); m.set(2, 'baz'); m.set(3, 'quux');" |
| 1395 " }});" |
| 1396 " m.set(1, 'foo');" |
| 1397 " m.set(2, 'bar');" |
| 1398 " return m;" |
| 1399 "})()", |
| 1400 [this](Local<Value> value) { |
| 1401 ASSERT_TRUE(value->IsMap()); |
| 1402 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1403 "Array.from(result.keys()).toString() === '0,1,2'")); |
| 1404 EXPECT_TRUE(EvaluateScriptForResultBool("result.get(1) === 'foo'")); |
| 1405 EXPECT_TRUE(EvaluateScriptForResultBool("result.get(2) === 'bar'")); |
| 1406 }); |
| 1407 // However, deeper modifications of objects yet to be serialized still apply. |
| 1408 RoundTripTest( |
| 1409 "(() => {" |
| 1410 " var m = new Map();" |
| 1411 " var key = { get a() { value.foo = 'bar'; } };" |
| 1412 " var value = { get a() { key.baz = 'quux'; } };" |
| 1413 " m.set(key, value);" |
| 1414 " return m;" |
| 1415 "})()", |
| 1416 [this](Local<Value> value) { |
| 1417 ASSERT_TRUE(value->IsMap()); |
| 1418 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1419 "!('baz' in Array.from(result.keys())[0])")); |
| 1420 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1421 "Array.from(result.values())[0].foo === 'bar'")); |
| 1422 }); |
| 1423 } |
| 1424 |
| 1425 TEST_F(ValueSerializerTest, RoundTripSet) { |
| 1426 RoundTripTest( |
| 1427 "(() => { var s = new Set(); s.add(42); s.add('foo'); return s; })()", |
| 1428 [this](Local<Value> value) { |
| 1429 ASSERT_TRUE(value->IsSet()); |
| 1430 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1431 "Object.getPrototypeOf(result) === Set.prototype")); |
| 1432 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 2")); |
| 1433 EXPECT_TRUE(EvaluateScriptForResultBool("result.has(42)")); |
| 1434 EXPECT_TRUE(EvaluateScriptForResultBool("result.has('foo')")); |
| 1435 }); |
| 1436 RoundTripTest( |
| 1437 "(() => { var s = new Set(); s.add(s); return s; })()", |
| 1438 [this](Local<Value> value) { |
| 1439 ASSERT_TRUE(value->IsSet()); |
| 1440 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1441 EXPECT_TRUE(EvaluateScriptForResultBool("result.has(result)")); |
| 1442 }); |
| 1443 // Iteration order must be preserved. |
| 1444 RoundTripTest( |
| 1445 "(() => {" |
| 1446 " var s = new Set();" |
| 1447 " s.add(1); s.add('a'); s.add(3); s.add(2);" |
| 1448 " return s;" |
| 1449 "})()", |
| 1450 [this](Local<Value> value) { |
| 1451 ASSERT_TRUE(value->IsSet()); |
| 1452 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1453 "Array.from(result.keys()).toString() === '1,a,3,2'")); |
| 1454 }); |
| 1455 } |
| 1456 |
| 1457 TEST_F(ValueSerializerTest, DecodeSet) { |
| 1458 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x27, 0x3f, 0x01, 0x49, 0x54, 0x3f, 0x01, |
| 1459 0x53, 0x03, 0x66, 0x6f, 0x6f, 0x2c, 0x02}, |
| 1460 [this](Local<Value> value) { |
| 1461 ASSERT_TRUE(value->IsSet()); |
| 1462 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1463 "Object.getPrototypeOf(result) === Set.prototype")); |
| 1464 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 2")); |
| 1465 EXPECT_TRUE(EvaluateScriptForResultBool("result.has(42)")); |
| 1466 EXPECT_TRUE(EvaluateScriptForResultBool("result.has('foo')")); |
| 1467 }); |
| 1468 DecodeTest( |
| 1469 {0xff, 0x09, 0x3f, 0x00, 0x27, 0x3f, 0x01, 0x5e, 0x00, 0x2c, 0x01, 0x00}, |
| 1470 [this](Local<Value> value) { |
| 1471 ASSERT_TRUE(value->IsSet()); |
| 1472 EXPECT_TRUE(EvaluateScriptForResultBool("result.size === 1")); |
| 1473 EXPECT_TRUE(EvaluateScriptForResultBool("result.has(result)")); |
| 1474 }); |
| 1475 // Iteration order must be preserved. |
| 1476 DecodeTest( |
| 1477 {0xff, 0x09, 0x3f, 0x00, 0x27, 0x3f, 0x01, 0x49, 0x02, 0x3f, 0x01, 0x53, |
| 1478 0x01, 0x61, 0x3f, 0x01, 0x49, 0x06, 0x3f, 0x01, 0x49, 0x04, 0x2c, 0x04}, |
| 1479 [this](Local<Value> value) { |
| 1480 ASSERT_TRUE(value->IsSet()); |
| 1481 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1482 "Array.from(result.keys()).toString() === '1,a,3,2'")); |
| 1483 }); |
| 1484 } |
| 1485 |
| 1486 TEST_F(ValueSerializerTest, RoundTripSetWithTrickyGetters) { |
| 1487 // Even if an element is added or removed during serialization, the original |
| 1488 // set of elements is used. |
| 1489 RoundTripTest( |
| 1490 "(() => {" |
| 1491 " var s = new Set();" |
| 1492 " s.add({ get a() { s.delete(1); s.add(2); } });" |
| 1493 " s.add(1);" |
| 1494 " return s;" |
| 1495 "})()", |
| 1496 [this](Local<Value> value) { |
| 1497 ASSERT_TRUE(value->IsSet()); |
| 1498 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1499 "Array.from(result.keys()).toString() === '[object Object],1'")); |
| 1500 }); |
| 1501 // However, deeper modifications of objects yet to be serialized still apply. |
| 1502 RoundTripTest( |
| 1503 "(() => {" |
| 1504 " var s = new Set();" |
| 1505 " var first = { get a() { second.foo = 'bar'; } };" |
| 1506 " var second = { get a() { first.baz = 'quux'; } };" |
| 1507 " s.add(first);" |
| 1508 " s.add(second);" |
| 1509 " return s;" |
| 1510 "})()", |
| 1511 [this](Local<Value> value) { |
| 1512 ASSERT_TRUE(value->IsSet()); |
| 1513 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1514 "!('baz' in Array.from(result.keys())[0])")); |
| 1515 EXPECT_TRUE(EvaluateScriptForResultBool( |
| 1516 "Array.from(result.keys())[1].foo === 'bar'")); |
| 1517 }); |
| 1518 } |
| 1519 |
1325 } // namespace | 1520 } // namespace |
1326 } // namespace v8 | 1521 } // namespace v8 |
OLD | NEW |