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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/js/runtime.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins.cc
diff --git a/src/builtins.cc b/src/builtins.cc
index dba56372e469814cb5c4652ef01e1d5d660918ee..805537448a6468d10659b611e4ea6f5a987409fd 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -929,7 +929,7 @@ void CollectElementIndices(Handle<JSObject> object, uint32_t range,
}
-bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver,
+bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
uint32_t length, ArrayConcatVisitor* visitor) {
for (uint32_t i = 0; i < length; ++i) {
HandleScope loop_scope(isolate);
@@ -949,7 +949,7 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver,
/**
- * A helper function that visits elements of a JSObject in numerical
+ * A helper function that visits "array" elements of a JSReceiver in numerical
* order.
*
* The visitor argument called for each existing element in the array
@@ -958,7 +958,7 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSObject> receiver,
* length.
* Returns false if any access threw an exception, otherwise true.
*/
-bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
+bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
ArrayConcatVisitor* visitor) {
uint32_t length = 0;
@@ -984,15 +984,16 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
// use the slow case.
return IterateElementsSlow(isolate, receiver, length, visitor);
}
+ Handle<JSObject> array = Handle<JSObject>::cast(receiver);
- switch (receiver->GetElementsKind()) {
+ switch (array->GetElementsKind()) {
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS: {
// Run through the elements FixedArray and use HasElement and GetElement
// to check the prototype for missing elements.
- Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
+ Handle<FixedArray> elements(FixedArray::cast(array->elements()));
int fast_length = static_cast<int>(length);
DCHECK(fast_length <= elements->length());
for (int j = 0; j < fast_length; j++) {
@@ -1001,14 +1002,14 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
if (!element_value->IsTheHole()) {
visitor->visit(j, element_value);
} else {
- Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
+ Maybe<bool> maybe = JSReceiver::HasElement(array, j);
if (!maybe.IsJust()) return false;
if (maybe.FromJust()) {
- // Call GetElement on receiver, not its prototype, or getters won't
+ // Call GetElement on array, not its prototype, or getters won't
// have the correct receiver.
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, element_value,
- Object::GetElement(isolate, receiver, j), false);
+ isolate, element_value, Object::GetElement(isolate, array, j),
+ false);
visitor->visit(j, element_value);
}
}
@@ -1021,12 +1022,12 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
if (length == 0) break;
// Run through the elements FixedArray and use HasElement and GetElement
// to check the prototype for missing elements.
- if (receiver->elements()->IsFixedArray()) {
- DCHECK(receiver->elements()->length() == 0);
+ if (array->elements()->IsFixedArray()) {
+ DCHECK(array->elements()->length() == 0);
break;
}
Handle<FixedDoubleArray> elements(
- FixedDoubleArray::cast(receiver->elements()));
+ FixedDoubleArray::cast(array->elements()));
int fast_length = static_cast<int>(length);
DCHECK(fast_length <= elements->length());
for (int j = 0; j < fast_length; j++) {
@@ -1037,15 +1038,15 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
isolate->factory()->NewNumber(double_value);
visitor->visit(j, element_value);
} else {
- Maybe<bool> maybe = JSReceiver::HasElement(receiver, j);
+ Maybe<bool> maybe = JSReceiver::HasElement(array, j);
if (!maybe.IsJust()) return false;
if (maybe.FromJust()) {
- // Call GetElement on receiver, not its prototype, or getters won't
+ // Call GetElement on array, not its prototype, or getters won't
// have the correct receiver.
Handle<Object> element_value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, element_value,
- Object::GetElement(isolate, receiver, j), false);
+ isolate, element_value, Object::GetElement(isolate, array, j),
+ false);
visitor->visit(j, element_value);
}
}
@@ -1055,17 +1056,17 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
case DICTIONARY_ELEMENTS: {
// CollectElementIndices() can't be called when there's a JSProxy
// on the prototype chain.
- for (PrototypeIterator iter(isolate, receiver); !iter.IsAtEnd();
+ for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
iter.Advance()) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
- return IterateElementsSlow(isolate, receiver, length, visitor);
+ return IterateElementsSlow(isolate, array, length, visitor);
}
}
- Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
+ Handle<SeededNumberDictionary> dict(array->element_dictionary());
List<uint32_t> indices(dict->Capacity() / 2);
// Collect all indices in the object and the prototypes less
// than length. This might introduce duplicates in the indices list.
- CollectElementIndices(receiver, length, &indices);
+ CollectElementIndices(array, length, &indices);
indices.Sort(&compareUInt32);
int j = 0;
int n = indices.length();
@@ -1074,8 +1075,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
uint32_t index = indices[j];
Handle<Object> element;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, element, Object::GetElement(isolate, receiver, index),
- false);
+ isolate, element, Object::GetElement(isolate, array, index), false);
visitor->visit(index, element);
// Skip to next different index (i.e., omit duplicates).
do {
@@ -1086,7 +1086,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
}
case UINT8_CLAMPED_ELEMENTS: {
Handle<FixedUint8ClampedArray> pixels(
- FixedUint8ClampedArray::cast(receiver->elements()));
+ FixedUint8ClampedArray::cast(array->elements()));
for (uint32_t j = 0; j < length; j++) {
Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
visitor->visit(j, e);
@@ -1094,43 +1094,43 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
break;
}
case INT8_ELEMENTS: {
- IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, receiver, true,
+ IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true,
true, visitor);
break;
}
case UINT8_ELEMENTS: {
- IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, receiver,
- true, true, visitor);
+ IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true,
+ true, visitor);
break;
}
case INT16_ELEMENTS: {
- IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, receiver,
- true, true, visitor);
+ IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true,
+ true, visitor);
break;
}
case UINT16_ELEMENTS: {
IterateTypedArrayElements<FixedUint16Array, uint16_t>(
- isolate, receiver, true, true, visitor);
+ isolate, array, true, true, visitor);
break;
}
case INT32_ELEMENTS: {
- IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, receiver,
- true, false, visitor);
+ IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true,
+ false, visitor);
break;
}
case UINT32_ELEMENTS: {
IterateTypedArrayElements<FixedUint32Array, uint32_t>(
- isolate, receiver, true, false, visitor);
+ isolate, array, true, false, visitor);
break;
}
case FLOAT32_ELEMENTS: {
- IterateTypedArrayElements<FixedFloat32Array, float>(
- isolate, receiver, false, false, visitor);
+ IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false,
+ false, visitor);
break;
}
case FLOAT64_ELEMENTS: {
IterateTypedArrayElements<FixedFloat64Array, double>(
- isolate, receiver, false, false, visitor);
+ isolate, array, false, false, visitor);
break;
}
case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
@@ -1139,8 +1139,7 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
HandleScope loop_scope(isolate);
Handle<Object> element;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
- isolate, element, Object::GetElement(isolate, receiver, index),
- false);
+ isolate, element, Object::GetElement(isolate, array, index), false);
visitor->visit(index, element);
}
break;
@@ -1152,37 +1151,29 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
+ DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
if (!FLAG_harmony_concat_spreadable) return false;
Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
- Maybe<bool> maybe =
- JSReceiver::HasProperty(Handle<JSReceiver>::cast(obj), key);
- if (!maybe.IsJust()) return false;
- return maybe.FromJust();
+ Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
+ return maybe.FromMaybe(false);
}
-bool IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
+static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
HandleScope handle_scope(isolate);
- if (!obj->IsJSReceiver()) return false;
+ if (!obj->IsJSReceiver()) return Just(false);
if (FLAG_harmony_concat_spreadable) {
Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
Handle<Object> value;
MaybeHandle<Object> maybeValue =
i::Runtime::GetObjectProperty(isolate, obj, key);
- if (maybeValue.ToHandle(&value) && !value->IsUndefined()) {
- return value->BooleanValue();
- }
+ if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
+ if (!value->IsUndefined()) return Just(value->BooleanValue());
}
- return obj->IsJSArray();
+ return Object::IsArray(obj);
}
-/**
- * Array::concat implementation.
- * See ECMAScript 262, 15.4.4.4.
- * TODO(581): Fix non-compliance for very large concatenations and update to
- * following the ECMAScript 5 specification.
- */
Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
int argument_count = args->length();
@@ -1338,10 +1329,10 @@ Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
for (int i = 0; i < argument_count; i++) {
Handle<Object> obj((*args)[i], isolate);
- bool spreadable = IsConcatSpreadable(isolate, obj);
- if (isolate->has_pending_exception()) return isolate->heap()->exception();
- if (spreadable) {
- Handle<JSObject> object = Handle<JSObject>::cast(obj);
+ Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
+ MAYBE_RETURN(spreadable, isolate->heap()->exception());
+ if (spreadable.FromJust()) {
+ Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
if (!IterateElements(isolate, object, &visitor)) {
return isolate->heap()->exception();
}
@@ -1401,6 +1392,7 @@ MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
} // namespace
+// ES6 22.1.3.1 Array.prototype.concat
BUILTIN(ArrayConcat) {
HandleScope scope(isolate);
@@ -1423,7 +1415,7 @@ BUILTIN(ArrayConcat) {
}
-// ES6 section 22.1.2.2 Array.isArray
+// ES6 22.1.2.2 Array.isArray
BUILTIN(ArrayIsArray) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
« 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