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

Side by Side Diff: src/builtins.cc

Issue 1525983002: [proxies] Make Array.prototype.concat work correctly with proxies. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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 | « no previous file | src/js/runtime.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/builtins.h" 5 #include "src/builtins.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 PrototypeIterator iter(isolate, object); 922 PrototypeIterator iter(isolate, object);
923 if (!iter.IsAtEnd()) { 923 if (!iter.IsAtEnd()) {
924 // The prototype will usually have no inherited element indices, 924 // The prototype will usually have no inherited element indices,
925 // but we have to check. 925 // but we have to check.
926 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range, 926 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
927 indices); 927 indices);
928 } 928 }
929 } 929 }
930 930
931 931
932 bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver, 932 bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
933 uint32_t length, ArrayConcatVisitor* visitor) { 933 uint32_t length, ArrayConcatVisitor* visitor) {
934 for (uint32_t i = 0; i < length; ++i) { 934 for (uint32_t i = 0; i < length; ++i) {
935 HandleScope loop_scope(isolate); 935 HandleScope loop_scope(isolate);
936 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); 936 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
937 if (!maybe.IsJust()) return false; 937 if (!maybe.IsJust()) return false;
938 if (maybe.FromJust()) { 938 if (maybe.FromJust()) {
939 Handle<Object> element_value; 939 Handle<Object> element_value;
940 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, 940 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value,
941 Object::GetElement(isolate, receiver, i), 941 Object::GetElement(isolate, receiver, i),
942 false); 942 false);
943 visitor->visit(i, element_value); 943 visitor->visit(i, element_value);
944 } 944 }
945 } 945 }
946 visitor->increase_index_offset(length); 946 visitor->increase_index_offset(length);
947 return true; 947 return true;
948 } 948 }
949 949
950 950
951 /** 951 /**
952 * A helper function that visits elements of a JSObject in numerical 952 * A helper function that visits "array" elements of a JSReceiver in numerical
953 * order. 953 * order.
954 * 954 *
955 * The visitor argument called for each existing element in the array 955 * The visitor argument called for each existing element in the array
956 * with the element index and the element's value. 956 * with the element index and the element's value.
957 * Afterwards it increments the base-index of the visitor by the array 957 * Afterwards it increments the base-index of the visitor by the array
958 * length. 958 * length.
959 * Returns false if any access threw an exception, otherwise true. 959 * Returns false if any access threw an exception, otherwise true.
960 */ 960 */
961 bool IterateElements(Isolate* isolate, Handle<JSObject> receiver, 961 bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
962 ArrayConcatVisitor* visitor) { 962 ArrayConcatVisitor* visitor) {
963 uint32_t length = 0; 963 uint32_t length = 0;
964 964
965 if (receiver->IsJSArray()) { 965 if (receiver->IsJSArray()) {
966 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 966 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
967 length = static_cast<uint32_t>(array->length()->Number()); 967 length = static_cast<uint32_t>(array->length()->Number());
968 } else { 968 } else {
969 Handle<Object> val; 969 Handle<Object> val;
970 Handle<Object> key = isolate->factory()->length_string(); 970 Handle<Object> key = isolate->factory()->length_string();
971 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 971 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
972 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key), 972 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
973 false); 973 false);
974 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val, 974 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
975 Object::ToLength(isolate, val), false); 975 Object::ToLength(isolate, val), false);
976 // TODO(caitp): Support larger element indexes (up to 2^53-1). 976 // TODO(caitp): Support larger element indexes (up to 2^53-1).
977 if (!val->ToUint32(&length)) { 977 if (!val->ToUint32(&length)) {
978 length = 0; 978 length = 0;
979 } 979 }
980 } 980 }
981 981
982 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) { 982 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) {
983 // For classes which are not known to be safe to access via elements alone, 983 // For classes which are not known to be safe to access via elements alone,
984 // use the slow case. 984 // use the slow case.
985 return IterateElementsSlow(isolate, receiver, length, visitor); 985 return IterateElementsSlow(isolate, receiver, length, visitor);
986 } 986 }
987 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
987 988
988 switch (receiver->GetElementsKind()) { 989 switch (array->GetElementsKind()) {
989 case FAST_SMI_ELEMENTS: 990 case FAST_SMI_ELEMENTS:
990 case FAST_ELEMENTS: 991 case FAST_ELEMENTS:
991 case FAST_HOLEY_SMI_ELEMENTS: 992 case FAST_HOLEY_SMI_ELEMENTS:
992 case FAST_HOLEY_ELEMENTS: { 993 case FAST_HOLEY_ELEMENTS: {
993 // Run through the elements FixedArray and use HasElement and GetElement 994 // Run through the elements FixedArray and use HasElement and GetElement
994 // to check the prototype for missing elements. 995 // to check the prototype for missing elements.
995 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); 996 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
996 int fast_length = static_cast<int>(length); 997 int fast_length = static_cast<int>(length);
997 DCHECK(fast_length <= elements->length()); 998 DCHECK(fast_length <= elements->length());
998 for (int j = 0; j < fast_length; j++) { 999 for (int j = 0; j < fast_length; j++) {
999 HandleScope loop_scope(isolate); 1000 HandleScope loop_scope(isolate);
1000 Handle<Object> element_value(elements->get(j), isolate); 1001 Handle<Object> element_value(elements->get(j), isolate);
1001 if (!element_value->IsTheHole()) { 1002 if (!element_value->IsTheHole()) {
1002 visitor->visit(j, element_value); 1003 visitor->visit(j, element_value);
1003 } else { 1004 } else {
1004 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); 1005 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1005 if (!maybe.IsJust()) return false; 1006 if (!maybe.IsJust()) return false;
1006 if (maybe.FromJust()) { 1007 if (maybe.FromJust()) {
1007 // Call GetElement on receiver, not its prototype, or getters won't 1008 // Call GetElement on array, not its prototype, or getters won't
1008 // have the correct receiver. 1009 // have the correct receiver.
1009 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1010 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1010 isolate, element_value, 1011 isolate, element_value, Object::GetElement(isolate, array, j),
1011 Object::GetElement(isolate, receiver, j), false); 1012 false);
1012 visitor->visit(j, element_value); 1013 visitor->visit(j, element_value);
1013 } 1014 }
1014 } 1015 }
1015 } 1016 }
1016 break; 1017 break;
1017 } 1018 }
1018 case FAST_HOLEY_DOUBLE_ELEMENTS: 1019 case FAST_HOLEY_DOUBLE_ELEMENTS:
1019 case FAST_DOUBLE_ELEMENTS: { 1020 case FAST_DOUBLE_ELEMENTS: {
1020 // Empty array is FixedArray but not FixedDoubleArray. 1021 // Empty array is FixedArray but not FixedDoubleArray.
1021 if (length == 0) break; 1022 if (length == 0) break;
1022 // Run through the elements FixedArray and use HasElement and GetElement 1023 // Run through the elements FixedArray and use HasElement and GetElement
1023 // to check the prototype for missing elements. 1024 // to check the prototype for missing elements.
1024 if (receiver->elements()->IsFixedArray()) { 1025 if (array->elements()->IsFixedArray()) {
1025 DCHECK(receiver->elements()->length() == 0); 1026 DCHECK(array->elements()->length() == 0);
1026 break; 1027 break;
1027 } 1028 }
1028 Handle<FixedDoubleArray> elements( 1029 Handle<FixedDoubleArray> elements(
1029 FixedDoubleArray::cast(receiver->elements())); 1030 FixedDoubleArray::cast(array->elements()));
1030 int fast_length = static_cast<int>(length); 1031 int fast_length = static_cast<int>(length);
1031 DCHECK(fast_length <= elements->length()); 1032 DCHECK(fast_length <= elements->length());
1032 for (int j = 0; j < fast_length; j++) { 1033 for (int j = 0; j < fast_length; j++) {
1033 HandleScope loop_scope(isolate); 1034 HandleScope loop_scope(isolate);
1034 if (!elements->is_the_hole(j)) { 1035 if (!elements->is_the_hole(j)) {
1035 double double_value = elements->get_scalar(j); 1036 double double_value = elements->get_scalar(j);
1036 Handle<Object> element_value = 1037 Handle<Object> element_value =
1037 isolate->factory()->NewNumber(double_value); 1038 isolate->factory()->NewNumber(double_value);
1038 visitor->visit(j, element_value); 1039 visitor->visit(j, element_value);
1039 } else { 1040 } else {
1040 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); 1041 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1041 if (!maybe.IsJust()) return false; 1042 if (!maybe.IsJust()) return false;
1042 if (maybe.FromJust()) { 1043 if (maybe.FromJust()) {
1043 // Call GetElement on receiver, not its prototype, or getters won't 1044 // Call GetElement on array, not its prototype, or getters won't
1044 // have the correct receiver. 1045 // have the correct receiver.
1045 Handle<Object> element_value; 1046 Handle<Object> element_value;
1046 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1047 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1047 isolate, element_value, 1048 isolate, element_value, Object::GetElement(isolate, array, j),
1048 Object::GetElement(isolate, receiver, j), false); 1049 false);
1049 visitor->visit(j, element_value); 1050 visitor->visit(j, element_value);
1050 } 1051 }
1051 } 1052 }
1052 } 1053 }
1053 break; 1054 break;
1054 } 1055 }
1055 case DICTIONARY_ELEMENTS: { 1056 case DICTIONARY_ELEMENTS: {
1056 // CollectElementIndices() can't be called when there's a JSProxy 1057 // CollectElementIndices() can't be called when there's a JSProxy
1057 // on the prototype chain. 1058 // on the prototype chain.
1058 for (PrototypeIterator iter(isolate, receiver); !iter.IsAtEnd(); 1059 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
1059 iter.Advance()) { 1060 iter.Advance()) {
1060 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 1061 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1061 return IterateElementsSlow(isolate, receiver, length, visitor); 1062 return IterateElementsSlow(isolate, array, length, visitor);
1062 } 1063 }
1063 } 1064 }
1064 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); 1065 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1065 List<uint32_t> indices(dict->Capacity() / 2); 1066 List<uint32_t> indices(dict->Capacity() / 2);
1066 // Collect all indices in the object and the prototypes less 1067 // Collect all indices in the object and the prototypes less
1067 // than length. This might introduce duplicates in the indices list. 1068 // than length. This might introduce duplicates in the indices list.
1068 CollectElementIndices(receiver, length, &indices); 1069 CollectElementIndices(array, length, &indices);
1069 indices.Sort(&compareUInt32); 1070 indices.Sort(&compareUInt32);
1070 int j = 0; 1071 int j = 0;
1071 int n = indices.length(); 1072 int n = indices.length();
1072 while (j < n) { 1073 while (j < n) {
1073 HandleScope loop_scope(isolate); 1074 HandleScope loop_scope(isolate);
1074 uint32_t index = indices[j]; 1075 uint32_t index = indices[j];
1075 Handle<Object> element; 1076 Handle<Object> element;
1076 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1077 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1077 isolate, element, Object::GetElement(isolate, receiver, index), 1078 isolate, element, Object::GetElement(isolate, array, index), false);
1078 false);
1079 visitor->visit(index, element); 1079 visitor->visit(index, element);
1080 // Skip to next different index (i.e., omit duplicates). 1080 // Skip to next different index (i.e., omit duplicates).
1081 do { 1081 do {
1082 j++; 1082 j++;
1083 } while (j < n && indices[j] == index); 1083 } while (j < n && indices[j] == index);
1084 } 1084 }
1085 break; 1085 break;
1086 } 1086 }
1087 case UINT8_CLAMPED_ELEMENTS: { 1087 case UINT8_CLAMPED_ELEMENTS: {
1088 Handle<FixedUint8ClampedArray> pixels( 1088 Handle<FixedUint8ClampedArray> pixels(
1089 FixedUint8ClampedArray::cast(receiver->elements())); 1089 FixedUint8ClampedArray::cast(array->elements()));
1090 for (uint32_t j = 0; j < length; j++) { 1090 for (uint32_t j = 0; j < length; j++) {
1091 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); 1091 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
1092 visitor->visit(j, e); 1092 visitor->visit(j, e);
1093 } 1093 }
1094 break; 1094 break;
1095 } 1095 }
1096 case INT8_ELEMENTS: { 1096 case INT8_ELEMENTS: {
1097 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, receiver, true, 1097 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true,
1098 true, visitor); 1098 true, visitor);
1099 break; 1099 break;
1100 } 1100 }
1101 case UINT8_ELEMENTS: { 1101 case UINT8_ELEMENTS: {
1102 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, receiver, 1102 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true,
1103 true, true, visitor); 1103 true, visitor);
1104 break; 1104 break;
1105 } 1105 }
1106 case INT16_ELEMENTS: { 1106 case INT16_ELEMENTS: {
1107 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, receiver, 1107 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true,
1108 true, true, visitor); 1108 true, visitor);
1109 break; 1109 break;
1110 } 1110 }
1111 case UINT16_ELEMENTS: { 1111 case UINT16_ELEMENTS: {
1112 IterateTypedArrayElements<FixedUint16Array, uint16_t>( 1112 IterateTypedArrayElements<FixedUint16Array, uint16_t>(
1113 isolate, receiver, true, true, visitor); 1113 isolate, array, true, true, visitor);
1114 break; 1114 break;
1115 } 1115 }
1116 case INT32_ELEMENTS: { 1116 case INT32_ELEMENTS: {
1117 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, receiver, 1117 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true,
1118 true, false, visitor); 1118 false, visitor);
1119 break; 1119 break;
1120 } 1120 }
1121 case UINT32_ELEMENTS: { 1121 case UINT32_ELEMENTS: {
1122 IterateTypedArrayElements<FixedUint32Array, uint32_t>( 1122 IterateTypedArrayElements<FixedUint32Array, uint32_t>(
1123 isolate, receiver, true, false, visitor); 1123 isolate, array, true, false, visitor);
1124 break; 1124 break;
1125 } 1125 }
1126 case FLOAT32_ELEMENTS: { 1126 case FLOAT32_ELEMENTS: {
1127 IterateTypedArrayElements<FixedFloat32Array, float>( 1127 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false,
1128 isolate, receiver, false, false, visitor); 1128 false, visitor);
1129 break; 1129 break;
1130 } 1130 }
1131 case FLOAT64_ELEMENTS: { 1131 case FLOAT64_ELEMENTS: {
1132 IterateTypedArrayElements<FixedFloat64Array, double>( 1132 IterateTypedArrayElements<FixedFloat64Array, double>(
1133 isolate, receiver, false, false, visitor); 1133 isolate, array, false, false, visitor);
1134 break; 1134 break;
1135 } 1135 }
1136 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 1136 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1137 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 1137 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1138 for (uint32_t index = 0; index < length; index++) { 1138 for (uint32_t index = 0; index < length; index++) {
1139 HandleScope loop_scope(isolate); 1139 HandleScope loop_scope(isolate);
1140 Handle<Object> element; 1140 Handle<Object> element;
1141 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1141 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1142 isolate, element, Object::GetElement(isolate, receiver, index), 1142 isolate, element, Object::GetElement(isolate, array, index), false);
1143 false);
1144 visitor->visit(index, element); 1143 visitor->visit(index, element);
1145 } 1144 }
1146 break; 1145 break;
1147 } 1146 }
1148 } 1147 }
1149 visitor->increase_index_offset(length); 1148 visitor->increase_index_offset(length);
1150 return true; 1149 return true;
1151 } 1150 }
1152 1151
1153 1152
1154 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { 1153 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1154 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
1155 if (!FLAG_harmony_concat_spreadable) return false; 1155 if (!FLAG_harmony_concat_spreadable) return false;
1156 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1156 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1157 Maybe<bool> maybe = 1157 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1158 JSReceiver::HasProperty(Handle<JSReceiver>::cast(obj), key); 1158 return maybe.FromMaybe(false);
1159 if (!maybe.IsJust()) return false;
1160 return maybe.FromJust();
1161 } 1159 }
1162 1160
1163 1161
1164 bool IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) { 1162 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1165 HandleScope handle_scope(isolate); 1163 HandleScope handle_scope(isolate);
1166 if (!obj->IsJSReceiver()) return false; 1164 if (!obj->IsJSReceiver()) return Just(false);
1167 if (FLAG_harmony_concat_spreadable) { 1165 if (FLAG_harmony_concat_spreadable) {
1168 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol()); 1166 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1169 Handle<Object> value; 1167 Handle<Object> value;
1170 MaybeHandle<Object> maybeValue = 1168 MaybeHandle<Object> maybeValue =
1171 i::Runtime::GetObjectProperty(isolate, obj, key); 1169 i::Runtime::GetObjectProperty(isolate, obj, key);
1172 if (maybeValue.ToHandle(&value) && !value->IsUndefined()) { 1170 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1173 return value->BooleanValue(); 1171 if (!value->IsUndefined()) return Just(value->BooleanValue());
1174 }
1175 } 1172 }
1176 return obj->IsJSArray(); 1173 return Object::IsArray(obj);
1177 } 1174 }
1178 1175
1179 1176
1180 /**
1181 * Array::concat implementation.
1182 * See ECMAScript 262, 15.4.4.4.
1183 * TODO(581): Fix non-compliance for very large concatenations and update to
1184 * following the ECMAScript 5 specification.
1185 */
1186 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { 1177 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1187 int argument_count = args->length(); 1178 int argument_count = args->length();
1188 1179
1189 // Pass 1: estimate the length and number of elements of the result. 1180 // Pass 1: estimate the length and number of elements of the result.
1190 // The actual length can be larger if any of the arguments have getters 1181 // The actual length can be larger if any of the arguments have getters
1191 // that mutate other arguments (but will otherwise be precise). 1182 // that mutate other arguments (but will otherwise be precise).
1192 // The number of elements is precise if there are no inherited elements. 1183 // The number of elements is precise if there are no inherited elements.
1193 1184
1194 ElementsKind kind = FAST_SMI_ELEMENTS; 1185 ElementsKind kind = FAST_SMI_ELEMENTS;
1195 1186
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 uint32_t at_least_space_for = 1322 uint32_t at_least_space_for =
1332 estimate_nof_elements + (estimate_nof_elements >> 2); 1323 estimate_nof_elements + (estimate_nof_elements >> 2);
1333 storage = Handle<FixedArray>::cast( 1324 storage = Handle<FixedArray>::cast(
1334 SeededNumberDictionary::New(isolate, at_least_space_for)); 1325 SeededNumberDictionary::New(isolate, at_least_space_for));
1335 } 1326 }
1336 1327
1337 ArrayConcatVisitor visitor(isolate, storage, fast_case); 1328 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1338 1329
1339 for (int i = 0; i < argument_count; i++) { 1330 for (int i = 0; i < argument_count; i++) {
1340 Handle<Object> obj((*args)[i], isolate); 1331 Handle<Object> obj((*args)[i], isolate);
1341 bool spreadable = IsConcatSpreadable(isolate, obj); 1332 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1342 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1333 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1343 if (spreadable) { 1334 if (spreadable.FromJust()) {
1344 Handle<JSObject> object = Handle<JSObject>::cast(obj); 1335 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1345 if (!IterateElements(isolate, object, &visitor)) { 1336 if (!IterateElements(isolate, object, &visitor)) {
1346 return isolate->heap()->exception(); 1337 return isolate->heap()->exception();
1347 } 1338 }
1348 } else { 1339 } else {
1349 visitor.visit(0, obj); 1340 visitor.visit(0, obj);
1350 visitor.increase_index_offset(1); 1341 visitor.increase_index_offset(1);
1351 } 1342 }
1352 } 1343 }
1353 1344
1354 if (visitor.exceeds_array_limit()) { 1345 if (visitor.exceeds_array_limit()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 NewRangeError(MessageTemplate::kInvalidArrayLength), 1385 NewRangeError(MessageTemplate::kInvalidArrayLength),
1395 JSArray); 1386 JSArray);
1396 } 1387 }
1397 } 1388 }
1398 } 1389 }
1399 return ElementsAccessor::Concat(isolate, args, n_arguments); 1390 return ElementsAccessor::Concat(isolate, args, n_arguments);
1400 } 1391 }
1401 1392
1402 } // namespace 1393 } // namespace
1403 1394
1395 // ES6 22.1.3.1 Array.prototype.concat
1404 BUILTIN(ArrayConcat) { 1396 BUILTIN(ArrayConcat) {
1405 HandleScope scope(isolate); 1397 HandleScope scope(isolate);
1406 1398
1407 Handle<Object> receiver; 1399 Handle<Object> receiver;
1408 if (!Object::ToObject(isolate, handle(args[0], isolate)) 1400 if (!Object::ToObject(isolate, handle(args[0], isolate))
1409 .ToHandle(&receiver)) { 1401 .ToHandle(&receiver)) {
1410 THROW_NEW_ERROR_RETURN_FAILURE( 1402 THROW_NEW_ERROR_RETURN_FAILURE(
1411 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, 1403 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1412 isolate->factory()->NewStringFromAsciiChecked( 1404 isolate->factory()->NewStringFromAsciiChecked(
1413 "Array.prototype.concat"))); 1405 "Array.prototype.concat")));
1414 } 1406 }
1415 args[0] = *receiver; 1407 args[0] = *receiver;
1416 1408
1417 Handle<JSArray> result_array; 1409 Handle<JSArray> result_array;
1418 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { 1410 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1419 return *result_array; 1411 return *result_array;
1420 } 1412 }
1421 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1413 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1422 return Slow_ArrayConcat(&args, isolate); 1414 return Slow_ArrayConcat(&args, isolate);
1423 } 1415 }
1424 1416
1425 1417
1426 // ES6 section 22.1.2.2 Array.isArray 1418 // ES6 22.1.2.2 Array.isArray
1427 BUILTIN(ArrayIsArray) { 1419 BUILTIN(ArrayIsArray) {
1428 HandleScope scope(isolate); 1420 HandleScope scope(isolate);
1429 DCHECK_EQ(2, args.length()); 1421 DCHECK_EQ(2, args.length());
1430 Handle<Object> object = args.at<Object>(1); 1422 Handle<Object> object = args.at<Object>(1);
1431 Maybe<bool> result = Object::IsArray(object); 1423 Maybe<bool> result = Object::IsArray(object);
1432 MAYBE_RETURN(result, isolate->heap()->exception()); 1424 MAYBE_RETURN(result, isolate->heap()->exception());
1433 return *isolate->factory()->ToBoolean(result.FromJust()); 1425 return *isolate->factory()->ToBoolean(result.FromJust());
1434 } 1426 }
1435 1427
1436 1428
(...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after
2514 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 2506 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
2515 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 2507 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
2516 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 2508 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
2517 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 2509 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
2518 #undef DEFINE_BUILTIN_ACCESSOR_C 2510 #undef DEFINE_BUILTIN_ACCESSOR_C
2519 #undef DEFINE_BUILTIN_ACCESSOR_A 2511 #undef DEFINE_BUILTIN_ACCESSOR_A
2520 2512
2521 2513
2522 } // namespace internal 2514 } // namespace internal
2523 } // namespace v8 2515 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/js/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698