mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Fix for bug 798264 (Split property tables). r=bz.
--HG-- extra : rebase_source : 71456ae48d3d3e6014e8095837f7942cfe733a37
This commit is contained in:
parent
68f37a763d
commit
7964385bcb
@ -8,6 +8,7 @@
|
||||
|
||||
#include "BindingUtils.h"
|
||||
|
||||
#include "AccessCheck.h"
|
||||
#include "WrapperFactory.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "XPCQuickStubs.h"
|
||||
@ -140,8 +141,8 @@ static JSObject*
|
||||
CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
JSClass* constructorClass, JSNative constructorNative,
|
||||
unsigned ctorNargs, JSObject* proto,
|
||||
Prefable<JSFunctionSpec>* staticMethods,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name)
|
||||
{
|
||||
JSObject* constructor;
|
||||
@ -164,10 +165,6 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (staticMethods && !DefinePrefable(cx, constructor, staticMethods)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (constructorClass) {
|
||||
JSFunction* toString = js::DefineFunctionWithReserved(cx, constructor,
|
||||
"toString",
|
||||
@ -189,8 +186,28 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
STRING_TO_JSVAL(str));
|
||||
}
|
||||
|
||||
if (constants && !DefinePrefable(cx, constructor, constants)) {
|
||||
return NULL;
|
||||
if (properties) {
|
||||
if (properties->staticMethods &&
|
||||
!DefinePrefable(cx, constructor, properties->staticMethods)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (properties->constants &&
|
||||
!DefinePrefable(cx, constructor, properties->constants)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties) {
|
||||
if (chromeOnlyProperties->staticMethods &&
|
||||
!DefinePrefable(cx, constructor, chromeOnlyProperties->staticMethods)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->constants &&
|
||||
!DefinePrefable(cx, constructor, chromeOnlyProperties->constants)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
|
||||
@ -215,9 +232,8 @@ CreateInterfaceObject(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
static JSObject*
|
||||
CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
|
||||
JSObject* parentProto, JSClass* protoClass,
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
Prefable<JSPropertySpec>* properties,
|
||||
Prefable<ConstantSpec>* constants)
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties)
|
||||
{
|
||||
JSObject* ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto,
|
||||
global);
|
||||
@ -225,16 +241,38 @@ CreateInterfacePrototypeObject(JSContext* cx, JSObject* global,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (methods && !DefinePrefable(cx, ourProto, methods)) {
|
||||
return NULL;
|
||||
if (properties) {
|
||||
if (properties->methods &&
|
||||
!DefinePrefable(cx, ourProto, properties->methods)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (properties->attributes &&
|
||||
!DefinePrefable(cx, ourProto, properties->attributes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (properties->constants &&
|
||||
!DefinePrefable(cx, ourProto, properties->constants)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties && !DefinePrefable(cx, ourProto, properties)) {
|
||||
return NULL;
|
||||
}
|
||||
if (chromeOnlyProperties) {
|
||||
if (chromeOnlyProperties->methods &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->methods)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (constants && !DefinePrefable(cx, ourProto, constants)) {
|
||||
return NULL;
|
||||
if (chromeOnlyProperties->attributes &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->attributes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->constants &&
|
||||
!DefinePrefable(cx, ourProto, chromeOnlyProperties->constants)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return ourProto;
|
||||
@ -245,16 +283,21 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
|
||||
JSObject* protoProto, JSClass* protoClass,
|
||||
JSClass* constructorClass, JSNative constructor,
|
||||
unsigned ctorNargs, const DOMClass* domClass,
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
Prefable<JSPropertySpec>* properties,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
Prefable<JSFunctionSpec>* staticMethods, const char* name)
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeOnlyProperties,
|
||||
const char* name)
|
||||
{
|
||||
MOZ_ASSERT(protoClass || constructorClass || constructor,
|
||||
"Need at least one class or a constructor!");
|
||||
MOZ_ASSERT(!(methods || properties) || protoClass,
|
||||
MOZ_ASSERT(!((properties &&
|
||||
(properties->methods || properties->attributes)) ||
|
||||
(chromeOnlyProperties &&
|
||||
(chromeOnlyProperties->methods ||
|
||||
chromeOnlyProperties->attributes))) || protoClass,
|
||||
"Methods or properties but no protoClass!");
|
||||
MOZ_ASSERT(!staticMethods || constructorClass || constructor,
|
||||
MOZ_ASSERT(!((properties && properties->staticMethods) ||
|
||||
(chromeOnlyProperties && chromeOnlyProperties->staticMethods)) ||
|
||||
constructorClass || constructor,
|
||||
"Static methods but no constructorClass or constructor!");
|
||||
MOZ_ASSERT(bool(name) == bool(constructorClass || constructor),
|
||||
"Must have name precisely when we have an interface object");
|
||||
@ -263,7 +306,7 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
|
||||
JSObject* proto;
|
||||
if (protoClass) {
|
||||
proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
|
||||
methods, properties, constants);
|
||||
properties, chromeOnlyProperties);
|
||||
if (!proto) {
|
||||
return NULL;
|
||||
}
|
||||
@ -279,7 +322,7 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject *receiver,
|
||||
if (constructorClass || constructor) {
|
||||
interface = CreateInterfaceObject(cx, global, receiver, constructorClass,
|
||||
constructor, ctorNargs, proto,
|
||||
staticMethods, constants, name);
|
||||
properties, chromeOnlyProperties, name);
|
||||
if (!interface) {
|
||||
return NULL;
|
||||
}
|
||||
@ -420,104 +463,100 @@ ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
return ThrowErrorMessage(cx, MSG_ILLEGAL_CONSTRUCTOR);
|
||||
}
|
||||
|
||||
bool
|
||||
static bool
|
||||
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
JSPropertyDescriptor* desc,
|
||||
// And the things we need to determine the descriptor
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
jsid* methodIds,
|
||||
JSFunctionSpec* methodSpecs,
|
||||
size_t methodCount,
|
||||
Prefable<JSPropertySpec>* attributes,
|
||||
jsid* attributeIds,
|
||||
JSPropertySpec* attributeSpecs,
|
||||
size_t attributeCount,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
jsid* constantIds,
|
||||
ConstantSpec* constantSpecs,
|
||||
size_t constantCount)
|
||||
const NativeProperties* nativeProperties)
|
||||
{
|
||||
for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
|
||||
MOZ_ASSERT(methods[prefIdx].specs);
|
||||
if (methods[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = methods[prefIdx].specs - methodSpecs;
|
||||
for ( ; methodIds[i] != JSID_VOID; ++i) {
|
||||
if (id == methodIds[i]) {
|
||||
JSFunction *fun = JS_NewFunctionById(cx, methodSpecs[i].call.op,
|
||||
methodSpecs[i].nargs, 0,
|
||||
wrapper, id);
|
||||
if (!fun) {
|
||||
return false;
|
||||
if (nativeProperties->methods) {
|
||||
Prefable<JSFunctionSpec>* method;
|
||||
for (method = nativeProperties->methods; method->specs; ++method) {
|
||||
if (method->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = method->specs - nativeProperties->methodsSpecs;
|
||||
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
|
||||
if (id == nativeProperties->methodIds[i]) {
|
||||
JSFunctionSpec& methodSpec = nativeProperties->methodsSpecs[i];
|
||||
JSFunction *fun = JS_NewFunctionById(cx, methodSpec.call.op,
|
||||
methodSpec.nargs, 0,
|
||||
wrapper, id);
|
||||
if (!fun) {
|
||||
return false;
|
||||
}
|
||||
SET_JITINFO(fun, methodSpec.call.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->value.setObject(*funobj);
|
||||
desc->attrs = methodSpec.flags;
|
||||
desc->obj = wrapper;
|
||||
desc->setter = nullptr;
|
||||
desc->getter = nullptr;
|
||||
return true;
|
||||
}
|
||||
SET_JITINFO(fun, methodSpecs[i].call.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->value.setObject(*funobj);
|
||||
desc->attrs = methodSpecs[i].flags;
|
||||
desc->obj = wrapper;
|
||||
desc->setter = nullptr;
|
||||
desc->getter = nullptr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
|
||||
MOZ_ASSERT(attributes[prefIdx].specs);
|
||||
if (attributes[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = attributes[prefIdx].specs - attributeSpecs;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if (id == attributeIds[i]) {
|
||||
// Because of centralization, we need to make sure we fault in the
|
||||
// JitInfos as well. At present, until the JSAPI changes, the easiest
|
||||
// way to do this is wrap them up as functions ourselves.
|
||||
desc->attrs = attributeSpecs[i].flags & ~JSPROP_NATIVE_ACCESSORS;
|
||||
// They all have getters, so we can just make it.
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSFunction *fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].getter.op,
|
||||
0, 0, global, NULL);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attributeSpecs[i].getter.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->getter = js::CastAsJSPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_GETTER;
|
||||
if (attributeSpecs[i].setter.op) {
|
||||
// We have a setter! Make it.
|
||||
fun = JS_NewFunction(cx, (JSNative)attributeSpecs[i].setter.op,
|
||||
1, 0, global, NULL);
|
||||
if (nativeProperties->attributes) {
|
||||
Prefable<JSPropertySpec>* attr;
|
||||
for (attr = nativeProperties->attributes; attr->specs; ++attr) {
|
||||
if (attr->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = attr->specs - nativeProperties->attributeSpecs;
|
||||
for ( ; nativeProperties->attributeIds[i] != JSID_VOID; ++i) {
|
||||
if (id == nativeProperties->attributeIds[i]) {
|
||||
JSPropertySpec& attrSpec = nativeProperties->attributeSpecs[i];
|
||||
// Because of centralization, we need to make sure we fault in the
|
||||
// JitInfos as well. At present, until the JSAPI changes, the easiest
|
||||
// way to do this is wrap them up as functions ourselves.
|
||||
desc->attrs = attrSpec.flags & ~JSPROP_NATIVE_ACCESSORS;
|
||||
// They all have getters, so we can just make it.
|
||||
JSObject *global = JS_GetGlobalForObject(cx, wrapper);
|
||||
JSFunction *fun = JS_NewFunction(cx, (JSNative)attrSpec.getter.op,
|
||||
0, 0, global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attributeSpecs[i].setter.info);
|
||||
funobj = JS_GetFunctionObject(fun);
|
||||
desc->setter = js::CastAsJSStrictPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_SETTER;
|
||||
} else {
|
||||
desc->setter = NULL;
|
||||
SET_JITINFO(fun, attrSpec.getter.info);
|
||||
JSObject *funobj = JS_GetFunctionObject(fun);
|
||||
desc->getter = js::CastAsJSPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_GETTER;
|
||||
if (attrSpec.setter.op) {
|
||||
// We have a setter! Make it.
|
||||
fun = JS_NewFunction(cx, (JSNative)attrSpec.setter.op, 1, 0,
|
||||
global, nullptr);
|
||||
if (!fun)
|
||||
return false;
|
||||
SET_JITINFO(fun, attrSpec.setter.info);
|
||||
funobj = JS_GetFunctionObject(fun);
|
||||
desc->setter = js::CastAsJSStrictPropertyOp(funobj);
|
||||
desc->attrs |= JSPROP_SETTER;
|
||||
} else {
|
||||
desc->setter = nullptr;
|
||||
}
|
||||
desc->obj = wrapper;
|
||||
return true;
|
||||
}
|
||||
desc->obj = wrapper;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
|
||||
MOZ_ASSERT(constants[prefIdx].specs);
|
||||
if (constants[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = constants[prefIdx].specs - constantSpecs;
|
||||
for ( ; constantIds[i] != JSID_VOID; ++i) {
|
||||
if (id == constantIds[i]) {
|
||||
desc->attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
desc->obj = wrapper;
|
||||
desc->value = constantSpecs[i].value;
|
||||
return true;
|
||||
if (nativeProperties->constants) {
|
||||
Prefable<ConstantSpec>* constant;
|
||||
for (constant = nativeProperties->constants; constant->specs; ++constant) {
|
||||
if (constant->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = constant->specs - nativeProperties->constantSpecs;
|
||||
for ( ; nativeProperties->constantIds[i] != JSID_VOID; ++i) {
|
||||
if (id == nativeProperties->constantIds[i]) {
|
||||
desc->attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
desc->obj = wrapper;
|
||||
desc->value = nativeProperties->constantSpecs[i].value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -527,59 +566,75 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
}
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
jsid* methodIds,
|
||||
JSFunctionSpec* methodSpecs,
|
||||
size_t methodCount,
|
||||
Prefable<JSPropertySpec>* attributes,
|
||||
jsid* attributeIds,
|
||||
JSPropertySpec* attributeSpecs,
|
||||
size_t attributeCount,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
jsid* constantIds,
|
||||
ConstantSpec* constantSpecs,
|
||||
size_t constantCount)
|
||||
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
JSPropertyDescriptor* desc,
|
||||
const NativeProperties* nativeProperties,
|
||||
const NativeProperties* chromeOnlyNativeProperties)
|
||||
{
|
||||
for (size_t prefIdx = 0; prefIdx < methodCount; ++prefIdx) {
|
||||
MOZ_ASSERT(methods[prefIdx].specs);
|
||||
if (methods[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = methods[prefIdx].specs - methodSpecs;
|
||||
for ( ; methodIds[i] != JSID_VOID; ++i) {
|
||||
if ((methodSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(methodIds[i])) {
|
||||
return false;
|
||||
if (nativeProperties &&
|
||||
!XrayResolveProperty(cx, wrapper, id, desc, nativeProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!desc->obj &&
|
||||
chromeOnlyNativeProperties &&
|
||||
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
|
||||
!XrayResolveProperty(cx, wrapper, id, desc, chromeOnlyNativeProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
const NativeProperties* nativeProperties)
|
||||
{
|
||||
if (nativeProperties->methods) {
|
||||
Prefable<JSFunctionSpec>* method;
|
||||
for (method = nativeProperties->methods; method->specs; ++method) {
|
||||
if (method->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = method->specs - nativeProperties->methodsSpecs;
|
||||
for ( ; nativeProperties->methodIds[i] != JSID_VOID; ++i) {
|
||||
if ((nativeProperties->methodsSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(nativeProperties->methodIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t prefIdx = 0; prefIdx < attributeCount; ++prefIdx) {
|
||||
MOZ_ASSERT(attributes[prefIdx].specs);
|
||||
if (attributes[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = attributes[prefIdx].specs - attributeSpecs;
|
||||
for ( ; attributeIds[i] != JSID_VOID; ++i) {
|
||||
if ((attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(attributeIds[i])) {
|
||||
return false;
|
||||
if (nativeProperties->attributes) {
|
||||
Prefable<JSPropertySpec>* attr;
|
||||
for (attr = nativeProperties->attributes; attr->specs; ++attr) {
|
||||
if (attr->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = attr->specs - nativeProperties->attributeSpecs;
|
||||
for ( ; nativeProperties->attributeIds[i] != JSID_VOID; ++i) {
|
||||
if ((nativeProperties->attributeSpecs[i].flags & JSPROP_ENUMERATE) &&
|
||||
!props.append(nativeProperties->attributeIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t prefIdx = 0; prefIdx < constantCount; ++prefIdx) {
|
||||
MOZ_ASSERT(constants[prefIdx].specs);
|
||||
if (constants[prefIdx].enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = constants[prefIdx].specs - constantSpecs;
|
||||
for ( ; constantIds[i] != JSID_VOID; ++i) {
|
||||
if (!props.append(constantIds[i])) {
|
||||
return false;
|
||||
if (nativeProperties->constants) {
|
||||
Prefable<ConstantSpec>* constant;
|
||||
for (constant = nativeProperties->constants; constant->specs; ++constant) {
|
||||
if (constant->enabled) {
|
||||
// Set i to be the index into our full list of ids/specs that we're
|
||||
// looking at now.
|
||||
size_t i = constant->specs - nativeProperties->constantSpecs;
|
||||
for ( ; nativeProperties->constantIds[i] != JSID_VOID; ++i) {
|
||||
if (!props.append(nativeProperties->constantIds[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -588,6 +643,26 @@ XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JSObject* wrapper,
|
||||
JS::AutoIdVector& props,
|
||||
const NativeProperties* nativeProperties,
|
||||
const NativeProperties* chromeOnlyNativeProperties)
|
||||
{
|
||||
if (nativeProperties &&
|
||||
!XrayEnumerateProperties(props, nativeProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chromeOnlyNativeProperties &&
|
||||
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
|
||||
!XrayEnumerateProperties(props, chromeOnlyNativeProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropertyOnPrototype(JSContext* cx, JSObject* proxy, jsid id, bool* found,
|
||||
JS::Value* vp)
|
||||
|
@ -344,6 +344,22 @@ struct Prefable {
|
||||
T* specs;
|
||||
};
|
||||
|
||||
struct NativeProperties
|
||||
{
|
||||
Prefable<JSFunctionSpec>* staticMethods;
|
||||
jsid* staticMethodIds;
|
||||
JSFunctionSpec* staticMethodsSpecs;
|
||||
Prefable<JSFunctionSpec>* methods;
|
||||
jsid* methodIds;
|
||||
JSFunctionSpec* methodsSpecs;
|
||||
Prefable<JSPropertySpec>* attributes;
|
||||
jsid* attributeIds;
|
||||
JSPropertySpec* attributeSpecs;
|
||||
Prefable<ConstantSpec>* constants;
|
||||
jsid* constantIds;
|
||||
ConstantSpec* constantSpecs;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a DOM interface object (if constructorClass is non-null) and/or a
|
||||
* DOM interface prototype object (if protoClass is non-null).
|
||||
@ -365,15 +381,14 @@ struct Prefable {
|
||||
* object of constructorClass, unless that's also null, in which
|
||||
* case we should not create an interface object at all.
|
||||
* ctorNargs is the length of the constructor function; 0 if no constructor
|
||||
* instanceClass is the JSClass of instance objects for this class. This can
|
||||
* be null if this is not a concrete proto.
|
||||
* methods and properties are to be defined on the interface prototype object;
|
||||
* these arguments are allowed to be null if there are no
|
||||
* methods or properties respectively.
|
||||
* constants are to be defined on the interface object and on the interface
|
||||
* prototype object; allowed to be null if there are no constants.
|
||||
* staticMethods are to be defined on the interface object; allowed to be null
|
||||
* if there are no static methods.
|
||||
* domClass is the DOMClass of instance objects for this class. This can be
|
||||
* null if this is not a concrete proto.
|
||||
* properties contains the methods, attributes and constants to be defined on
|
||||
* objects in any compartment.
|
||||
* chromeProperties contains the methods, attributes and constants to be defined
|
||||
* on objects in chrome compartments. This must be null if the
|
||||
* interface doesn't have any ChromeOnly properties or if the
|
||||
* object is being created in non-chrome compartment.
|
||||
*
|
||||
* At least one of protoClass and constructorClass should be non-null.
|
||||
* If constructorClass is non-null, the resulting interface object will be
|
||||
@ -388,10 +403,9 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* receiver,
|
||||
JSObject* protoProto, JSClass* protoClass,
|
||||
JSClass* constructorClass, JSNative constructor,
|
||||
unsigned ctorNargs, const DOMClass* domClass,
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
Prefable<JSPropertySpec>* properties,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
Prefable<JSFunctionSpec>* staticMethods, const char* name);
|
||||
const NativeProperties* properties,
|
||||
const NativeProperties* chromeProperties,
|
||||
const char* name);
|
||||
|
||||
template <class T>
|
||||
inline bool
|
||||
@ -1178,34 +1192,14 @@ public:
|
||||
bool
|
||||
XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
||||
JSPropertyDescriptor* desc,
|
||||
// And the things we need to determine the descriptor
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
jsid* methodIds,
|
||||
JSFunctionSpec* methodSpecs,
|
||||
size_t methodCount,
|
||||
Prefable<JSPropertySpec>* attributes,
|
||||
jsid* attributeIds,
|
||||
JSPropertySpec* attributeSpecs,
|
||||
size_t attributeCount,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
jsid* constantIds,
|
||||
ConstantSpec* constantSpecs,
|
||||
size_t constantCount);
|
||||
const NativeProperties* nativeProperties,
|
||||
const NativeProperties* chromeOnlyNativeProperties);
|
||||
|
||||
bool
|
||||
XrayEnumerateProperties(JS::AutoIdVector& props,
|
||||
Prefable<JSFunctionSpec>* methods,
|
||||
jsid* methodIds,
|
||||
JSFunctionSpec* methodSpecs,
|
||||
size_t methodCount,
|
||||
Prefable<JSPropertySpec>* attributes,
|
||||
jsid* attributeIds,
|
||||
JSPropertySpec* attributeSpecs,
|
||||
size_t attributeCount,
|
||||
Prefable<ConstantSpec>* constants,
|
||||
jsid* constantIds,
|
||||
ConstantSpec* constantSpecs,
|
||||
size_t constantCount);
|
||||
XrayEnumerateProperties(JSObject* wrapper,
|
||||
JS::AutoIdVector& props,
|
||||
const NativeProperties* nativeProperties,
|
||||
const NativeProperties* chromeOnlyNativeProperties);
|
||||
|
||||
// Transfer reference in ptr to smartPtr.
|
||||
template<class T>
|
||||
|
@ -866,9 +866,8 @@ class PropertyDefiner:
|
||||
|
||||
Subclasses should implement generateArray to generate the actual arrays of
|
||||
things we're defining. They should also set self.chrome to the list of
|
||||
things exposed to chrome and self.regular to the list of things exposed to
|
||||
web pages. self.chrome must be a superset of self.regular but also include
|
||||
all the ChromeOnly stuff.
|
||||
things only exposed to chrome and self.regular to the list of things exposed
|
||||
to both chrome and web pages.
|
||||
"""
|
||||
def __init__(self, descriptor, name):
|
||||
self.descriptor = descriptor
|
||||
@ -878,33 +877,31 @@ class PropertyDefiner:
|
||||
# in as needed.
|
||||
self.prefCacheData = []
|
||||
def hasChromeOnly(self):
|
||||
return len(self.chrome) > len(self.regular)
|
||||
return len(self.chrome) > 0
|
||||
def hasNonChromeOnly(self):
|
||||
return len(self.regular) > 0
|
||||
def variableName(self, chrome):
|
||||
if chrome and self.hasChromeOnly():
|
||||
return "sChrome" + self.name
|
||||
if self.hasNonChromeOnly():
|
||||
return "s" + self.name
|
||||
return "NULL"
|
||||
def usedForXrays(self, chrome):
|
||||
# We only need Xrays for methods, attributes and constants. And we only
|
||||
# need them for the non-chrome ones if we have no chromeonly things.
|
||||
# Otherwise (we have chromeonly attributes) we need Xrays for the chrome
|
||||
# methods/attributes/constants. Finally, in workers there are no Xrays.
|
||||
return ((self.name is "Methods" or self.name is "Attributes" or
|
||||
self.name is "Constants") and
|
||||
chrome == self.hasChromeOnly() and
|
||||
not self.descriptor.workers)
|
||||
if chrome:
|
||||
if self.hasChromeOnly():
|
||||
return "sChrome" + self.name
|
||||
else:
|
||||
if self.hasNonChromeOnly():
|
||||
return "s" + self.name
|
||||
return "nullptr"
|
||||
def usedForXrays(self):
|
||||
# We only need Xrays for methods, attributes and constants, but in
|
||||
# workers there are no Xrays.
|
||||
return (self.name is "Methods" or self.name is "Attributes" or
|
||||
self.name is "Constants") and not self.descriptor.workers
|
||||
|
||||
def __str__(self):
|
||||
# We only need to generate id arrays for things that will end
|
||||
# up used via ResolveProperty or EnumerateProperties.
|
||||
str = self.generateArray(self.regular, self.variableName(False),
|
||||
self.usedForXrays(False))
|
||||
self.usedForXrays())
|
||||
if self.hasChromeOnly():
|
||||
str += self.generateArray(self.chrome, self.variableName(True),
|
||||
self.usedForXrays(True))
|
||||
self.usedForXrays())
|
||||
return str
|
||||
|
||||
@staticmethod
|
||||
@ -1018,7 +1015,7 @@ class MethodDefiner(PropertyDefiner):
|
||||
"length": methodLength(m),
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"pref": PropertyDefiner.getControllingPref(m) }
|
||||
for m in methods]
|
||||
for m in methods if isChromeOnly(m)]
|
||||
self.regular = [{"name": m.identifier.name,
|
||||
"length": methodLength(m),
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
@ -1027,12 +1024,6 @@ class MethodDefiner(PropertyDefiner):
|
||||
|
||||
# FIXME Check for an existing iterator on the interface first.
|
||||
if any(m.isGetter() and m.isIndexed() for m in methods):
|
||||
self.chrome.append({"name": 'iterator',
|
||||
"methodInfo": False,
|
||||
"nativeName": "JS_ArrayIterator",
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"pref": None })
|
||||
self.regular.append({"name": 'iterator',
|
||||
"methodInfo": False,
|
||||
"nativeName": "JS_ArrayIterator",
|
||||
@ -1083,8 +1074,9 @@ class AttrDefiner(PropertyDefiner):
|
||||
def __init__(self, descriptor, name):
|
||||
PropertyDefiner.__init__(self, descriptor, name)
|
||||
self.name = name
|
||||
self.chrome = [m for m in descriptor.interface.members if m.isAttr()]
|
||||
self.regular = [m for m in self.chrome if not isChromeOnly(m)]
|
||||
attributes = [m for m in descriptor.interface.members if m.isAttr()]
|
||||
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
||||
self.regular = [m for m in attributes if not isChromeOnly(m)]
|
||||
|
||||
def generateArray(self, array, name, doIdArrays):
|
||||
if len(array) == 0:
|
||||
@ -1127,8 +1119,9 @@ class ConstDefiner(PropertyDefiner):
|
||||
def __init__(self, descriptor, name):
|
||||
PropertyDefiner.__init__(self, descriptor, name)
|
||||
self.name = name
|
||||
self.chrome = [m for m in descriptor.interface.members if m.isConst()]
|
||||
self.regular = [m for m in self.chrome if not isChromeOnly(m)]
|
||||
constants = [m for m in descriptor.interface.members if m.isConst()]
|
||||
self.chrome = [m for m in constants if isChromeOnly(m)]
|
||||
self.regular = [m for m in constants if not isChromeOnly(m)]
|
||||
|
||||
def generateArray(self, array, name, doIdArrays):
|
||||
if len(array) == 0:
|
||||
@ -1161,19 +1154,49 @@ class PropertyArrays():
|
||||
return [ "methods", "attrs", "consts" ]
|
||||
|
||||
def hasChromeOnly(self):
|
||||
return reduce(lambda b, a: b or getattr(self, a).hasChromeOnly(),
|
||||
self.arrayNames(), False)
|
||||
def variableNames(self, chrome):
|
||||
names = {}
|
||||
for array in self.arrayNames():
|
||||
names[array] = getattr(self, array).variableName(chrome)
|
||||
return names
|
||||
return any(getattr(self, a).hasChromeOnly() for a in self.arrayNames())
|
||||
def hasNonChromeOnly(self):
|
||||
return any(getattr(self, a).hasNonChromeOnly() for a in self.arrayNames())
|
||||
def __str__(self):
|
||||
define = ""
|
||||
for array in self.arrayNames():
|
||||
define += str(getattr(self, array))
|
||||
return define
|
||||
|
||||
class CGNativeProperties(CGList):
|
||||
def __init__(self, descriptor, properties):
|
||||
def generateNativeProperties(name, chrome):
|
||||
def check(p):
|
||||
return p.hasChromeOnly() if chrome else p.hasNonChromeOnly()
|
||||
|
||||
nativeProps = []
|
||||
for array in properties.arrayNames():
|
||||
propertyArray = getattr(properties, array)
|
||||
if check(propertyArray):
|
||||
if descriptor.workers:
|
||||
props = "%(name)s, nullptr, %(name)s_specs"
|
||||
else:
|
||||
if propertyArray.usedForXrays():
|
||||
ids = "%(name)s_ids"
|
||||
else:
|
||||
ids = "nullptr"
|
||||
props = "%(name)s, " + ids + ", %(name)s_specs"
|
||||
props = (props %
|
||||
{ 'name': propertyArray.variableName(chrome) })
|
||||
else:
|
||||
props = "nullptr, nullptr, nullptr"
|
||||
nativeProps.append(CGGeneric(props))
|
||||
return CGWrapper(CGIndenter(CGList(nativeProps, ",\n")),
|
||||
pre="static const NativeProperties %s = {\n" % name,
|
||||
post="\n};")
|
||||
|
||||
regular = generateNativeProperties("sNativeProperties", False)
|
||||
chrome = generateNativeProperties("sChromeOnlyNativeProperties", True)
|
||||
CGList.__init__(self, [regular, chrome], "\n\n")
|
||||
|
||||
def declare(self):
|
||||
return ""
|
||||
|
||||
class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
"""
|
||||
Generate the CreateInterfaceObjects method for an interface descriptor.
|
||||
@ -1209,7 +1232,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
# We only have non-chrome ids to init if we have no chrome ids.
|
||||
if props.hasChromeOnly():
|
||||
idsToInit.append(props.variableName(True))
|
||||
elif props.hasNonChromeOnly():
|
||||
if props.hasNonChromeOnly():
|
||||
idsToInit.append(props.variableName(False))
|
||||
if len(idsToInit) > 0:
|
||||
initIds = CGList(
|
||||
@ -1270,32 +1293,34 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||
else:
|
||||
domClass = "nullptr"
|
||||
|
||||
if self.properties.hasNonChromeOnly():
|
||||
properties = "&sNativeProperties"
|
||||
else:
|
||||
properties = "nullptr"
|
||||
if self.properties.hasChromeOnly():
|
||||
if self.descriptor.workers:
|
||||
accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
|
||||
else:
|
||||
accessCheck = "xpc::AccessCheck::isChrome(aGlobal)"
|
||||
chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr"
|
||||
else:
|
||||
chromeProperties = "nullptr"
|
||||
call = """return dom::CreateInterfaceObjects(aCx, aGlobal, aReceiver, parentProto,
|
||||
%s, %s, %s, %d,
|
||||
%s,
|
||||
%%(methods)s, %%(attrs)s,
|
||||
%%(consts)s, %%(staticMethods)s,
|
||||
%s,
|
||||
%s,
|
||||
%s);""" % (
|
||||
"&PrototypeClass" if needInterfacePrototypeObject else "NULL",
|
||||
"&InterfaceObjectClass" if needInterfaceObjectClass else "NULL",
|
||||
constructHook if needConstructor else "NULL",
|
||||
constructArgs,
|
||||
domClass,
|
||||
properties,
|
||||
chromeProperties,
|
||||
'"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "NULL")
|
||||
if self.properties.hasChromeOnly():
|
||||
if self.descriptor.workers:
|
||||
accessCheck = "mozilla::dom::workers::GetWorkerPrivateFromContext(aCx)->IsChromeWorker()"
|
||||
else:
|
||||
accessCheck = "xpc::AccessCheck::isChrome(js::GetObjectCompartment(aGlobal))"
|
||||
chrome = CGIfWrapper(CGGeneric(call % self.properties.variableNames(True)),
|
||||
accessCheck)
|
||||
chrome = CGWrapper(chrome, pre="\n\n")
|
||||
else:
|
||||
chrome = None
|
||||
|
||||
functionBody = CGList(
|
||||
[CGGeneric(getParentProto), initIds, prefCache, chrome,
|
||||
CGGeneric(call % self.properties.variableNames(False))],
|
||||
[CGGeneric(getParentProto), initIds, prefCache, CGGeneric(call)],
|
||||
"\n\n")
|
||||
return CGIndenter(functionBody).define()
|
||||
|
||||
@ -4541,36 +4566,20 @@ class CGXrayHelper(CGAbstractMethod):
|
||||
self.properties = properties
|
||||
|
||||
def definition_body(self):
|
||||
varNames = self.properties.variableNames(True)
|
||||
|
||||
methods = self.properties.methods
|
||||
if methods.hasNonChromeOnly() or methods.hasChromeOnly():
|
||||
methodArgs = """// %(methods)s has an end-of-list marker at the end that we ignore
|
||||
%(methods)s, %(methods)s_ids, %(methods)s_specs, ArrayLength(%(methods)s) - 1""" % varNames
|
||||
else:
|
||||
methodArgs = "NULL, NULL, NULL, 0"
|
||||
methodArgs = CGGeneric(methodArgs)
|
||||
|
||||
attrs = self.properties.attrs
|
||||
if attrs.hasNonChromeOnly() or attrs.hasChromeOnly():
|
||||
attrArgs = """// %(attrs)s has an end-of-list marker at the end that we ignore
|
||||
%(attrs)s, %(attrs)s_ids, %(attrs)s_specs, ArrayLength(%(attrs)s) - 1""" % varNames
|
||||
else:
|
||||
attrArgs = "NULL, NULL, NULL, 0"
|
||||
attrArgs = CGGeneric(attrArgs)
|
||||
|
||||
consts = self.properties.consts
|
||||
if consts.hasNonChromeOnly() or consts.hasChromeOnly():
|
||||
constArgs = """// %(consts)s has an end-of-list marker at the end that we ignore
|
||||
%(consts)s, %(consts)s_ids, %(consts)s_specs, ArrayLength(%(consts)s) - 1""" % varNames
|
||||
else:
|
||||
constArgs = "NULL, NULL, NULL, 0"
|
||||
constArgs = CGGeneric(constArgs)
|
||||
|
||||
prefixArgs = CGGeneric(self.getPrefixArgs())
|
||||
if self.properties.hasNonChromeOnly():
|
||||
regular = "&sNativeProperties"
|
||||
else:
|
||||
regular = "nullptr"
|
||||
regular = CGGeneric(regular)
|
||||
if self.properties.hasChromeOnly():
|
||||
chrome = "&sChromeOnlyNativeProperties"
|
||||
else:
|
||||
chrome = "nullptr"
|
||||
chrome = CGGeneric(chrome)
|
||||
|
||||
return CGIndenter(
|
||||
CGWrapper(CGList([prefixArgs, methodArgs, attrArgs, constArgs], ",\n"),
|
||||
CGWrapper(CGList([prefixArgs, regular, chrome], ",\n"),
|
||||
pre=("return Xray%s(" % self.name),
|
||||
post=");",
|
||||
reindent=True)).define()
|
||||
@ -4595,7 +4604,7 @@ class CGEnumerateProperties(CGXrayHelper):
|
||||
properties)
|
||||
|
||||
def getPrefixArgs(self):
|
||||
return "props"
|
||||
return "wrapper, props"
|
||||
|
||||
class CGPrototypeTraitsClass(CGClass):
|
||||
def __init__(self, descriptor, indent=''):
|
||||
@ -5248,6 +5257,7 @@ class CGDescriptor(CGThing):
|
||||
|
||||
properties = PropertyArrays(descriptor)
|
||||
cgThings.append(CGGeneric(define=str(properties)))
|
||||
cgThings.append(CGNativeProperties(descriptor, properties))
|
||||
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
|
||||
if descriptor.interface.hasInterfacePrototypeObject():
|
||||
cgThings.append(CGGetProtoObjectMethod(descriptor))
|
||||
|
Loading…
Reference in New Issue
Block a user