Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: test/unittests/value-serializer-unittest.cc

Issue 2255313002: Revert of Blink-compatible serialization of arrays, both dense and sparse. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/value-serializer.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 DecodeTestForVersion0( 700 DecodeTestForVersion0(
701 {0x49, 0x54, 0x53, 0x01, 0x61, 0x53, 0x01, 0x61, 0x49, 0x54, 0x7b, 0x02}, 701 {0x49, 0x54, 0x53, 0x01, 0x61, 0x53, 0x01, 0x61, 0x49, 0x54, 0x7b, 0x02},
702 [this](Local<Value> value) { 702 [this](Local<Value> value) {
703 EXPECT_TRUE(EvaluateScriptForResultBool( 703 EXPECT_TRUE(EvaluateScriptForResultBool(
704 "Object.getOwnPropertyNames(result).toString() === '42,a'")); 704 "Object.getOwnPropertyNames(result).toString() === '42,a'"));
705 EXPECT_TRUE(EvaluateScriptForResultBool("result[42] === 'a'")); 705 EXPECT_TRUE(EvaluateScriptForResultBool("result[42] === 'a'"));
706 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === 42")); 706 EXPECT_TRUE(EvaluateScriptForResultBool("result.a === 42"));
707 }); 707 });
708 } 708 }
709 709
710 TEST_F(ValueSerializerTest, RoundTripArray) {
711 // A simple array of integers.
712 RoundTripTest("[1, 2, 3, 4, 5]", [this](Local<Value> value) {
713 ASSERT_TRUE(value->IsArray());
714 EXPECT_EQ(5, Array::Cast(*value)->Length());
715 EXPECT_TRUE(EvaluateScriptForResultBool(
716 "Object.getPrototypeOf(result) === Array.prototype"));
717 EXPECT_TRUE(
718 EvaluateScriptForResultBool("result.toString() === '1,2,3,4,5'"));
719 });
720 // A long (sparse) array.
721 RoundTripTest(
722 "(() => { var x = new Array(1000); x[500] = 42; return x; })()",
723 [this](Local<Value> value) {
724 ASSERT_TRUE(value->IsArray());
725 EXPECT_EQ(1000, Array::Cast(*value)->Length());
726 EXPECT_TRUE(EvaluateScriptForResultBool("result[500] === 42"));
727 });
728 // Duplicate reference.
729 RoundTripTest(
730 "(() => { var y = {}; return [y, y]; })()", [this](Local<Value> value) {
731 ASSERT_TRUE(value->IsArray());
732 ASSERT_EQ(2, Array::Cast(*value)->Length());
733 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result[1]"));
734 });
735 // Duplicate reference in a sparse array.
736 RoundTripTest(
737 "(() => { var x = new Array(1000); x[1] = x[500] = {}; return x; })()",
738 [this](Local<Value> value) {
739 ASSERT_TRUE(value->IsArray());
740 ASSERT_EQ(1000, Array::Cast(*value)->Length());
741 EXPECT_TRUE(
742 EvaluateScriptForResultBool("typeof result[1] === 'object'"));
743 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === result[500]"));
744 });
745 // Self reference.
746 RoundTripTest(
747 "(() => { var y = []; y[0] = y; return y; })()",
748 [this](Local<Value> value) {
749 ASSERT_TRUE(value->IsArray());
750 ASSERT_EQ(1, Array::Cast(*value)->Length());
751 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result"));
752 });
753 // Self reference in a sparse array.
754 RoundTripTest(
755 "(() => { var y = new Array(1000); y[519] = y; return y; })()",
756 [this](Local<Value> value) {
757 ASSERT_TRUE(value->IsArray());
758 ASSERT_EQ(1000, Array::Cast(*value)->Length());
759 EXPECT_TRUE(EvaluateScriptForResultBool("result[519] === result"));
760 });
761 // Array with additional properties.
762 RoundTripTest(
763 "(() => { var y = [1, 2]; y.foo = 'bar'; return y; })()",
764 [this](Local<Value> value) {
765 ASSERT_TRUE(value->IsArray());
766 ASSERT_EQ(2, Array::Cast(*value)->Length());
767 EXPECT_TRUE(EvaluateScriptForResultBool("result.toString() === '1,2'"));
768 EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
769 });
770 // Sparse array with additional properties.
771 RoundTripTest(
772 "(() => { var y = new Array(1000); y.foo = 'bar'; return y; })()",
773 [this](Local<Value> value) {
774 ASSERT_TRUE(value->IsArray());
775 ASSERT_EQ(1000, Array::Cast(*value)->Length());
776 EXPECT_TRUE(EvaluateScriptForResultBool(
777 "result.toString() === ','.repeat(999)"));
778 EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
779 });
780 // The distinction between holes and undefined elements must be maintained.
781 RoundTripTest("[,undefined]", [this](Local<Value> value) {
782 ASSERT_TRUE(value->IsArray());
783 ASSERT_EQ(2, Array::Cast(*value)->Length());
784 EXPECT_TRUE(
785 EvaluateScriptForResultBool("typeof result[0] === 'undefined'"));
786 EXPECT_TRUE(
787 EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
788 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(0)"));
789 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty(1)"));
790 });
791 }
792
793 TEST_F(ValueSerializerTest, DecodeArray) {
794 // A simple array of integers.
795 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x41, 0x05, 0x3f, 0x01, 0x49, 0x02,
796 0x3f, 0x01, 0x49, 0x04, 0x3f, 0x01, 0x49, 0x06, 0x3f, 0x01,
797 0x49, 0x08, 0x3f, 0x01, 0x49, 0x0a, 0x24, 0x00, 0x05, 0x00},
798 [this](Local<Value> value) {
799 ASSERT_TRUE(value->IsArray());
800 EXPECT_EQ(5, Array::Cast(*value)->Length());
801 EXPECT_TRUE(EvaluateScriptForResultBool(
802 "Object.getPrototypeOf(result) === Array.prototype"));
803 EXPECT_TRUE(EvaluateScriptForResultBool(
804 "result.toString() === '1,2,3,4,5'"));
805 });
806 // A long (sparse) array.
807 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
808 0xe8, 0x07, 0x3f, 0x01, 0x49, 0x54, 0x40, 0x01, 0xe8, 0x07},
809 [this](Local<Value> value) {
810 ASSERT_TRUE(value->IsArray());
811 EXPECT_EQ(1000, Array::Cast(*value)->Length());
812 EXPECT_TRUE(EvaluateScriptForResultBool("result[500] === 42"));
813 });
814 // Duplicate reference.
815 DecodeTest(
816 {0xff, 0x09, 0x3f, 0x00, 0x41, 0x02, 0x3f, 0x01, 0x6f, 0x7b, 0x00, 0x3f,
817 0x02, 0x5e, 0x01, 0x24, 0x00, 0x02},
818 [this](Local<Value> value) {
819 ASSERT_TRUE(value->IsArray());
820 ASSERT_EQ(2, Array::Cast(*value)->Length());
821 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result[1]"));
822 });
823 // Duplicate reference in a sparse array.
824 DecodeTest(
825 {0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
826 0x02, 0x3f, 0x01, 0x6f, 0x7b, 0x00, 0x3f, 0x02, 0x49, 0xe8,
827 0x07, 0x3f, 0x02, 0x5e, 0x01, 0x40, 0x02, 0xe8, 0x07, 0x00},
828 [this](Local<Value> value) {
829 ASSERT_TRUE(value->IsArray());
830 ASSERT_EQ(1000, Array::Cast(*value)->Length());
831 EXPECT_TRUE(
832 EvaluateScriptForResultBool("typeof result[1] === 'object'"));
833 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === result[500]"));
834 });
835 // Self reference.
836 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x41, 0x01, 0x3f, 0x01, 0x5e, 0x00, 0x24,
837 0x00, 0x01, 0x00},
838 [this](Local<Value> value) {
839 ASSERT_TRUE(value->IsArray());
840 ASSERT_EQ(1, Array::Cast(*value)->Length());
841 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === result"));
842 });
843 // Self reference in a sparse array.
844 DecodeTest(
845 {0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01, 0x49,
846 0x8e, 0x08, 0x3f, 0x01, 0x5e, 0x00, 0x40, 0x01, 0xe8, 0x07},
847 [this](Local<Value> value) {
848 ASSERT_TRUE(value->IsArray());
849 ASSERT_EQ(1000, Array::Cast(*value)->Length());
850 EXPECT_TRUE(EvaluateScriptForResultBool("result[519] === result"));
851 });
852 // Array with additional properties.
853 DecodeTest(
854 {0xff, 0x09, 0x3f, 0x00, 0x41, 0x02, 0x3f, 0x01, 0x49, 0x02, 0x3f,
855 0x01, 0x49, 0x04, 0x3f, 0x01, 0x53, 0x03, 0x66, 0x6f, 0x6f, 0x3f,
856 0x01, 0x53, 0x03, 0x62, 0x61, 0x72, 0x24, 0x01, 0x02, 0x00},
857 [this](Local<Value> value) {
858 ASSERT_TRUE(value->IsArray());
859 ASSERT_EQ(2, Array::Cast(*value)->Length());
860 EXPECT_TRUE(EvaluateScriptForResultBool("result.toString() === '1,2'"));
861 EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
862 });
863 // Sparse array with additional properties.
864 DecodeTest({0xff, 0x09, 0x3f, 0x00, 0x61, 0xe8, 0x07, 0x3f, 0x01,
865 0x53, 0x03, 0x66, 0x6f, 0x6f, 0x3f, 0x01, 0x53, 0x03,
866 0x62, 0x61, 0x72, 0x40, 0x01, 0xe8, 0x07, 0x00},
867 [this](Local<Value> value) {
868 ASSERT_TRUE(value->IsArray());
869 ASSERT_EQ(1000, Array::Cast(*value)->Length());
870 EXPECT_TRUE(EvaluateScriptForResultBool(
871 "result.toString() === ','.repeat(999)"));
872 EXPECT_TRUE(EvaluateScriptForResultBool("result.foo === 'bar'"));
873 });
874 // The distinction between holes and undefined elements must be maintained.
875 // Note that since the previous output from Chrome fails this test, an
876 // encoding using the sparse format was constructed instead.
877 DecodeTest(
878 {0xff, 0x09, 0x61, 0x02, 0x49, 0x02, 0x5f, 0x40, 0x01, 0x02},
879 [this](Local<Value> value) {
880 ASSERT_TRUE(value->IsArray());
881 ASSERT_EQ(2, Array::Cast(*value)->Length());
882 EXPECT_TRUE(
883 EvaluateScriptForResultBool("typeof result[0] === 'undefined'"));
884 EXPECT_TRUE(
885 EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
886 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(0)"));
887 EXPECT_TRUE(EvaluateScriptForResultBool("result.hasOwnProperty(1)"));
888 });
889 }
890
891 TEST_F(ValueSerializerTest, RoundTripArrayWithNonEnumerableElement) {
892 // Even though this array looks like [1,5,3], the 5 should be missing from the
893 // perspective of structured clone, which only clones properties that were
894 // enumerable.
895 RoundTripTest(
896 "(() => {"
897 " var x = [1,2,3];"
898 " Object.defineProperty(x, '1', {enumerable:false, value:5});"
899 " return x;"
900 "})()",
901 [this](Local<Value> value) {
902 ASSERT_TRUE(value->IsArray());
903 ASSERT_EQ(3, Array::Cast(*value)->Length());
904 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty('1')"));
905 });
906 }
907
908 TEST_F(ValueSerializerTest, RoundTripArrayWithTrickyGetters) {
909 // If an element is deleted before it is serialized, then it's deleted.
910 RoundTripTest(
911 "(() => {"
912 " var x = [{ get a() { delete x[1]; }}, 42];"
913 " return x;"
914 "})()",
915 [this](Local<Value> value) {
916 ASSERT_TRUE(value->IsArray());
917 ASSERT_EQ(2, Array::Cast(*value)->Length());
918 EXPECT_TRUE(
919 EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
920 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(1)"));
921 });
922 // Same for sparse arrays.
923 RoundTripTest(
924 "(() => {"
925 " var x = [{ get a() { delete x[1]; }}, 42];"
926 " x.length = 1000;"
927 " return x;"
928 "})()",
929 [this](Local<Value> value) {
930 ASSERT_TRUE(value->IsArray());
931 ASSERT_EQ(1000, Array::Cast(*value)->Length());
932 EXPECT_TRUE(
933 EvaluateScriptForResultBool("typeof result[1] === 'undefined'"));
934 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(1)"));
935 });
936 // If the length is changed, then the resulting array still has the original
937 // length, but elements that were not yet serialized are gone.
938 RoundTripTest(
939 "(() => {"
940 " var x = [1, { get a() { x.length = 0; }}, 3, 4];"
941 " return x;"
942 "})()",
943 [this](Local<Value> value) {
944 ASSERT_TRUE(value->IsArray());
945 ASSERT_EQ(4, Array::Cast(*value)->Length());
946 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === 1"));
947 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(2)"));
948 });
949 // Same for sparse arrays.
950 RoundTripTest(
951 "(() => {"
952 " var x = [1, { get a() { x.length = 0; }}, 3, 4];"
953 " x.length = 1000;"
954 " return x;"
955 "})()",
956 [this](Local<Value> value) {
957 ASSERT_TRUE(value->IsArray());
958 ASSERT_EQ(1000, Array::Cast(*value)->Length());
959 EXPECT_TRUE(EvaluateScriptForResultBool("result[0] === 1"));
960 EXPECT_TRUE(EvaluateScriptForResultBool("!result.hasOwnProperty(2)"));
961 });
962 // If a getter makes a property non-enumerable, it should still be enumerated
963 // as enumeration happens once before getters are invoked.
964 RoundTripTest(
965 "(() => {"
966 " var x = [{ get a() {"
967 " Object.defineProperty(x, '1', { value: 3, enumerable: false });"
968 " }}, 2];"
969 " return x;"
970 "})()",
971 [this](Local<Value> value) {
972 ASSERT_TRUE(value->IsArray());
973 ASSERT_EQ(2, Array::Cast(*value)->Length());
974 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 3"));
975 });
976 // Same for sparse arrays.
977 RoundTripTest(
978 "(() => {"
979 " var x = [{ get a() {"
980 " Object.defineProperty(x, '1', { value: 3, enumerable: false });"
981 " }}, 2];"
982 " x.length = 1000;"
983 " return x;"
984 "})()",
985 [this](Local<Value> value) {
986 ASSERT_TRUE(value->IsArray());
987 ASSERT_EQ(1000, Array::Cast(*value)->Length());
988 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 3"));
989 });
990 // Getters on the array itself must also run.
991 RoundTripTest(
992 "(() => {"
993 " var x = [1, 2, 3];"
994 " Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
995 " return x;"
996 "})()",
997 [this](Local<Value> value) {
998 ASSERT_TRUE(value->IsArray());
999 ASSERT_EQ(3, Array::Cast(*value)->Length());
1000 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 4"));
1001 });
1002 // Same for sparse arrays.
1003 RoundTripTest(
1004 "(() => {"
1005 " var x = [1, 2, 3];"
1006 " Object.defineProperty(x, '1', { enumerable: true, get: () => 4 });"
1007 " x.length = 1000;"
1008 " return x;"
1009 "})()",
1010 [this](Local<Value> value) {
1011 ASSERT_TRUE(value->IsArray());
1012 ASSERT_EQ(1000, Array::Cast(*value)->Length());
1013 EXPECT_TRUE(EvaluateScriptForResultBool("result[1] === 4"));
1014 });
1015 // Even with a getter that deletes things, we don't read from the prototype.
1016 RoundTripTest(
1017 "(() => {"
1018 " var x = [{ get a() { delete x[1]; } }, 2];"
1019 " x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
1020 " return x;"
1021 "})()",
1022 [this](Local<Value> value) {
1023 ASSERT_TRUE(value->IsArray());
1024 ASSERT_EQ(2, Array::Cast(*value)->Length());
1025 EXPECT_TRUE(EvaluateScriptForResultBool("!(1 in result)"));
1026 });
1027 // Same for sparse arrays.
1028 RoundTripTest(
1029 "(() => {"
1030 " var x = [{ get a() { delete x[1]; } }, 2];"
1031 " x.__proto__ = Object.create(Array.prototype, { 1: { value: 6 } });"
1032 " x.length = 1000;"
1033 " return x;"
1034 "})()",
1035 [this](Local<Value> value) {
1036 ASSERT_TRUE(value->IsArray());
1037 ASSERT_EQ(1000, Array::Cast(*value)->Length());
1038 EXPECT_TRUE(EvaluateScriptForResultBool("!(1 in result)"));
1039 });
1040 }
1041
1042 } // namespace 710 } // namespace
1043 } // namespace v8 711 } // namespace v8
OLDNEW
« no previous file with comments | « src/value-serializer.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698