Browse Source

deps: V8: backport e560815 from upstream

Original commit message:
  [runtime] Fix Array.prototype.concat with complex @@species
  Array.prototype.concat does not properly handle JSProxy species that will
  modify the currently visited array.

  BUG=682194

  Review-Url: https://codereview.chromium.org/2655623004
  Cr-Commit-Position: refs/heads/master@{#42640}

Refs: https://github.com/nodejs/node/pull/12779

PR-URL: https://github.com/nodejs/node/pull/16133
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
v6.x-staging
Ali Ijaz Sheikh 7 years ago
committed by Myles Borins
parent
commit
f35071b39c
No known key found for this signature in database GPG Key ID: 933B01F40B5CA946
  1. 25
      deps/v8/src/builtins.cc
  2. 35
      deps/v8/test/mjsunit/regress/regress-crbug-682194.js

25
deps/v8/src/builtins.cc

@ -795,14 +795,18 @@ namespace {
*/
class ArrayConcatVisitor {
public:
ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
ArrayConcatVisitor(Isolate* isolate, Handle<HeapObject> storage,
bool fast_elements)
: isolate_(isolate),
storage_(isolate->global_handles()->Create(*storage)),
index_offset_(0u),
bit_field_(FastElementsField::encode(fast_elements) |
bit_field_(
FastElementsField::encode(fast_elements) |
ExceedsLimitField::encode(false) |
IsFixedArrayField::encode(storage->IsFixedArray())) {
IsFixedArrayField::encode(storage->IsFixedArray()) |
HasSimpleElementsField::encode(storage->IsFixedArray() ||
storage->map()->instance_type() >
LAST_CUSTOM_ELEMENTS_RECEIVER)) {
DCHECK(!(this->fast_elements() && !is_fixed_array()));
}
@ -891,12 +895,16 @@ class ArrayConcatVisitor {
// (otherwise)
Handle<FixedArray> storage_fixed_array() {
DCHECK(is_fixed_array());
DCHECK(has_simple_elements());
return Handle<FixedArray>::cast(storage_);
}
Handle<JSReceiver> storage_jsreceiver() {
DCHECK(!is_fixed_array());
return Handle<JSReceiver>::cast(storage_);
}
bool has_simple_elements() const {
return HasSimpleElementsField::decode(bit_field_);
}
private:
// Convert storage to dictionary mode.
@ -929,12 +937,14 @@ class ArrayConcatVisitor {
inline void set_storage(FixedArray* storage) {
DCHECK(is_fixed_array());
DCHECK(has_simple_elements());
storage_ = isolate_->global_handles()->Create(storage);
}
class FastElementsField : public BitField<bool, 0, 1> {};
class ExceedsLimitField : public BitField<bool, 1, 1> {};
class IsFixedArrayField : public BitField<bool, 2, 1> {};
class HasSimpleElementsField : public BitField<bool, 3, 1> {};
bool fast_elements() const { return FastElementsField::decode(bit_field_); }
void set_fast_elements(bool fast) {
@ -1166,8 +1176,6 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
visitor->increase_index_offset(length);
return true;
}
/**
* A helper function that visits "array" elements of a JSReceiver in numerical
* order.
@ -1201,7 +1209,8 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
return IterateElementsSlow(isolate, receiver, length, visitor);
}
if (!HasOnlySimpleElements(isolate, *receiver)) {
if (!HasOnlySimpleElements(isolate, *receiver) ||
!visitor->has_simple_elements()) {
return IterateElementsSlow(isolate, receiver, length, visitor);
}
Handle<JSObject> array = Handle<JSObject>::cast(receiver);
@ -1476,7 +1485,7 @@ Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
// In case of failure, fall through.
}
Handle<Object> storage;
Handle<HeapObject> storage;
if (fast_case) {
// The backing storage array must have non-existing elements to preserve
// holes across concat operations.
@ -1494,7 +1503,7 @@ Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, storage_object,
Execution::New(isolate, species, species, 1, &length));
storage = storage_object;
storage = Handle<HeapObject>::cast(storage_object);
}
ArrayConcatVisitor visitor(isolate, storage, fast_case);

35
deps/v8/test/mjsunit/regress/regress-crbug-682194.js

@ -0,0 +1,35 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-gc
var proxy = new Proxy([], {
defineProperty() {
w.length = 1; // shorten the array so the backstore pointer is relocated
gc(); // force gc to move the array's elements backstore
return Object.defineProperty.apply(this, arguments);
}
});
class MyArray extends Array {
// custom constructor which returns a proxy object
static get[Symbol.species](){
return function() {
return proxy;
}
};
}
var w = new MyArray(100);
w[1] = 0.1;
w[2] = 0.1;
var result = Array.prototype.concat.call(w);
assertEquals(undefined, result[0]);
assertEquals(0.1, result[1]);
for (var i = 2; i < 200; i++) {
assertEquals(undefined, result[i]);
}
Loading…
Cancel
Save