Fix for bug 798264 (Split property tables). r=bz.

--HG--
extra : rebase_source : 71456ae48d3d3e6014e8095837f7942cfe733a37
This commit is contained in:
Peter Van der Beken 2012-10-09 20:50:05 +02:00
parent 68f37a763d
commit 7964385bcb
3 changed files with 349 additions and 270 deletions

View File

@ -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)

View File

@ -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>

View File

@ -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))