mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Implement static attributes (fixes #1989).
This commit is contained in:
parent
6d2784aece
commit
4f0d6979e7
4 changed files with 113 additions and 28 deletions
|
@ -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,18 +3964,29 @@ class CGDescriptor(CGThing):
|
||||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||||
hasMethod = True
|
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:
|
||||||
|
|
|
@ -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),
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -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() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue