зеркало из https://github.com/mozilla/gecko-dev.git
Bug 992958 - Add support for prototype JSPropertySpecs on ClassSpec. r=luke
This commit is contained in:
Родитель
8cb3d69adf
Коммит
09f9f51b84
|
@ -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));
|
||||
|
|
Загрузка…
Ссылка в новой задаче