Bug 1131043 - Part 2: Implement Map[@@species] and Set[@@species] getter. r=evilpie

This commit is contained in:
Tooru Fujisawa 2015-05-15 11:47:18 +09:00
parent c240fdbf02
commit 37a9d0086b
7 changed files with 66 additions and 3 deletions

View File

@ -32,3 +32,9 @@ function MapForEach(callbackfn, thisArg = undefined) {
callFunction(callbackfn, thisArg, entry[1], entry[0], M);
}
}
// ES6 final draft 23.1.2.2.
function MapSpecies() {
// Step 1.
return this;
}

View File

@ -1050,9 +1050,15 @@ const JSFunctionSpec MapObject::methods[] = {
JS_FS_END
};
const JSPropertySpec MapObject::staticProperties[] = {
JS_SELF_HOSTED_SYM_GET(species, "MapSpecies", 0),
JS_PS_END
};
static JSObject*
InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSProtoKey key, Native construct,
const JSPropertySpec* properties, const JSFunctionSpec* methods)
const JSPropertySpec* properties, const JSFunctionSpec* methods,
const JSPropertySpec* staticProperties)
{
RootedNativeObject proto(cx, global->createBlankPrototype(cx, clasp));
if (!proto)
@ -1061,6 +1067,7 @@ InitClass(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp, JSPro
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0));
if (!ctor ||
!JS_DefineProperties(cx, ctor, staticProperties) ||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
!GlobalObject::initBuiltinConstructor(cx, global, key, ctor, proto))
@ -1075,7 +1082,8 @@ MapObject::initClass(JSContext* cx, JSObject* obj)
{
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx,
InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods));
InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods,
staticProperties));
if (proto) {
// Define the "entries" method.
JSFunction* fun = JS_DefineFunction(cx, proto, "entries", entries, 0, 0);
@ -1782,12 +1790,18 @@ const JSFunctionSpec SetObject::methods[] = {
JS_FS_END
};
const JSPropertySpec SetObject::staticProperties[] = {
JS_SELF_HOSTED_SYM_GET(species, "SetSpecies", 0),
JS_PS_END
};
JSObject*
SetObject::initClass(JSContext* cx, JSObject* obj)
{
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
RootedObject proto(cx,
InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods));
InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods,
staticProperties));
if (proto) {
// Define the "values" method.
JSFunction* fun = JS_DefineFunction(cx, proto, "values", values, 0, 0);

View File

@ -108,6 +108,7 @@ class MapObject : public NativeObject {
private:
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];
static const JSPropertySpec staticProperties[];
ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
static ValueMap & extract(HandleObject o);
static ValueMap & extract(CallReceiver call);
@ -153,6 +154,7 @@ class SetObject : public NativeObject {
private:
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];
static const JSPropertySpec staticProperties[];
ValueSet* getData() { return static_cast<ValueSet*>(getPrivate()); }
static ValueSet & extract(CallReceiver call);
static void mark(JSTracer* trc, JSObject* obj);

View File

@ -32,3 +32,9 @@ function SetForEach(callbackfn, thisArg = undefined) {
callFunction(callbackfn, thisArg, value, value, S);
}
}
// ES6 final draft 23.2.2.2.
function SetSpecies() {
// Step 1.
return this;
}

View File

@ -2095,6 +2095,11 @@ inline int CheckIsSetterOp(JSSetterOp op);
{ nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \
{ nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } }
#define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) }
#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
{reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \
{ { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \
JSNATIVE_WRAPPER(nullptr) }
/*
* To define a native function, set call to a JSNativeWrapper. To define a

View File

@ -0,0 +1,22 @@
var BUGNUMBER = 1131043;
var summary = "Implement @@species getter for builtin types";
print(BUGNUMBER + ": " + summary);
for (var C of [Map, Set]) {
assertEq(C[Symbol.species], C);
}
for (C of [Map, Set]) {
var desc = Object.getOwnPropertyDescriptor(C, Symbol.species);
assertDeepEq(Object.keys(desc).sort(), ["configurable", "enumerable", "get", "set"]);
assertEq(desc.set, undefined);
assertEq(desc.enumerable, false);
assertEq(desc.configurable, true);
assertEq(desc.get.apply(null), null);
assertEq(desc.get.apply(undefined), undefined);
assertEq(desc.get.apply(42), 42);
}
if (typeof reportCompare === "function")
reportCompare(0, 0);

View File

@ -391,6 +391,14 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> globa
return false;
}
RootedValue std_species(cx);
std_species.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::species));
if (!JS_DefineProperty(cx, global, "std_species", std_species,
JSPROP_PERMANENT | JSPROP_READONLY))
{
return false;
}
return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&