auto merge of #2599 : Ms2ger/servo/constantspec, r=jdm

This commit is contained in:
bors-servo 2014-06-06 14:04:29 -04:00
commit eae9b94399
2 changed files with 80 additions and 106 deletions

View file

@ -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,

View file

@ -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;