Bug 1121332. Part 3 - export MapObject from JS. r=jorendorff.

This commit is contained in:
JW Wang 2015-01-31 13:22:48 +13:00
parent 54a7b4ad6d
commit 35dfd3bbc3
3 changed files with 207 additions and 36 deletions

View File

@ -1305,11 +1305,24 @@ 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)
{
@ -1318,15 +1331,21 @@ MapObject::extract(CallReceiver call)
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;
}
@ -1337,19 +1356,31 @@ MapObject::size(JSContext *cx, unsigned argc, Value *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
@ -1359,15 +1390,31 @@ MapObject::get(JSContext *cx, unsigned argc, Value *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
@ -1433,16 +1480,21 @@ MapObject::delete_(JSContext *cx, unsigned argc, Value *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
@ -1487,13 +1539,9 @@ MapObject::entries(JSContext *cx, unsigned argc, Value *vp)
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
@ -1503,6 +1551,18 @@ MapObject::clear(JSContext *cx, unsigned argc, Value *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)
{
@ -2033,3 +2093,75 @@ 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);
}

View File

@ -95,20 +95,28 @@ class MapObject : public NativeObject {
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);

View File

@ -4558,6 +4558,37 @@ 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 */
/*