зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 763643 (Implement static operations and attributes for WebIDL). r=bz.
--HG-- extra : rebase_source : d9dd5450af5d2b1f3e7e3a738ec2efdc7f7053da
This commit is contained in:
Родитель
df40ca231f
Коммит
80ecd8538f
|
@ -218,6 +218,11 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (properties->staticAttributes &&
|
||||
!DefinePrefable(cx, constructor, properties->staticAttributes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (properties->constants &&
|
||||
!DefinePrefable(cx, constructor, properties->constants)) {
|
||||
return nullptr;
|
||||
|
@ -230,6 +235,12 @@ CreateInterfaceObject(JSContext* cx, JSObject* global,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->staticAttributes &&
|
||||
!DefinePrefable(cx, constructor,
|
||||
chromeOnlyProperties->staticAttributes)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (chromeOnlyProperties->constants &&
|
||||
!DefinePrefable(cx, constructor, chromeOnlyProperties->constants)) {
|
||||
return nullptr;
|
||||
|
@ -322,8 +333,11 @@ CreateInterfaceObjects(JSContext* cx, JSObject* global, JSObject* protoProto,
|
|||
(chromeOnlyProperties->methods ||
|
||||
chromeOnlyProperties->attributes))) || protoClass,
|
||||
"Methods or properties but no protoClass!");
|
||||
MOZ_ASSERT(!((properties && properties->staticMethods) ||
|
||||
(chromeOnlyProperties && chromeOnlyProperties->staticMethods)) ||
|
||||
MOZ_ASSERT(!((properties &&
|
||||
(properties->staticMethods || properties->staticAttributes)) ||
|
||||
(chromeOnlyProperties &&
|
||||
(chromeOnlyProperties->staticMethods ||
|
||||
chromeOnlyProperties->staticAttributes))) ||
|
||||
constructorClass || constructor,
|
||||
"Static methods but no constructorClass or constructor!");
|
||||
MOZ_ASSERT(bool(name) == bool(constructorClass || constructor),
|
||||
|
@ -637,7 +651,19 @@ XrayResolveProperty(JSContext* cx, JSObject* wrapper, jsid id,
|
|||
}
|
||||
}
|
||||
|
||||
if (type != eInterface) {
|
||||
if (type == eInterface) {
|
||||
if (nativeProperties->staticAttributes) {
|
||||
if (!XrayResolveAttribute(cx, wrapper, id,
|
||||
nativeProperties->staticAttributes,
|
||||
nativeProperties->staticAttributeIds,
|
||||
nativeProperties->staticAttributeSpecs, desc)) {
|
||||
return false;
|
||||
}
|
||||
if (desc->obj) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nativeProperties->attributes) {
|
||||
if (!XrayResolveAttribute(cx, wrapper, id,
|
||||
nativeProperties->attributes,
|
||||
|
@ -836,7 +862,15 @@ XrayEnumerateProperties(JS::AutoIdVector& props, DOMObjectType type,
|
|||
}
|
||||
}
|
||||
|
||||
if (type != eInterface) {
|
||||
if (type == eInterface) {
|
||||
if (nativeProperties->staticAttributes &&
|
||||
!XrayEnumerateAttributes(nativeProperties->staticAttributes,
|
||||
nativeProperties->staticAttributeIds,
|
||||
nativeProperties->staticAttributeSpecs,
|
||||
props)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (nativeProperties->attributes &&
|
||||
!XrayEnumerateAttributes(nativeProperties->attributes,
|
||||
nativeProperties->attributeIds,
|
||||
|
|
|
@ -1073,16 +1073,18 @@ class MethodDefiner(PropertyDefiner):
|
|||
methods = [m for m in descriptor.interface.members if
|
||||
m.isMethod() and m.isStatic() == static and
|
||||
not m.isIdentifierLess()]
|
||||
self.chrome = [{"name": m.identifier.name,
|
||||
"length": methodLength(m),
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"pref": PropertyDefiner.getControllingPref(m) }
|
||||
for m in methods if isChromeOnly(m)]
|
||||
self.regular = [{"name": m.identifier.name,
|
||||
"length": methodLength(m),
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"pref": PropertyDefiner.getControllingPref(m) }
|
||||
for m in methods if not isChromeOnly(m)]
|
||||
self.chrome = []
|
||||
self.regular = []
|
||||
for m in methods:
|
||||
method = { "name": m.identifier.name,
|
||||
"methodInfo": not m.isStatic(),
|
||||
"length": methodLength(m),
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"pref": PropertyDefiner.getControllingPref(m) }
|
||||
if isChromeOnly(m):
|
||||
self.chrome.append(method)
|
||||
else:
|
||||
self.regular.append(method)
|
||||
|
||||
# FIXME Check for an existing iterator on the interface first.
|
||||
if any(m.isGetter() and m.isIndexed() for m in methods):
|
||||
|
@ -1146,15 +1148,27 @@ class MethodDefiner(PropertyDefiner):
|
|||
pref, specData, doIdArrays)
|
||||
|
||||
class AttrDefiner(PropertyDefiner):
|
||||
def __init__(self, descriptor, name, unforgeable):
|
||||
def __init__(self, descriptor, name, static, unforgeable=False):
|
||||
assert not (static and unforgeable)
|
||||
PropertyDefiner.__init__(self, descriptor, name)
|
||||
self.name = name
|
||||
attributes = [m for m in descriptor.interface.members
|
||||
if m.isAttr() and m.isUnforgeable() == unforgeable]
|
||||
attributes = [m for m in descriptor.interface.members if
|
||||
m.isAttr() and m.isStatic() == static and
|
||||
m.isUnforgeable() == unforgeable]
|
||||
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
||||
self.regular = [m for m in attributes if not isChromeOnly(m)]
|
||||
self.static = static
|
||||
self.unforgeable = unforgeable
|
||||
|
||||
if static:
|
||||
if not descriptor.interface.hasInterfaceObject():
|
||||
# static attributes go on the interface object
|
||||
assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
|
||||
else:
|
||||
if not descriptor.interface.hasInterfacePrototypeObject():
|
||||
# non-static attributes go on the interface prototype object
|
||||
assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
|
||||
|
||||
if unforgeable and len(attributes) != 0 and descriptor.proxy:
|
||||
raise TypeError("Unforgeable properties are not supported on "
|
||||
"proxy bindings without [NamedPropertiesObject]. "
|
||||
|
@ -1172,20 +1186,26 @@ class AttrDefiner(PropertyDefiner):
|
|||
unforgeable)
|
||||
|
||||
def getter(attr):
|
||||
native = ("genericLenientGetter" if attr.hasLenientThis()
|
||||
else "genericGetter")
|
||||
return ("{(JSPropertyOp)%(native)s, &%(name)s_getterinfo}"
|
||||
% {"name" : attr.identifier.name,
|
||||
"native" : native})
|
||||
if self.static:
|
||||
accessor = 'get_' + attr.identifier.name
|
||||
jitinfo = "nullptr"
|
||||
else:
|
||||
accessor = ("genericLenientGetter" if attr.hasLenientThis()
|
||||
else "genericGetter")
|
||||
jitinfo = "&%s_getterinfo" % attr.identifier.name
|
||||
return "{ (JSPropertyOp)%s, %s }" % (accessor, jitinfo)
|
||||
|
||||
def setter(attr):
|
||||
if attr.readonly and attr.getExtendedAttribute("PutForwards") is None:
|
||||
return "JSOP_NULLWRAPPER"
|
||||
native = ("genericLenientSetter" if attr.hasLenientThis()
|
||||
else "genericSetter")
|
||||
return ("{(JSStrictPropertyOp)%(native)s, &%(name)s_setterinfo}"
|
||||
% {"name" : attr.identifier.name,
|
||||
"native" : native})
|
||||
if self.static:
|
||||
accessor = 'set_' + attr.identifier.name
|
||||
jitinfo = "nullptr"
|
||||
else:
|
||||
if attr.readonly and attr.getExtendedAttribute("PutForwards") is None:
|
||||
return "JSOP_NULLWRAPPER"
|
||||
accessor = ("genericLenientSetter" if attr.hasLenientThis()
|
||||
else "genericSetter")
|
||||
jitinfo = "&%s_setterinfo" % attr.identifier.name
|
||||
return "{ (JSStrictPropertyOp)%s, %s }" % (accessor, jitinfo)
|
||||
|
||||
def specData(attr):
|
||||
return (attr.identifier.name, flags(attr), getter(attr),
|
||||
|
@ -1226,18 +1246,20 @@ class ConstDefiner(PropertyDefiner):
|
|||
|
||||
class PropertyArrays():
|
||||
def __init__(self, descriptor):
|
||||
self.staticMethods = MethodDefiner(descriptor, "StaticMethods", True)
|
||||
self.staticAttrs = None
|
||||
self.methods = MethodDefiner(descriptor, "Methods", False)
|
||||
self.attrs = AttrDefiner(descriptor, "Attributes", unforgeable=False)
|
||||
self.staticMethods = MethodDefiner(descriptor, "StaticMethods",
|
||||
static=True)
|
||||
self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes",
|
||||
static=True)
|
||||
self.methods = MethodDefiner(descriptor, "Methods", static=False)
|
||||
self.attrs = AttrDefiner(descriptor, "Attributes", static=False)
|
||||
self.unforgeableAttrs = AttrDefiner(descriptor, "UnforgeableAttributes",
|
||||
unforgeable=True)
|
||||
static=False, unforgeable=True)
|
||||
self.consts = ConstDefiner(descriptor, "Constants")
|
||||
|
||||
@staticmethod
|
||||
def arrayNames():
|
||||
return [ "staticMethods", "methods", "attrs", "unforgeableAttrs",
|
||||
"consts" ]
|
||||
return [ "staticMethods", "staticAttrs", "methods", "attrs",
|
||||
"unforgeableAttrs", "consts" ]
|
||||
|
||||
@staticmethod
|
||||
def xrayRelevantArrayNames():
|
||||
|
@ -3681,9 +3703,13 @@ class CGGetterCall(CGPerSignatureCall):
|
|||
getter.
|
||||
"""
|
||||
def __init__(self, returnType, nativeMethodName, descriptor, attr):
|
||||
CGPerSignatureCall.__init__(self, returnType, [], [],
|
||||
nativeMethodName, False, descriptor,
|
||||
attr, getter=True)
|
||||
if attr.isStatic():
|
||||
argsPre = [ "global" ]
|
||||
else:
|
||||
argsPre = []
|
||||
CGPerSignatureCall.__init__(self, returnType, argsPre, [],
|
||||
nativeMethodName, attr.isStatic(),
|
||||
descriptor, attr, getter=True)
|
||||
|
||||
class FakeArgument():
|
||||
"""
|
||||
|
@ -3710,10 +3736,14 @@ class CGSetterCall(CGPerSignatureCall):
|
|||
setter.
|
||||
"""
|
||||
def __init__(self, argType, nativeMethodName, descriptor, attr):
|
||||
CGPerSignatureCall.__init__(self, None, [],
|
||||
if attr.isStatic():
|
||||
argsPre = [ "global" ]
|
||||
else:
|
||||
argsPre = []
|
||||
CGPerSignatureCall.__init__(self, None, argsPre,
|
||||
[FakeArgument(argType, attr)],
|
||||
nativeMethodName, False, descriptor, attr,
|
||||
setter=True)
|
||||
nativeMethodName, attr.isStatic(),
|
||||
descriptor, attr, setter=True)
|
||||
def wrap_return_value(self):
|
||||
# We have no return value
|
||||
return "\nreturn true;"
|
||||
|
@ -3752,21 +3782,60 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
|
|||
# we're someone's consequential interface. But for this-unwrapping, we
|
||||
# know that we're the real deal. So fake a descriptor here for
|
||||
# consumption by FailureFatalCastableObjectUnwrapper.
|
||||
unwrapThis = CGIndenter(CGGeneric(
|
||||
getThis = CGGeneric("""js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
%s* self;""" % self.descriptor.nativeType)
|
||||
unwrapThis = CGGeneric(
|
||||
str(CastableObjectUnwrapper(
|
||||
FakeCastableDescriptor(self.descriptor),
|
||||
"obj", "self", self.unwrapFailureCode))))
|
||||
return CGList([ self.getThis(), unwrapThis,
|
||||
"obj", "self", self.unwrapFailureCode)))
|
||||
return CGList([ CGIndenter(getThis), CGIndenter(unwrapThis),
|
||||
self.generate_code() ], "\n").define()
|
||||
|
||||
def getThis(self):
|
||||
return CGIndenter(
|
||||
CGGeneric("js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));\n"
|
||||
"if (!obj) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"%s* self;" % self.descriptor.nativeType))
|
||||
def generate_code(self):
|
||||
assert(False) # Override me
|
||||
|
||||
class CGAbstractStaticBindingMethod(CGAbstractStaticMethod):
|
||||
"""
|
||||
Common class to generate the JSNatives for all our static methods, getters
|
||||
and setters. This will generate the function declaration and unwrap the
|
||||
global object. Subclasses are expected to override the generate_code
|
||||
function to do the rest of the work. This function should return a
|
||||
CGThing which is already properly indented.
|
||||
"""
|
||||
def __init__(self, descriptor, name, args):
|
||||
CGAbstractStaticMethod.__init__(self, descriptor, name, "JSBool", args)
|
||||
|
||||
def definition_body(self):
|
||||
isMainThread = toStringBool(not self.descriptor.workers)
|
||||
unwrap = CGGeneric("""js::RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js::IsWrapper(obj)) {
|
||||
obj = XPCWrapper::Unwrap(cx, obj, false);
|
||||
if (!obj) {
|
||||
return Throw<%s>(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO);
|
||||
}
|
||||
}
|
||||
|
||||
nsISupports* global;
|
||||
xpc_qsSelfRef globalRef;
|
||||
{
|
||||
JS::Value val;
|
||||
val.setObjectOrNull(JS_GetGlobalForObject(cx, obj));
|
||||
nsresult rv = xpc_qsUnwrapArg<nsISupports>(cx, val, &global, &globalRef.ptr,
|
||||
&val);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
}""" % (isMainThread, isMainThread))
|
||||
return CGList([ CGIndenter(unwrap),
|
||||
self.generate_code() ], "\n\n").define()
|
||||
|
||||
def generate_code(self):
|
||||
assert(False) # Override me
|
||||
|
@ -3813,6 +3882,23 @@ class CGSpecializedMethod(CGAbstractStaticMethod):
|
|||
name = method.identifier.name
|
||||
return MakeNativeName(descriptor.binaryNames.get(name, name))
|
||||
|
||||
class CGStaticMethod(CGAbstractStaticBindingMethod):
|
||||
"""
|
||||
A class for generating the C++ code for an IDL static method.
|
||||
"""
|
||||
def __init__(self, descriptor, method):
|
||||
self.method = method
|
||||
name = method.identifier.name
|
||||
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
|
||||
Argument('JS::Value*', 'vp')]
|
||||
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
|
||||
|
||||
def generate_code(self):
|
||||
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
|
||||
self.method)
|
||||
return CGMethodCall([ "global" ], nativeName, True, self.descriptor,
|
||||
self.method)
|
||||
|
||||
class CGGenericGetter(CGAbstractBindingMethod):
|
||||
"""
|
||||
A class for generating the C++ code for an IDL attribute getter.
|
||||
|
@ -3871,6 +3957,23 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
|
|||
nativeName = "Get" + nativeName
|
||||
return nativeName
|
||||
|
||||
class CGStaticGetter(CGAbstractStaticBindingMethod):
|
||||
"""
|
||||
A class for generating the C++ code for an IDL static attribute getter.
|
||||
"""
|
||||
def __init__(self, descriptor, attr):
|
||||
self.attr = attr
|
||||
name = 'get_' + attr.identifier.name
|
||||
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
|
||||
Argument('JS::Value*', 'vp')]
|
||||
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
|
||||
|
||||
def generate_code(self):
|
||||
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
|
||||
self.attr)
|
||||
return CGIndenter(CGGetterCall(self.attr.type, nativeName,
|
||||
self.descriptor, self.attr))
|
||||
|
||||
class CGGenericSetter(CGAbstractBindingMethod):
|
||||
"""
|
||||
A class for generating the C++ code for an IDL attribute setter.
|
||||
|
@ -3929,6 +4032,29 @@ class CGSpecializedSetter(CGAbstractStaticMethod):
|
|||
name = attr.identifier.name
|
||||
return "Set" + MakeNativeName(descriptor.binaryNames.get(name, name))
|
||||
|
||||
class CGStaticSetter(CGAbstractStaticBindingMethod):
|
||||
"""
|
||||
A class for generating the C++ code for an IDL static attribute setter.
|
||||
"""
|
||||
def __init__(self, descriptor, attr):
|
||||
self.attr = attr
|
||||
name = 'set_' + attr.identifier.name
|
||||
args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
|
||||
Argument('JS::Value*', 'vp')]
|
||||
CGAbstractStaticBindingMethod.__init__(self, descriptor, name, args)
|
||||
|
||||
def generate_code(self):
|
||||
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
|
||||
self.attr)
|
||||
argv = CGGeneric("""JS::Value* argv = JS_ARGV(cx, vp);
|
||||
JS::Value undef = JS::UndefinedValue();
|
||||
if (argc == 0) {
|
||||
argv = &undef;
|
||||
}""")
|
||||
call = CGSetterCall(self.attr.type, nativeName, self.descriptor,
|
||||
self.attr)
|
||||
return CGIndenter(CGList([ argv, call ], "\n"))
|
||||
|
||||
class CGSpecializedForwardingSetter(CGSpecializedSetter):
|
||||
"""
|
||||
A class for generating the code for a specialized attribute setter with
|
||||
|
@ -5334,30 +5460,42 @@ class CGDescriptor(CGThing):
|
|||
|
||||
cgThings = []
|
||||
if descriptor.interface.hasInterfacePrototypeObject():
|
||||
# These are set to true if at least one non-static
|
||||
# method/getter/setter exist on the interface.
|
||||
(hasMethod, hasGetter, hasLenientGetter,
|
||||
hasSetter, hasLenientSetter) = False, False, False, False, False
|
||||
for m in descriptor.interface.members:
|
||||
if (m.isMethod() and not m.isStatic() and
|
||||
if (m.isMethod() and
|
||||
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
|
||||
cgThings.append(CGSpecializedMethod(descriptor, m))
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
hasMethod = True
|
||||
elif m.isAttr():
|
||||
cgThings.append(CGSpecializedGetter(descriptor, m))
|
||||
if m.hasLenientThis():
|
||||
hasLenientGetter = True
|
||||
if m.isStatic():
|
||||
cgThings.append(CGStaticMethod(descriptor, m))
|
||||
else:
|
||||
hasGetter = True
|
||||
if not m.readonly:
|
||||
cgThings.append(CGSpecializedSetter(descriptor, m))
|
||||
cgThings.append(CGSpecializedMethod(descriptor, m))
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
hasMethod = True
|
||||
elif m.isAttr():
|
||||
if m.isStatic():
|
||||
cgThings.append(CGStaticGetter(descriptor, m))
|
||||
else:
|
||||
cgThings.append(CGSpecializedGetter(descriptor, m))
|
||||
if m.hasLenientThis():
|
||||
hasLenientSetter = True
|
||||
hasLenientGetter = True
|
||||
else:
|
||||
hasSetter = True
|
||||
hasGetter = True
|
||||
if not m.readonly:
|
||||
if m.isStatic():
|
||||
cgThings.append(CGStaticSetter(descriptor, m))
|
||||
else:
|
||||
cgThings.append(CGSpecializedSetter(descriptor, m))
|
||||
if m.hasLenientThis():
|
||||
hasLenientSetter = True
|
||||
else:
|
||||
hasSetter = True
|
||||
elif m.getExtendedAttribute("PutForwards"):
|
||||
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
|
||||
hasSetter = True
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if not m.isStatic():
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if hasMethod: cgThings.append(CGGenericMethod(descriptor))
|
||||
if hasGetter: cgThings.append(CGGenericGetter(descriptor))
|
||||
if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
|
||||
|
@ -6028,7 +6166,7 @@ class CGExampleMember(CGThing):
|
|||
static = "static " if self.member.isStatic() else ""
|
||||
# Mark our getters, which are attrs that have a non-void return type,
|
||||
# as const.
|
||||
if self.member.isAttr() and not self.signatures[0][0].isVoid():
|
||||
if not self.member.isStatic() and self.member.isAttr() and not self.signatures[0][0].isVoid():
|
||||
const = " const"
|
||||
else:
|
||||
const = ""
|
||||
|
@ -6558,7 +6696,7 @@ struct PrototypeIDMap;
|
|||
|
||||
curr = CGWrapper(curr, post='\n')
|
||||
|
||||
curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr)
|
||||
curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h", "XPCWrapper.h"], [], curr)
|
||||
|
||||
# Add include guards.
|
||||
curr = CGIncludeGuard('UnionConversions', curr)
|
||||
|
|
|
@ -71,6 +71,9 @@ struct NativeProperties
|
|||
Prefable<JSFunctionSpec>* staticMethods;
|
||||
jsid* staticMethodIds;
|
||||
JSFunctionSpec* staticMethodsSpecs;
|
||||
Prefable<JSPropertySpec>* staticAttributes;
|
||||
jsid* staticAttributeIds;
|
||||
JSPropertySpec* staticAttributeSpecs;
|
||||
Prefable<JSFunctionSpec>* methods;
|
||||
jsid* methodIds;
|
||||
JSFunctionSpec* methodsSpecs;
|
||||
|
|
|
@ -36,18 +36,25 @@ def parseInt(literal):
|
|||
return value * sign
|
||||
|
||||
# Magic for creating enums
|
||||
def M_add_class_attribs(attribs):
|
||||
def M_add_class_attribs(attribs, start):
|
||||
def foo(name, bases, dict_):
|
||||
for v, k in enumerate(attribs):
|
||||
dict_[k] = v
|
||||
dict_[k] = start + v
|
||||
assert 'length' not in dict_
|
||||
dict_['length'] = len(attribs)
|
||||
dict_['length'] = start + len(attribs)
|
||||
return type(name, bases, dict_)
|
||||
return foo
|
||||
|
||||
def enum(*names):
|
||||
class Foo(object):
|
||||
__metaclass__ = M_add_class_attribs(names)
|
||||
def enum(*names, **kw):
|
||||
if len(kw) == 1:
|
||||
base = kw['base'].__class__
|
||||
start = base.length
|
||||
else:
|
||||
assert len(kw) == 0
|
||||
base = object
|
||||
start = 0
|
||||
class Foo(base):
|
||||
__metaclass__ = M_add_class_attribs(names, start)
|
||||
def __setattr__(self, name, value): # this makes it read-only
|
||||
raise NotImplementedError
|
||||
return Foo()
|
||||
|
@ -1928,6 +1935,11 @@ class IDLInterfaceMember(IDLObjectWithIdentifier):
|
|||
'Method'
|
||||
)
|
||||
|
||||
Special = enum(
|
||||
'Static',
|
||||
'Stringifier'
|
||||
)
|
||||
|
||||
def __init__(self, location, identifier, tag):
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
self.tag = tag
|
||||
|
@ -1991,8 +2003,8 @@ class IDLConst(IDLInterfaceMember):
|
|||
pass
|
||||
|
||||
class IDLAttribute(IDLInterfaceMember):
|
||||
def __init__(self, location, identifier, type, readonly, inherit,
|
||||
static=False):
|
||||
def __init__(self, location, identifier, type, readonly, inherit=False,
|
||||
static=False, stringifier=False):
|
||||
IDLInterfaceMember.__init__(self, location, identifier,
|
||||
IDLInterfaceMember.Tags.Attr)
|
||||
|
||||
|
@ -2003,6 +2015,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
self.static = static
|
||||
self.lenientThis = False
|
||||
self._unforgeable = False
|
||||
self.stringifier = stringifier
|
||||
|
||||
if readonly and inherit:
|
||||
raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
|
||||
|
@ -2265,14 +2278,12 @@ class IDLMethodOverload:
|
|||
class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||
|
||||
Special = enum(
|
||||
'None',
|
||||
'Getter',
|
||||
'Setter',
|
||||
'Creator',
|
||||
'Deleter',
|
||||
'LegacyCaller',
|
||||
'Stringifier',
|
||||
'Static'
|
||||
base=IDLInterfaceMember.Special
|
||||
)
|
||||
|
||||
TypeSuffixModifier = enum(
|
||||
|
@ -3096,16 +3107,32 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
def p_AttributeWithQualifier(self, p):
|
||||
"""
|
||||
Attribute : Qualifier AttributeRest
|
||||
"""
|
||||
static = IDLInterfaceMember.Special.Static in p[1]
|
||||
stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
|
||||
(location, identifier, type, readonly) = p[2]
|
||||
p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
|
||||
stringifier=stringifier)
|
||||
|
||||
def p_Attribute(self, p):
|
||||
"""
|
||||
Attribute : Inherit ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
|
||||
Attribute : Inherit AttributeRest
|
||||
"""
|
||||
location = self.getLocation(p, 3)
|
||||
inherit = p[1]
|
||||
readonly = p[2]
|
||||
t = p[4]
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
|
||||
p[0] = IDLAttribute(location, identifier, t, readonly, inherit)
|
||||
(location, identifier, type, readonly) = p[2]
|
||||
p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
|
||||
|
||||
def p_AttributeRest(self, p):
|
||||
"""
|
||||
AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
|
||||
"""
|
||||
location = self.getLocation(p, 2)
|
||||
readonly = p[1]
|
||||
t = p[3]
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4])
|
||||
p[0] = (location, identifier, t, readonly)
|
||||
|
||||
def p_ReadOnly(self, p):
|
||||
"""
|
||||
|
@ -3142,17 +3169,21 @@ class Parser(Tokenizer):
|
|||
raise WebIDLError("Duplicate qualifiers are not allowed",
|
||||
[self.getLocation(p, 1)])
|
||||
|
||||
static = True if IDLMethod.Special.Static in p[1] else False
|
||||
static = IDLInterfaceMember.Special.Static in p[1]
|
||||
# If static is there that's all that's allowed. This is disallowed
|
||||
# by the parser, so we can assert here.
|
||||
assert not static or len(qualifiers) == 1
|
||||
|
||||
stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
|
||||
# If stringifier is there that's all that's allowed. This is disallowed
|
||||
# by the parser, so we can assert here.
|
||||
assert not stringifier or len(qualifiers) == 1
|
||||
|
||||
getter = True if IDLMethod.Special.Getter in p[1] else False
|
||||
setter = True if IDLMethod.Special.Setter in p[1] else False
|
||||
creator = True if IDLMethod.Special.Creator in p[1] else False
|
||||
deleter = True if IDLMethod.Special.Deleter in p[1] else False
|
||||
legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
|
||||
stringifier = True if IDLMethod.Special.Stringifier in p[1] else False
|
||||
|
||||
if getter or deleter:
|
||||
if setter or creator:
|
||||
|
@ -3260,15 +3291,22 @@ class Parser(Tokenizer):
|
|||
legacycaller=legacycaller, stringifier=stringifier)
|
||||
p[0] = method
|
||||
|
||||
def p_QualifiersStatic(self, p):
|
||||
def p_QualifierStatic(self, p):
|
||||
"""
|
||||
Qualifiers : STATIC
|
||||
Qualifier : STATIC
|
||||
"""
|
||||
p[0] = [IDLMethod.Special.Static]
|
||||
p[0] = [IDLInterfaceMember.Special.Static]
|
||||
|
||||
def p_QualifiersSpecials(self, p):
|
||||
def p_QualifierStringifier(self, p):
|
||||
"""
|
||||
Qualifiers : Specials
|
||||
Qualifier : STRINGIFIER
|
||||
"""
|
||||
p[0] = [IDLInterfaceMember.Special.Stringifier]
|
||||
|
||||
def p_Qualifiers(self, p):
|
||||
"""
|
||||
Qualifiers : Qualifier
|
||||
| Specials
|
||||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
|
@ -3315,12 +3353,6 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
p[0] = IDLMethod.Special.LegacyCaller
|
||||
|
||||
def p_SpecialStringifier(self, p):
|
||||
"""
|
||||
Special : STRINGIFIER
|
||||
"""
|
||||
p[0] = IDLMethod.Special.Stringifier
|
||||
|
||||
def p_OperationRest(self, p):
|
||||
"""
|
||||
OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON
|
||||
|
|
|
@ -428,6 +428,11 @@ public:
|
|||
already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
|
||||
void ExerciseTypedefInterfaces3(TestInterface&);
|
||||
|
||||
// Static methods and attributes
|
||||
static void StaticMethod(nsISupports*, bool);
|
||||
static bool StaticAttribute(nsISupports*);
|
||||
static void SetStaticAttribute(nsISupports*, bool);
|
||||
|
||||
// Miscellania
|
||||
int32_t AttrWithLenientThis();
|
||||
void SetAttrWithLenientThis(int32_t);
|
||||
|
|
|
@ -334,6 +334,10 @@ interface TestInterface {
|
|||
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
|
||||
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
|
||||
|
||||
// Static methods and attributes
|
||||
static attribute boolean staticAttribute;
|
||||
static void staticMethod(boolean arg);
|
||||
|
||||
// Miscellania
|
||||
[LenientThis] attribute long attrWithLenientThis;
|
||||
[Unforgeable] readonly attribute long unforgeableAttr;
|
||||
|
|
|
@ -301,6 +301,10 @@ interface TestExampleInterface {
|
|||
AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
|
||||
void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
|
||||
|
||||
// Static methods and attributes
|
||||
static attribute boolean staticAttribute;
|
||||
static void staticMethod(boolean arg);
|
||||
|
||||
// Miscellania
|
||||
[LenientThis] attribute long attrWithLenientThis;
|
||||
[Unforgeable] readonly attribute long unforgeableAttr;
|
||||
|
|
Загрузка…
Ссылка в новой задаче