Merge pull request #2699 from Ms2ger/static-methods

Implement static IDL members; r=jdm
This commit is contained in:
Ms2ger 2014-06-22 15:55:10 +02:00
commit edba815cf5
4 changed files with 194 additions and 44 deletions

View file

@ -1126,6 +1126,7 @@ class MethodDefiner(PropertyDefiner):
m.isMethod() and m.isStatic() == static and m.isMethod() and m.isStatic() == static and
not m.isIdentifierLess()] not m.isIdentifierLess()]
self.regular = [{"name": m.identifier.name, self.regular = [{"name": m.identifier.name,
"methodInfo": not m.isStatic(),
"length": methodLength(m), "length": methodLength(m),
"flags": "JSPROP_ENUMERATE" } "flags": "JSPROP_ENUMERATE" }
for m in methods] for m in methods]
@ -1164,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:
@ -1177,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),
@ -1833,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 = {}
@ -2292,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():
@ -2321,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
@ -2368,6 +2394,30 @@ class CGAbstractBindingMethod(CGAbstractExternMethod):
def generate_code(self): def generate_code(self):
assert(False) # Override me assert(False) # Override me
class CGAbstractStaticBindingMethod(CGAbstractMethod):
"""
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 = [
Argument('*mut JSContext', 'cx'),
Argument('libc::c_uint', 'argc'),
Argument('*mut JSVal', 'vp'),
]
CGAbstractMethod.__init__(self, descriptor, name, "JSBool", args, extern=True)
def definition_body(self):
return self.generate_code()
def generate_code(self):
assert False # Override me
class CGGenericMethod(CGAbstractBindingMethod): class CGGenericMethod(CGAbstractBindingMethod):
""" """
A class for generating the C++ code for an IDL method.. A class for generating the C++ code for an IDL method..
@ -2396,12 +2446,32 @@ class CGSpecializedMethod(CGAbstractExternMethod):
CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args) CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args)
def definition_body(self): def definition_body(self):
name = self.method.identifier.name nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
return CGWrapper(CGMethodCall([], MakeNativeName(name), self.method.isStatic(), self.method)
return CGWrapper(CGMethodCall([], nativeName, self.method.isStatic(),
self.descriptor, self.method), self.descriptor, self.method),
pre="let this = JS::from_raw(this);\n" pre="let this = JS::from_raw(this);\n"
"let mut this = this.root();\n") "let mut this = this.root();\n")
@staticmethod
def makeNativeName(descriptor, method):
return MakeNativeName(method.identifier.name)
class CGStaticMethod(CGAbstractStaticBindingMethod):
"""
A class for generating the Rust code for an IDL static method.
"""
def __init__(self, descriptor, method):
self.method = method
name = method.identifier.name
CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
def generate_code(self):
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
self.method)
return CGMethodCall([], nativeName, True, self.descriptor, self.method)
class CGGenericGetter(CGAbstractBindingMethod): class CGGenericGetter(CGAbstractBindingMethod):
""" """
A class for generating the C++ code for an IDL attribute getter. A class for generating the C++ code for an IDL attribute getter.
@ -2441,18 +2511,41 @@ class CGSpecializedGetter(CGAbstractExternMethod):
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
def definition_body(self): def definition_body(self):
name = self.attr.identifier.name nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
nativeName = MakeNativeName(name) self.attr)
infallible = ('infallible' in
self.descriptor.getExtendedAttributes(self.attr,
getter=True))
if self.attr.type.nullable() or not infallible:
nativeName = "Get" + nativeName
return CGWrapper(CGGetterCall([], self.attr.type, nativeName, return CGWrapper(CGGetterCall([], self.attr.type, nativeName,
self.descriptor, self.attr), self.descriptor, self.attr),
pre="let this = JS::from_raw(this);\n" pre="let this = JS::from_raw(this);\n"
"let mut this = this.root();\n") "let mut this = this.root();\n")
@staticmethod
def makeNativeName(descriptor, attr):
nativeName = MakeNativeName(attr.identifier.name)
infallible = ('infallible' in
descriptor.getExtendedAttributes(attr, getter=True))
if attr.type.nullable() or not infallible:
return "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
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.
@ -2497,13 +2590,40 @@ class CGSpecializedSetter(CGAbstractExternMethod):
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
def definition_body(self): def definition_body(self):
name = self.attr.identifier.name nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
return CGWrapper(CGSetterCall([], self.attr.type, self.attr)
"Set" + MakeNativeName(name), return CGWrapper(CGSetterCall([], self.attr.type, nativeName,
self.descriptor, self.attr), self.descriptor, self.attr),
pre="let this = JS::from_raw(this);\n" pre="let this = JS::from_raw(this);\n"
"let mut this = this.root();\n") "let mut this = this.root();\n")
@staticmethod
def makeNativeName(descriptor, attr):
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):
""" """
@ -3835,23 +3955,38 @@ class CGDescriptor(CGThing):
(hasMethod, hasGetter, hasLenientGetter, (hasMethod, hasGetter, hasLenientGetter,
hasSetter, hasLenientSetter) = False, False, False, False, False hasSetter, hasLenientSetter) = False, False, False, False, False
for m in descriptor.interface.members: for m in descriptor.interface.members:
if m.isMethod() and not m.isStatic() and not m.isIdentifierLess(): if m.isMethod() and not m.isIdentifierLess():
cgThings.append(CGSpecializedMethod(descriptor, m)) if m.isStatic():
cgThings.append(CGMemberJITInfo(descriptor, m)) assert descriptor.interface.hasInterfaceObject()
hasMethod = True cgThings.append(CGStaticMethod(descriptor, m))
elif descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGSpecializedMethod(descriptor, m))
cgThings.append(CGMemberJITInfo(descriptor, m))
hasMethod = True
elif m.isAttr(): elif m.isAttr():
cgThings.append(CGSpecializedGetter(descriptor, m)) if m.isStatic():
if m.hasLenientThis(): assert descriptor.interface.hasInterfaceObject()
hasLenientGetter = True cgThings.append(CGStaticGetter(descriptor, m))
else: elif descriptor.interface.hasInterfacePrototypeObject():
hasGetter = True cgThings.append(CGSpecializedGetter(descriptor, m))
if not m.readonly:
cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientSetter = True hasLenientGetter = True
else: else:
hasSetter = True hasGetter = True
cgThings.append(CGMemberJITInfo(descriptor, m))
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))
if m.hasLenientThis():
hasLenientSetter = True
else:
hasSetter = True
if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
cgThings.append(CGMemberJITInfo(descriptor, m))
if hasMethod: if hasMethod:
cgThings.append(CGGenericMethod(descriptor)) cgThings.append(CGGenericMethod(descriptor))
if hasGetter: if hasGetter:

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

@ -296,6 +296,12 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
} }
} }
impl TestBinding {
pub fn BooleanAttributeStatic() -> bool { false }
pub fn SetBooleanAttributeStatic(_: bool) {}
pub fn ReceiveVoidStatic() {}
}
impl Reflectable for TestBinding { impl Reflectable for TestBinding {
fn reflector<'a>(&'a self) -> &'a Reflector { fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector &self.reflector

View file

@ -266,4 +266,7 @@ interface TestBinding {
void passVariadicUnion2((Event or DOMString)... args); void passVariadicUnion2((Event or DOMString)... args);
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();
}; };