diff --git a/.gitignore b/.gitignore index c74b3251780..0eaec0d4ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,9 @@ build config.mk config.stamp parser.out +src/servo/dom/bindings/codegen/*.rs +src/servo/dom/bindings/codegen/_cache/ +src/servo/dom/bindings/codegen/test/*.rs +src/servo/dom/bindings/codegen/PrototypeList.h +src/servo/dom/bindings/codegen/UnionTypes.h +src/servo/dom/bindings/codegen/UnionConversions.h diff --git a/Makefile.in b/Makefile.in index fd5f105fc41..4d713ce8945 100644 --- a/Makefile.in +++ b/Makefile.in @@ -154,7 +154,9 @@ DEPS_servo_gfx = $(CRATE_servo_gfx) $(SRC_servo_gfx) $(DONE_SUBMODULES) RFLAGS_servo = $(strip $(CFG_RUSTC_FLAGS)) $(addprefix -L $(B)src/,$(DEPS_SUBMODULES)) -L $(B)src/servo-gfx -SRC_servo = $(call rwildcard,$(S)src/servo/,*.rs) +WEBIDL_servo = $(call rwildcard,$(S)src/servo/,*.webidl) +AUTOGEN_SRC_servo = $(patsubst %.webidl, %Binding.rs, $(WEBIDL_servo)) +SRC_servo = $(call rwildcard,$(S)src/servo/,*.rs) $(AUTOGEN_SRC_servo) CRATE_servo = $(S)src/servo/servo.rc DEPS_servo = $(CRATE_servo) $(SRC_servo) $(DONE_SUBMODULES) $(DONE_servo_gfx) @@ -172,6 +174,35 @@ all: servo package $(DONE_servo_gfx): $(DEPS_servo_gfx) $(RUSTC) $(RFLAGS_servo_gfx) -o $@ $< && touch $@ +BINDINGS_SRC = $(S)/src/servo/dom/bindings/codegen + +CACHE_DIR = $(BINDINGS_SRC)/_cache + +bindinggen_dependencies := $(addprefix $(BINDINGS_SRC)/, BindingGen.py Bindings.conf Configuration.py CodegenRust.py parser/WebIDL.py ParserResults.pkl) + +$(AUTOGEN_SRC_servo): %Binding.rs: $(bindinggen_dependencies) \ + %.webidl + PYTHONDONTWRITEBYTECODE=1 python $(BINDINGS_SRC)/pythonpath.py \ + -I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \ + -D$(BINDINGS_SRC) \ + $(BINDINGS_SRC)/BindingGen.py rs \ + $(BINDINGS_SRC)/Bindings.conf $*Binding $*.webidl + +globalgen_dependencies := $(addprefix $(BINDINGS_SRC)/, GlobalGen.py Bindings.conf Configuration.py CodegenRust.py parser/WebIDL.py) $(CACHE_DIR)/.done + +$(CACHE_DIR)/.done: + mkdir -p $(CACHE_DIR) + @touch $@ + +$(BINDINGS_SRC)/ParserResults.pkl: $(globalgen_dependencies) \ + $(WEBIDL_servo) + PYTHONDONTWRITEBYTECODE=1 python $(BINDINGS_SRC)/pythonpath.py \ + -I$(BINDINGS_SRC)/parser -I$(BINDINGS_SRC)/ply \ + -D$(BINDINGS_SRC) \ + $(BINDINGS_SRC)/GlobalGen.py $(BINDINGS_SRC)/Bindings.conf . \ + --cachedir=$(CACHE_DIR) \ + $(WEBIDL_servo) + # Servo binaries servo: $(DEPS_servo) diff --git a/src/servo/dom/bindings/clientrect.rs b/src/servo/dom/bindings/clientrect.rs index 3caa87c25db..03e97163b92 100644 --- a/src/servo/dom/bindings/clientrect.rs +++ b/src/servo/dom/bindings/clientrect.rs @@ -1,6 +1,6 @@ use content::content_task::task_from_context; use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, OpaqueBindingReference}; -use dom::bindings::ClientRectBinding; +use dom::bindings::codegen::ClientRectBinding; use js::jsapi::{JSObject, JSContext}; pub trait ClientRect { diff --git a/src/servo/dom/bindings/clientrectlist.rs b/src/servo/dom/bindings/clientrectlist.rs index c7366523880..4241faf3717 100644 --- a/src/servo/dom/bindings/clientrectlist.rs +++ b/src/servo/dom/bindings/clientrectlist.rs @@ -1,6 +1,6 @@ use content::content_task::task_from_context; use dom::bindings::clientrect::{ClientRect, ClientRectImpl}; -use dom::bindings::ClientRectListBinding; +use dom::bindings::codegen::ClientRectListBinding; use dom::bindings::utils::{WrapperCache, CacheableWrapper, BindingObject, OpaqueBindingReference}; use dom::window::Window; use dom::bindings::window::Window; diff --git a/src/servo/dom/bindings/codegen/CodegenRust.py b/src/servo/dom/bindings/codegen/CodegenRust.py index 9b0294521fb..a20f5ff2966 100644 --- a/src/servo/dom/bindings/codegen/CodegenRust.py +++ b/src/servo/dom/bindings/codegen/CodegenRust.py @@ -69,6 +69,14 @@ builtinNames = { IDLType.Tags.double: 'f64' } +numericTags = [ + IDLType.Tags.int8, IDLType.Tags.uint8, + IDLType.Tags.int16, IDLType.Tags.uint16, + IDLType.Tags.int32, IDLType.Tags.uint32, + IDLType.Tags.int64, IDLType.Tags.uint64, + IDLType.Tags.float, IDLType.Tags.double + ] + class CastableObjectUnwrapper(): """ A class for unwrapping an object named by the "source" argument @@ -193,11 +201,15 @@ class CGMethodCall(CGThing): signature[1][argCount].optional and (argCount+1) in allowedArgCounts and len(method.signaturesForArgCount(argCount+1)) == 1): - argCountCases.append( - CGCase(str(argCount), None, True)) + #XXXjdm unfinished + pass + #argCountCases.append( + # CGCase(str(argCount), None, True)) else: - argCountCases.append( - CGCase(str(argCount), getPerSignatureCall(signature))) + pass + #XXXjdm unfinished + #argCountCases.append( + # CGCase(str(argCount), getPerSignatureCall(signature))) continue distinguishingIndex = method.distinguishingIndexForArgCount(argCount) @@ -342,17 +354,19 @@ class CGMethodCall(CGThing): caseBody.append(CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);" % toStringBool(not descriptor.workers))) - argCountCases.append(CGCase(str(argCount), - CGList(caseBody, "\n"))) + #XXXjdm unfinished + #argCountCases.append(CGCase(str(argCount), + # CGList(caseBody, "\n"))) overloadCGThings = [] overloadCGThings.append( CGGeneric("unsigned argcount = NS_MIN(argc, %du);" % maxArgCount)) - overloadCGThings.append( - CGSwitch("argcount", - argCountCases, - CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName))) + #XXXjdm unfinished + #overloadCGThings.append( + # CGSwitch("argcount", + # argCountCases, + # CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName))) overloadCGThings.append( CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n' 'return false;')) @@ -371,6 +385,27 @@ class FakeCastableDescriptor(): self.name = descriptor.name self.hasXPConnectImpls = descriptor.hasXPConnectImpls +def dictionaryHasSequenceMember(dictionary): + return (any(typeIsSequenceOrHasSequenceMember(m.type) for m in + dictionary.members) or + (dictionary.parent and + dictionaryHasSequenceMember(dictionary.parent))) + +def typeIsSequenceOrHasSequenceMember(type): + if type.nullable(): + type = type.inner + if type.isSequence(): + return True + if type.isArray(): + elementType = type.inner + return typeIsSequenceOrHasSequenceMember(elementType) + if type.isDictionary(): + return dictionaryHasSequenceMember(type.inner) + if type.isUnion(): + return any(typeIsSequenceOrHasSequenceMember(m.type) for m in + type.flatMemberTypes) + return False + def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, isDefinitelyObject=False, isMember=False, @@ -871,11 +906,14 @@ for (uint32_t i = 0; i < length; ++i) { "${declName}", failureCode)) else: - templateBody += str(FailureFatalCastableObjectUnwrapper( - descriptor, - "&${val}.toObject()", - "${declName}")) - elif descriptor.interface.isCallback(): + pass + #XXXjdm unfinished + #templateBody += str(FailureFatalCastableObjectUnwrapper( + # descriptor, + # "&${val}.toObject()", + # "${declName}")) + elif descriptor.interface.isCallback() and False: + #XXXjdm unfinished templateBody += str(CallbackObjectUnwrapper( descriptor, "&${val}.toObject()", @@ -1077,10 +1115,11 @@ for (uint32_t i = 0; i < length; ++i) { if defaultValue is not None: assert(defaultValue.type.tag() == IDLType.Tags.domstring) - template = handleDefault(template, - ("${declName} = %sValues::%s" % - (enum, - getEnumValueName(defaultValue.value)))) + template = "" #XXXjdm unfinished + #template = handleDefault(template, + # ("${declName} = %sValues::%s" % + # (enum, + # getEnumValueName(defaultValue.value)))) return (template, CGGeneric(enum), None, isOptional) if type.isCallback(): @@ -1139,8 +1178,9 @@ for (uint32_t i = 0; i < length; ++i) { # should be able to assume not isOptional here. assert not isOptional - typeName = CGDictionary.makeDictionaryName(type.inner, - descriptorProvider.workers) + typeName = "" #XXXjdm unfinished + #typeName = CGDictionary.makeDictionaryName(type.inner, + # descriptorProvider.workers) actualTypeName = typeName selfRef = "${declName}" @@ -2550,7 +2590,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): idsToInit = [] # There is no need to init any IDs in workers, because worker bindings # don't have Xrays. - if not self.descriptor.workers: + if False and not self.descriptor.workers: #XXXjdm don't need xray stuff yet for var in self.properties.xrayRelevantArrayNames(): props = getattr(self.properties, var) # We only have non-chrome ids to init if we have no chrome ids. @@ -2559,6 +2599,8 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): elif props.hasNonChromeOnly(): idsToInit.append(props.variableName(False)) if len(idsToInit) > 0: + setup = CGList([CGGeneric("let content = task_from_context(aCx);"), + CGList([CGGeneric("let %s_ids_mut = (*content).dom_static.attribute_ids.get(&(prototypes::id::%s as uint));" % (varname, self.descriptor.name)) for varname in idsToInit], '\n')], '\n') initIds = CGList( [CGGeneric("!InitIds(aCx, %s, *%s_ids_mut)" % (varname, varname)) for varname in idsToInit], ' ||\n') @@ -2569,8 +2611,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): "\n") initIds = CGWrapper(initIds, pre="if ", post=" {", reindent=True) initIds = CGList( - [CGGeneric("let content = task_from_context(aCx);\n" + -"let sAttributes_ids_mut = (*content).dom_static.attribute_ids.get(&(prototypes::id::%s as uint));" % self.descriptor.name), + [setup, initIds, CGGeneric((" %s_ids_mut[0] = JSID_VOID;\n" " return ptr::null();") % idsToInit[0]), @@ -2816,6 +2857,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): body += """ (*content).dom_static.attribute_ids.insert(prototypes::id::%s as uint, vec::cast_to_mut(vec::from_slice(sAttributes_ids))); """ % self.descriptor.name + body = "" #XXXjdm xray stuff isn't necessary yet return (body + " let global: *JSObject = JS_GetGlobalForObject(aCx, aReceiver);\n" + CheckPref(self.descriptor, "global", "*aEnabled", "false") + @@ -3247,8 +3289,8 @@ class CGXrayHelper(CGAbstractExternMethod): methods = self.properties.methods if methods.hasNonChromeOnly() or methods.hasChromeOnly(): - methodArgs = """// %(methods)s has an end-of-list marker at the end that we ignore -%(methods)s, %(methods)s_ids, %(methods)s_specs, ArrayLength(%(methods)s) - 1""" % varNames + methodArgs = "Some(vec::zip_slice(%(methods)s, *method_ids))" % varNames + setup += "let method_ids = (*content).dom_static.method_ids.get(&(prototypes::id::ClientRect as uint));\n" else: methodArgs = "None" methodArgs = CGGeneric(methodArgs) @@ -3263,8 +3305,8 @@ class CGXrayHelper(CGAbstractExternMethod): consts = self.properties.consts if consts.hasNonChromeOnly() or consts.hasChromeOnly(): - constArgs = """// %(consts)s has an end-of-list marker at the end that we ignore -%(consts)s, %(consts)s_ids, %(consts)s_specs, ArrayLength(%(consts)s) - 1""" % varNames + constArgs = "Some(vec::zip_slice(%(consts)s, *const_ids))" % varNames + setup += "let const_ids = (*content).dom_static.const_ids.get(&(prototypes::id::ClientRect as uint));\n" else: constArgs = "None" constArgs = CGGeneric(constArgs) @@ -3414,7 +3456,7 @@ if expando.is_not_null() { getIndexedOrExpando = getFromExpando + "\n" namedGetter = self.descriptor.operations['NamedGetter'] - if namedGetter: + if namedGetter and False: #XXXjdm unfinished getNamed = ("if (JSID_IS_STRING(id)) {\n" + " JS::Value nameVal = STRING_TO_JSVAL(JSID_TO_STRING(id));\n" + " FakeDependentString name;\n" diff --git a/src/servo/dom/bindings/codegen/PrototypeList.h b/src/servo/dom/bindings/codegen/PrototypeList.h deleted file mode 100644 index c62465b8703..00000000000 --- a/src/servo/dom/bindings/codegen/PrototypeList.h +++ /dev/null @@ -1,59 +0,0 @@ -/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */ - -#ifndef mozilla_dom_PrototypeList_h__ -#define mozilla_dom_PrototypeList_h__ - -namespace mozilla { -namespace dom { -namespace prototypes { - -namespace id { - -enum ID -{ - ClientRect = 0, - _ID_Count -}; - -} // namespace id - -typedef id::ID ID; - -const unsigned MaxProtoChainLength = 1; - -} // namespace prototypes -} // namespace dom -} // namespace mozilla - -namespace mozilla { -namespace dom { -namespace constructors { - -namespace id { - -enum ID -{ - _ID_Count -}; - -} // namespace id - -typedef id::ID ID; - -} // namespace constructors -} // namespace dom -} // namespace mozilla - -namespace mozilla { -namespace dom { - -template -struct PrototypeTraits; - -template -struct PrototypeIDMap; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_PrototypeList_h__ diff --git a/src/servo/dom/bindings/codegen/UnionConversions.h b/src/servo/dom/bindings/codegen/UnionConversions.h deleted file mode 100644 index e186ea7e22a..00000000000 --- a/src/servo/dom/bindings/codegen/UnionConversions.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef mozilla_dom_UnionConversions_h__ -#define mozilla_dom_UnionConversions_h__ - -#include "mozilla/dom/UnionTypes.h" -#include "nsDOMQS.h" -#include "nsDebug.h" - -namespace mozilla { -namespace dom { - - -} // namespace dom -} // namespace mozilla - - -#endif // mozilla_dom_UnionConversions_h__ diff --git a/src/servo/dom/bindings/codegen/UnionTypes.h b/src/servo/dom/bindings/codegen/UnionTypes.h deleted file mode 100644 index b0fe29337b1..00000000000 --- a/src/servo/dom/bindings/codegen/UnionTypes.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef mozilla_dom_UnionTypes_h__ -#define mozilla_dom_UnionTypes_h__ - -#include "mozilla/dom/BindingUtils.h" - -namespace mozilla { -namespace dom { -} // namespace dom -} // namespace mozilla - - -#endif // mozilla_dom_UnionTypes_h__ diff --git a/src/servo/dom/bindings/codegen/pythonpath.py b/src/servo/dom/bindings/codegen/pythonpath.py new file mode 100644 index 00000000000..49b2d2f740f --- /dev/null +++ b/src/servo/dom/bindings/codegen/pythonpath.py @@ -0,0 +1,60 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +""" +Run a python script, adding extra directories to the python path. +""" + + +def main(args): + def usage(): + print >>sys.stderr, "pythonpath.py -I directory script.py [args...]" + sys.exit(150) + + paths = [] + + while True: + try: + arg = args[0] + except IndexError: + usage() + + if arg == '-I': + args.pop(0) + try: + path = args.pop(0) + except IndexError: + usage() + + paths.append(os.path.abspath(path)) + continue + + if arg.startswith('-I'): + paths.append(os.path.abspath(args.pop(0)[2:])) + continue + + if arg.startswith('-D'): + os.chdir(args.pop(0)[2:]) + continue + + break + + script = args[0] + + sys.path[0:0] = [os.path.abspath(os.path.dirname(script))] + paths + sys.argv = args + sys.argc = len(args) + + frozenglobals['__name__'] = '__main__' + frozenglobals['__file__'] = script + + execfile(script, frozenglobals) + +# Freeze scope here ... why this makes things work I have no idea ... +frozenglobals = globals() + +import sys, os + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/src/servo/dom/bindings/utils.rs b/src/servo/dom/bindings/utils.rs index 68fc35f6ca5..9e633205e8c 100644 --- a/src/servo/dom/bindings/utils.rs +++ b/src/servo/dom/bindings/utils.rs @@ -30,13 +30,17 @@ const TOSTRING_NAME_RESERVED_SLOT: u64 = 1; struct GlobalStaticData { mut proxy_handlers: linear::LinearMap, - mut attribute_ids: linear::LinearMap + mut attribute_ids: linear::LinearMap, + mut method_ids: linear::LinearMap, + mut constant_ids: linear::LinearMap } pub fn GlobalStaticData() -> GlobalStaticData { GlobalStaticData { proxy_handlers: linear::LinearMap::new(), - attribute_ids: linear::LinearMap::new() + attribute_ids: linear::LinearMap::new(), + method_ids: linear::LinearMap::new(), + constant_ids: linear::LinearMap::new() } } @@ -326,7 +330,7 @@ pub struct ConstantSpec { pub struct DOMClass { // A list of interfaces that this object implements, in order of decreasing // derivedness. - interface_chain: [prototypes::id::Prototype * 1 /*prototypes::id::_ID_Count*/], + interface_chain: [prototypes::id::Prototype * 2 /*prototypes::id::_ID_Count*/], unused: bool, // DOMObjectIsISupports (always false) native_hooks: *NativePropertyHooks diff --git a/src/servo/dom/node.rs b/src/servo/dom/node.rs index 7f163e73cdb..408c60942a8 100644 --- a/src/servo/dom/node.rs +++ b/src/servo/dom/node.rs @@ -3,6 +3,7 @@ // use dom::bindings; +use dom::bindings::codegen; use dom::bindings::utils::WrapperCache; use dom::document::Document; use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTypeId}; @@ -381,10 +382,10 @@ pub fn define_bindings(compartment: @mut Compartment, doc: @Document, win: @Wind bindings::element::init(compartment); bindings::utils::initialize_global(compartment.global_obj.ptr); let mut unused = false; - assert bindings::ClientRectBinding::DefineDOMInterface(compartment.cx.ptr, - compartment.global_obj.ptr, - &mut unused); - assert bindings::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr, - compartment.global_obj.ptr, - &mut unused); + assert codegen::ClientRectBinding::DefineDOMInterface(compartment.cx.ptr, + compartment.global_obj.ptr, + &mut unused); + assert codegen::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr, + compartment.global_obj.ptr, + &mut unused); } diff --git a/src/servo/servo.rc b/src/servo/servo.rc index 5668f9c1f70..f2dbdef6ec8 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -49,8 +49,10 @@ pub mod dom { pub mod proxyhandler; pub mod clientrect; pub mod clientrectlist; - pub mod ClientRectBinding; - pub mod ClientRectListBinding; + pub mod codegen { + pub mod ClientRectBinding; + pub mod ClientRectListBinding; + } } pub mod document; pub mod element;