72bc4b5c8a
Use a single JSIteratorResult type for all implementation provided iterator results (i.e. the String, Array and collection iterators, and also for generators). This removes one source of unnecessary polymorphism in for-of loops. It is accomplished by a new intrinsic %_CreateIterResultObject() that should be used to create iterator result objects from JavaScript builtins (there's a matching factory method for C++ code). Also restructure the %StringIteratorPrototype%.next() and %ArrayIteratorPrototype%.next() functions to be a bit more friendly to optimizing compilers. R=ishell@chromium.org Review URL: https://codereview.chromium.org/1302173007 Cr-Commit-Position: refs/heads/master@{#30557}
169 lines
4.7 KiB
JavaScript
169 lines
4.7 KiB
JavaScript
// Copyright 2013 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.
|
|
|
|
var $arrayValues;
|
|
|
|
(function(global, utils) {
|
|
|
|
"use strict";
|
|
|
|
%CheckIsBootstrapping();
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Imports
|
|
|
|
var arrayIterationKindSymbol =
|
|
utils.ImportNow("array_iteration_kind_symbol");
|
|
var arrayIteratorNextIndexSymbol =
|
|
utils.ImportNow("array_iterator_next_symbol");
|
|
var arrayIteratorObjectSymbol =
|
|
utils.ImportNow("array_iterator_object_symbol");
|
|
var GlobalArray = global.Array;
|
|
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
|
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
|
|
|
macro TYPED_ARRAYS(FUNCTION)
|
|
FUNCTION(Uint8Array)
|
|
FUNCTION(Int8Array)
|
|
FUNCTION(Uint16Array)
|
|
FUNCTION(Int16Array)
|
|
FUNCTION(Uint32Array)
|
|
FUNCTION(Int32Array)
|
|
FUNCTION(Float32Array)
|
|
FUNCTION(Float64Array)
|
|
FUNCTION(Uint8ClampedArray)
|
|
endmacro
|
|
|
|
macro COPY_FROM_GLOBAL(NAME)
|
|
var GlobalNAME = global.NAME;
|
|
endmacro
|
|
|
|
TYPED_ARRAYS(COPY_FROM_GLOBAL)
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
function ArrayIterator() {}
|
|
|
|
|
|
// TODO(wingo): Update section numbers when ES6 has stabilized. The
|
|
// section numbers below are already out of date as of the May 2014
|
|
// draft.
|
|
|
|
|
|
// 15.4.5.1 CreateArrayIterator Abstract Operation
|
|
function CreateArrayIterator(array, kind) {
|
|
var object = TO_OBJECT(array);
|
|
var iterator = new ArrayIterator;
|
|
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
|
|
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
|
|
SET_PRIVATE(iterator, arrayIterationKindSymbol, kind);
|
|
return iterator;
|
|
}
|
|
|
|
|
|
// 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]
|
|
function ArrayIteratorIterator() {
|
|
return this;
|
|
}
|
|
|
|
|
|
// ES6 section 22.1.5.2.1 %ArrayIteratorPrototype%.next( )
|
|
function ArrayIteratorNext() {
|
|
var iterator = this;
|
|
var value = UNDEFINED;
|
|
var done = true;
|
|
|
|
if (!IS_SPEC_OBJECT(iterator) ||
|
|
!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
|
|
throw MakeTypeError(kIncompatibleMethodReceiver,
|
|
'Array Iterator.prototype.next', this);
|
|
}
|
|
|
|
var array = GET_PRIVATE(iterator, arrayIteratorObjectSymbol);
|
|
if (!IS_UNDEFINED(array)) {
|
|
var index = GET_PRIVATE(iterator, arrayIteratorNextIndexSymbol);
|
|
var itemKind = GET_PRIVATE(iterator, arrayIterationKindSymbol);
|
|
var length = TO_UINT32(array.length);
|
|
|
|
// "sparse" is never used.
|
|
|
|
if (index >= length) {
|
|
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, UNDEFINED);
|
|
} else {
|
|
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
|
|
|
|
if (itemKind == ITERATOR_KIND_VALUES) {
|
|
value = array[index];
|
|
} else if (itemKind == ITERATOR_KIND_ENTRIES) {
|
|
value = [index, array[index]];
|
|
} else {
|
|
value = index;
|
|
}
|
|
done = false;
|
|
}
|
|
}
|
|
|
|
return %_CreateIterResultObject(value, done);
|
|
}
|
|
|
|
|
|
function ArrayEntries() {
|
|
return CreateArrayIterator(this, ITERATOR_KIND_ENTRIES);
|
|
}
|
|
|
|
|
|
function ArrayValues() {
|
|
return CreateArrayIterator(this, ITERATOR_KIND_VALUES);
|
|
}
|
|
|
|
|
|
function ArrayKeys() {
|
|
return CreateArrayIterator(this, ITERATOR_KIND_KEYS);
|
|
}
|
|
|
|
|
|
%FunctionSetPrototype(ArrayIterator, {__proto__: $iteratorPrototype});
|
|
%FunctionSetInstanceClassName(ArrayIterator, 'Array Iterator');
|
|
|
|
utils.InstallFunctions(ArrayIterator.prototype, DONT_ENUM, [
|
|
'next', ArrayIteratorNext
|
|
]);
|
|
utils.SetFunctionName(ArrayIteratorIterator, iteratorSymbol);
|
|
%AddNamedProperty(ArrayIterator.prototype, iteratorSymbol,
|
|
ArrayIteratorIterator, DONT_ENUM);
|
|
%AddNamedProperty(ArrayIterator.prototype, toStringTagSymbol,
|
|
"Array Iterator", READ_ONLY | DONT_ENUM);
|
|
|
|
utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
|
|
// No 'values' since it breaks webcompat: http://crbug.com/409858
|
|
'entries', ArrayEntries,
|
|
'keys', ArrayKeys
|
|
]);
|
|
|
|
// TODO(adam): Remove this call once 'values' is in the above
|
|
// InstallFunctions block, as it'll be redundant.
|
|
utils.SetFunctionName(ArrayValues, 'values');
|
|
|
|
%AddNamedProperty(GlobalArray.prototype, iteratorSymbol, ArrayValues,
|
|
DONT_ENUM);
|
|
|
|
macro EXTEND_TYPED_ARRAY(NAME)
|
|
%AddNamedProperty(GlobalNAME.prototype, 'entries', ArrayEntries, DONT_ENUM);
|
|
%AddNamedProperty(GlobalNAME.prototype, 'values', ArrayValues, DONT_ENUM);
|
|
%AddNamedProperty(GlobalNAME.prototype, 'keys', ArrayKeys, DONT_ENUM);
|
|
%AddNamedProperty(GlobalNAME.prototype, iteratorSymbol, ArrayValues,
|
|
DONT_ENUM);
|
|
endmacro
|
|
|
|
TYPED_ARRAYS(EXTEND_TYPED_ARRAY)
|
|
|
|
// -------------------------------------------------------------------
|
|
// Exports
|
|
|
|
$arrayValues = ArrayValues;
|
|
|
|
%InstallToContext(["array_values_iterator", ArrayValues]);
|
|
|
|
})
|