/**
* Returns true if this value is a Map.
- * This is an experimental feature.
*/
bool IsMap() const;
/**
* Returns true if this value is a Set.
- * This is an experimental feature.
*/
bool IsSet() const;
/**
* Returns true if this value is a Map Iterator.
- * This is an experimental feature.
*/
bool IsMapIterator() const;
/**
* Returns true if this value is a Set Iterator.
- * This is an experimental feature.
*/
bool IsSetIterator() const;
/**
* Returns true if this value is a WeakMap.
- * This is an experimental feature.
*/
bool IsWeakMap() const;
/**
* Returns true if this value is a WeakSet.
- * This is an experimental feature.
*/
bool IsWeakSet() const;
};
+/**
+ * An instance of the built-in Map constructor (ECMA-262, 6th Edition, 23.1.1).
+ */
+class V8_EXPORT Map : public Object {
+ public:
+ size_t Size() const;
+
+ /**
+ * Creates a new Map.
+ */
+ static Local<Map> New(Isolate* isolate);
+
+ V8_INLINE static Map* Cast(Value* obj);
+
+ private:
+ Map();
+ static void CheckCast(Value* obj);
+};
+
+
+/**
+ * An instance of the built-in Set constructor (ECMA-262, 6th Edition, 23.2.1).
+ */
+class V8_EXPORT Set : public Object {
+ public:
+ size_t Size() const;
+
+ /**
+ * Creates a new Set.
+ */
+ static Local<Set> New(Isolate* isolate);
+
+ V8_INLINE static Set* Cast(Value* obj);
+
+ private:
+ Set();
+ static void CheckCast(Value* obj);
+};
+
+
template<typename T>
class ReturnValue {
public:
}
+Map* Map::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Map*>(value);
+}
+
+
+Set* Set::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Set*>(value);
+}
+
+
Promise* Promise::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
}
+void v8::Map::CheckCast(Value* that) {
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ Utils::ApiCheck(obj->IsJSMap(), "v8::Map::Cast()",
+ "Could not convert to Map");
+}
+
+
+void v8::Set::CheckCast(Value* that) {
+ i::Handle<i::Object> obj = Utils::OpenHandle(that);
+ Utils::ApiCheck(obj->IsJSSet(), "v8::Set::Cast()",
+ "Could not convert to Set");
+}
+
+
void v8::Promise::CheckCast(Value* that) {
Utils::ApiCheck(that->IsPromise(),
"v8::Promise::Cast()",
}
+Local<v8::Map> v8::Map::New(Isolate* isolate) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ LOG_API(i_isolate, "Map::New");
+ ENTER_V8(i_isolate);
+ i::Handle<i::JSMap> obj = i_isolate->factory()->NewJSMap();
+ return Utils::ToLocal(obj);
+}
+
+
+size_t v8::Map::Size() const {
+ i::Handle<i::JSMap> obj = Utils::OpenHandle(this);
+ return i::OrderedHashMap::cast(obj->table())->NumberOfElements();
+}
+
+
+Local<v8::Set> v8::Set::New(Isolate* isolate) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ LOG_API(i_isolate, "Set::New");
+ ENTER_V8(i_isolate);
+ i::Handle<i::JSSet> obj = i_isolate->factory()->NewJSSet();
+ return Utils::ToLocal(obj);
+}
+
+
+size_t v8::Set::Size() const {
+ i::Handle<i::JSSet> obj = Utils::OpenHandle(this);
+ return i::OrderedHashSet::cast(obj->table())->NumberOfElements();
+}
+
+
bool Value::IsPromise() const {
auto self = Utils::OpenHandle(this);
return i::Object::IsPromise(self);
V(RegExp, JSRegExp) \
V(Object, JSObject) \
V(Array, JSArray) \
+ V(Map, JSMap) \
+ V(Set, JSSet) \
V(ArrayBuffer, JSArrayBuffer) \
V(ArrayBufferView, JSArrayBufferView) \
V(TypedArray, JSTypedArray) \
v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Array> ToLocal(
v8::internal::Handle<v8::internal::JSArray> obj);
+ static inline Local<Map> ToLocal(
+ v8::internal::Handle<v8::internal::JSMap> obj);
+ static inline Local<Set> ToLocal(
+ v8::internal::Handle<v8::internal::JSSet> obj);
static inline Local<ArrayBuffer> ToLocal(
v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
static inline Local<ArrayBufferView> ToLocal(
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
+MAKE_TO_LOCAL(ToLocal, JSMap, Map)
+MAKE_TO_LOCAL(ToLocal, JSSet, Set)
MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
native_context()->set_data_view_fun(*data_view_fun);
}
- // -- M a p
- InstallFunction(global, "Map", JS_MAP_TYPE, JSMap::kSize,
- isolate->initial_object_prototype(), Builtins::kIllegal);
+ { // -- M a p
+ Handle<JSFunction> js_map_fun = InstallFunction(
+ global, "Map", JS_MAP_TYPE, JSMap::kSize,
+ isolate->initial_object_prototype(), Builtins::kIllegal);
+ native_context()->set_js_map_map(js_map_fun->initial_map());
+ }
- // -- S e t
- InstallFunction(global, "Set", JS_SET_TYPE, JSSet::kSize,
- isolate->initial_object_prototype(), Builtins::kIllegal);
+ { // -- S e t
+ Handle<JSFunction> js_set_fun = InstallFunction(
+ global, "Set", JS_SET_TYPE, JSSet::kSize,
+ isolate->initial_object_prototype(), Builtins::kIllegal);
+ native_context()->set_js_set_map(js_set_fun->initial_map());
+ }
{ // Set up the iterator result object
STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2);
V(STRONG_GENERATOR_FUNCTION_MAP_INDEX, Map, strong_generator_function_map) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \
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_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) \
STRONG_GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
ITERATOR_RESULT_MAP_INDEX,
+ JS_MAP_MAP_INDEX,
+ JS_SET_MAP_INDEX,
MAP_ITERATOR_MAP_INDEX,
SET_ITERATOR_MAP_INDEX,
ARRAY_VALUES_ITERATOR_INDEX,
}
+Handle<JSMap> Factory::NewJSMap() {
+ Handle<Map> map(isolate()->native_context()->js_map_map());
+ Handle<JSMap> js_map = Handle<JSMap>::cast(NewJSObjectFromMap(map));
+ Runtime::JSMapInitialize(isolate(), js_map);
+ return js_map;
+}
+
+
+Handle<JSSet> Factory::NewJSSet() {
+ Handle<Map> map(isolate()->native_context()->js_set_map());
+ Handle<JSSet> js_set = Handle<JSSet>::cast(NewJSObjectFromMap(map));
+ Runtime::JSSetInitialize(isolate(), js_set);
+ return js_set;
+}
+
+
Handle<JSMapIterator> Factory::NewJSMapIterator() {
Handle<Map> map(isolate()->native_context()->map_iterator_map());
CALL_HEAP_FUNCTION(isolate(),
Handle<JSDataView> NewJSDataView(Handle<JSArrayBuffer> buffer,
size_t byte_offset, size_t byte_length);
+ Handle<JSMap> NewJSMap();
+ Handle<JSSet> NewJSSet();
+
// TODO(aandrey): Maybe these should take table, index and kind arguments.
Handle<JSMapIterator> NewJSMapIterator();
Handle<JSSetIterator> NewJSSetIterator();
}
+void Runtime::JSSetInitialize(Isolate* isolate, Handle<JSSet> set) {
+ Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
+ set->set_table(*table);
+}
+
+
RUNTIME_FUNCTION(Runtime_SetInitialize) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
- Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
- holder->set_table(*table);
+ Runtime::JSSetInitialize(isolate, holder);
return *holder;
}
}
+void Runtime::JSMapInitialize(Isolate* isolate, Handle<JSMap> map) {
+ Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
+ map->set_table(*table);
+}
+
+
RUNTIME_FUNCTION(Runtime_MapInitialize) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
- Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
- holder->set_table(*table);
+ Runtime::JSMapInitialize(isolate, holder);
return *holder;
}
Isolate* isolate, Handle<FixedArray> literals,
Handle<FixedArray> elements, bool is_strong);
+
+ static void JSMapInitialize(Isolate* isolate, Handle<JSMap> map);
+ static void JSSetInitialize(Isolate* isolate, Handle<JSSet> set);
+
static void WeakCollectionInitialize(
Isolate* isolate, Handle<JSWeakCollection> weak_collection);
static void WeakCollectionSet(Handle<JSWeakCollection> weak_collection,
CHECK(result->Value() == 5.0);
}
+
+
+TEST(Map) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Map> map = v8::Map::New(isolate);
+ CHECK(map->IsObject());
+ CHECK(map->IsMap());
+ CHECK_EQ(0, map->Size());
+
+ v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
+ CHECK(val->IsMap());
+ map = v8::Local<v8::Map>::Cast(val);
+ CHECK_EQ(2, map->Size());
+}
+
+
+TEST(Set) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Set> set = v8::Set::New(isolate);
+ CHECK(set->IsObject());
+ CHECK(set->IsSet());
+ CHECK_EQ(0, set->Size());
+
+ v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
+ CHECK(val->IsSet());
+ set = v8::Local<v8::Set>::Cast(val);
+ CHECK_EQ(2, set->Size());
+}
}
-TEST(Set) {
+TEST(HashSet) {
TestSet(Hash, 100);
TestSet(CollisionHash, 50);
}