Implement static attributes (fixes #1989).

This commit is contained in:
Ms2ger 2014-06-20 23:20:12 +02:00
parent 6d2784aece
commit 4f0d6979e7
4 changed files with 113 additions and 28 deletions

View file

@ -1165,10 +1165,15 @@ class MethodDefiner(PropertyDefiner):
specData) specData)
class AttrDefiner(PropertyDefiner): class AttrDefiner(PropertyDefiner):
def __init__(self, descriptor, name): def __init__(self, descriptor, name, static):
PropertyDefiner.__init__(self, descriptor, name) PropertyDefiner.__init__(self, descriptor, name)
self.name = name self.name = name
self.regular = [m for m in descriptor.interface.members if m.isAttr()] self.regular = [
m
for m in descriptor.interface.members
if m.isAttr() and m.isStatic() == static
]
self.static = static
def generateArray(self, array, name): def generateArray(self, array, name):
if len(array) == 0: if len(array) == 0:
@ -1178,20 +1183,37 @@ class AttrDefiner(PropertyDefiner):
return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS" return "JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS"
def getter(attr): def getter(attr):
native = ("genericLenientGetter" if attr.hasLenientThis() if self.static:
else "genericGetter") accessor = 'get_' + attr.identifier.name
return ("JSPropertyOpWrapper {op: Some(%(native)s), info: &%(name)s_getterinfo as *JSJitInfo}" jitinfo = "0"
% {"name" : attr.identifier.name, else:
"native" : native}) if attr.hasLenientThis():
accessor = "genericLenientGetter"
else:
accessor = "genericGetter"
jitinfo = "&%s_getterinfo" % attr.identifier.name
return ("JSPropertyOpWrapper {op: Some(%(native)s), info: %(info)s as *JSJitInfo}"
% {"info" : jitinfo,
"native" : accessor})
def setter(attr): def setter(attr):
if attr.readonly: if attr.readonly:
return "JSStrictPropertyOpWrapper {op: None, info: 0 as *JSJitInfo}" return "JSStrictPropertyOpWrapper {op: None, info: 0 as *JSJitInfo}"
native = ("genericLenientSetter" if attr.hasLenientThis()
else "genericSetter") if self.static:
return ("JSStrictPropertyOpWrapper {op: Some(%(native)s), info: &%(name)s_setterinfo as *JSJitInfo}" accessor = 'set_' + attr.identifier.name
% {"name" : attr.identifier.name, jitinfo = "0"
"native" : native}) else:
if attr.hasLenientThis():
accessor = "genericLenientSetter"
else:
accessor = "genericSetter"
jitinfo = "&%s_setterinfo" % attr.identifier.name
return ("JSStrictPropertyOpWrapper {op: Some(%(native)s), info: %(info)s as *JSJitInfo}"
% {"info" : jitinfo,
"native" : accessor})
def specData(attr): def specData(attr):
return (attr.identifier.name, flags(attr), getter(attr), return (attr.identifier.name, flags(attr), getter(attr),
@ -1834,15 +1856,18 @@ class CGAbstractExternMethod(CGAbstractMethod):
class PropertyArrays(): class PropertyArrays():
def __init__(self, descriptor): def __init__(self, descriptor):
self.staticMethods = MethodDefiner(descriptor, "StaticMethods", True) self.staticMethods = MethodDefiner(descriptor, "StaticMethods",
self.methods = MethodDefiner(descriptor, "Methods", False) static=True)
self.attrs = AttrDefiner(descriptor, "Attributes") self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes",
static=True)
self.methods = MethodDefiner(descriptor, "Methods", static=False)
self.attrs = AttrDefiner(descriptor, "Attributes", static=False)
self.consts = ConstDefiner(descriptor, "Constants") self.consts = ConstDefiner(descriptor, "Constants")
pass pass
@staticmethod @staticmethod
def arrayNames(): def arrayNames():
return [ "staticMethods", "methods", "attrs", "consts" ] return [ "staticMethods", "staticAttrs", "methods", "attrs", "consts" ]
def variableNames(self): def variableNames(self):
names = {} names = {}
@ -2293,7 +2318,7 @@ class CGGetterCall(CGPerSignatureCall):
""" """
def __init__(self, argsPre, returnType, nativeMethodName, descriptor, attr): def __init__(self, argsPre, returnType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, returnType, argsPre, [], CGPerSignatureCall.__init__(self, returnType, argsPre, [],
nativeMethodName, False, descriptor, nativeMethodName, attr.isStatic(), descriptor,
attr, getter=True) attr, getter=True)
class FakeArgument(): class FakeArgument():
@ -2322,7 +2347,7 @@ class CGSetterCall(CGPerSignatureCall):
def __init__(self, argsPre, argType, nativeMethodName, descriptor, attr): def __init__(self, argsPre, argType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, None, argsPre, CGPerSignatureCall.__init__(self, None, argsPre,
[FakeArgument(argType, attr, allowTreatNonObjectAsNull=True)], [FakeArgument(argType, attr, allowTreatNonObjectAsNull=True)],
nativeMethodName, False, descriptor, attr, nativeMethodName, attr.isStatic(), descriptor, attr,
setter=True) setter=True)
def wrap_return_value(self): def wrap_return_value(self):
# We have no return value # We have no return value
@ -2505,6 +2530,22 @@ class CGSpecializedGetter(CGAbstractExternMethod):
return 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
CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
def generate_code(self):
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
self.attr)
return CGGetterCall([], self.attr.type, nativeName, self.descriptor,
self.attr)
class CGGenericSetter(CGAbstractBindingMethod): class CGGenericSetter(CGAbstractBindingMethod):
""" """
A class for generating the Rust code for an IDL attribute setter. A class for generating the Rust code for an IDL attribute setter.
@ -2560,6 +2601,30 @@ class CGSpecializedSetter(CGAbstractExternMethod):
def makeNativeName(descriptor, attr): def makeNativeName(descriptor, attr):
return "Set" + MakeNativeName(attr.identifier.name) return "Set" + MakeNativeName(attr.identifier.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
CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
def generate_code(self):
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
self.attr)
checkForArg = CGGeneric(
"let argv = JS_ARGV(cx, vp);\n"
"if (argc == 0) {\n"
" // XXXjdmreturn ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, \"%s setter\");\n"
" return 0;\n"
"}\n" % self.attr.identifier.name)
call = CGSetterCall([], self.attr.type, nativeName, self.descriptor,
self.attr)
return CGList([checkForArg, call])
class CGMemberJITInfo(CGThing): class CGMemberJITInfo(CGThing):
""" """
A class for generating the JITInfo for a property that points to A class for generating the JITInfo for a property that points to
@ -3899,17 +3964,28 @@ class CGDescriptor(CGThing):
cgThings.append(CGMemberJITInfo(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True hasMethod = True
elif m.isAttr(): elif m.isAttr():
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticGetter(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedGetter(descriptor, m)) cgThings.append(CGSpecializedGetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientGetter = True hasLenientGetter = True
else: else:
hasGetter = True hasGetter = True
if not m.readonly: if not m.readonly:
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
cgThings.append(CGStaticSetter(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedSetter(descriptor, m)) cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientSetter = True hasLenientSetter = True
else: else:
hasSetter = True hasSetter = True
if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGMemberJITInfo(descriptor, m)) cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: if hasMethod:
cgThings.append(CGGenericMethod(descriptor)) cgThings.append(CGGenericMethod(descriptor))

View file

@ -220,6 +220,7 @@ pub struct NativeProperties {
pub attrs: Option<&'static [JSPropertySpec]>, pub attrs: Option<&'static [JSPropertySpec]>,
pub consts: Option<&'static [ConstantSpec]>, pub consts: Option<&'static [ConstantSpec]>,
pub staticMethods: Option<&'static [JSFunctionSpec]>, pub staticMethods: Option<&'static [JSFunctionSpec]>,
pub staticAttrs: Option<&'static [JSPropertySpec]>,
} }
pub type NonNullJSNative = pub type NonNullJSNative =
@ -271,6 +272,11 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m
_ => (), _ => (),
} }
match members.staticAttrs {
Some(staticProperties) => DefineProperties(cx, constructor, staticProperties),
_ => (),
}
match members.consts { match members.consts {
Some(constants) => DefineConstants(cx, constructor, constants), Some(constants) => DefineConstants(cx, constructor, constants),
_ => (), _ => (),

View file

@ -297,6 +297,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
} }
impl TestBinding { impl TestBinding {
pub fn BooleanAttributeStatic() -> bool { false }
pub fn SetBooleanAttributeStatic(_: bool) {}
pub fn ReceiveVoidStatic() {} pub fn ReceiveVoidStatic() {}
} }

View file

@ -267,5 +267,6 @@ interface TestBinding {
void passVariadicUnion3((Blob or DOMString)... args); void passVariadicUnion3((Blob or DOMString)... args);
void passVariadicAny(any... args); void passVariadicAny(any... args);
static attribute boolean booleanAttributeStatic;
static void receiveVoidStatic(); static void receiveVoidStatic();
}; };