Reviewers: jochen, arv,

https://codereview.chromium.org/1155893003/diff/1/include/v8.h
File include/v8.h (right):

https://codereview.chromium.org/1155893003/diff/1/include/v8.h#newcode2986
include/v8.h:2986: * Guaranteed to be side-effect free if the array
contains no holes.
On 2015/05/26 16:37:40, arv wrote:
If the main use case is structured clone we could do an array where
the keys and
values are interleaved.

[k0, v0, k1, v1, ... kn, vn]

Let's leave this for a later round where we optimize the performance.
For now I'd rather leave this symmetric with AsArray().

https://codereview.chromium.org/1155893003/diff/1/src/collection.js
File src/collection.js (right):

https://codereview.chromium.org/1155893003/diff/1/src/collection.js#newcode451
src/collection.js:451: }
On 2015/05/26 16:37:40, arv wrote:
;

Done.

https://codereview.chromium.org/1155893003/diff/1/src/collection.js#newcode460
src/collection.js:460: }
On 2015/05/26 16:37:40, arv wrote:
;

Done.

Description:
Add {Map,Set}::FromArray to the API

Depends on https://codereview.chromium.org/1148383007/.

These are similar to the Map/Set constructors when called with an array,
except that they are guaranteed to be side-effect free if called with
a packed array.

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

Please review this at https://codereview.chromium.org/1155893003/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+77, -2 lines):
  M include/v8.h
  M src/api.cc
  M src/bootstrapper.cc
  M src/collection.js
  M src/contexts.h
  M test/cctest/test-api.cc


Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index 00bc3364bb8edbaef662039533c5432c52e6ba56..a7390555d565fe683d5d9001a90cb25b0c05c7f9 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2976,10 +2976,18 @@ class V8_EXPORT Map : public Object {
   Local<Array> AsArray() const;

   /**
-   * Creates a new Map.
+   * Creates a new empty Map.
    */
   static Local<Map> New(Isolate* isolate);

+  /**
+ * Creates a new Map containing the elements of array, which must be comprised
+   * of [key, value] arrays.
+   * Guaranteed to be side-effect free if the array contains no holes.
+   */
+ static V8_WARN_UNUSED_RESULT MaybeLocal<Map> FromArray(Local<Context> context, + Local<Array> array);
+
   V8_INLINE static Map* Cast(Value* obj);

  private:
@@ -3001,10 +3009,17 @@ class V8_EXPORT Set : public Object {
   Local<Array> AsArray() const;

   /**
-   * Creates a new Set.
+   * Creates a new empty Set.
    */
   static Local<Set> New(Isolate* isolate);

+  /**
+   * Creates a new Set containing the items in array.
+   * Guaranteed to be side-effect free if the array contains no holes.
+   */
+ static V8_WARN_UNUSED_RESULT MaybeLocal<Set> FromArray(Local<Context> context, + Local<Array> array);
+
   V8_INLINE static Set* Cast(Value* obj);

  private:
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index d469917be6a9ae6f2924f69ac3240eeed33fff47..147b9f0242e3898def561185eaccbd36a67179d7 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -6154,6 +6154,19 @@ Local<Array> Map::AsArray() const {
 }


+MaybeLocal<Map> Map::FromArray(Local<Context> context, Local<Array> array) {
+  PREPARE_FOR_EXECUTION(context, "Map::FromArray", Map);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*array)};
+  has_pending_exception =
+      !i::Execution::Call(isolate, isolate->map_from_array(),
+                          isolate->factory()->undefined_value(),
+                          arraysize(argv), argv, false).ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Map);
+  RETURN_ESCAPED(Local<Map>::Cast(Utils::ToLocal(result)));
+}
+
+
 Local<v8::Set> v8::Set::New(Isolate* isolate) {
   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
   LOG_API(i_isolate, "Set::New");
@@ -6190,6 +6203,19 @@ Local<Array> Set::AsArray() const {
 }


+MaybeLocal<Set> Set::FromArray(Local<Context> context, Local<Array> array) {
+  PREPARE_FOR_EXECUTION(context, "Set::FromArray", Set);
+  i::Handle<i::Object> result;
+  i::Handle<i::Object> argv[] = {Utils::OpenHandle(*array)};
+  has_pending_exception =
+      !i::Execution::Call(isolate, isolate->set_from_array(),
+                          isolate->factory()->undefined_value(),
+                          arraysize(argv), argv, false).ToHandle(&result);
+  RETURN_ON_FAILED_EXECUTION(Set);
+  RETURN_ESCAPED(Local<Set>::Cast(Utils::ToLocal(result)));
+}
+
+
 bool Value::IsPromise() const {
   auto self = Utils::OpenHandle(this);
   return i::Object::IsPromise(self);
Index: src/bootstrapper.cc
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 597c1d1a53565f2c4316fb26dc0142d15c3bebdf..e32ce41cf5aef1fb5dfd89c045101c219bfdc837 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1647,6 +1647,8 @@ void Genesis::InstallNativeFunctions() {
   INSTALL_NATIVE(JSFunction, "$observeNativeObjectNotifierPerformChange",
                  native_object_notifier_perform_change);
   INSTALL_NATIVE(JSFunction, "$arrayValues", array_values_iterator);
+  INSTALL_NATIVE(JSFunction, "$mapFromArray", map_from_array);
+  INSTALL_NATIVE(JSFunction, "$setFromArray", set_from_array);
 }


Index: src/collection.js
diff --git a/src/collection.js b/src/collection.js
index eddf0f32655f1ed0be27c2a496c2a803e09d4391..00a14aa77c1347592d0f8481da4c5b0d4b410f6f 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+var $mapFromArray;
+var $setFromArray;
+
 (function(global, shared, exports) {

 "use strict";
@@ -437,4 +440,23 @@ $installFunctions(GlobalMap.prototype, DONT_ENUM, [
   "forEach", MapForEach
 ]);

+$mapFromArray = function(array) {
+  var map = new GlobalMap;
+  var length = array.length;
+  for (var i = 0; i < length; ++i) {
+    var entry = array[i];
+    %_CallFunction(map, entry[0], entry[1], MapSet);
+  }
+  return map;
+}
+
+$setFromArray = function(array) {
+  var set = new GlobalSet;
+  var length = array.length;
+  for (var i = 0; i < length; ++i) {
+    %_CallFunction(set, array[i], SetAdd);
+  }
+  return set;
+}
+
 })
Index: src/contexts.h
diff --git a/src/contexts.h b/src/contexts.h
index b1461f7cd87dd6d930851acc3eb813ebe52a5476..0e7e14a33fb46c44235d7f4d411bb699c7ea7ed6 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -186,6 +186,8 @@ enum BindingFlags {
V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \ V(JS_MAP_MAP_INDEX, Map, js_map_map) \ V(JS_SET_MAP_INDEX, Map, js_set_map) \ + V(MAP_FROM_ARRAY_INDEX, JSFunction, map_from_array) \ + V(SET_FROM_ARRAY_INDEX, JSFunction, set_from_array) \ V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \ V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \ V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator) \
@@ -426,6 +428,8 @@ class Context: public FixedArray {
     ITERATOR_RESULT_MAP_INDEX,
     JS_MAP_MAP_INDEX,
     JS_SET_MAP_INDEX,
+    MAP_FROM_ARRAY_INDEX,
+    SET_FROM_ARRAY_INDEX,
     MAP_ITERATOR_MAP_INDEX,
     SET_ITERATOR_MAP_INDEX,
     ARRAY_VALUES_ITERATOR_INDEX,
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 983586071574641910207e932ec88206ed414a84..c4748a11908c5914a341099718da3911f2f8cbe2 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -21151,6 +21151,9 @@ TEST(Map) {
   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());
+
+  map = v8::Map::FromArray(env.local(), entries).ToLocalChecked();
+  CHECK_EQ(2, map->Size());
 }


@@ -21173,4 +21176,7 @@ TEST(Set) {
   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());
+
+  set = v8::Set::FromArray(env.local(), keys).ToLocalChecked();
+  CHECK_EQ(2, set->Size());
 }


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to