diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index 9536d67b13..e11722a95c 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -1247,9 +1247,13 @@ RUNTIME_FUNCTION(Runtime_CreateDataProperty) { RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); - CONVERT_ARG_HANDLE_CHECKED(HeapObject, obj, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); - if (!obj->IsJSObject()) return isolate->heap()->ToBoolean(false); + // If an iterator symbol is added to the Number prototype, we could see a Smi. + if (obj->IsSmi()) return isolate->heap()->ToBoolean(false); + if (!HeapObject::cast(*obj)->IsJSObject()) { + return isolate->heap()->ToBoolean(false); + } // While iteration alone may not have observable side-effects, calling // toNumber on an object will. Make sure the arg is not an array of objects. diff --git a/test/mjsunit/es6/typedarray-from.js b/test/mjsunit/es6/typedarray-from.js index bd8ab6e4b1..8157658249 100644 --- a/test/mjsunit/es6/typedarray-from.js +++ b/test/mjsunit/es6/typedarray-from.js @@ -151,14 +151,6 @@ for (var constructor of typedArrayConstructors) { assertThrows(function() { constructor.from([], 'noncallable'); }, TypeError); - source = [1, 2, 3]; - source[Symbol.iterator] = undefined; - assertArrayLikeEquals(constructor.from(source), source, constructor); - - source = [{ valueOf: function(){ return 42; }}]; - source[Symbol.iterator] = undefined; - assertArrayLikeEquals(constructor.from(source), [42], constructor); - source = [1, 2, 3]; var proxy = new Proxy(source, {}); assertArrayLikeEquals(constructor.from(proxy), source, constructor); @@ -171,6 +163,26 @@ for (var constructor of typedArrayConstructors) { } }); assertArrayLikeEquals(constructor.from(proxy), [2, 3, 4], constructor); +} + +// Tests that modify global state in a way that affects fast paths e.g. by +// invalidating protectors or changing prototypes. +for (var constructor of typedArrayConstructors) { + source = [1, 2, 3]; + source[Symbol.iterator] = undefined; + assertArrayLikeEquals(constructor.from(source), source, constructor); + + source = [{ valueOf: function(){ return 42; }}]; + source[Symbol.iterator] = undefined; + assertArrayLikeEquals(constructor.from(source), [42], constructor); + + Number.prototype[Symbol.iterator] = function* () { + yield 1; + yield 2; + yield 3; + } + assertArrayLikeEquals(constructor.from(1), [1, 2, 3], constructor); + assertArrayLikeEquals(constructor.from(1.1), [1, 2, 3], constructor); var nullIterator = {}; nullIterator[Symbol.iterator] = null; diff --git a/test/mjsunit/regress/regress-814643.js b/test/mjsunit/regress/regress-814643.js new file mode 100644 index 0000000000..085c56fe84 --- /dev/null +++ b/test/mjsunit/regress/regress-814643.js @@ -0,0 +1,6 @@ +// Copyright 2018 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. + +Number.prototype.__proto__ = String.prototype; +Uint8Array.from(1);