From 3dece6b7ab428e528b78155e69e63fba17f1e1b9 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 6 Jun 2014 13:22:47 +0200 Subject: [PATCH 1/4] Remove some code to support preffing off APIs. We won't be using this feature in the near future, and the implementation is not really Rustic. --- .../dom/bindings/codegen/CodegenRust.py | 52 +++---------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 171301ac7d4..899ba0c755e 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1062,7 +1062,7 @@ class PropertyDefiner: return prefName[0] def generatePrefableArray(self, array, name, specTemplate, specTerminator, - specType, getPref, getDataTuple): + specType, getDataTuple): """ This method generates our various arrays. @@ -1072,58 +1072,21 @@ class PropertyDefiner: specTemplate is a template for each entry of the spec array - specTerminator is a terminator for the spec array (inserted every time - our controlling pref changes and at the end of the array) + specTerminator is a terminator for the spec array (inserted at the end + of the array) 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 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) - lastPref = getPref(array[0]) # So we won't put a specTerminator - # at the very front of the list. 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: - 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(specTerminator) - prefableSpecs.append(" { false, NULL }"); return (("static %s: [%s, ..%i] = [\n" + ",\n".join(specs) + "\n" + @@ -1194,9 +1157,6 @@ class MethodDefiner(PropertyDefiner): if len(array) == 0: return "" - def pref(m): - return m["pref"] - def specData(m): if m.get("methodInfo", True): jitinfo = ("&%s_methodinfo" % m["name"]) @@ -1216,7 +1176,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: 0 as *libc::c_char, call: JSNativeWrapper {op: None, info: 0 as *JSJitInfo}, nargs: 0, flags: 0, selfHostedName: 0 as *libc::c_char }', 'JSFunctionSpec', - pref, specData) + specData) class AttrDefiner(PropertyDefiner): def __init__(self, descriptor, name): @@ -1264,7 +1224,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: 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', - PropertyDefiner.getControllingPref, specData) + specData) class ConstDefiner(PropertyDefiner): """ @@ -1296,7 +1256,7 @@ class ConstDefiner(PropertyDefiner): ' ConstantSpec { name: &%s_name as *u8 as *libc::c_char, value: %s }', ' ConstantSpec { name: 0 as *libc::c_char, value: VoidVal }', 'ConstantSpec', - PropertyDefiner.getControllingPref, specData) + specData) # 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 From 0c54cd1634c54429f25953a62dcd6c56680ae3b3 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 6 Jun 2014 14:01:09 +0200 Subject: [PATCH 2/4] Pass slices to CreateInterfaceObjects2 rather than raw pointers. --- .../dom/bindings/codegen/CodegenRust.py | 4 +- src/components/script/dom/bindings/utils.rs | 111 +++++++++++------- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 899ba0c755e..d23dc062dab 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1942,8 +1942,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): def arrayPtr(name): val = ('%(' + name + ')s') % self.properties.variableNames(False) if val == "ptr::null()": - return val - return "&%s[0]" % val + return "None" + return "Some(%s.as_slice())" % val call = """return CreateInterfaceObjects2(aCx, aGlobal, aReceiver, parentProto, %s, %s, %d, diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index e0a867ceaf2..c7020823273 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -219,10 +219,10 @@ pub fn CreateInterfaceObjects2(cx: *mut JSContext, global: *mut JSObject, receiv constructor: JSNative, ctorNargs: u32, domClass: *DOMClass, - methods: *JSFunctionSpec, - properties: *JSPropertySpec, - constants: *ConstantSpec, - staticMethods: *JSFunctionSpec, + methods: Option<&'static [JSFunctionSpec]>, + properties: Option<&'static [JSPropertySpec]>, + constants: Option<&'static [ConstantSpec]>, + staticMethods: Option<&'static [JSFunctionSpec]>, name: &str) -> *mut JSObject { let mut proto = ptr::mut_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, constructorNative: JSNative, ctorNargs: u32, proto: *mut JSObject, - staticMethods: *JSFunctionSpec, - constants: *ConstantSpec, + staticMethods: Option<&'static [JSFunctionSpec]>, + constants: Option<&'static [ConstantSpec]>, name: *libc::c_char) -> *mut JSObject { unsafe { 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); assert!(constructor.is_not_null()); - if staticMethods.is_not_null() && - !DefineMethods(cx, constructor, staticMethods) { - return ptr::mut_null(); + match staticMethods { + Some(staticMethods) => { + if !DefineMethods(cx, constructor, staticMethods) { + return ptr::mut_null(); + } + }, + _ => (), } - if constants.is_not_null() && - !DefineConstants(cx, constructor, constants) { - return ptr::mut_null(); + match constants { + Some(constants) => { + if !DefineConstants(cx, constructor, constants) { + return ptr::mut_null(); + } + }, + _ => (), } if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 { @@ -303,22 +311,20 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m } } -fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: *ConstantSpec) -> bool { - let mut i = 0; - loop { +fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ConstantSpec]) -> bool { + for spec in constants.iter() { + if spec.name.is_null() { + return true; + } + 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 { - let spec = *constants.offset(i); - if spec.name.is_null() { - return true; - } - 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, @@ -327,43 +333,58 @@ fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: *ConstantS return false; } } - i += 1; + } + fail!(); +} + +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 { - JS_DefineFunctions(cx, obj, methods) != 0 - } -} - -fn DefineProperties(cx: *mut JSContext, obj: *mut JSObject, properties: *JSPropertySpec) -> bool { - unsafe { - JS_DefineProperties(cx, obj, properties) != 0 + JS_DefineProperties(cx, obj, properties.as_ptr()) != 0 } } fn CreateInterfacePrototypeObject(cx: *mut JSContext, global: *mut JSObject, parentProto: *mut JSObject, protoClass: *JSClass, - methods: *JSFunctionSpec, - properties: *JSPropertySpec, - constants: *ConstantSpec) -> *mut JSObject { + methods: Option<&'static [JSFunctionSpec]>, + properties: Option<&'static [JSPropertySpec]>, + constants: Option<&'static [ConstantSpec]>) -> *mut JSObject { unsafe { let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global); if ourProto.is_null() { return ptr::mut_null(); } - if methods.is_not_null() && !DefineMethods(cx, ourProto, methods) { - return ptr::mut_null(); + match methods { + Some(methods) => { + if !DefineMethods(cx, ourProto, methods) { + return ptr::mut_null(); + } + }, + _ => (), } - if properties.is_not_null() && !DefineProperties(cx, ourProto, properties) { - return ptr::mut_null(); + match properties { + Some(properties) => { + if !DefineProperties(cx, ourProto, properties) { + return ptr::mut_null(); + } + }, + _ => (), } - if constants.is_not_null() && !DefineConstants(cx, ourProto, constants) { - return ptr::mut_null(); + match constants { + Some(constants) => { + if !DefineConstants(cx, ourProto, constants) { + return ptr::mut_null(); + } + }, + _ => (), } return ourProto; From ba68203ebf5117b56cb2e67b220a8549591421eb Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 6 Jun 2014 14:10:41 +0200 Subject: [PATCH 3/4] Remove the pointless terminator from ConstantSpec slices. --- .../dom/bindings/codegen/CodegenRust.py | 7 ++++--- src/components/script/dom/bindings/utils.rs | 19 ++++++------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index d23dc062dab..47dda13927f 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1073,7 +1073,7 @@ class PropertyDefiner: specTemplate is a template for each entry of the spec array specTerminator is a terminator for the spec array (inserted at the end - of the array) + of the array), or None specType is the actual typename of our spec @@ -1086,7 +1086,8 @@ class PropertyDefiner: for member in array: specs.append(specTemplate % getDataTuple(member)) - specs.append(specTerminator) + if specTerminator: + specs.append(specTerminator) return (("static %s: [%s, ..%i] = [\n" + ",\n".join(specs) + "\n" + @@ -1254,7 +1255,7 @@ class ConstDefiner(PropertyDefiner): return decls + self.generatePrefableArray( array, name, ' ConstantSpec { name: &%s_name as *u8 as *libc::c_char, value: %s }', - ' ConstantSpec { name: 0 as *libc::c_char, value: VoidVal }', + None, 'ConstantSpec', specData) diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index c7020823273..f6e9a1e1ba6 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -312,10 +312,8 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m } fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ConstantSpec]) -> bool { - for spec in constants.iter() { - if spec.name.is_null() { - return true; - } + constants.iter().all(|spec| { + assert!(spec.name.is_not_null()); let jsval = match spec.value { NullVal => NullValue(), IntVal(i) => Int32Value(i), @@ -325,16 +323,11 @@ fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ VoidVal => UndefinedValue(), }; unsafe { - if JS_DefineProperty(cx, obj, spec.name, - jsval, None, - None, - JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT) == 0 { - return false; - } + JS_DefineProperty(cx, obj, spec.name, jsval, None, None, + JSPROP_ENUMERATE | JSPROP_READONLY | + JSPROP_PERMANENT) != 0 } - } - fail!(); + }) } fn DefineMethods(cx: *mut JSContext, obj: *mut JSObject, methods: &'static [JSFunctionSpec]) -> bool { From d882bb7cc0e1b7558ef580a0c87ae982f6c1693d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 6 Jun 2014 14:23:09 +0200 Subject: [PATCH 4/4] Store a slice in ConstantSpec, rather than a raw pointer. --- src/components/script/dom/bindings/codegen/CodegenRust.py | 5 ++--- src/components/script/dom/bindings/utils.rs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 47dda13927f..ba9e96d64d1 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -1247,14 +1247,13 @@ class ConstDefiner(PropertyDefiner): def stringDecl(const): name = const.identifier.name - return "static %s_name: [u8, ..%i] = %s;\n" % (name, len(name) + 1, - str_to_const_array(name)) + return "static %s_name: &'static [u8] = &%s;\n" % (name, str_to_const_array(name)) decls = ''.join([stringDecl(m) for m in array]) return decls + self.generatePrefableArray( array, name, - ' ConstantSpec { name: &%s_name as *u8 as *libc::c_char, value: %s }', + ' ConstantSpec { name: %s_name, value: %s }', None, 'ConstantSpec', specData) diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index f6e9a1e1ba6..2da31f8bf2f 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -192,7 +192,7 @@ pub enum ConstantVal { #[deriving(Clone)] pub struct ConstantSpec { - pub name: *libc::c_char, + pub name: &'static [u8], pub value: ConstantVal } @@ -313,7 +313,6 @@ fn CreateInterfaceObject(cx: *mut JSContext, global: *mut JSObject, receiver: *m fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ConstantSpec]) -> bool { constants.iter().all(|spec| { - assert!(spec.name.is_not_null()); let jsval = match spec.value { NullVal => NullValue(), IntVal(i) => Int32Value(i), @@ -323,7 +322,8 @@ fn DefineConstants(cx: *mut JSContext, obj: *mut JSObject, constants: &'static [ VoidVal => UndefinedValue(), }; unsafe { - JS_DefineProperty(cx, obj, spec.name, jsval, None, None, + JS_DefineProperty(cx, obj, spec.name.as_ptr() as *libc::c_char, + jsval, None, None, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT) != 0 }