Bug 992958 - Add support for prototype JSPropertySpecs on ClassSpec. r=luke

This commit is contained in:
Bobby Holley 2014-05-23 16:53:03 -07:00
Родитель 8cb3d69adf
Коммит 09f9f51b84
4 изменённых файлов: 72 добавлений и 31 удалений

Просмотреть файл

@ -292,6 +292,7 @@ struct ClassSpec
ClassObjectCreationOp createPrototype;
const JSFunctionSpec *constructorFunctions;
const JSFunctionSpec *prototypeFunctions;
const JSPropertySpec *prototypeProperties;
FinishClassInitOp finishInit;
bool defined() const { return !!createConstructor; }
};
@ -322,7 +323,7 @@ struct ClassExtension
JSWeakmapKeyDelegateOp weakmapKeyDelegateOp;
};
#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr}
#define JS_NULL_CLASS_SPEC {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
#define JS_NULL_CLASS_EXT {nullptr,nullptr,nullptr,false,nullptr}
struct ObjectOps
@ -365,7 +366,7 @@ typedef void (*JSClassInternal)();
struct JSClass {
JS_CLASS_MEMBERS(JSFinalizeOp);
void *reserved[31];
void *reserved[32];
};
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot

Просмотреть файл

@ -3049,6 +3049,7 @@ const Class DateObject::class_ = {
GenericCreatePrototype<&DateObject::class_>,
date_static_methods,
date_methods,
nullptr,
FinishDateClassInit
}
};

Просмотреть файл

@ -383,7 +383,8 @@ GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JS
}
// We don't always have a prototype (i.e. Math and JSON). If we don't,
// |createPrototype| and |prototypeFunctions| should both be null.
// |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
// should all be null.
RootedObject proto(cx);
if (clasp->spec.createPrototype) {
proto = clasp->spec.createPrototype(cx, key);
@ -394,6 +395,10 @@ GlobalObject::resolveConstructor(JSContext *cx, Handle<GlobalObject*> global, JS
if (!JS_DefineFunctions(cx, proto, funs))
return false;
}
if (const JSPropertySpec *props = clasp->spec.prototypeProperties) {
if (!JS_DefineProperties(cx, proto, props))
return false;
}
// If the prototype exists, link it with the constructor.
if (proto && !LinkConstructorAndPrototype(cx, ctor, proto))

Просмотреть файл

@ -443,41 +443,68 @@ JSXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper,
return true;
}
// Find the properties available, if any.
const JSFunctionSpec *fs = clasp->spec.prototypeFunctions;
if (!fs)
return true;
// Compute the property name we're looking for. We'll handle indexed
// properties when we start supporting arrays.
if (!JSID_IS_STRING(id))
return true;
Rooted<JSFlatString*> str(cx, JSID_TO_FLAT_STRING(id));
// Scan through the properties. If we don't find anything, we're done.
for (; fs->name; ++fs) {
// Scan through the functions.
const JSFunctionSpec *fsMatch = nullptr;
for (const JSFunctionSpec *fs = clasp->spec.prototypeFunctions; fs && fs->name; ++fs) {
// We don't support self-hosted functions yet. See bug 972987.
if (fs->selfHostedName)
continue;
if (JS_FlatStringEqualsAscii(str, fs->name))
if (JS_FlatStringEqualsAscii(str, fs->name)) {
fsMatch = fs;
break;
}
}
if (!fs->name)
return true;
if (fsMatch) {
// Generate an Xrayed version of the method.
Rooted<JSFunction*> fun(cx, JS_NewFunctionById(cx, fsMatch->call.op, fsMatch->nargs,
0, wrapper, id));
if (!fun)
return false;
// Generate an Xrayed version of the method.
Rooted<JSFunction*> fun(cx, JS_NewFunctionById(cx, fs->call.op, fs->nargs,
0, wrapper, id));
if (!fun)
return false;
// The generic Xray machinery only defines non-own properties on the holder.
// This is broken, and will be fixed at some point, but for now we need to
// cache the value explicitly. See the corresponding call to
// JS_GetPropertyById at the top of this function.
RootedObject funObj(cx, JS_GetFunctionObject(fun));
return JS_DefinePropertyById(cx, holder, id, funObj, 0) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
}
// The generic Xray machinery only defines non-own properties on the holder.
// This is broken, and will be fixed at some point, but for now we need to
// cache the value explicitly. See the corresponding call to
// JS_GetPropertyById at the top of this function.
RootedValue value(cx, ObjectValue(*JS_GetFunctionObject(fun)));
return JS_DefinePropertyById(cx, holder, id, value, 0) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
// Scan through the properties.
const JSPropertySpec *psMatch = nullptr;
for (const JSPropertySpec *ps = clasp->spec.prototypeProperties; ps && ps->name; ++ps) {
// We don't support self-hosted accessors yet (see bug 972987). And given
// the confusion outlined in bug 992977, we can't support JSPropertyOp-
// backed entries either (which in practice is fine).
if (!(ps->flags & JSPROP_NATIVE_ACCESSORS))
continue;
if (JS_FlatStringEqualsAscii(str, ps->name)) {
psMatch = ps;
break;
}
}
if (psMatch) {
// The generic Xray machinery only defines non-own properties on the holder.
// This is broken, and will be fixed at some point, but for now we need to
// cache the value explicitly. See the corresponding call to
// JS_GetPropertyById at the top of this function.
//
// Note also that the public-facing API here doesn't give us a way to
// pass along JITInfo. It's probably ok though, since Xrays are already
// pretty slow.
return JS_DefinePropertyById(cx, holder, id,
UndefinedHandleValue, psMatch->flags,
psMatch->getter.propertyOp.op, psMatch->setter.propertyOp.op) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
}
return true;
}
bool
@ -498,13 +525,8 @@ JSXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags
MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == getProtoKey(holder));
MOZ_ASSERT(clasp->spec.defined());
// Find the properties available, if any.
const JSFunctionSpec *fs = clasp->spec.prototypeFunctions;
if (!fs)
return true;
// Intern all the strings, and pass theme to the caller.
for (; fs->name; ++fs) {
for (const JSFunctionSpec *fs = clasp->spec.prototypeFunctions; fs && fs->name; ++fs) {
// We don't support self-hosted functions yet. See bug 972987.
if (fs->selfHostedName)
continue;
@ -514,6 +536,18 @@ JSXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags
if (!props.append(INTERNED_STRING_TO_JSID(cx, str)))
return false;
}
for (const JSPropertySpec *ps = clasp->spec.prototypeProperties; ps && ps->name; ++ps) {
// We don't support self-hosted functions yet. See bug 972987.
// Note that this is also kind of an abuse of JSPROP_NATIVE_ACCESSORS.
// See bug 992977.
if (!(ps->flags & JSPROP_NATIVE_ACCESSORS))
continue;
RootedString str(cx, JS_InternString(cx, ps->name));
if (!str)
return false;
if (!props.append(INTERNED_STRING_TO_JSID(cx, str)))
return false;
}
// Add the 'constructor' property.
return props.append(GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONSTRUCTOR));