aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/servo/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--src/servo/dom/bindings/codegen/CodegenRust.py139
1 files changed, 95 insertions, 44 deletions
diff --git a/src/servo/dom/bindings/codegen/CodegenRust.py b/src/servo/dom/bindings/codegen/CodegenRust.py
index 71c22234ec5..50dd7f6aa24 100644
--- a/src/servo/dom/bindings/codegen/CodegenRust.py
+++ b/src/servo/dom/bindings/codegen/CodegenRust.py
@@ -1098,22 +1098,19 @@ for (uint32_t i = 0; i < length; ++i) {
"yet")
enum = type.inner.identifier.name
if invalidEnumValueFatal:
- handleInvalidEnumValueCode = " MOZ_ASSERT(index >= 0);\n"
+ handleInvalidEnumValueCode = " return 0;\n"
else:
- handleInvalidEnumValueCode = (
- " if (index < 0) {\n"
- " return true;\n"
- " }\n")
+ handleInvalidEnumValueCode = " return 1;\n"
template = (
"{\n"
- " bool ok;\n"
- " int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, \"%(enumtype)s\", &ok);\n"
- " if (!ok) {\n"
- " return false;\n"
- " }\n"
+ #" int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, \"%(enumtype)s\", &ok);\n"
+ " let result = FindEnumStringIndex(cx, ${val}, %(values)s);\n"
+ " if result.is_err() {\n"
"%(handleInvalidEnumValueCode)s"
- " ${declName} = static_cast<%(enumtype)s>(index);\n"
+ " }\n"
+ " let index = result.get();\n"
+ " ${declName} = cast::transmute(index); //XXXjdm need some range checks up in here\n"
"}" % { "enumtype" : enum,
"values" : enum + "Values::strings",
"invalidEnumValueFatal" : toStringBool(invalidEnumValueFatal),
@@ -1529,7 +1526,7 @@ for (uint32_t i = 0; i < length; ++i) {
if not isCreator:
raise MethodNotCreatorError(descriptor.interface.identifier.name)
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
- wrap = "%s(cx, ${obj}, %s, ${jsvalPtr})" % (wrapMethod, result)
+ wrap = "%s(cx, ${obj}, %s as @mut CacheableWrapper, ${jsvalPtr})" % (wrapMethod, result)
# We don't support prefable stuff in workers.
assert(not descriptor.prefable or not descriptor.workers)
if not descriptor.prefable:
@@ -1547,12 +1544,11 @@ for (uint32_t i = 0; i < length; ++i) {
failed = wrapAndSetPtr("HandleNewBindingWrappingFailure(cx, ${obj}, %s, ${jsvalPtr})" % result)
wrappingCode += wrapAndSetPtr(wrap, failed)
else:
- if descriptor.notflattened:
- getIID = "&NS_GET_IID(%s), " % descriptor.nativeType
- else:
- getIID = ""
#wrap = "WrapObject(cx, ${obj}, %s, %s${jsvalPtr})" % (result, getIID)
- wrap = "%s.wrap(cx, ${obj}, %s${jsvalPtr})" % (result, getIID)
+ if descriptor.pointerType == '':
+ wrap = "%s.wrap(cx, ${obj}, ${jsvalPtr})" % result
+ else:
+ wrap = "if WrapNewBindingObject(cx, ${obj}, %s as @mut CacheableWrapper, ${jsvalPtr}) { 1 } else { 0 };" % result
wrappingCode += wrapAndSetPtr(wrap)
return (wrappingCode, False)
@@ -1701,10 +1697,10 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
descriptor = descriptorProvider.getDescriptor(
returnType.unroll().inner.identifier.name)
result = CGGeneric(descriptor.nativeType)
- if resultAlreadyAddRefed:
+ if returnType.nullable():
result = CGWrapper(result, pre=("Option<" + descriptor.pointerType), post=">")
else:
- result = CGWrapper(result, post="*")
+ result = CGWrapper(result, pre=descriptor.pointerType)
return result, False
if returnType.isCallback():
# XXXbz we're going to assume that callback types are always
@@ -2154,20 +2150,23 @@ class CGIfWrapper(CGWrapper):
post="\n}")
class CGNamespace(CGWrapper):
- def __init__(self, namespace, child, declareOnly=False):
- pre = "mod %s {\n" % namespace
+ def __init__(self, namespace, child, declareOnly=False, public=False):
+ pre = "%smod %s {\n" % ("pub " if public else "", namespace)
post = "} // mod %s\n" % namespace
CGWrapper.__init__(self, child, pre=pre, post=post,
declareOnly=declareOnly)
@staticmethod
- def build(namespaces, child, declareOnly=False):
+ def build(namespaces, child, declareOnly=False, public=False):
"""
Static helper method to build multiple wrapped namespaces.
"""
if not namespaces:
return CGWrapper(child, declareOnly=declareOnly)
- inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly)
- return CGNamespace(namespaces[0], inner, declareOnly=declareOnly)
+ inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly, public=public)
+ return CGNamespace(namespaces[0], inner, declareOnly=declareOnly, public=public)
+
+ def declare(self):
+ return ""
def DOMClass(descriptor):
protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
@@ -2474,7 +2473,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
return """ *aTriedToWrap = true;
let mut parent = aObject.GetParentObject(aCx);
- let parent = WrapNativeParent(aCx, aScope, &mut parent);
+ let parent = WrapNativeParent(aCx, aScope, parent);
if parent.is_null() {
return ptr::null();
}
@@ -2502,11 +2501,11 @@ class CGWrapMethod(CGAbstractMethod):
# XXX can we wrap if we don't have an interface prototype object?
assert descriptor.interface.hasInterfacePrototypeObject()
args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aScope'),
- Argument('~' + descriptor.nativeType, 'aObject'), Argument('*mut bool', 'aTriedToWrap')]
+ Argument(descriptor.pointerType + descriptor.nativeType, 'aObject'), Argument('*mut bool', 'aTriedToWrap')]
CGAbstractMethod.__init__(self, descriptor, 'Wrap', '*JSObject', args, inline=True, pub=True)
def definition_body(self):
- return " let mut binding = BindingReference(Left(aObject)); \
+ return " let mut binding = BindingReference(Right(aObject)); \
return Wrap_(aCx, aScope, &mut binding, aTriedToWrap);"
class CGWrapNonWrapperCacheMethod(CGAbstractMethod):
@@ -3289,6 +3288,46 @@ class CGMemberJITInfo(CGThing):
return result
raise TypeError("Illegal member type to CGPropertyJITInfo")
+def getEnumValueName(value):
+ # Some enum values can be empty strings. Others might have weird
+ # characters in them. Deal with the former by returning "_empty",
+ # deal with possible name collisions from that by throwing if the
+ # enum value is actually "_empty", and throw on any value
+ # containing non-ASCII chars for now. Replace all chars other than
+ # [0-9A-Za-z_] with '_'.
+ if re.match("[^\x20-\x7E]", value):
+ raise SyntaxError('Enum value "' + value + '" contains non-ASCII characters')
+ if re.match("^[0-9]", value):
+ raise SyntaxError('Enum value "' + value + '" starts with a digit')
+ value = re.sub(r'[^0-9A-Za-z_]', '_', value)
+ if re.match("^_[A-Z]|__", value):
+ raise SyntaxError('Enum value "' + value + '" is reserved by the C++ spec')
+ if value == "_empty":
+ raise SyntaxError('"_empty" is not an IDL enum value we support yet')
+ if value == "":
+ return "_empty"
+ return MakeNativeName(value)
+
+class CGEnum(CGThing):
+ def __init__(self, enum):
+ CGThing.__init__(self)
+ self.enum = enum
+
+ def declare(self):
+ return ""
+
+ def define(self):
+ return """
+ pub enum valuelist {
+ %s
+ }
+
+ pub static strings: &'static [EnumEntry] = &[
+ %s,
+ ];
+""" % (",\n ".join(map(getEnumValueName, self.enum.values())),
+ ",\n ".join(['EnumEntry {value: &"' + val + '", length: ' + str(len(val)) + '}' for val in self.enum.values()]))
+
class CGXrayHelper(CGAbstractExternMethod):
def __init__(self, descriptor, name, args, properties):
CGAbstractExternMethod.__init__(self, descriptor, name, "bool", args)
@@ -3574,42 +3613,38 @@ let _: %s = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val));
#return clearWrapper + release
return release
-class CGClassConstructHook(CGAbstractStaticMethod):
+class CGClassConstructHook(CGAbstractExternMethod):
"""
JS-visible constructor for our objects
"""
def __init__(self, descriptor):
- args = [Argument('*JSContext', 'cx'), Argument('unsigned', 'argc'), Argument('*jsval', 'vp')]
- CGAbstractStaticMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME,
+ args = [Argument('*JSContext', 'cx'), Argument('u32', 'argc'), Argument('*mut JSVal', 'vp')]
+ CGAbstractExternMethod.__init__(self, descriptor, CONSTRUCT_HOOK_NAME,
'JSBool', args)
self._ctor = self.descriptor.interface.ctor()
def define(self):
if not self._ctor:
return ""
- return CGAbstractStaticMethod.define(self)
+ return CGAbstractExternMethod.define(self)
def definition_body(self):
return self.generate_code()
def generate_code(self):
preamble = """
- JSObject* obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+ //JSObject* obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
"""
if self.descriptor.workers:
preArgs = ["cx", "obj"]
else:
preamble += """
- nsISupports* global;
- xpc_qsSelfRef globalRef;
- {
- nsresult rv;
- JS::Value val = OBJECT_TO_JSVAL(obj);
- rv = xpc_qsUnwrapArg<nsISupports>(cx, val, &global, &globalRef.ptr, &val);
- if (NS_FAILED(rv)) {
- return Throw<true>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
- }
- }
+ //XXXjdm Gecko obtains a GlobalObject from the global (maybe from the private value,
+ // or through unwrapping a slot or something). We'll punt and get the Window
+ // from the context for now.
+ let content = task_from_context(cx);
+ let global = (*content).window.get();
+ let obj = global.get_wrappercache().get_wrapper();
"""
preArgs = ["global"]
@@ -3835,6 +3870,17 @@ class CGBindingRoot(CGThing):
cgthings = []
+ # Do codegen for all the enums
+ def makeEnum(e):
+ return CGNamespace.build([e.identifier.name + "Values"],
+ CGList([CGGeneric(" use dom::bindings::utils::EnumEntry;"),
+ CGEnum(e)]), public=True)
+ def makeEnumTypedef(e):
+ return CGGeneric(declare=("pub type %s = self::%sValues::valuelist;\n" %
+ (e.identifier.name, e.identifier.name)))
+ cgthings = [ fun(e) for e in config.getEnums(webIDLFile)
+ for fun in [makeEnum, makeEnumTypedef] ]
+
# Do codegen for all the descriptors
cgthings.extend([CGDescriptor(x) for x in descriptors])
@@ -3846,6 +3892,8 @@ class CGBindingRoot(CGThing):
# CGWrapper(curr, pre="\n"))
# Add imports
+ #XXXjdm This should only import the namespace for the current binding,
+ # not every binding ever.
curr = CGImports(descriptors,
dictionaries,
['js::*',
@@ -3854,14 +3902,17 @@ class CGBindingRoot(CGThing):
'js::jsfriendapi::bindgen::*',
'js::glue::bindgen::*',
'js::glue::*',
- 'dom::node::AbstractNode',
+ 'dom::node::AbstractNode', #XXXjdm
+ 'dom::document::Document', #XXXjdm
'dom::bindings::utils::*',
'dom::bindings::conversions::*',
'dom::bindings::clientrect::*', #XXXjdm
'dom::bindings::clientrectlist::*', #XXXjdm
'dom::bindings::htmlcollection::*', #XXXjdm
'dom::bindings::proxyhandler::*',
- 'content::content_task::task_from_context'
+ 'dom::domparser::*', #XXXjdm
+ 'content::content_task::task_from_context',
+ 'dom::bindings::utils::EnumEntry',
],
[],
curr)