Skip to content

Commit

Permalink
deps: cherry-pick e560815 from upstream v8
Browse files Browse the repository at this point in the history
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}

PR-URL: #12779
Reviewed-By: bnoordhuis - Ben Noordhuis <[email protected]>
Reviewed-By: targos - Michaël Zasso <[email protected]>
Reviewed-By: jasnell - James M Snell <[email protected]>
Reviewed-By: mhdawson - Michael Dawson <[email protected]>
  • Loading branch information
ofrobots committed May 12, 2017
1 parent 69a8053 commit 57c0e71
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
2 changes: 1 addition & 1 deletion deps/v8/include/v8-version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 5
#define V8_MINOR_VERSION 5
#define V8_BUILD_NUMBER 372
#define V8_PATCH_LEVEL 43
#define V8_PATCH_LEVEL 44

// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Expand Down
26 changes: 18 additions & 8 deletions deps/v8/src/builtins/builtins-array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,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) |
ExceedsLimitField::encode(false) |
IsFixedArrayField::encode(storage->IsFixedArray())) {
bit_field_(
FastElementsField::encode(fast_elements) |
ExceedsLimitField::encode(false) |
IsFixedArrayField::encode(storage->IsFixedArray()) |
HasSimpleElementsField::encode(storage->IsFixedArray() ||
storage->map()->instance_type() >
LAST_CUSTOM_ELEMENTS_RECEIVER)) {
DCHECK(!(this->fast_elements() && !is_fixed_array()));
}

Expand Down Expand Up @@ -503,12 +507,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.
Expand Down Expand Up @@ -541,12 +549,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) {
Expand Down Expand Up @@ -772,7 +782,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.
Expand Down Expand Up @@ -802,7 +811,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);
Expand Down Expand Up @@ -1071,7 +1081,7 @@ Object* Slow_ArrayConcat(BuiltinArguments* 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.
Expand All @@ -1089,7 +1099,7 @@ Object* Slow_ArrayConcat(BuiltinArguments* 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);
Expand Down
35 changes: 35 additions & 0 deletions deps/v8/test/mjsunit/regress/regress-crbug-682194.js
Original file line number Diff line number Diff line change
@@ -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]);
}

0 comments on commit 57c0e71

Please sign in to comment.