Bug 1121332. Part 3 - export MapObject from JS. r=jorendorff. a=lmandel
authorJW Wang <jwwang@mozilla.com>
Sat, 31 Jan 2015 13:22:48 +1300
changeset 250185 e29d774c7215
parent 250184 ffdf11b39ebf
child 250186 3d9497f46338
push id4521
push usercpearce@mozilla.com
push date2015-03-04 01:22 +0000
treeherdermozilla-beta@8abdbdecd2d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, lmandel
bugs1121332
milestone37.0
Bug 1121332. Part 3 - export MapObject from JS. r=jorendorff. a=lmandel
js/src/builtin/MapObject.cpp
js/src/builtin/MapObject.h
js/src/jsapi.h
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1305,79 +1305,126 @@ MapObject::construct(JSContext *cx, unsi
 }
 
 bool
 MapObject::is(HandleValue v)
 {
     return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().as<MapObject>().getPrivate();
 }
 
+bool
+MapObject::is(HandleObject o)
+{
+    return o->hasClass(&class_) && o->as<MapObject>().getPrivate();
+}
+
 #define ARG0_KEY(cx, args, key)                                               \
     AutoHashableValueRooter key(cx);                                          \
     if (args.length() > 0 && !key.setValue(cx, args[0]))                      \
         return false
 
 ValueMap &
+MapObject::extract(HandleObject o)
+{
+    MOZ_ASSERT(o->hasClass(&MapObject::class_));
+    return *o->as<MapObject>().getData();
+}
+
+ValueMap &
 MapObject::extract(CallReceiver call)
 {
     MOZ_ASSERT(call.thisv().isObject());
     MOZ_ASSERT(call.thisv().toObject().hasClass(&MapObject::class_));
     return *call.thisv().toObject().as<MapObject>().getData();
 }
 
+uint32_t
+MapObject::size(JSContext *cx, HandleObject obj)
+{
+    MOZ_ASSERT(MapObject::is(obj));
+    ValueMap &map = extract(obj);
+    static_assert(sizeof(map.count()) <= sizeof(uint32_t),
+                  "map count must be precisely representable as a JS number");
+    return map.count();
+}
+
 bool
 MapObject::size_impl(JSContext *cx, CallArgs args)
 {
-    MOZ_ASSERT(MapObject::is(args.thisv()));
-
-    ValueMap &map = extract(args);
-    static_assert(sizeof(map.count()) <= sizeof(uint32_t),
-                  "map count must be precisely representable as a JS number");
-    args.rval().setNumber(map.count());
+    RootedObject obj(cx, &args.thisv().toObject());
+    args.rval().setNumber(size(cx, obj));
     return true;
 }
 
 bool
 MapObject::size(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::size_impl>(cx, args);
 }
 
 bool
+MapObject::get(JSContext *cx, HandleObject obj,
+               HandleValue key, MutableHandleValue rval)
+{
+    MOZ_ASSERT(MapObject::is(obj));
+
+    ValueMap &map = extract(obj);
+    AutoHashableValueRooter k(cx);
+
+    if (!k.setValue(cx, key))
+        return false;
+
+    if (ValueMap::Entry *p = map.get(k))
+        rval.set(p->value);
+    else
+        rval.setUndefined();
+
+    return true;
+}
+
+bool
 MapObject::get_impl(JSContext *cx, CallArgs args)
 {
-    MOZ_ASSERT(MapObject::is(args.thisv()));
-
-    ValueMap &map = extract(args);
-    ARG0_KEY(cx, args, key);
-
-    if (ValueMap::Entry *p = map.get(key))
-        args.rval().set(p->value);
-    else
-        args.rval().setUndefined();
-    return true;
+    RootedObject obj(cx, &args.thisv().toObject());
+    return get(cx, obj, args.get(0), args.rval());
 }
 
 bool
 MapObject::get(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::get_impl>(cx, args);
 }
 
 bool
+MapObject::has(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    MOZ_ASSERT(MapObject::is(obj));
+
+    ValueMap &map = extract(obj);
+    AutoHashableValueRooter k(cx);
+
+    if (!k.setValue(cx, key))
+        return false;
+
+    *rval = map.has(k);
+    return true;
+}
+
+bool
 MapObject::has_impl(JSContext *cx, CallArgs args)
 {
-    MOZ_ASSERT(MapObject::is(args.thisv()));
-
-    ValueMap &map = extract(args);
-    ARG0_KEY(cx, args, key);
-    args.rval().setBoolean(map.has(key));
-    return true;
+    bool found;
+    RootedObject obj(cx, &args.thisv().toObject());
+    if (has(cx, obj, args.get(0), &found)) {
+        args.rval().setBoolean(found);
+        return true;
+    }
+    return false;
 }
 
 bool
 MapObject::has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::has_impl>(cx, args);
 }
@@ -1434,25 +1481,30 @@ MapObject::delete_impl(JSContext *cx, Ca
 bool
 MapObject::delete_(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::delete_impl>(cx, args);
 }
 
 bool
+MapObject::iterator(JSContext *cx, IteratorKind kind,
+                    HandleObject obj, MutableHandleValue iter)
+{
+    MOZ_ASSERT(MapObject::is(obj));
+    ValueMap &map = extract(obj);
+    Rooted<JSObject*> iterobj(cx, MapIteratorObject::create(cx, obj, &map, kind));
+    return iterobj && (iter.setObject(*iterobj), true);
+}
+
+bool
 MapObject::iterator_impl(JSContext *cx, CallArgs args, IteratorKind kind)
 {
-    Rooted<MapObject*> mapobj(cx, &args.thisv().toObject().as<MapObject>());
-    ValueMap &map = *mapobj->getData();
-    Rooted<JSObject*> iterobj(cx, MapIteratorObject::create(cx, mapobj, &map, kind));
-    if (!iterobj)
-        return false;
-    args.rval().setObject(*iterobj);
-    return true;
+    RootedObject obj(cx, &args.thisv().toObject());
+    return iterator(cx, kind, obj, args.rval());
 }
 
 bool
 MapObject::keys_impl(JSContext *cx, CallArgs args)
 {
     return iterator_impl(cx, args, Keys);
 }
 
@@ -1487,32 +1539,40 @@ MapObject::entries(JSContext *cx, unsign
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, is, entries_impl, args);
 }
 
 bool
 MapObject::clear_impl(JSContext *cx, CallArgs args)
 {
-    Rooted<MapObject*> mapobj(cx, &args.thisv().toObject().as<MapObject>());
-    if (!mapobj->getData()->clear()) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
+    RootedObject obj(cx, &args.thisv().toObject());
     args.rval().setUndefined();
-    return true;
+    return clear(cx, obj);
 }
 
 bool
 MapObject::clear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, is, clear_impl, args);
 }
 
+bool
+MapObject::clear(JSContext *cx, HandleObject obj)
+{
+    MOZ_ASSERT(MapObject::is(obj));
+    ValueMap &map = extract(obj);
+    if (!map.clear()) {
+        js_ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
 JSObject *
 js_InitMapClass(JSContext *cx, HandleObject obj)
 {
     return MapObject::initClass(cx, obj);
 }
 
 
 /*** SetIterator *********************************************************************************/
@@ -2038,8 +2098,80 @@ const JSFunctionSpec selfhosting_collect
     JS_FS_END
 };
 
 bool
 js::InitSelfHostingCollectionIteratorFunctions(JSContext *cx, HandleObject obj)
 {
     return JS_DefineFunctions(cx, obj, selfhosting_collection_iterator_methods);
 }
+
+/*** JS public APIs **********************************************************/
+
+JS_PUBLIC_API(JSObject *)
+JS::NewMapObject(JSContext *cx)
+{
+    return MapObject::create(cx);
+}
+
+JS_PUBLIC_API(uint32_t)
+JS::MapSize(JSContext *cx, HandleObject obj)
+{
+    CHECK_REQUEST(cx);
+    return MapObject::size(cx, obj);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapGet(JSContext *cx, HandleObject obj,
+           HandleValue key, MutableHandleValue rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, key, rval);
+    return MapObject::get(cx, obj, key, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapHas(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, key);
+    return MapObject::has(cx, obj, key, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapSet(JSContext *cx, HandleObject obj,
+           HandleValue key, HandleValue val)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, key, val);
+    return MapObject::set(cx, obj, key, val);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapClear(JSContext *cx, HandleObject obj)
+{
+    CHECK_REQUEST(cx);
+    return MapObject::clear(cx, obj);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapKeys(JSContext *cx, HandleObject obj, MutableHandleValue rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, rval);
+    return MapObject::iterator(cx, MapObject::Keys, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapValues(JSContext *cx, HandleObject obj, MutableHandleValue rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, rval);
+    return MapObject::iterator(cx, MapObject::Values, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapEntries(JSContext *cx, HandleObject obj, MutableHandleValue rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, rval);
+    return MapObject::iterator(cx, MapObject::Entries, obj, rval);
+}
--- a/js/src/builtin/MapObject.h
+++ b/js/src/builtin/MapObject.h
@@ -90,30 +90,38 @@ class MapObject : public NativeObject {
     enum IteratorKind { Keys, Values, Entries };
 
     static JSObject *initClass(JSContext *cx, JSObject *obj);
     static const Class class_;
 
     static bool getKeysAndValuesInterleaved(JSContext *cx, HandleObject obj,
                                             JS::AutoValueVector *entries);
     static bool entries(JSContext *cx, unsigned argc, Value *vp);
-    static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue value);
     static bool has(JSContext *cx, unsigned argc, Value *vp);
     static MapObject* create(JSContext *cx);
 
+    static uint32_t size(JSContext *cx, HandleObject obj);
+    static bool get(JSContext *cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
+    static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
+    static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
+    static bool clear(JSContext *cx, HandleObject obj);
+    static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
+
   private:
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
     ValueMap *getData() { return static_cast<ValueMap *>(getPrivate()); }
+    static ValueMap & extract(HandleObject o);
     static ValueMap & extract(CallReceiver call);
     static void mark(JSTracer *trc, JSObject *obj);
     static void finalize(FreeOp *fop, JSObject *obj);
     static bool construct(JSContext *cx, unsigned argc, Value *vp);
 
     static bool is(HandleValue v);
+    static bool is(HandleObject o);
 
     static bool iterator_impl(JSContext *cx, CallArgs args, IteratorKind kind);
 
     static bool size_impl(JSContext *cx, CallArgs args);
     static bool size(JSContext *cx, unsigned argc, Value *vp);
     static bool get_impl(JSContext *cx, CallArgs args);
     static bool get(JSContext *cx, unsigned argc, Value *vp);
     static bool has_impl(JSContext *cx, CallArgs args);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4849,16 +4849,47 @@ IsWeakMapObject(JSObject *obj);
 extern JS_PUBLIC_API(bool)
 GetWeakMapEntry(JSContext *cx, JS::HandleObject mapObj, JS::HandleObject key,
                 JS::MutableHandleValue val);
 
 extern JS_PUBLIC_API(bool)
 SetWeakMapEntry(JSContext *cx, JS::HandleObject mapObj, JS::HandleObject key,
                 JS::HandleValue val);
 
+/*
+ * Map
+ */
+extern JS_PUBLIC_API(JSObject *)
+NewMapObject(JSContext *cx);
+
+extern JS_PUBLIC_API(uint32_t)
+MapSize(JSContext *cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+MapGet(JSContext *cx, HandleObject obj,
+       HandleValue key, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapHas(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
+
+extern JS_PUBLIC_API(bool)
+MapSet(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
+
+extern JS_PUBLIC_API(bool)
+MapClear(JSContext *cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+MapKeys(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapValues(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapEntries(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
 } /* namespace JS */
 
 /*
  * Dates.
  */
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec);