Commit 630b2a5f authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[builtins] Implement Array.from in CodeStubAssembler

This removes the Javascript version of Array.from in js/array.js and
adds a CodeStubAssembler version in src/builtins/builtins-array-gen.cc.

Also modify IteratorBuiltinsAssembler to allow querying the existence
of the iterator method without calling it so we can fall back to the
array-like behavior.

BUG=v8:1956

Change-Id: Ibfb3cef002d72d70bd30b4de676fd22becde006c
Reviewed-on: https://chromium-review.googlesource.com/887066Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51208}
parent 74c4e985
......@@ -1705,6 +1705,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
array_function, "isArray", Builtins::kArrayIsArray, 1, true);
native_context()->set_is_arraylike(*is_arraylike);
SimpleInstallFunction(array_function, "from", Builtins::kArrayFrom, 1,
false);
SimpleInstallFunction(array_function, "of", Builtins::kArrayOf, 0, false);
JSObject::AddProperty(proto, factory->constructor_string(), array_function,
......
This diff is collapsed.
......@@ -244,6 +244,8 @@ namespace internal {
CPP(ArrayConcat) \
/* ES6 #sec-array.isarray */ \
TFJ(ArrayIsArray, 1, kArg) \
/* ES6 #sec-array.from */ \
TFJ(ArrayFrom, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.of */ \
TFJ(ArrayOf, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES7 #sec-array.prototype.includes */ \
......
......@@ -11,11 +11,16 @@ namespace internal {
using compiler::Node;
Node* IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,
Node* object) {
return GetProperty(context, object, factory()->iterator_symbol());
}
IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
Node* object,
Label* if_exception,
Variable* exception) {
Node* method = GetProperty(context, object, factory()->iterator_symbol());
Node* method = GetIteratorMethod(context, object);
return GetIterator(context, object, method, if_exception, exception);
}
......
......@@ -17,6 +17,9 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
explicit IteratorBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
// Returns object[Symbol.iterator].
Node* GetIteratorMethod(Node* context, Node* object);
// https://tc39.github.io/ecma262/#sec-getiterator --- never used for
// @@asyncIterator.
IteratorRecord GetIterator(Node* context, Node* object,
......
......@@ -1157,6 +1157,9 @@ class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
operator Node*() const { return value(); }
void operator=(TNode<T> value) { Bind(value); }
void operator=(const TypedCodeAssemblerVariable<T>& variable) {
Bind(variable.value());
}
private:
using CodeAssemblerVariable::Bind;
......
......@@ -1153,63 +1153,6 @@ DEFINE_METHOD_LEN(
1 /* Set function length */
);
// ES6, draft 10-14-14, section 22.1.2.1
DEFINE_METHOD_LEN(
GlobalArray,
'from'(arrayLike, mapfn, receiver) {
var items = TO_OBJECT(arrayLike);
var mapping = !IS_UNDEFINED(mapfn);
if (mapping) {
if (!IS_CALLABLE(mapfn)) {
throw %make_type_error(kCalledNonCallable, mapfn);
}
}
var iterable = GetMethod(items, iteratorSymbol);
var k;
var result;
var mappedValue;
var nextValue;
if (!IS_UNDEFINED(iterable)) {
result = %IsConstructor(this) ? new this() : [];
k = 0;
for (nextValue of
{ [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
}
%CreateDataProperty(result, k, mappedValue);
k++;
}
result.length = k;
return result;
} else {
var len = TO_LENGTH(items.length);
result = %IsConstructor(this) ? new this(len) : new GlobalArray(len);
for (k = 0; k < len; ++k) {
nextValue = items[k];
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
}
%CreateDataProperty(result, k, mappedValue);
}
result.length = k;
return result;
}
},
1 /* Set function length. */
);
// Set up unscopable properties on the Array.prototype object.
var unscopables = {
__proto__: null,
......
......@@ -161,6 +161,14 @@ assertThrows(function () { Array.from.call(exotic, [1]); }, TypeError);
// The setter wasn't called
assertEquals(0, setterCalled);
// Non-callable iterators should cause a TypeError before calling the target
// constructor.
items = {};
items[Symbol.iterator] = 7;
function TestError() {}
function ArrayLike() { throw new TestError() }
assertThrows(function() { Array.from.call(ArrayLike, items); }, TypeError);
// Check that array properties defined are writable, enumerable, configurable
function ordinary() { }
var x = Array.from.call(ordinary, [2]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment