Commit a8d9c58b authored by adamk's avatar adamk Committed by Commit bot

Add {Map,Set}::AsArray to the API

These return arrays representing the current contents of the given
Map/Set. They are similar to what would be returned by the JS code:

  Array.from(collection)

except that they are guaranteed side-effect free.

This will be useful in implementing structured clone which, as
specified in HTML, speaks in terms of the internal [[MapData]]
and [[SetData]] slots without going through the exposed iteration
ES semantics.

BUG=v8:3340
LOG=y

Review URL: https://codereview.chromium.org/1148383007

Cr-Commit-Position: refs/heads/master@{#28640}
parent 28cea2b7
......@@ -2951,6 +2951,12 @@ class V8_EXPORT Map : public Object {
public:
size_t Size() const;
/**
* Returns an array of [key, value] arrays representing the contents
* of this Map.
*/
Local<Array> AsArray() const;
/**
* Creates a new Map.
*/
......@@ -2971,6 +2977,11 @@ class V8_EXPORT Set : public Object {
public:
size_t Size() const;
/**
* Returns an array of the keys in this Set.
*/
Local<Array> AsArray() const;
/**
* Creates a new Set.
*/
......
......@@ -6131,6 +6131,31 @@ size_t v8::Map::Size() const {
}
Local<Array> Map::AsArray() const {
i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
i::Isolate* isolate = obj->GetIsolate();
i::Factory* factory = isolate->factory();
LOG_API(isolate, "Map::AsArray");
ENTER_V8(isolate);
i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(obj->table()));
int length = table->NumberOfElements();
i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
for (int i = 0; i < length; ++i) {
if (table->KeyAt(i)->IsTheHole()) continue;
i::HandleScope handle_scope(isolate);
i::Handle<i::FixedArray> entry = factory->NewFixedArray(2);
entry->set(0, table->KeyAt(i));
entry->set(1, table->ValueAt(i));
i::Handle<i::JSArray> entry_array =
factory->NewJSArrayWithElements(entry, i::FAST_ELEMENTS, 2);
result->set(i, *entry_array);
}
i::Handle<i::JSArray> result_array =
factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
return Utils::ToLocal(result_array);
}
Local<v8::Set> v8::Set::New(Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
LOG_API(i_isolate, "Set::New");
......@@ -6146,6 +6171,27 @@ size_t v8::Set::Size() const {
}
Local<Array> Set::AsArray() const {
i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
i::Isolate* isolate = obj->GetIsolate();
i::Factory* factory = isolate->factory();
LOG_API(isolate, "Set::AsArray");
ENTER_V8(isolate);
i::Handle<i::OrderedHashSet> table(i::OrderedHashSet::cast(obj->table()));
int length = table->NumberOfElements();
i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
for (int i = 0; i < length; ++i) {
i::Object* key = table->KeyAt(i);
if (!key->IsTheHole()) {
result->set(i, key);
}
}
i::Handle<i::JSArray> result_array =
factory->NewJSArrayWithElements(result, i::FAST_ELEMENTS, length);
return Utils::ToLocal(result_array);
}
bool Value::IsPromise() const {
auto self = Utils::OpenHandle(this);
return i::Object::IsPromise(self);
......
......@@ -21116,6 +21116,17 @@ TEST(Map) {
CHECK(val->IsMap());
map = v8::Local<v8::Map>::Cast(val);
CHECK_EQ(2, map->Size());
v8::Local<v8::Array> entries = map->AsArray();
CHECK_EQ(2, entries->Length());
v8::Local<v8::Array> entry = entries->Get(0).As<v8::Array>();
CHECK_EQ(2, entry->Length());
CHECK_EQ(1, entry->Get(0).As<v8::Int32>()->Value());
CHECK_EQ(2, entry->Get(1).As<v8::Int32>()->Value());
entry = entries->Get(1).As<v8::Array>();
CHECK_EQ(2, entry->Length());
CHECK_EQ(3, entry->Get(0).As<v8::Int32>()->Value());
CHECK_EQ(4, entry->Get(1).As<v8::Int32>()->Value());
}
......@@ -21133,4 +21144,9 @@ TEST(Set) {
CHECK(val->IsSet());
set = v8::Local<v8::Set>::Cast(val);
CHECK_EQ(2, set->Size());
v8::Local<v8::Array> keys = set->AsArray();
CHECK_EQ(2, keys->Length());
CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
}
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