From 2e0d55a5b9a31296956d029896e6d47a8c1605c9 Mon Sep 17 00:00:00 2001 From: yangguo Date: Thu, 6 Aug 2015 03:28:29 -0700 Subject: [PATCH] Fix Array.prototype.concat for arguments object with getter. R=adamk@chromium.org BUG=chromium:516775 LOG=N Review URL: https://codereview.chromium.org/1270403002 Cr-Commit-Position: refs/heads/master@{#30042} --- src/runtime/runtime-array.cc | 6 +--- test/mjsunit/regress/regress-crbug-516775.js | 53 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 test/mjsunit/regress/regress-crbug-516775.js diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc index 4cbd570..e29ecd6 100644 --- a/src/runtime/runtime-array.cc +++ b/src/runtime/runtime-array.cc @@ -437,12 +437,8 @@ static void CollectElementIndices(Handle object, uint32_t range, } case FAST_SLOPPY_ARGUMENTS_ELEMENTS: case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { - MaybeHandle length_obj = - Object::GetProperty(object, isolate->factory()->length_string()); - double length_num = length_obj.ToHandleChecked()->Number(); - uint32_t length = static_cast(DoubleToInt32(length_num)); ElementsAccessor* accessor = object->GetElementsAccessor(); - for (uint32_t i = 0; i < length; i++) { + for (uint32_t i = 0; i < range; i++) { if (accessor->HasElement(object, i)) { indices->Add(i); } diff --git a/test/mjsunit/regress/regress-crbug-516775.js b/test/mjsunit/regress/regress-crbug-516775.js new file mode 100644 index 0000000..25d4d01 --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-516775.js @@ -0,0 +1,53 @@ +// Copyright 2015 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: --allow-natives-syntax --harmony-concat-spreadable + +function arguments_with_length_getter(f) { + arguments.__defineGetter__('length', f); + return arguments; +} + +var count = 0; +function increment_count_return() { count++; return "boom"; } +function increment_count_throw() { count++; throw "boom"; } + +// Do not read the length of an arguments object on the prototype chain of +// an array. +var a1 = []; +%NormalizeElements(a1); +a1.__proto__ = arguments_with_length_getter(increment_count_return); +[].concat(a1); +assertEquals(0, count); + +var a2 = []; +%NormalizeElements(a2); +a2.__proto__ = arguments_with_length_getter(increment_count_throw); +[].concat(a2); +assertEquals(0, count); + +// Do read the length of an arguments object if spreadable. +var a3 = arguments_with_length_getter(increment_count_return); +a3[Symbol.isConcatSpreadable] = true; +[].concat(a3); +assertEquals(1, count); + +var a4 = arguments_with_length_getter(increment_count_throw); +a4[Symbol.isConcatSpreadable] = true; +assertThrows(function() { [].concat(a4); }); +assertEquals(2, count); + +// Do read the length of an arguments object on the prototype chain of +// an object. +var a5 = {}; +a5.__proto__ = arguments_with_length_getter(increment_count_return); +a5[Symbol.isConcatSpreadable] = true; +[].concat(a5); +assertEquals(3, count); + +var a6 = {}; +a6.__proto__ = arguments_with_length_getter(increment_count_throw); +a6[Symbol.isConcatSpreadable] = true; +assertThrows(function() { [].concat(a6); }); +assertEquals(4, count); -- 2.7.4