ES6: Add support for values/keys/entries for Map and Set
This allows code like this: var map = new Map(); map.set(1, 'One'); ... var iter = map.values(); var res; while (!(res = iter.next()).done) { print(res.value); } BUG=v8:1793 LOG=Y R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/259883002 Patch from Erik Arvidsson <arv@chromium.org>. git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21615 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1d57c2d65f
commit
509a1a405c
@ -1347,16 +1347,24 @@ void Genesis::InitializeExperimentalGlobal() {
|
||||
InstallFunction(global, "Set", JS_SET_TYPE, JSSet::kSize,
|
||||
isolate()->initial_object_prototype(), Builtins::kIllegal);
|
||||
{ // -- S e t I t e r a t o r
|
||||
Handle<Map> map = isolate()->factory()->NewMap(
|
||||
JS_SET_ITERATOR_TYPE, JSSetIterator::kSize);
|
||||
map->set_constructor(native_context()->closure());
|
||||
native_context()->set_set_iterator_map(*map);
|
||||
Handle<JSObject> builtins(native_context()->builtins());
|
||||
Handle<JSFunction> set_iterator_function =
|
||||
InstallFunction(builtins, "SetIterator", JS_SET_ITERATOR_TYPE,
|
||||
JSSetIterator::kSize,
|
||||
isolate()->initial_object_prototype(),
|
||||
Builtins::kIllegal);
|
||||
native_context()->set_set_iterator_map(
|
||||
set_iterator_function->initial_map());
|
||||
}
|
||||
{ // -- M a p I t e r a t o r
|
||||
Handle<Map> map = isolate()->factory()->NewMap(
|
||||
JS_MAP_ITERATOR_TYPE, JSMapIterator::kSize);
|
||||
map->set_constructor(native_context()->closure());
|
||||
native_context()->set_map_iterator_map(*map);
|
||||
Handle<JSObject> builtins(native_context()->builtins());
|
||||
Handle<JSFunction> map_iterator_function =
|
||||
InstallFunction(builtins, "MapIterator", JS_MAP_ITERATOR_TYPE,
|
||||
JSMapIterator::kSize,
|
||||
isolate()->initial_object_prototype(),
|
||||
Builtins::kIllegal);
|
||||
native_context()->set_map_iterator_map(
|
||||
map_iterator_function->initial_map());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2013,6 +2021,7 @@ bool Genesis::InstallExperimentalNatives() {
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, symbols, "symbol.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, collections, "collection.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, collections, "collection-iterator.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, generators, "generator.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, iteration, "array-iterator.js")
|
||||
INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js")
|
||||
|
162
src/collection-iterator.js
Normal file
162
src/collection-iterator.js
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
// This file relies on the fact that the following declaration has been made
|
||||
// in runtime.js:
|
||||
// var $Set = global.Set;
|
||||
// var $Map = global.Map;
|
||||
|
||||
|
||||
function SetIteratorConstructor(set, kind) {
|
||||
%SetIteratorInitialize(this, set, kind);
|
||||
}
|
||||
|
||||
|
||||
function SetIteratorNextJS() {
|
||||
if (!IS_SET_ITERATOR(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Set Iterator.prototype.next', this]);
|
||||
}
|
||||
return %SetIteratorNext(this);
|
||||
}
|
||||
|
||||
|
||||
function SetIteratorSymbolIterator() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function SetEntries() {
|
||||
if (!IS_SET(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Set.prototype.entries', this]);
|
||||
}
|
||||
return new SetIterator(this, ITERATOR_KIND_ENTRIES);
|
||||
}
|
||||
|
||||
|
||||
function SetValues() {
|
||||
if (!IS_SET(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Set.prototype.values', this]);
|
||||
}
|
||||
return new SetIterator(this, ITERATOR_KIND_VALUES);
|
||||
}
|
||||
|
||||
|
||||
function SetUpSetIterator() {
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
%SetCode(SetIterator, SetIteratorConstructor);
|
||||
%FunctionSetPrototype(SetIterator, new $Object());
|
||||
%FunctionSetInstanceClassName(SetIterator, 'Set Iterator');
|
||||
InstallFunctions(SetIterator.prototype, DONT_ENUM, $Array(
|
||||
'next', SetIteratorNextJS
|
||||
));
|
||||
|
||||
%FunctionSetName(SetIteratorSymbolIterator, '[Symbol.iterator]');
|
||||
%SetProperty(SetIterator.prototype, InternalSymbol('Symbol.iterator'),
|
||||
SetIteratorSymbolIterator, DONT_ENUM);
|
||||
}
|
||||
|
||||
SetUpSetIterator();
|
||||
|
||||
|
||||
function ExtendSetPrototype() {
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
InstallFunctions($Set.prototype, DONT_ENUM, $Array(
|
||||
'entries', SetEntries,
|
||||
'values', SetValues
|
||||
));
|
||||
|
||||
%SetProperty($Set.prototype, InternalSymbol('Symbol.iterator'), SetValues,
|
||||
DONT_ENUM);
|
||||
}
|
||||
|
||||
ExtendSetPrototype();
|
||||
|
||||
|
||||
|
||||
function MapIteratorConstructor(map, kind) {
|
||||
%MapIteratorInitialize(this, map, kind);
|
||||
}
|
||||
|
||||
|
||||
function MapIteratorSymbolIterator() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
function MapIteratorNextJS() {
|
||||
if (!IS_MAP_ITERATOR(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Map Iterator.prototype.next', this]);
|
||||
}
|
||||
return %MapIteratorNext(this);
|
||||
}
|
||||
|
||||
|
||||
function MapEntries() {
|
||||
if (!IS_MAP(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Map.prototype.entries', this]);
|
||||
}
|
||||
return new MapIterator(this, ITERATOR_KIND_ENTRIES);
|
||||
}
|
||||
|
||||
|
||||
function MapKeys() {
|
||||
if (!IS_MAP(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Map.prototype.keys', this]);
|
||||
}
|
||||
return new MapIterator(this, ITERATOR_KIND_KEYS);
|
||||
}
|
||||
|
||||
|
||||
function MapValues() {
|
||||
if (!IS_MAP(this)) {
|
||||
throw MakeTypeError('incompatible_method_receiver',
|
||||
['Map.prototype.values', this]);
|
||||
}
|
||||
return new MapIterator(this, ITERATOR_KIND_VALUES);
|
||||
}
|
||||
|
||||
|
||||
function SetUpMapIterator() {
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
%SetCode(MapIterator, MapIteratorConstructor);
|
||||
%FunctionSetPrototype(MapIterator, new $Object());
|
||||
%FunctionSetInstanceClassName(MapIterator, 'Map Iterator');
|
||||
InstallFunctions(MapIterator.prototype, DONT_ENUM, $Array(
|
||||
'next', MapIteratorNextJS
|
||||
));
|
||||
|
||||
%FunctionSetName(MapIteratorSymbolIterator, '[Symbol.iterator]');
|
||||
%SetProperty(MapIterator.prototype, InternalSymbol('Symbol.iterator'),
|
||||
MapIteratorSymbolIterator, DONT_ENUM);
|
||||
}
|
||||
|
||||
SetUpMapIterator();
|
||||
|
||||
|
||||
function ExtendMapPrototype() {
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
InstallFunctions($Map.prototype, DONT_ENUM, $Array(
|
||||
'entries', MapEntries,
|
||||
'keys', MapKeys,
|
||||
'values', MapValues
|
||||
));
|
||||
|
||||
%SetProperty($Map.prototype, InternalSymbol('Symbol.iterator'), MapEntries,
|
||||
DONT_ENUM);
|
||||
}
|
||||
|
||||
ExtendMapPrototype();
|
@ -79,7 +79,7 @@ function SetForEach(f, receiver) {
|
||||
throw MakeTypeError('called_non_callable', [f]);
|
||||
}
|
||||
|
||||
var iterator = %SetCreateIterator(this, ITERATOR_KIND_VALUES);
|
||||
var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
|
||||
var entry;
|
||||
var stepping = %_DebugCallbackSupportsStepping(f);
|
||||
while (!(entry = %SetIteratorNext(iterator)).done) {
|
||||
@ -190,7 +190,7 @@ function MapForEach(f, receiver) {
|
||||
throw MakeTypeError('called_non_callable', [f]);
|
||||
}
|
||||
|
||||
var iterator = %MapCreateIterator(this, ITERATOR_KIND_ENTRIES);
|
||||
var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
|
||||
var entry;
|
||||
var stepping = %_DebugCallbackSupportsStepping(f);
|
||||
while (!(entry = %MapIteratorNext(iterator)).done) {
|
||||
|
@ -178,6 +178,7 @@ DEFINE_implication(harmony, harmony_numeric_literals)
|
||||
DEFINE_implication(harmony, harmony_strings)
|
||||
DEFINE_implication(harmony, harmony_arrays)
|
||||
DEFINE_implication(harmony_modules, harmony_scoping)
|
||||
DEFINE_implication(harmony_collections, harmony_symbols)
|
||||
|
||||
DEFINE_implication(harmony, es_staging)
|
||||
DEFINE_implication(es_staging, harmony_maths)
|
||||
|
@ -126,6 +126,8 @@ macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
|
||||
macro IS_ARRAYBUFFER(arg) = (%_ClassOf(arg) === 'ArrayBuffer');
|
||||
macro IS_DATAVIEW(arg) = (%_ClassOf(arg) === 'DataView');
|
||||
macro IS_GENERATOR(arg) = (%_ClassOf(arg) === 'Generator');
|
||||
macro IS_SET_ITERATOR(arg) = (%_ClassOf(arg) === 'Set Iterator');
|
||||
macro IS_MAP_ITERATOR(arg) = (%_ClassOf(arg) === 'Map Iterator');
|
||||
macro IS_UNDETECTABLE(arg) = (%_IsUndetectableObject(arg));
|
||||
macro FLOOR(arg) = $floor(arg);
|
||||
|
||||
|
@ -701,8 +701,8 @@ void JSSetIterator::JSSetIteratorVerify() {
|
||||
JSObjectVerify();
|
||||
VerifyHeapPointer(table());
|
||||
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
|
||||
CHECK(index()->IsSmi());
|
||||
CHECK(kind()->IsSmi());
|
||||
CHECK(index()->IsSmi() || index()->IsUndefined());
|
||||
CHECK(kind()->IsSmi() || kind()->IsUndefined());
|
||||
}
|
||||
|
||||
|
||||
@ -711,8 +711,8 @@ void JSMapIterator::JSMapIteratorVerify() {
|
||||
JSObjectVerify();
|
||||
VerifyHeapPointer(table());
|
||||
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined());
|
||||
CHECK(index()->IsSmi());
|
||||
CHECK(kind()->IsSmi());
|
||||
CHECK(index()->IsSmi() || index()->IsUndefined());
|
||||
CHECK(kind()->IsSmi() || kind()->IsUndefined());
|
||||
}
|
||||
|
||||
|
||||
|
@ -6127,20 +6127,6 @@ SeededNumberDictionary* JSObject::element_dictionary() {
|
||||
}
|
||||
|
||||
|
||||
Handle<JSSetIterator> JSSetIterator::Create(
|
||||
Handle<OrderedHashSet> table,
|
||||
int kind) {
|
||||
return CreateInternal(table->GetIsolate()->set_iterator_map(), table, kind);
|
||||
}
|
||||
|
||||
|
||||
Handle<JSMapIterator> JSMapIterator::Create(
|
||||
Handle<OrderedHashMap> table,
|
||||
int kind) {
|
||||
return CreateInternal(table->GetIsolate()->map_iterator_map(), table, kind);
|
||||
}
|
||||
|
||||
|
||||
bool Name::IsHashFieldComputed(uint32_t field) {
|
||||
return (field & kHashNotComputedMask) == 0;
|
||||
}
|
||||
|
@ -16480,22 +16480,6 @@ void OrderedHashTableIterator<Derived, TableType>::Transition() {
|
||||
}
|
||||
|
||||
|
||||
template<class Derived, class TableType>
|
||||
Handle<Derived> OrderedHashTableIterator<Derived, TableType>::CreateInternal(
|
||||
Handle<Map> map,
|
||||
Handle<TableType> table,
|
||||
int kind) {
|
||||
Isolate* isolate = table->GetIsolate();
|
||||
|
||||
Handle<Derived> new_iterator = Handle<Derived>::cast(
|
||||
isolate->factory()->NewJSObjectFromMap(map));
|
||||
new_iterator->set_table(*table);
|
||||
new_iterator->set_index(Smi::FromInt(0));
|
||||
new_iterator->set_kind(Smi::FromInt(kind));
|
||||
return new_iterator;
|
||||
}
|
||||
|
||||
|
||||
template Handle<JSObject>
|
||||
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
|
||||
Handle<JSSetIterator> iterator);
|
||||
@ -16503,10 +16487,6 @@ OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
|
||||
template void
|
||||
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
|
||||
|
||||
template Handle<JSSetIterator>
|
||||
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CreateInternal(
|
||||
Handle<Map> map, Handle<OrderedHashSet> table, int kind);
|
||||
|
||||
|
||||
template Handle<JSObject>
|
||||
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
|
||||
@ -16515,10 +16495,6 @@ OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
|
||||
template void
|
||||
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
|
||||
|
||||
template Handle<JSMapIterator>
|
||||
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CreateInternal(
|
||||
Handle<Map> map, Handle<OrderedHashMap> table, int kind);
|
||||
|
||||
|
||||
Handle<Object> JSSetIterator::ValueForKind(
|
||||
Handle<JSSetIterator> iterator, int entry_index) {
|
||||
|
@ -9985,10 +9985,6 @@ class OrderedHashTableIterator: public JSObject {
|
||||
// end.
|
||||
static Handle<JSObject> Next(Handle<Derived> iterator);
|
||||
|
||||
protected:
|
||||
static Handle<Derived> CreateInternal(
|
||||
Handle<Map> map, Handle<TableType> table, int kind);
|
||||
|
||||
private:
|
||||
// Transitions the iterator to the non obsolote backing store. This is a NOP
|
||||
// if the [table] is not obsolete.
|
||||
@ -10001,11 +9997,6 @@ class OrderedHashTableIterator: public JSObject {
|
||||
class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
|
||||
OrderedHashSet> {
|
||||
public:
|
||||
// Creates a new iterator associated with [table].
|
||||
// [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
|
||||
static inline Handle<JSSetIterator> Create(
|
||||
Handle<OrderedHashSet> table, int kind);
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(JSSetIterator)
|
||||
DECLARE_VERIFIER(JSSetIterator)
|
||||
@ -10025,11 +10016,6 @@ class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
|
||||
class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
|
||||
OrderedHashMap> {
|
||||
public:
|
||||
// Creates a new iterator associated with [table].
|
||||
// [kind] needs to be one of the OrderedHashTableIterator Kind enum values.
|
||||
static inline Handle<JSMapIterator> Create(
|
||||
Handle<OrderedHashMap> table, int kind);
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(JSMapIterator)
|
||||
DECLARE_VERIFIER(JSMapIterator)
|
||||
|
@ -1584,15 +1584,19 @@ RUNTIME_FUNCTION(Runtime_SetGetSize) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_SetCreateIterator) {
|
||||
RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
|
||||
CONVERT_SMI_ARG_CHECKED(kind, 1)
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
|
||||
CONVERT_SMI_ARG_CHECKED(kind, 2)
|
||||
RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
|
||||
kind == JSSetIterator::kKindEntries);
|
||||
Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
|
||||
return *JSSetIterator::Create(table, kind);
|
||||
Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
|
||||
holder->set_table(*table);
|
||||
holder->set_index(Smi::FromInt(0));
|
||||
holder->set_kind(Smi::FromInt(kind));
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
@ -1683,16 +1687,20 @@ RUNTIME_FUNCTION(Runtime_MapGetSize) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_MapCreateIterator) {
|
||||
RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
|
||||
CONVERT_SMI_ARG_CHECKED(kind, 1)
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
|
||||
CONVERT_SMI_ARG_CHECKED(kind, 2)
|
||||
RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys
|
||||
|| kind == JSMapIterator::kKindValues
|
||||
|| kind == JSMapIterator::kKindEntries);
|
||||
Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
|
||||
return *JSMapIterator::Create(table, kind);
|
||||
Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
|
||||
holder->set_table(*table);
|
||||
holder->set_index(Smi::FromInt(0));
|
||||
holder->set_kind(Smi::FromInt(kind));
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,8 +272,8 @@ namespace internal {
|
||||
F(SetDelete, 2, 1) \
|
||||
F(SetClear, 1, 1) \
|
||||
F(SetGetSize, 1, 1) \
|
||||
F(SetCreateIterator, 2, 1) \
|
||||
\
|
||||
F(SetIteratorInitialize, 3, 1) \
|
||||
F(SetIteratorNext, 1, 1) \
|
||||
\
|
||||
/* Harmony maps */ \
|
||||
@ -284,8 +284,8 @@ namespace internal {
|
||||
F(MapClear, 1, 1) \
|
||||
F(MapSet, 3, 1) \
|
||||
F(MapGetSize, 1, 1) \
|
||||
F(MapCreateIterator, 2, 1) \
|
||||
\
|
||||
F(MapIteratorInitialize, 3, 1) \
|
||||
F(MapIteratorNext, 1, 1) \
|
||||
\
|
||||
/* Harmony weak maps and sets */ \
|
||||
|
@ -21466,6 +21466,7 @@ THREADED_TEST(Regress157124) {
|
||||
|
||||
THREADED_TEST(Regress2535) {
|
||||
i::FLAG_harmony_collections = true;
|
||||
i::FLAG_harmony_symbols = true;
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
Local<Value> set_value = CompileRun("new Set();");
|
||||
|
@ -37,21 +37,6 @@ namespace {
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
void CheckIterResultObject(Isolate* isolate,
|
||||
Handle<JSObject> result,
|
||||
Handle<Object> value,
|
||||
bool done) {
|
||||
Handle<Object> value_object =
|
||||
Object::GetProperty(isolate, result, "value").ToHandleChecked();
|
||||
Handle<Object> done_object =
|
||||
Object::GetProperty(isolate, result, "done").ToHandleChecked();
|
||||
|
||||
CHECK_EQ(*value_object, *value);
|
||||
CHECK(done_object->IsBoolean());
|
||||
CHECK_EQ(done_object->BooleanValue(), done);
|
||||
}
|
||||
|
||||
|
||||
TEST(Set) {
|
||||
i::FLAG_harmony_collections = true;
|
||||
|
||||
@ -64,11 +49,6 @@ TEST(Set) {
|
||||
CHECK_EQ(0, ordered_set->NumberOfElements());
|
||||
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
|
||||
|
||||
Handle<JSSetIterator> value_iterator =
|
||||
JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
|
||||
Handle<JSSetIterator> value_iterator_2 =
|
||||
JSSetIterator::Create(ordered_set, JSSetIterator::kKindValues);
|
||||
|
||||
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
|
||||
CHECK(!ordered_set->Contains(obj));
|
||||
@ -97,18 +77,6 @@ TEST(Set) {
|
||||
CHECK(ordered_set->Contains(obj2));
|
||||
CHECK(ordered_set->Contains(obj3));
|
||||
|
||||
// Test iteration
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator), obj1, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator), obj2, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator), obj3, false);
|
||||
CheckIterResultObject(isolate,
|
||||
JSSetIterator::Next(value_iterator),
|
||||
factory->undefined_value(),
|
||||
true);
|
||||
|
||||
// Test growth
|
||||
ordered_set = OrderedHashSet::Add(ordered_set, obj);
|
||||
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
|
||||
@ -122,22 +90,6 @@ TEST(Set) {
|
||||
CHECK_EQ(0, ordered_set->NumberOfDeletedElements());
|
||||
CHECK_EQ(4, ordered_set->NumberOfBuckets());
|
||||
|
||||
// Test iteration after growth
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator_2), obj1, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator_2), obj2, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator_2), obj3, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator_2), obj, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSSetIterator::Next(value_iterator_2), obj4, false);
|
||||
CheckIterResultObject(isolate,
|
||||
JSSetIterator::Next(value_iterator_2),
|
||||
factory->undefined_value(),
|
||||
true);
|
||||
|
||||
// Test shrinking
|
||||
ordered_set = OrderedHashSet::Remove(ordered_set, obj, &was_present);
|
||||
CHECK(was_present);
|
||||
@ -164,11 +116,6 @@ TEST(Map) {
|
||||
CHECK_EQ(0, ordered_map->NumberOfElements());
|
||||
CHECK_EQ(0, ordered_map->NumberOfDeletedElements());
|
||||
|
||||
Handle<JSMapIterator> value_iterator =
|
||||
JSMapIterator::Create(ordered_map, JSMapIterator::kKindValues);
|
||||
Handle<JSMapIterator> key_iterator =
|
||||
JSMapIterator::Create(ordered_map, JSMapIterator::kKindKeys);
|
||||
|
||||
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
Handle<JSObject> obj = factory->NewJSObjectFromMap(map);
|
||||
Handle<JSObject> val = factory->NewJSObjectFromMap(map);
|
||||
@ -196,18 +143,6 @@ TEST(Map) {
|
||||
CHECK(ordered_map->Lookup(obj2)->SameValue(*val2));
|
||||
CHECK(ordered_map->Lookup(obj3)->SameValue(*val3));
|
||||
|
||||
// Test iteration
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(value_iterator), val1, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(value_iterator), val2, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(value_iterator), val3, false);
|
||||
CheckIterResultObject(isolate,
|
||||
JSMapIterator::Next(value_iterator),
|
||||
factory->undefined_value(),
|
||||
true);
|
||||
|
||||
// Test growth
|
||||
ordered_map = OrderedHashMap::Put(ordered_map, obj, val);
|
||||
Handle<JSObject> obj4 = factory->NewJSObjectFromMap(map);
|
||||
@ -221,22 +156,6 @@ TEST(Map) {
|
||||
CHECK_EQ(5, ordered_map->NumberOfElements());
|
||||
CHECK_EQ(4, ordered_map->NumberOfBuckets());
|
||||
|
||||
// Test iteration after growth
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(key_iterator), obj1, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(key_iterator), obj2, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(key_iterator), obj3, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(key_iterator), obj, false);
|
||||
CheckIterResultObject(
|
||||
isolate, JSMapIterator::Next(key_iterator), obj4, false);
|
||||
CheckIterResultObject(isolate,
|
||||
JSMapIterator::Next(key_iterator),
|
||||
factory->undefined_value(),
|
||||
true);
|
||||
|
||||
// Test shrinking
|
||||
ordered_map = OrderedHashMap::Put(
|
||||
ordered_map, obj, factory->the_hole_value());
|
||||
|
195
test/mjsunit/harmony/collection-iterator.js
Normal file
195
test/mjsunit/harmony/collection-iterator.js
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright 2014 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: --harmony-collections --allow-natives-syntax
|
||||
|
||||
|
||||
(function TestSetIterator() {
|
||||
var s = new Set;
|
||||
var iter = s.values();
|
||||
assertEquals('Set Iterator', %_ClassOf(iter));
|
||||
|
||||
var SetIteratorPrototype = iter.__proto__;
|
||||
assertFalse(SetIteratorPrototype.hasOwnProperty('constructor'));
|
||||
assertEquals(SetIteratorPrototype.__proto__, Object.prototype);
|
||||
|
||||
var propertyNames = Object.getOwnPropertyNames(SetIteratorPrototype);
|
||||
assertArrayEquals(['next'], propertyNames);
|
||||
|
||||
assertEquals(new Set().values().__proto__, SetIteratorPrototype);
|
||||
assertEquals(new Set().entries().__proto__, SetIteratorPrototype);
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetIteratorValues() {
|
||||
var s = new Set;
|
||||
s.add(1);
|
||||
s.add(2);
|
||||
s.add(3);
|
||||
var iter = s.values();
|
||||
|
||||
assertEquals({value: 1, done: false}, iter.next());
|
||||
assertEquals({value: 2, done: false}, iter.next());
|
||||
assertEquals({value: 3, done: false}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetIteratorEntries() {
|
||||
var s = new Set;
|
||||
s.add(1);
|
||||
s.add(2);
|
||||
s.add(3);
|
||||
var iter = s.entries();
|
||||
|
||||
assertEquals({value: [1, 1], done: false}, iter.next());
|
||||
assertEquals({value: [2, 2], done: false}, iter.next());
|
||||
assertEquals({value: [3, 3], done: false}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetIteratorMutations() {
|
||||
var s = new Set;
|
||||
s.add(1);
|
||||
var iter = s.values();
|
||||
assertEquals({value: 1, done: false}, iter.next());
|
||||
s.add(2);
|
||||
s.add(3);
|
||||
s.add(4);
|
||||
s.add(5);
|
||||
assertEquals({value: 2, done: false}, iter.next());
|
||||
s.delete(3);
|
||||
assertEquals({value: 4, done: false}, iter.next());
|
||||
s.delete(5);
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
s.add(4);
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetInvalidReceiver() {
|
||||
assertThrows(function() {
|
||||
Set.prototype.values.call({});
|
||||
}, TypeError);
|
||||
assertThrows(function() {
|
||||
Set.prototype.entries.call({});
|
||||
}, TypeError);
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetIteratorInvalidReceiver() {
|
||||
var iter = new Set().values();
|
||||
assertThrows(function() {
|
||||
iter.next.call({});
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
(function TestSetIteratorSymbol() {
|
||||
assertEquals(Set.prototype[Symbol.iterator], Set.prototype.values);
|
||||
assertTrue(Set.prototype.hasOwnProperty(Symbol.iterator));
|
||||
assertFalse(Set.prototype.propertyIsEnumerable(Symbol.iterator));
|
||||
|
||||
var iter = new Set().values();
|
||||
assertEquals(iter, iter[Symbol.iterator]());
|
||||
assertEquals(iter[Symbol.iterator].name, '[Symbol.iterator]');
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIterator() {
|
||||
var m = new Map;
|
||||
var iter = m.values();
|
||||
assertEquals('Map Iterator', %_ClassOf(iter));
|
||||
|
||||
var MapIteratorPrototype = iter.__proto__;
|
||||
assertFalse(MapIteratorPrototype.hasOwnProperty('constructor'));
|
||||
assertEquals(MapIteratorPrototype.__proto__, Object.prototype);
|
||||
|
||||
var propertyNames = Object.getOwnPropertyNames(MapIteratorPrototype);
|
||||
assertArrayEquals(['next'], propertyNames);
|
||||
|
||||
assertEquals(new Map().values().__proto__, MapIteratorPrototype);
|
||||
assertEquals(new Map().keys().__proto__, MapIteratorPrototype);
|
||||
assertEquals(new Map().entries().__proto__, MapIteratorPrototype);
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIteratorValues() {
|
||||
var m = new Map;
|
||||
m.set(1, 11);
|
||||
m.set(2, 22);
|
||||
m.set(3, 33);
|
||||
var iter = m.values();
|
||||
|
||||
assertEquals({value: 11, done: false}, iter.next());
|
||||
assertEquals({value: 22, done: false}, iter.next());
|
||||
assertEquals({value: 33, done: false}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIteratorKeys() {
|
||||
var m = new Map;
|
||||
m.set(1, 11);
|
||||
m.set(2, 22);
|
||||
m.set(3, 33);
|
||||
var iter = m.keys();
|
||||
|
||||
assertEquals({value: 1, done: false}, iter.next());
|
||||
assertEquals({value: 2, done: false}, iter.next());
|
||||
assertEquals({value: 3, done: false}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIteratorEntries() {
|
||||
var m = new Map;
|
||||
m.set(1, 11);
|
||||
m.set(2, 22);
|
||||
m.set(3, 33);
|
||||
var iter = m.entries();
|
||||
|
||||
assertEquals({value: [1, 11], done: false}, iter.next());
|
||||
assertEquals({value: [2, 22], done: false}, iter.next());
|
||||
assertEquals({value: [3, 33], done: false}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
assertEquals({value: undefined, done: true}, iter.next());
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapInvalidReceiver() {
|
||||
assertThrows(function() {
|
||||
Map.prototype.values.call({});
|
||||
}, TypeError);
|
||||
assertThrows(function() {
|
||||
Map.prototype.keys.call({});
|
||||
}, TypeError);
|
||||
assertThrows(function() {
|
||||
Map.prototype.entries.call({});
|
||||
}, TypeError);
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIteratorInvalidReceiver() {
|
||||
var iter = new Map().values();
|
||||
assertThrows(function() {
|
||||
iter.next.call({});
|
||||
}, TypeError);
|
||||
})();
|
||||
|
||||
|
||||
(function TestMapIteratorSymbol() {
|
||||
assertEquals(Map.prototype[Symbol.iterator], Map.prototype.entries);
|
||||
assertTrue(Map.prototype.hasOwnProperty(Symbol.iterator));
|
||||
assertFalse(Map.prototype.propertyIsEnumerable(Symbol.iterator));
|
||||
|
||||
var iter = new Map().values();
|
||||
assertEquals(iter, iter[Symbol.iterator]());
|
||||
assertEquals(iter[Symbol.iterator].name, '[Symbol.iterator]');
|
||||
})();
|
@ -2,12 +2,11 @@
|
||||
// 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-collections
|
||||
|
||||
// Flags: --harmony-collections --expose-natives-as=builtins
|
||||
// Should not crash or raise an exception.
|
||||
|
||||
var s = new Set();
|
||||
var setIterator = %SetCreateIterator(s, 2);
|
||||
var setIterator = new builtins.SetIterator(s, 2);
|
||||
|
||||
var m = new Map();
|
||||
var mapIterator = %MapCreateIterator(m, 2);
|
||||
var mapIterator = new builtins.MapIterator(m, 2);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||
// Flags: --allow-natives-syntax --harmony
|
||||
var _holder = new Map();
|
||||
var _holder = new Map().entries();
|
||||
var _map = new Map();
|
||||
var _kind = 1;
|
||||
%MapCreateIterator(_holder, _kind);
|
||||
%MapIteratorInitialize(_holder, _map, _kind);
|
@ -1,5 +1,5 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||
// Flags: --allow-natives-syntax --harmony
|
||||
var _holder = %MapCreateIterator(new Map(), 3);
|
||||
var _holder = new Map().entries();
|
||||
%MapIteratorNext(_holder);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||
// Flags: --allow-natives-syntax --harmony
|
||||
var _holder = new Set();
|
||||
var arg1 = 2;
|
||||
%SetCreateIterator(_holder, arg1);
|
||||
var _holder = new Set().values();
|
||||
var _set = new Set();
|
||||
var arg2 = 2;
|
||||
%SetIteratorInitialize(_holder, _set, arg2);
|
@ -1,5 +1,5 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
|
||||
// Flags: --allow-natives-syntax --harmony
|
||||
var _holder = %SetCreateIterator(new Set(), 2);
|
||||
var _holder = new Set().values();
|
||||
%SetIteratorNext(_holder);
|
||||
|
@ -51,7 +51,7 @@ EXPECTED_FUNCTION_COUNT = 358
|
||||
EXPECTED_FUZZABLE_COUNT = 325
|
||||
EXPECTED_CCTEST_COUNT = 6
|
||||
EXPECTED_UNKNOWN_COUNT = 5
|
||||
EXPECTED_BUILTINS_COUNT = 782
|
||||
EXPECTED_BUILTINS_COUNT = 797
|
||||
|
||||
|
||||
# Don't call these at all.
|
||||
@ -159,7 +159,7 @@ CUSTOM_KNOWN_GOOD_INPUT = {
|
||||
"RegExpExecMultiple": [None, None, "['a']", "['a']", None],
|
||||
"SetAccessorProperty": [None, None, "undefined", "undefined", None, None,
|
||||
None],
|
||||
"SetCreateIterator": [None, "2", None],
|
||||
"SetIteratorInitialize": [None, None, "2", None],
|
||||
"SetDebugEventListener": ["undefined", None, None],
|
||||
"SetFunctionBreakPoint": [None, 200, None, None],
|
||||
"StringBuilderConcat": ["[1, 2, 3]", 3, None, None],
|
||||
@ -523,8 +523,8 @@ class Generator(object):
|
||||
def _JSMapIterator(self, name, recursion_budget):
|
||||
map_name = name + "_map"
|
||||
result = self._JSMap(map_name, recursion_budget)
|
||||
iterator_type = random.randint(1, 3)
|
||||
return (result + self._Variable(name, "%%MapCreateIterator(%s, %d)" %
|
||||
iterator_type = random.choice(['keys', 'values', 'entries'])
|
||||
return (result + self._Variable(name, "%s.%s()" %
|
||||
(map_name, iterator_type)))
|
||||
|
||||
def _JSProxy(self, name, recursion_budget):
|
||||
@ -552,8 +552,8 @@ class Generator(object):
|
||||
def _JSSetIterator(self, name, recursion_budget):
|
||||
set_name = name + "_set"
|
||||
result = self._JSSet(set_name, recursion_budget)
|
||||
iterator_type = random.randint(2, 3)
|
||||
return (result + self._Variable(name, "%%SetCreateIterator(%s, %d)" %
|
||||
iterator_type = random.choice(['values', 'entries'])
|
||||
return (result + self._Variable(name, "%s.%s()" %
|
||||
(set_name, iterator_type)))
|
||||
|
||||
def _JSTypedArray(self, name, recursion_budget):
|
||||
@ -666,13 +666,13 @@ class Generator(object):
|
||||
_JSFunctionProxy],
|
||||
"JSGeneratorObject": ["(function*(){ yield 1; })()", _JSGeneratorObject],
|
||||
"JSMap": ["new Map()", _JSMap],
|
||||
"JSMapIterator": ["%MapCreateIterator(new Map(), 3)", _JSMapIterator],
|
||||
"JSMapIterator": ["new Map().entries()", _JSMapIterator],
|
||||
"JSObject": ["new Object()", _JSObject],
|
||||
"JSProxy": ["Proxy.create({})", _JSProxy],
|
||||
"JSReceiver": ["new Object()", _JSReceiver],
|
||||
"JSRegExp": ["/ab/g", _JSRegExp],
|
||||
"JSSet": ["new Set()", _JSSet],
|
||||
"JSSetIterator": ["%SetCreateIterator(new Set(), 2)", _JSSetIterator],
|
||||
"JSSetIterator": ["new Set().values()", _JSSetIterator],
|
||||
"JSTypedArray": ["new Int32Array(2)", _JSTypedArray],
|
||||
"JSValue": ["new String('foo')", _JSValue],
|
||||
"JSWeakCollection": ["new WeakMap()", _JSWeakCollection],
|
||||
|
@ -1129,6 +1129,7 @@
|
||||
'../../src/symbol.js',
|
||||
'../../src/proxy.js',
|
||||
'../../src/collection.js',
|
||||
'../../src/collection-iterator.js',
|
||||
'../../src/generator.js',
|
||||
'../../src/array-iterator.js',
|
||||
'../../src/harmony-string.js',
|
||||
|
Loading…
Reference in New Issue
Block a user