mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
auto merge of #2599 : Ms2ger/servo/constantspec, r=jdm
This commit is contained in:
commit
eae9b94399
2 changed files with 80 additions and 106 deletions
|
@ -1062,7 +1062,7 @@ class PropertyDefiner:
|
||||||
return prefName[0]
|
return prefName[0]
|
||||||
|
|
||||||
def generatePrefableArray(self, array, name, specTemplate, specTerminator,
|
def generatePrefableArray(self, array, name, specTemplate, specTerminator,
|
||||||
specType, getPref, getDataTuple):
|
specType, getDataTuple):
|
||||||
"""
|
"""
|
||||||
This method generates our various arrays.
|
This method generates our various arrays.
|
||||||
|
|
||||||
|
@ -1072,58 +1072,22 @@ class PropertyDefiner:
|
||||||
|
|
||||||
specTemplate is a template for each entry of the spec array
|
specTemplate is a template for each entry of the spec array
|
||||||
|
|
||||||
specTerminator is a terminator for the spec array (inserted every time
|
specTerminator is a terminator for the spec array (inserted at the end
|
||||||
our controlling pref changes and at the end of the array)
|
of the array), or None
|
||||||
|
|
||||||
specType is the actual typename of our spec
|
specType is the actual typename of our spec
|
||||||
|
|
||||||
getPref is a callback function that takes an array entry and returns
|
|
||||||
the corresponding pref value.
|
|
||||||
|
|
||||||
getDataTuple is a callback function that takes an array entry and
|
getDataTuple is a callback function that takes an array entry and
|
||||||
returns a tuple suitable for substitution into specTemplate.
|
returns a tuple suitable for substitution into specTemplate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# We want to generate a single list of specs, but with specTerminator
|
|
||||||
# inserted at every point where the pref name controlling the member
|
|
||||||
# changes. That will make sure the order of the properties as exposed
|
|
||||||
# on the interface and interface prototype objects does not change when
|
|
||||||
# pref control is added to members while still allowing us to define all
|
|
||||||
# the members in the smallest number of JSAPI calls.
|
|
||||||
assert(len(array) is not 0)
|
assert(len(array) is not 0)
|
||||||
lastPref = getPref(array[0]) # So we won't put a specTerminator
|
|
||||||
# at the very front of the list.
|
|
||||||
specs = []
|
specs = []
|
||||||
prefableSpecs = []
|
|
||||||
|
|
||||||
prefableTemplate = ' { true, &%s[%d] }'
|
|
||||||
prefCacheTemplate = '&%s[%d].enabled'
|
|
||||||
def switchToPref(props, pref):
|
|
||||||
# Remember the info about where our pref-controlled
|
|
||||||
# booleans live.
|
|
||||||
if pref is not None:
|
|
||||||
props.prefCacheData.append(
|
|
||||||
(pref, prefCacheTemplate % (name, len(prefableSpecs)))
|
|
||||||
)
|
|
||||||
# Set up pointers to the new sets of specs and ids
|
|
||||||
# inside prefableSpecs and prefableIds
|
|
||||||
prefableSpecs.append(prefableTemplate %
|
|
||||||
(name + "_specs", len(specs)))
|
|
||||||
|
|
||||||
switchToPref(self, lastPref)
|
|
||||||
|
|
||||||
for member in array:
|
for member in array:
|
||||||
curPref = getPref(member)
|
|
||||||
if lastPref != curPref:
|
|
||||||
# Terminate previous list
|
|
||||||
specs.append(specTerminator)
|
|
||||||
# And switch to our new pref
|
|
||||||
switchToPref(self, curPref)
|
|
||||||
lastPref = curPref
|
|
||||||
# And the actual spec
|
|
||||||
specs.append(specTemplate % getDataTuple(member))
|
specs.append(specTemplate % getDataTuple(member))
|
||||||
specs.append(specTerminator)
|
if specTerminator:
|
||||||
prefableSpecs.append(" { false, NULL }");
|
specs.append(specTerminator)
|
||||||
|
|
||||||
return (("static %s: [%s, ..%i] = [\n" +
|
return (("static %s: [%s, ..%i] = [\n" +
|
||||||
",\n".join(specs) + "\n" +
|
",\n".join(specs) + "\n" +
|
||||||
|
@ -1194,9 +1158,6 @@ class MethodDefiner(PropertyDefiner):
|
||||||
if len(array) == 0:
|
if len(array) == 0:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def pref(m):
|
|
||||||
return m["pref"]
|
|
||||||
|
|
||||||
def specData(m):
|
def specData(m):
|
||||||
if m.get("methodInfo", True):
|
if m.get("methodInfo", True):
|
||||||
jitinfo = ("&%s_methodinfo" % m["name"])
|
jitinfo = ("&%s_methodinfo" % m["name"])
|
||||||
|
@ -1216,7 +1177,7 @@ class MethodDefiner(PropertyDefiner):
|
||||||
' JSFunctionSpec {name: &%s_name as *u8 as *libc::c_char, call: JSNativeWrapper {op: Some(%s), info: %s}, nargs: %s, flags: %s as u16, selfHostedName: 0 as *libc::c_char }',
|
' JSFunctionSpec {name: &%s_name as *u8 as *libc::c_char, call: JSNativeWrapper {op: Some(%s), info: %s}, nargs: %s, flags: %s as u16, selfHostedName: 0 as *libc::c_char }',
|
||||||
' JSFunctionSpec {name: 0 as *libc::c_char, call: JSNativeWrapper {op: None, info: 0 as *JSJitInfo}, nargs: 0, flags: 0, selfHostedName: 0 as *libc::c_char }',
|
' JSFunctionSpec {name: 0 as *libc::c_char, call: JSNativeWrapper {op: None, info: 0 as *JSJitInfo}, nargs: 0, flags: 0, selfHostedName: 0 as *libc::c_char }',
|
||||||
'JSFunctionSpec',
|
'JSFunctionSpec',
|
||||||
pref, specData)
|
specData)
|
||||||
|
|
||||||
class AttrDefiner(PropertyDefiner):
|
class AttrDefiner(PropertyDefiner):
|
||||||
def __init__(self, descriptor, name):
|
def __init__(self, descriptor, name):
|
||||||
|
@ -1264,7 +1225,7 @@ class AttrDefiner(PropertyDefiner):
|
||||||
' JSPropertySpec { name: &%s_name as *u8 as *libc::c_char, tinyid: 0, flags: ((%s) & 0xFF) as u8, getter: %s, setter: %s }',
|
' JSPropertySpec { name: &%s_name as *u8 as *libc::c_char, tinyid: 0, flags: ((%s) & 0xFF) as u8, getter: %s, setter: %s }',
|
||||||
' JSPropertySpec { name: 0 as *libc::c_char, tinyid: 0, flags: 0, getter: JSPropertyOpWrapper {op: None, info: 0 as *JSJitInfo}, setter: JSStrictPropertyOpWrapper {op: None, info: 0 as *JSJitInfo} }',
|
' JSPropertySpec { name: 0 as *libc::c_char, tinyid: 0, flags: 0, getter: JSPropertyOpWrapper {op: None, info: 0 as *JSJitInfo}, setter: JSStrictPropertyOpWrapper {op: None, info: 0 as *JSJitInfo} }',
|
||||||
'JSPropertySpec',
|
'JSPropertySpec',
|
||||||
PropertyDefiner.getControllingPref, specData)
|
specData)
|
||||||
|
|
||||||
class ConstDefiner(PropertyDefiner):
|
class ConstDefiner(PropertyDefiner):
|
||||||
"""
|
"""
|
||||||
|
@ -1286,17 +1247,16 @@ class ConstDefiner(PropertyDefiner):
|
||||||
|
|
||||||
def stringDecl(const):
|
def stringDecl(const):
|
||||||
name = const.identifier.name
|
name = const.identifier.name
|
||||||
return "static %s_name: [u8, ..%i] = %s;\n" % (name, len(name) + 1,
|
return "static %s_name: &'static [u8] = &%s;\n" % (name, str_to_const_array(name))
|
||||||
str_to_const_array(name))
|
|
||||||
|
|
||||||
decls = ''.join([stringDecl(m) for m in array])
|
decls = ''.join([stringDecl(m) for m in array])
|
||||||
|
|
||||||
return decls + self.generatePrefableArray(
|
return decls + self.generatePrefableArray(
|
||||||
array, name,
|
array, name,
|
||||||
' ConstantSpec { name: &%s_name as *u8 as *libc::c_char, value: %s }',
|
' ConstantSpec { name: %s_name, value: %s }',
|
||||||
' ConstantSpec { name: 0 as *libc::c_char, value: VoidVal }',
|
None,
|
||||||
'ConstantSpec',
|
'ConstantSpec',
|
||||||
PropertyDefiner.getControllingPref, specData)
|
specData)
|
||||||
|
|
||||||
# We'll want to insert the indent at the beginnings of lines, but we
|
# We'll want to insert the indent at the beginnings of lines, but we
|
||||||
# don't want to indent empty lines. So only indent lines that have a
|
# don't want to indent empty lines. So only indent lines that have a
|
||||||
|
@ -1982,8 +1942,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||||
def arrayPtr(name):
|
def arrayPtr(name):
|
||||||
val = ('%(' + name + ')s') % self.properties.variableNames(False)
|
val = ('%(' + name + ')s') % self.properties.variableNames(False)
|
||||||
if val == "ptr::null()":
|
if val == "ptr::null()":
|
||||||
return val
|
return "None"
|
||||||
return "&%s[0]" % val
|
return "Some(%s.as_slice())" % val
|
||||||
|
|
||||||
call = """return CreateInterfaceObjects2(aCx, aGlobal, aReceiver, parentProto,
|
call = """return CreateInterfaceObjects2(aCx, aGlobal, aReceiver, parentProto,
|
||||||
%s, %s, %d,
|
%s, %s, %d,
|
||||||
|
|
|
@ -192,7 +192,7 @@ pub enum ConstantVal {
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ConstantSpec {
|
pub struct ConstantSpec {
|
||||||
pub name: *libc::c_char,
|
pub name: &'static [u8],
|
||||||
pub value: ConstantVal
|
pub value: ConstantVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,10 +219,10 @@ pub fn CreateInterfaceObjects2(cx: *mut JSContext, global: *mut JSObject, receiv
|
||||||
constructor: JSNative,
|
constructor: JSNative,
|
||||||
ctorNargs: u32,
|
ctorNargs: u32,
|
||||||
domClass: *DOMClass,
|
domClass: *DOMClass,
|
||||||
methods: *JSFunctionSpec,
|
methods: Option<&'static [JSFunctionSpec]>,
|
||||||
properties: *JSPropertySpec,
|
properties: Option<&'static [JSPropertySpec]>,
|
||||||
constants: *ConstantSpec,
|
constants: Option<&'static [ConstantSpec]>,
|
||||||
staticMethods: *JSFunctionSpec,
|
staticMethods: Option<&'static [JSFunctionSpec]>,
|
||||||
name: &str) -> *mut JSObject {
|
name: &str) -> *mut JSObject {
|
||||||
let mut proto = ptr::mut_null();
|
let mut proto = ptr::mut_null();
|
||||||
if protoClass.is_not_null() {
|
if protoClass.is_not_null() {
|
||||||
|
@ -261,8 +261,8 @@ pub fn CreateInterfaceObjects2(cx: *mut JSContext, global: *mut JSObject, receiv
|
||||||
fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *mut JSObject,
|
fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *mut JSObject,
|
||||||
constructorNative: JSNative,
|
constructorNative: JSNative,
|
||||||
ctorNargs: u32, proto: *mut JSObject,
|
ctorNargs: u32, proto: *mut JSObject,
|
||||||
staticMethods: *JSFunctionSpec,
|
staticMethods: Option<&'static [JSFunctionSpec]>,
|
||||||
constants: *ConstantSpec,
|
constants: Option<&'static [ConstantSpec]>,
|
||||||
name: *libc::c_char) -> *mut JSObject {
|
name: *libc::c_char) -> *mut JSObject {
|
||||||
unsafe {
|
unsafe {
|
||||||
let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
|
let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
|
||||||
|
@ -274,14 +274,22 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m
|
||||||
let constructor = JS_GetFunctionObject(fun);
|
let constructor = JS_GetFunctionObject(fun);
|
||||||
assert!(constructor.is_not_null());
|
assert!(constructor.is_not_null());
|
||||||
|
|
||||||
if staticMethods.is_not_null() &&
|
match staticMethods {
|
||||||
!DefineMethods(cx, constructor, staticMethods) {
|
Some(staticMethods) => {
|
||||||
return ptr::mut_null();
|
if !DefineMethods(cx, constructor, staticMethods) {
|
||||||
|
return ptr::mut_null();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.is_not_null() &&
|
match constants {
|
||||||
!DefineConstants(cx, constructor, constants) {
|
Some(constants) => {
|
||||||
return ptr::mut_null();
|
if !DefineConstants(cx, constructor, constants) {
|
||||||
|
return ptr::mut_null();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
|
if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
|
||||||
|
@ -303,67 +311,73 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: *ConstantSpec) -> bool {
|
fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ConstantSpec]) -> bool {
|
||||||
let mut i = 0;
|
constants.iter().all(|spec| {
|
||||||
loop {
|
let jsval = match spec.value {
|
||||||
|
NullVal => NullValue(),
|
||||||
|
IntVal(i) => Int32Value(i),
|
||||||
|
UintVal(u) => UInt32Value(u),
|
||||||
|
DoubleVal(d) => DoubleValue(d),
|
||||||
|
BoolVal(b) => BooleanValue(b),
|
||||||
|
VoidVal => UndefinedValue(),
|
||||||
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let spec = *constants.offset(i);
|
JS_DefineProperty(cx, obj, spec.name.as_ptr() as *libc::c_char,
|
||||||
if spec.name.is_null() {
|
jsval, None, None,
|
||||||
return true;
|
JSPROP_ENUMERATE | JSPROP_READONLY |
|
||||||
}
|
JSPROP_PERMANENT) != 0
|
||||||
let jsval = match spec.value {
|
|
||||||
NullVal => NullValue(),
|
|
||||||
IntVal(i) => Int32Value(i),
|
|
||||||
UintVal(u) => UInt32Value(u),
|
|
||||||
DoubleVal(d) => DoubleValue(d),
|
|
||||||
BoolVal(b) => BooleanValue(b),
|
|
||||||
VoidVal => UndefinedValue(),
|
|
||||||
};
|
|
||||||
if JS_DefineProperty(cx, obj, spec.name,
|
|
||||||
jsval, None,
|
|
||||||
None,
|
|
||||||
JSPROP_ENUMERATE | JSPROP_READONLY |
|
|
||||||
JSPROP_PERMANENT) == 0 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
i += 1;
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn DefineMethods(cx: *mut JSContext, obj: *mut JSObject, methods: &'static [JSFunctionSpec]) -> bool {
|
||||||
|
unsafe {
|
||||||
|
JS_DefineFunctions(cx, obj, methods.as_ptr()) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineMethods(cx: *mut JSContext, obj: *mut JSObject, methods: *JSFunctionSpec) -> bool {
|
fn DefineProperties(cx: *mut JSContext, obj: *mut JSObject, properties: &'static [JSPropertySpec]) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
JS_DefineFunctions(cx, obj, methods) != 0
|
JS_DefineProperties(cx, obj, properties.as_ptr()) != 0
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn DefineProperties(cx: *mut JSContext, obj: *mut JSObject, properties: *JSPropertySpec) -> bool {
|
|
||||||
unsafe {
|
|
||||||
JS_DefineProperties(cx, obj, properties) != 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CreateInterfacePrototypeObject(cx: *mut JSContext, global: *mut JSObject,
|
fn CreateInterfacePrototypeObject(cx: *mut JSContext, global: *mut JSObject,
|
||||||
parentProto: *mut JSObject, protoClass: *JSClass,
|
parentProto: *mut JSObject, protoClass: *JSClass,
|
||||||
methods: *JSFunctionSpec,
|
methods: Option<&'static [JSFunctionSpec]>,
|
||||||
properties: *JSPropertySpec,
|
properties: Option<&'static [JSPropertySpec]>,
|
||||||
constants: *ConstantSpec) -> *mut JSObject {
|
constants: Option<&'static [ConstantSpec]>) -> *mut JSObject {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
|
let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
|
||||||
if ourProto.is_null() {
|
if ourProto.is_null() {
|
||||||
return ptr::mut_null();
|
return ptr::mut_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if methods.is_not_null() && !DefineMethods(cx, ourProto, methods) {
|
match methods {
|
||||||
return ptr::mut_null();
|
Some(methods) => {
|
||||||
|
if !DefineMethods(cx, ourProto, methods) {
|
||||||
|
return ptr::mut_null();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if properties.is_not_null() && !DefineProperties(cx, ourProto, properties) {
|
match properties {
|
||||||
return ptr::mut_null();
|
Some(properties) => {
|
||||||
|
if !DefineProperties(cx, ourProto, properties) {
|
||||||
|
return ptr::mut_null();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.is_not_null() && !DefineConstants(cx, ourProto, constants) {
|
match constants {
|
||||||
return ptr::mut_null();
|
Some(constants) => {
|
||||||
|
if !DefineConstants(cx, ourProto, constants) {
|
||||||
|
return ptr::mut_null();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
return ourProto;
|
return ourProto;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue