auto merge of #573 : jdm/servo/domevent, r=metajack

This commit is contained in:
bors-servo 2013-07-12 08:45:33 -07:00
commit 0c4119b496
16 changed files with 895 additions and 146 deletions

View file

@ -256,6 +256,9 @@ DOMInterfaces = {
'workers': True, 'workers': True,
}], }],
'MouseEvent': {
},
'NodeList': [ 'NodeList': [
{ {
'nativeType': 'nsINodeList', 'nativeType': 'nsINodeList',
@ -333,6 +336,9 @@ DOMInterfaces = {
'resultNotAddRefed': [ 'getItem' ] 'resultNotAddRefed': [ 'getItem' ]
}], }],
'UIEvent': {
},
'WebGLRenderingContext': { 'WebGLRenderingContext': {
'nativeType': 'mozilla::WebGLContext', 'nativeType': 'mozilla::WebGLContext',
'headerFile': 'WebGLContext.h', 'headerFile': 'WebGLContext.h',
@ -499,7 +505,7 @@ def addExternalIface(iface, nativeType=None, headerFile=None, pointerType=None):
# If you add one of these, you need to make sure nsDOMQS.h has the relevant # If you add one of these, you need to make sure nsDOMQS.h has the relevant
# macros added for it # macros added for it
def addExternalHTMLElement(element): def addExternalHTMLElement(element):
nativeElement = 'ns' + element nativeElement = element
addExternalIface(element, nativeType=nativeElement, addExternalIface(element, nativeType=nativeElement,
headerFile=nativeElement + '.h') headerFile=nativeElement + '.h')
@ -520,7 +526,7 @@ addExternalIface('File')
addExternalIface('HitRegionOptions', nativeType='nsISupports') addExternalIface('HitRegionOptions', nativeType='nsISupports')
addExternalIface('HTMLElement') addExternalIface('HTMLElement')
addExternalIface('ImageData', nativeType='mozilla::dom::ImageData') addExternalIface('ImageData', nativeType='mozilla::dom::ImageData')
addExternalIface('Node', nativeType='nsINode') addExternalIface('Node', nativeType='AbstractNode<ScriptView>', pointerType='')
addExternalIface('PaintRequest') addExternalIface('PaintRequest')
addExternalIface('SVGLength') addExternalIface('SVGLength')
addExternalIface('SVGMatrix') addExternalIface('SVGMatrix')
@ -552,4 +558,5 @@ addExternalIface('WebGLShaderPrecisionFormat',
addExternalIface('WebGLTexture', nativeType='mozilla::WebGLTexture', addExternalIface('WebGLTexture', nativeType='mozilla::WebGLTexture',
headerFile='WebGLContext.h') headerFile='WebGLContext.h')
addExternalIface('Window') addExternalIface('Window')
addExternalIface('WindowProxy', nativeType='WindowProxy')
addExternalIface('XULElement') addExternalIface('XULElement')

View file

@ -24,16 +24,21 @@ def replaceFileIfChanged(filename, newContents):
Read a copy of the old file, so that we don't touch it if it hasn't changed. Read a copy of the old file, so that we don't touch it if it hasn't changed.
Returns True if the file was updated, false otherwise. Returns True if the file was updated, false otherwise.
""" """
oldFileContents = "" #XXXjdm This doesn't play well with make right now.
try: # Force the file to always be updated, or else changing CodegenRust.py
oldFile = open(filename, 'rb') # will cause many autogenerated bindings to be regenerated perpetually
oldFileContents = ''.join(oldFile.readlines()) # until the result is actually different.
oldFile.close()
except:
pass
if newContents == oldFileContents: #oldFileContents = ""
return False #try:
# oldFile = open(filename, 'rb')
# oldFileContents = ''.join(oldFile.readlines())
# oldFile.close()
#except:
# pass
#if newContents == oldFileContents:
# return False
f = open(filename, 'wb') f = open(filename, 'wb')
f.write(newContents) f.write(newContents)
@ -91,6 +96,8 @@ class CastableObjectUnwrapper():
assert descriptor.castable assert descriptor.castable
self.substitution = { "type" : descriptor.nativeType, self.substitution = { "type" : descriptor.nativeType,
"depth": descriptor.interface.inheritanceDepth(),
"prototype": "prototypes::id::" + descriptor.name,
"protoID" : "prototypes::id::" + descriptor.name + " as uint", "protoID" : "prototypes::id::" + descriptor.name + " as uint",
"source" : source, "source" : source,
"target" : target, "target" : target,
@ -115,8 +122,14 @@ class CastableObjectUnwrapper():
def __str__(self): def __str__(self):
return string.Template( return string.Template(
"""${target} = unwrap(${source}); """match unwrap_object(${source}, ${prototype}, ${depth}) {
Ok(val) => ${target} = val,
Err(()) => {
${codeOnFailure}
}
}
""").substitute(self.substitution) """).substitute(self.substitution)
#"""{ #"""{
# nsresult rv = UnwrapObject<${protoID}, ${type}>(cx, ${source}, ${target}); # nsresult rv = UnwrapObject<${protoID}, ${type}>(cx, ${source}, ${target});
# if (NS_FAILED(rv)) { # if (NS_FAILED(rv)) {
@ -130,7 +143,7 @@ class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
""" """
def __init__(self, descriptor, source, target): def __init__(self, descriptor, source, target):
CastableObjectUnwrapper.__init__(self, descriptor, source, target, CastableObjectUnwrapper.__init__(self, descriptor, source, target,
"return Throw<%s>(cx, rv);" % "return 0; //XXXjdm return Throw<%s>(cx, rv);" %
toStringBool(not descriptor.workers)) toStringBool(not descriptor.workers))
class CGThing(): class CGThing():
@ -394,6 +407,10 @@ class FakeCastableDescriptor():
self.pointerType = descriptor.pointerType self.pointerType = descriptor.pointerType
self.name = descriptor.name self.name = descriptor.name
self.hasXPConnectImpls = descriptor.hasXPConnectImpls self.hasXPConnectImpls = descriptor.hasXPConnectImpls
class FakeInterface:
def inheritanceDepth(self):
return descriptor.interface.inheritanceDepth()
self.interface = FakeInterface()
def dictionaryHasSequenceMember(dictionary): def dictionaryHasSequenceMember(dictionary):
return (any(typeIsSequenceOrHasSequenceMember(m.type) for m in return (any(typeIsSequenceOrHasSequenceMember(m.type) for m in
@ -543,7 +560,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
CGIndenter(CGGeneric(templateBody)).define() + "\n") CGIndenter(CGGeneric(templateBody)).define() + "\n")
if type.nullable(): if type.nullable():
templateBody += ( templateBody += (
"} else if (${val}.isNullOrUndefined()) {\n" "} else if RUST_JSVAL_IS_NULL(${val}) != 0 || RUST_JSVAL_IS_VOID(${val}) != 0 {\n"
" %s;\n" % codeToSetNull) " %s;\n" % codeToSetNull)
templateBody += ( templateBody += (
"} else {\n" + "} else {\n" +
@ -878,7 +895,7 @@ for (uint32_t i = 0; i < length; ++i) {
not descriptor.workers) or isMember not descriptor.workers) or isMember
typeName = descriptor.nativeType typeName = descriptor.nativeType
typePtr = typeName + "*" typePtr = descriptor.pointerType + typeName
# Compute a few things: # Compute a few things:
# - declType is the type we want to return as the first element of our # - declType is the type we want to return as the first element of our
@ -889,15 +906,9 @@ for (uint32_t i = 0; i < length; ++i) {
# Set up some sensible defaults for these things insofar as we can. # Set up some sensible defaults for these things insofar as we can.
holderType = None holderType = None
if argIsPointer: if argIsPointer:
if forceOwningType: declType = "Option<" + typePtr + ">"
declType = "nsRefPtr<" + typeName + ">"
else: else:
declType = typePtr declType = typePtr
else:
if forceOwningType:
declType = "OwningNonNull<" + typeName + ">"
else:
declType = descriptor.pointerType + typeName
templateBody = "" templateBody = ""
if descriptor.castable: if descriptor.castable:
@ -931,41 +942,19 @@ for (uint32_t i = 0; i < length; ++i) {
elif descriptor.workers: elif descriptor.workers:
templateBody += "${declName} = &${val}.toObject();" templateBody += "${declName} = &${val}.toObject();"
else: else:
# Either external, or new-binding non-castable. We always have a
# holder for these, because we don't actually know whether we have
# to addref when unwrapping or not. So we just pass an
# getter_AddRefs(nsRefPtr) to XPConnect and if we'll need a release
# it'll put a non-null pointer in there.
if forceOwningType:
# Don't return a holderType in this case; our declName
# will just own stuff.
templateBody += "nsRefPtr<" + typeName + "> ${holderName};\n"
else:
holderType = "nsRefPtr<" + typeName + ">"
templateBody += ( templateBody += (
"jsval tmpVal = ${val};\n" + "match unwrap_value::<" + typePtr + ">(&${val} as *JSVal, "
typePtr + " tmp;\n" "prototypes::id::%s, %d) {\n" % (descriptor.name, descriptor.interface.inheritanceDepth() if descriptor.concrete else 0) +
"if (NS_FAILED(xpc_qsUnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), &tmpVal))) {\n") " Err(()) => {")
templateBody += CGIndenter(onFailureBadType(failureCode, templateBody += CGIndenter(onFailureBadType(failureCode,
descriptor.interface.identifier.name)).define() descriptor.interface.identifier.name)).define()
templateBody += ("}\n"
"MOZ_ASSERT(tmp);\n")
if not isDefinitelyObject:
# Our tmpVal will go out of scope, so we can't rely on it
# for rooting
templateBody += ( templateBody += (
"if (tmpVal != ${val} && !${holderName}) {\n" " }\n"
" // We have to have a strong ref, because we got this off\n" " Ok(unwrapped) => ${declName} = Some(unwrapped)\n"
" // some random object that might get GCed\n"
" ${holderName} = tmp;\n"
"}\n") "}\n")
# And store our tmp, before it goes out of scope.
templateBody += "${declName} = tmp;"
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject, templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
type, "${declName} = NULL", type, "${declName} = None",
failureCode) failureCode)
declType = CGGeneric(declType) declType = CGGeneric(declType)
@ -1305,10 +1294,15 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
(holderType.define(), originalHolderName)) (holderType.define(), originalHolderName))
mutableHolderType = CGWrapper(holderType, pre="Optional< ", post=" >") mutableHolderType = CGWrapper(holderType, pre="Optional< ", post=" >")
holderType = CGWrapper(mutableHolderType, pre="const ") holderType = CGWrapper(mutableHolderType, pre="const ")
result.append( tmpresult = [CGGeneric("let "),
CGList([holderType, CGGeneric(" "),
CGGeneric(originalHolderName), CGGeneric(originalHolderName),
CGGeneric(";")])) CGGeneric(": "),
holderType]
if initialValue:
tmpresult += [CGGeneric(" = "),
initialValue]
tmpresult += [CGGeneric(";")]
result.append(CGList(tmpresult))
originalDeclName = replacements["declName"] originalDeclName = replacements["declName"]
if declType is not None: if declType is not None:
@ -2073,7 +2067,7 @@ class CGNativePropertyHooks(CGThing):
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks" parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks"
if parent else '0 as *NativePropertyHooks') if parent else '0 as *NativePropertyHooks')
return """ return """
static NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: %s }; static NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: /*%s*/ 0 as *NativePropertyHooks };
""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks) """ % (resolveOwnProperty, enumerateOwnProperties, parentHooks)
# 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
@ -2729,11 +2723,11 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
A method for getting a per-interface object (a prototype object or interface A method for getting a per-interface object (a prototype object or interface
constructor object). constructor object).
""" """
def __init__(self, descriptor, name, idPrefix=""): def __init__(self, descriptor, name, idPrefix="", pub=False):
args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aGlobal'), args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aGlobal'),
Argument('*JSObject', 'aReceiver')] Argument('*JSObject', 'aReceiver')]
CGAbstractMethod.__init__(self, descriptor, name, CGAbstractMethod.__init__(self, descriptor, name,
'*JSObject', args, inline=True) '*JSObject', args, inline=True, pub=pub)
self.id = idPrefix + "id::" + self.descriptor.name self.id = idPrefix + "id::" + self.descriptor.name
def definition_body(self): def definition_body(self):
return """ return """
@ -2765,7 +2759,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
""" """
def __init__(self, descriptor): def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject", CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
"prototypes::") "prototypes::", pub=True)
def definition_body(self): def definition_body(self):
return """ return """
/* Get the interface prototype object for this class. This will create the /* Get the interface prototype object for this class. This will create the
@ -2846,7 +2840,7 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
getPrototypeOf: ptr::null() getPrototypeOf: ptr::null()
}; };
(*script_context).dom_static.proxy_handlers.insert(prototypes::id::%s as uint, (*script_context).dom_static.proxy_handlers.insert(prototypes::id::%s as uint,
CreateProxyHandler(ptr::to_unsafe_ptr(&traps))); CreateProxyHandler(ptr::to_unsafe_ptr(&traps), ptr::to_unsafe_ptr(&Class) as *libc::c_void));
""" % self.descriptor.name """ % self.descriptor.name
else: else:
@ -3107,6 +3101,25 @@ class FakeArgument():
self.enforceRange = False self.enforceRange = False
self.clamp = False self.clamp = False
class CGSetterCall(CGPerSignatureCall):
"""
A class to generate a native object setter call for a particular IDL
setter.
"""
def __init__(self, argType, nativeMethodName, descriptor, attr):
CGPerSignatureCall.__init__(self, None, [],
[FakeArgument(argType, attr)],
nativeMethodName, False, descriptor, attr,
setter=True)
def wrap_return_value(self):
# We have no return value
return "\nreturn 1;"
def getArgc(self):
return "1"
def getArgvDecl(self):
# We just get our stuff from our last arg no matter what
return ""
class CGAbstractBindingMethod(CGAbstractExternMethod): class CGAbstractBindingMethod(CGAbstractExternMethod):
""" """
Common class to generate the JSNatives for all our methods, getters, and Common class to generate the JSNatives for all our methods, getters, and
@ -3119,7 +3132,7 @@ class CGAbstractBindingMethod(CGAbstractExternMethod):
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
if unwrapFailureCode is None: if unwrapFailureCode is None:
self.unwrapFailureCode = ("return Throw<%s>(cx, rv);" % self.unwrapFailureCode = ("return 0; //XXXjdm return Throw<%s>(cx, rv);" %
toStringBool(not descriptor.workers)) toStringBool(not descriptor.workers))
else: else:
self.unwrapFailureCode = unwrapFailureCode self.unwrapFailureCode = unwrapFailureCode
@ -3138,7 +3151,7 @@ class CGAbstractBindingMethod(CGAbstractExternMethod):
def getThis(self): def getThis(self):
return CGIndenter( return CGIndenter(
CGGeneric("let obj: *JSObject = JS_THIS_OBJECT(cx, vp);\n" CGGeneric("let obj: *JSObject = JS_THIS_OBJECT(cx, cast::transmute(vp));\n"
"if obj.is_null() {\n" "if obj.is_null() {\n"
" return false as JSBool;\n" " return false as JSBool;\n"
"}\n" "}\n"
@ -3248,6 +3261,56 @@ class CGSpecializedGetter(CGAbstractExternMethod):
self.descriptor, self.attr)), self.descriptor, self.attr)),
pre=" let obj = (*obj.unnamed);\n").define() pre=" let obj = (*obj.unnamed);\n").define()
class CGGenericSetter(CGAbstractBindingMethod):
"""
A class for generating the Rust code for an IDL attribute setter.
"""
def __init__(self, descriptor, lenientThis=False):
args = [Argument('*JSContext', 'cx'), Argument('uint', 'argc'),
Argument('*mut JSVal', 'vp')]
if lenientThis:
name = "genericLenientSetter"
unwrapFailureCode = (
"MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
"return true;")
else:
name = "genericSetter"
unwrapFailureCode = None
CGAbstractBindingMethod.__init__(self, descriptor, name, args,
unwrapFailureCode)
def generate_code(self):
return CGIndenter(CGGeneric(
"let undef = JSVAL_VOID;\n"
"let argv: *JSVal = if argc != 0 { JS_ARGV(cx, cast::transmute(vp)) } else { &undef as *JSVal };\n"
"let info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, cast::transmute(vp)));\n"
"if CallJitPropertyOp(info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, cast::transmute(vp)) == 0 {"
" return 0;\n"
"}\n"
"*vp = JSVAL_VOID;\n"
"return 1;"))
class CGSpecializedSetter(CGAbstractExternMethod):
"""
A class for generating the code for a specialized attribute setter
that the JIT can call with lower overhead.
"""
def __init__(self, descriptor, attr):
self.attr = attr
name = 'set_' + attr.identifier.name
args = [ Argument('*JSContext', 'cx'),
Argument('JSHandleObject', 'obj'),
Argument('*mut %s' % descriptor.nativeType, 'this'),
Argument('*mut JSVal', 'argv')]
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
def definition_body(self):
name = self.attr.identifier.name
nativeName = "Set" + MakeNativeName(self.descriptor.binaryNames.get(name, name))
return CGWrapper(CGIndenter(CGSetterCall(self.attr.type, nativeName,
self.descriptor, self.attr)),
pre=" let obj = (*obj.unnamed);\n").define()
def infallibleForMember(member, type, descriptorProvider): def infallibleForMember(member, type, descriptorProvider):
""" """
Determine the fallibility of changing a C++ value of IDL type "type" into Determine the fallibility of changing a C++ value of IDL type "type" into
@ -3786,7 +3849,7 @@ class CGDescriptor(CGThing):
else: else:
hasGetter = True hasGetter = True
if not m.readonly: if not m.readonly:
#cgThings.append(CGSpecializedSetter(descriptor, m)) cgThings.append(CGSpecializedSetter(descriptor, m))
if m.hasLenientThis(): if m.hasLenientThis():
hasLenientSetter = True hasLenientSetter = True
else: else:
@ -3796,7 +3859,7 @@ class CGDescriptor(CGThing):
if hasGetter: cgThings.append(CGGenericGetter(descriptor)) if hasGetter: cgThings.append(CGGenericGetter(descriptor))
#if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor, #if hasLenientGetter: cgThings.append(CGGenericGetter(descriptor,
# lenientThis=True)) # lenientThis=True))
#if hasSetter: cgThings.append(CGGenericSetter(descriptor)) if hasSetter: cgThings.append(CGGenericSetter(descriptor))
#if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor, #if hasLenientSetter: cgThings.append(CGGenericSetter(descriptor,
# lenientThis=True)) # lenientThis=True))
@ -3926,7 +3989,8 @@ class CGDictionary(CGThing):
return "" return ""
d = self.dictionary d = self.dictionary
if d.parent: if d.parent:
inheritance = ": public %s " % self.makeClassName(d.parent) #XXXjdm inheritance = " parent: %s::%s,\n" % (self.makeModuleName(d.parent),
self.makeClassName(d.parent))
else: else:
inheritance = "" inheritance = ""
memberDecls = [" %s: %s," % memberDecls = [" %s: %s," %
@ -3934,7 +3998,8 @@ class CGDictionary(CGThing):
for m in self.memberInfo] for m in self.memberInfo]
return (string.Template( return (string.Template(
"pub struct ${selfName} {\n" + #XXXjdm deal with inheritance "pub struct ${selfName} {\n" +
"${inheritance}" +
"\n".join(memberDecls) + "\n" + "\n".join(memberDecls) + "\n" +
# NOTE: jsids are per-runtime, so don't use them in workers # NOTE: jsids are per-runtime, so don't use them in workers
"\n".join(" //static jsid " + "\n".join(" //static jsid " +
@ -3949,13 +4014,13 @@ class CGDictionary(CGThing):
d = self.dictionary d = self.dictionary
if d.parent: if d.parent:
initParent = ("// Per spec, we init the parent's members first\n" initParent = ("// Per spec, we init the parent's members first\n"
"if (!%s::Init(cx, val)) {\n" "if self.parent.Init(cx, val) == 0 {\n"
" return false;\n" " return 0;\n"
"}\n" % self.makeClassName(d.parent)) "}\n")
else: else:
initParent = "" initParent = ""
memberInits = [CGIndenter(self.getMemberConversion(m)).define() memberInits = [CGIndenter(self.getMemberConversion(m), indentLevel=6).define()
for m in self.memberInfo] for m in self.memberInfo]
idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' % idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
(m.identifier.name + "_id", m.identifier.name)) (m.identifier.name + "_id", m.identifier.name))
@ -3970,11 +4035,11 @@ class CGDictionary(CGThing):
def defaultValue(ty): def defaultValue(ty):
if ty is "bool": if ty is "bool":
return "false" return "false"
elif ty in ["i32", "u32"]: elif ty in ["i32", "u32", "i16", "u16"]:
return "0" return "0"
elif ty is "nsString": elif ty is "nsString":
return "\"\"" return "\"\""
elif ty.startswith("Optional"): elif ty.startswith("Option"):
return "None" return "None"
else: else:
return "/* uh oh: %s */" % ty return "/* uh oh: %s */" % ty
@ -3987,24 +4052,25 @@ class CGDictionary(CGThing):
for m in d.members) + "\n" for m in d.members) + "\n"
"\n" "\n"
"impl ${selfName} {\n" "impl ${selfName} {\n"
"fn new() -> ${selfName} {\n" " pub fn new() -> ${selfName} {\n"
" ${selfName} {\n" + " ${selfName} {\n" +
((" parent: %s::%s::new(),\n" % (self.makeModuleName(d.parent),
self.makeClassName(d.parent))) if d.parent else "") +
"\n".join(" %s: %s," % (m[0].identifier.name, defaultValue(self.getMemberType(m))) for m in self.memberInfo) + "\n" "\n".join(" %s: %s," % (m[0].identifier.name, defaultValue(self.getMemberType(m))) for m in self.memberInfo) + "\n"
" }\n" " }\n"
" }\n" " }\n"
"\n" "\n"
"fn InitIds(cx: *JSContext) -> bool {\n" " pub fn InitIds(&mut self, cx: *JSContext) -> bool {\n"
" //MOZ_ASSERT(!initedIds);\n" " //MOZ_ASSERT(!initedIds);\n"
" /*${idInit}\n" " /*${idInit}\n"
" initedIds = true;*/ //XXXjdm\n" " initedIds = true;*/ //XXXjdm\n"
" return true;\n" " return true;\n"
" }\n" " }\n"
"\n" if not self.workers else "") + "\n" if not self.workers else "") +
"fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool\n" " pub fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool {\n"
"{\n"
" unsafe {\n" + " unsafe {\n" +
# NOTE: jsids are per-runtime, so don't use them in workers # NOTE: jsids are per-runtime, so don't use them in workers
(" if (!initedIds && !${selfName}::InitIds(cx)) {\n" (" if (!initedIds && !self.InitIds(cx)) {\n"
" return 0;\n" " return 0;\n"
" }\n" if not self.workers else "") + " }\n" if not self.workers else "") +
"${initParent}" "${initParent}"
@ -4022,7 +4088,7 @@ class CGDictionary(CGThing):
" }\n" " }\n"
"}").substitute({ "}").substitute({
"selfName": self.makeClassName(d), "selfName": self.makeClassName(d),
"initParent": CGIndenter(CGGeneric(initParent)).define(), "initParent": CGIndenter(CGGeneric(initParent), indentLevel=6).define(),
"initMembers": "\n\n".join(memberInits), "initMembers": "\n\n".join(memberInits),
"idInit": CGIndenter(idinit).define(), "idInit": CGIndenter(idinit).define(),
"isMainThread": toStringBool(not self.workers) "isMainThread": toStringBool(not self.workers)
@ -4036,6 +4102,15 @@ class CGDictionary(CGThing):
def makeClassName(self, dictionary): def makeClassName(self, dictionary):
return self.makeDictionaryName(dictionary, self.workers) return self.makeDictionaryName(dictionary, self.workers)
@staticmethod
def makeModuleName(dictionary):
name = dictionary.identifier.name
if name.endswith('Init'):
return toBindingNamespace(name.replace('Init', ''))
#XXXjdm This breaks on the test webidl files, sigh.
#raise TypeError("No idea how to find this dictionary's definition: " + name)
return "/* uh oh */ %s" % name
def getMemberType(self, memberInfo): def getMemberType(self, memberInfo):
(member, (templateBody, declType, (member, (templateBody, declType,
holderType, dealWithOptional, initialValue)) = memberInfo holderType, dealWithOptional, initialValue)) = memberInfo
@ -4209,6 +4284,10 @@ class CGBindingRoot(CGThing):
'dom::event::*', #XXXjdm 'dom::event::*', #XXXjdm
'dom::eventtarget::*', #XXXjdm 'dom::eventtarget::*', #XXXjdm
'dom::formdata::*', #XXXjdm 'dom::formdata::*', #XXXjdm
'dom::mouseevent::*', #XXXjdm
'dom::uievent::*', #XXXjdm
'dom::windowproxy::*', #XXXjdm
'dom::bindings::codegen::*', #XXXjdm
'script_task::task_from_context', 'script_task::task_from_context',
'dom::bindings::utils::EnumEntry', 'dom::bindings::utils::EnumEntry',
'dom::node::ScriptView', 'dom::node::ScriptView',

View file

@ -1,3 +1,15 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface please see
* http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[Constructor(DOMString type, optional EventInit eventInitDict)] [Constructor(DOMString type, optional EventInit eventInitDict)]
interface Event { interface Event {
readonly attribute DOMString type; readonly attribute DOMString type;

View file

@ -0,0 +1,76 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface please see
* http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface MouseEvent : UIEvent {
readonly attribute long screenX;
readonly attribute long screenY;
readonly attribute long clientX;
readonly attribute long clientY;
readonly attribute boolean ctrlKey;
readonly attribute boolean shiftKey;
readonly attribute boolean altKey;
readonly attribute boolean metaKey;
readonly attribute unsigned short button;
readonly attribute unsigned short buttons;
readonly attribute EventTarget? relatedTarget;
// Deprecated in DOM Level 3:
[Throws]
void initMouseEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
WindowProxy? viewArg,
long detailArg,
long screenXArg,
long screenYArg,
long clientXArg,
long clientYArg,
boolean ctrlKeyArg,
boolean altKeyArg,
boolean shiftKeyArg,
boolean metaKeyArg,
unsigned short buttonArg,
EventTarget? relatedTargetArg);
// Introduced in DOM Level 3:
boolean getModifierState(DOMString keyArg);
};
// Event Constructor Syntax:
[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)]
partial interface MouseEvent
{
};
// Suggested initMouseEvent replacement initializer:
dictionary MouseEventInit {
// Attributes from Event:
boolean bubbles = false;
boolean cancelable = false;
// Attributes from UIEvent:
WindowProxy? view = null;
long detail = 0;
// Attributes for MouseEvent:
long screenX = 0;
long screenY = 0;
long clientX = 0;
long clientY = 0;
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
unsigned short button = 0;
// Note: "buttons" was not previously initializable through initMouseEvent!
unsigned short buttons = 0;
EventTarget? relatedTarget = null;
};

View file

@ -1,34 +0,0 @@
#include "BlobBinding.h"
#include "ClientRectBinding.h"
#include "ClientRectListBinding.h"
#include "DOMParserBinding.h"
#include "EventBinding.h"
#include "EventTargetBinding.h"
#include "FormDataBinding.h"
#include "HTMLCollectionBinding.h"
#include "nsScriptNameSpaceManager.h"
namespace mozilla {
namespace dom {
void
Register(nsScriptNameSpaceManager* aNameSpaceManager)
{
#define REGISTER_PROTO(_dom_class, _pref_check) \
aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);
REGISTER_PROTO(Blob, nullptr);
REGISTER_PROTO(ClientRect, nullptr);
REGISTER_PROTO(ClientRectList, nullptr);
REGISTER_PROTO(DOMParser, nullptr);
REGISTER_PROTO(Event, nullptr);
REGISTER_PROTO(EventTarget, nullptr);
REGISTER_PROTO(FormData, nullptr);
REGISTER_PROTO(HTMLCollection, nullptr);
#undef REGISTER_PROTO
}
} // namespace dom
} // namespace mozilla

View file

@ -0,0 +1,48 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface please see
* http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface WindowProxy;
interface Node;
[Constructor(DOMString type, optional UIEventInit eventInitDict)]
interface UIEvent : Event
{
readonly attribute WindowProxy? view;
readonly attribute long detail;
void initUIEvent(DOMString aType,
boolean aCanBubble,
boolean aCancelable,
WindowProxy? aView,
long aDetail);
};
// Additional DOM0 properties.
partial interface UIEvent {
const long SCROLL_PAGE_UP = -32768;
const long SCROLL_PAGE_DOWN = 32768;
readonly attribute long layerX;
readonly attribute long layerY;
readonly attribute long pageX;
readonly attribute long pageY;
readonly attribute unsigned long which;
readonly attribute Node? rangeParent;
readonly attribute long rangeOffset;
attribute boolean cancelBubble;
readonly attribute boolean isChar;
};
dictionary UIEventInit : EventInit
{
WindowProxy? view = null;
long detail = 0;
};

View file

@ -429,17 +429,19 @@ class IDLExternalInterface(IDLObjectWithIdentifier):
pass pass
class IDLInterface(IDLObjectWithScope): class IDLInterface(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members): def __init__(self, location, parentScope, name, parent, members,
isPartial):
assert isinstance(parentScope, IDLScope) assert isinstance(parentScope, IDLScope)
assert isinstance(name, IDLUnresolvedIdentifier) assert isinstance(name, IDLUnresolvedIdentifier)
assert not parent or isinstance(parent, IDLIdentifierPlaceholder) assert not isPartial or not parent
self.parent = parent self.parent = None
self._callback = False self._callback = False
self._finished = False self._finished = False
self.members = list(members) # clone the list self.members = []
self.implementedInterfaces = set() self.implementedInterfaces = set()
self._consequential = False self._consequential = False
self._isPartial = True
# self.interfacesBasedOnSelf is the set of interfaces that inherit from # self.interfacesBasedOnSelf is the set of interfaces that inherit from
# self or have self as a consequential interface, including self itself. # self or have self as a consequential interface, including self itself.
# Used for distinguishability checking. # Used for distinguishability checking.
@ -447,6 +449,12 @@ class IDLInterface(IDLObjectWithScope):
IDLObjectWithScope.__init__(self, location, parentScope, name) IDLObjectWithScope.__init__(self, location, parentScope, name)
if not isPartial:
self.setNonPartial(location, parent, members)
else:
# Just remember our members for now
self.members = list(members) # clone the list
def __str__(self): def __str__(self):
return "Interface '%s'" % self.identifier.name return "Interface '%s'" % self.identifier.name
@ -482,6 +490,11 @@ class IDLInterface(IDLObjectWithScope):
self._finished = True self._finished = True
if self._isPartial:
raise WebIDLError("Interface %s does not have a non-partial "
"declaration" % self.identifier.name,
[self.location])
assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder) assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
parent = self.parent.finish(scope) if self.parent else None parent = self.parent.finish(scope) if self.parent else None
if parent and isinstance(parent, IDLExternalInterface): if parent and isinstance(parent, IDLExternalInterface):
@ -749,6 +762,21 @@ class IDLInterface(IDLObjectWithScope):
def getExtendedAttribute(self, name): def getExtendedAttribute(self, name):
return self._extendedAttrDict.get(name, None) return self._extendedAttrDict.get(name, None)
def setNonPartial(self, location, parent, members):
assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
if not self._isPartial:
raise WebIDLError("Two non-partial definitions for the "
"same interface",
[location, self.location])
self._isPartial = False
# Now make it look like we were parsed at this new location, since
# that's the place where the interface is "really" defined
self.location = location
assert not self.parent
self.parent = parent
# Put the new members at the beginning
self.members = members + self.members
class IDLDictionary(IDLObjectWithScope): class IDLDictionary(IDLObjectWithScope):
def __init__(self, location, parentScope, name, parent, members): def __init__(self, location, parentScope, name, parent, members):
assert isinstance(parentScope, IDLScope) assert isinstance(parentScope, IDLScope)
@ -2742,9 +2770,25 @@ class Parser(Tokenizer):
""" """
location = self.getLocation(p, 1) location = self.getLocation(p, 1)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
members = p[5] members = p[5]
p[0] = IDLInterface(location, self.globalScope(), identifier, p[3], members) parent = p[3]
try:
if self.globalScope()._lookupIdentifier(identifier):
p[0] = self.globalScope()._lookupIdentifier(identifier)
if not isinstance(p[0], IDLInterface):
raise WebIDLError("Partial interface has the same name as "
"non-interface object",
[location, p[0].location])
p[0].setNonPartial(location, parent, members)
return
except Exception, ex:
if isinstance(ex, WebIDLError):
raise ex
pass
p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
members, isPartial=False)
def p_InterfaceForwardDecl(self, p): def p_InterfaceForwardDecl(self, p):
""" """
@ -2766,6 +2810,29 @@ class Parser(Tokenizer):
""" """
PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
""" """
location = self.getLocation(p, 2)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
members = p[5]
try:
if self.globalScope()._lookupIdentifier(identifier):
p[0] = self.globalScope()._lookupIdentifier(identifier)
if not isinstance(p[0], IDLInterface):
raise WebIDLError("Partial interface has the same name as "
"non-interface object",
[location, p[0].location])
# Just throw our members into the existing IDLInterface. If we
# have extended attributes, those will get added to it
# automatically.
p[0].members.extend(members)
return
except Exception, ex:
if isinstance(ex, WebIDLError):
raise ex
pass
p[0] = IDLInterface(location, self.globalScope(), identifier, None,
members, isPartial=True)
pass pass
def p_Inheritance(self, p): def p_Inheritance(self, p):

View file

@ -25,6 +25,34 @@ impl JSValConvertible for u32 {
} }
} }
impl JSValConvertible for i32 {
fn to_jsval(&self) -> JSVal {
unsafe {
RUST_UINT_TO_JSVAL(*self as u32)
}
}
fn from_jsval(val: JSVal) -> Option<i32> {
unsafe {
Some(RUST_JSVAL_TO_INT(val) as i32)
}
}
}
impl JSValConvertible for u16 {
fn to_jsval(&self) -> JSVal {
unsafe {
RUST_UINT_TO_JSVAL(*self as u32)
}
}
fn from_jsval(val: JSVal) -> Option<u16> {
unsafe {
Some(RUST_JSVAL_TO_INT(val) as u16)
}
}
}
impl JSValConvertible for bool { impl JSValConvertible for bool {
fn to_jsval(&self) -> JSVal { fn to_jsval(&self) -> JSVal {
if *self { if *self {

View file

@ -17,6 +17,7 @@ use std::uint;
use std::unstable::intrinsics; use std::unstable::intrinsics;
use js::glue::*; use js::glue::*;
use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL}; use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB}; use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction}; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction};
use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
@ -117,16 +118,62 @@ fn is_dom_class(clasp: *JSClass) -> bool {
} }
} }
fn is_dom_proxy(obj: *JSObject) -> bool {
unsafe {
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) &&
IsProxyHandlerFamily(obj)
}
}
pub unsafe fn unwrap<T>(obj: *JSObject) -> T { pub unsafe fn unwrap<T>(obj: *JSObject) -> T {
let slot = if is_dom_class(JS_GetClass(obj)) { let clasp = JS_GetClass(obj);
let slot = if is_dom_class(clasp) {
DOM_OBJECT_SLOT DOM_OBJECT_SLOT
} else { } else {
assert!(is_dom_proxy(obj));
DOM_PROXY_OBJECT_SLOT DOM_PROXY_OBJECT_SLOT
} as u32; } as u32;
let val = JS_GetReservedSlot(obj, slot); let val = JS_GetReservedSlot(obj, slot);
cast::transmute(RUST_JSVAL_TO_PRIVATE(val)) cast::transmute(RUST_JSVAL_TO_PRIVATE(val))
} }
pub unsafe fn get_dom_class(obj: *JSObject) -> Result<DOMClass, ()> {
let clasp = JS_GetClass(obj);
if is_dom_class(clasp) {
debug!("plain old dom object");
let domjsclass: *DOMJSClass = cast::transmute(clasp);
return Ok((*domjsclass).dom_class);
}
if is_dom_proxy(obj) {
debug!("proxy dom object");
let dom_class: *DOMClass = cast::transmute(GetProxyHandlerExtra(obj));
return Ok(*dom_class);
}
debug!("not a dom object");
return Err(());
}
pub fn unwrap_object<T>(obj: *JSObject, proto_id: prototypes::id::Prototype, proto_depth: uint) -> Result<T, ()> {
unsafe {
do get_dom_class(obj).chain |dom_class| {
if dom_class.interface_chain[proto_depth] == proto_id {
debug!("good prototype");
Ok(unwrap(obj))
} else {
debug!("bad prototype");
Err(())
}
}
}
}
pub fn unwrap_value<T>(val: *JSVal, proto_id: prototypes::id::Prototype, proto_depth: uint) -> Result<T, ()> {
unsafe {
let obj = RUST_JSVAL_TO_OBJECT(*val);
unwrap_object(obj, proto_id, proto_depth)
}
}
pub unsafe fn squirrel_away<T>(x: @mut T) -> *rust_box<T> { pub unsafe fn squirrel_away<T>(x: @mut T) -> *rust_box<T> {
let y: *rust_box<T> = cast::transmute(x); let y: *rust_box<T> = cast::transmute(x);
cast::forget(x); cast::forget(x);
@ -353,7 +400,7 @@ pub struct ConstantSpec {
pub struct DOMClass { pub struct DOMClass {
// A list of interfaces that this object implements, in order of decreasing // A list of interfaces that this object implements, in order of decreasing
// derivedness. // derivedness.
interface_chain: [prototypes::id::Prototype, ..2 /*max prototype chain length*/], interface_chain: [prototypes::id::Prototype, ..3 /*max prototype chain length*/],
unused: bool, // DOMObjectIsISupports (always false) unused: bool, // DOMObjectIsISupports (always false)
native_hooks: *NativePropertyHooks native_hooks: *NativePropertyHooks
@ -373,7 +420,9 @@ pub fn GetProtoOrIfaceArray(global: *JSObject) -> **JSObject {
pub mod prototypes { pub mod prototypes {
pub mod id { pub mod id {
#[deriving(Eq)]
pub enum Prototype { pub enum Prototype {
Blob,
ClientRect, ClientRect,
ClientRectList, ClientRectList,
DOMParser, DOMParser,
@ -381,6 +430,9 @@ pub mod prototypes {
Event, Event,
EventTarget, EventTarget,
FormData, FormData,
UIEvent,
MouseEvent,
WindowProxy,
_ID_Count _ID_Count
} }
} }
@ -583,7 +635,7 @@ pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) ->
} }
pub fn initialize_global(global: *JSObject) { pub fn initialize_global(global: *JSObject) {
let protoArray = @mut ([0 as *JSObject, ..7]); //XXXjdm prototypes::_ID_COUNT let protoArray = @mut ([0 as *JSObject, ..10]); //XXXjdm prototypes::_ID_COUNT
unsafe { unsafe {
//XXXjdm we should be storing the box pointer instead of the inner //XXXjdm we should be storing the box pointer instead of the inner
let box = squirrel_away(protoArray); let box = squirrel_away(protoArray);

View file

@ -0,0 +1,184 @@
/* 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/. */
use dom::bindings::codegen::MouseEventBinding;
use dom::bindings::utils::{ErrorResult, DOMString};
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
use dom::eventtarget::EventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use script_task::{global_script_context};
use js::glue::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSObject, JSContext, JSVal};
pub struct MouseEvent {
parent: UIEvent,
screen_x: i32,
screen_y: i32,
client_x: i32,
client_y: i32,
ctrl_key: bool,
shift_key: bool,
alt_key: bool,
meta_key: bool,
button: u16,
related_target: Option<@mut EventTarget>
}
impl MouseEvent {
pub fn new(type_: DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32, screen_x: i32,
screen_y: i32, client_x: i32, client_y: i32, ctrl_key: bool,
shift_key: bool, alt_key: bool, meta_key: bool, button: u16,
_buttons: u16, related_target: Option<@mut EventTarget>) -> MouseEvent {
MouseEvent {
parent: UIEvent::new(type_, can_bubble, cancelable, view, detail),
screen_x: screen_x,
screen_y: screen_y,
client_x: client_x,
client_y: client_y,
ctrl_key: ctrl_key,
shift_key: shift_key,
alt_key: alt_key,
meta_key: meta_key,
button: button,
related_target: related_target
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
pub fn Constructor(_owner: @mut Window,
type_: DOMString,
init: &MouseEventBinding::MouseEventInit,
_rv: &mut ErrorResult) -> @mut MouseEvent {
@mut MouseEvent::new(type_, init.bubbles, init.cancelable, init.view, init.detail,
init.screenX, init.screenY, init.clientX, init.clientY,
init.ctrlKey, init.shiftKey, init.altKey, init.metaKey,
init.button, init.buttons, init.relatedTarget)
}
pub fn ScreenX(&self) -> i32 {
self.screen_x
}
pub fn ScreenY(&self) -> i32 {
self.screen_y
}
pub fn ClientX(&self) -> i32 {
self.client_x
}
pub fn ClientY(&self) -> i32 {
self.client_y
}
pub fn CtrlKey(&self) -> bool {
self.ctrl_key
}
pub fn ShiftKey(&self) -> bool {
self.shift_key
}
pub fn AltKey(&self) -> bool {
self.alt_key
}
pub fn MetaKey(&self) -> bool {
self.meta_key
}
pub fn Button(&self) -> u16 {
self.button
}
pub fn Buttons(&self)-> u16 {
//TODO
0
}
pub fn GetRelatedTarget(&self) -> Option<@mut EventTarget> {
self.related_target
}
pub fn GetModifierState(&self, _keyArg: DOMString) -> bool {
//TODO
false
}
pub fn InitMouseEvent(&mut self,
typeArg: DOMString,
canBubbleArg: bool,
cancelableArg: bool,
viewArg: Option<@mut WindowProxy>,
detailArg: i32,
screenXArg: i32,
screenYArg: i32,
clientXArg: i32,
clientYArg: i32,
ctrlKeyArg: bool,
altKeyArg: bool,
shiftKeyArg: bool,
metaKeyArg: bool,
buttonArg: u16,
relatedTargetArg: Option<@mut EventTarget>,
_rv: &mut ErrorResult) {
self.parent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
self.screen_x = screenXArg;
self.screen_y = screenYArg;
self.client_x = clientXArg;
self.client_y = clientYArg;
self.ctrl_key = ctrlKeyArg;
self.alt_key = altKeyArg;
self.shift_key = shiftKeyArg;
self.meta_key = metaKeyArg;
self.button = buttonArg;
self.related_target = relatedTargetArg;
}
}
impl CacheableWrapper for MouseEvent {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.parent.get_wrappercache()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
let mut unused = false;
MouseEventBinding::Wrap(cx, scope, self, &mut unused)
}
}
impl BindingObject for MouseEvent {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
self.parent.GetParentObject(cx)
}
}
impl DerivedWrapper for MouseEvent {
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
fail!(~"nyi")
}
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
let obj = self.wrap_object_shared(cx, scope);
if obj.is_null() {
return 0;
} else {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
return 1;
}
}
}

View file

@ -514,4 +514,13 @@ pub fn define_bindings(compartment: @mut Compartment) {
assert!(codegen::EventTargetBinding::DefineDOMInterface(compartment.cx.ptr, assert!(codegen::EventTargetBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr, compartment.global_obj.ptr,
&mut unused)); &mut unused));
assert!(codegen::FormDataBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
assert!(codegen::MouseEventBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
assert!(codegen::UIEventBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr,
&mut unused));
} }

View file

@ -0,0 +1,158 @@
/* 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/. */
use dom::bindings::codegen::UIEventBinding;
use dom::bindings::utils::{ErrorResult, DOMString};
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
use dom::node::{AbstractNode, ScriptView};
use dom::event::Event_;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use script_task::global_script_context;
use js::glue::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSObject, JSContext, JSVal};
pub struct UIEvent {
parent: Event_,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>,
detail: i32
}
impl UIEvent {
pub fn new(type_: DOMString, can_bubble: bool, cancelable: bool,
view: Option<@mut WindowProxy>, detail: i32) -> UIEvent {
UIEvent {
parent: Event_::new(type_),
can_bubble: can_bubble,
cancelable: cancelable,
view: view,
detail: detail
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
pub fn Constructor(_owner: @mut Window,
type_: DOMString,
init: &UIEventBinding::UIEventInit,
_rv: &mut ErrorResult) -> @mut UIEvent {
@mut UIEvent::new(type_, init.parent.bubbles, init.parent.cancelable,
init.view, init.detail)
}
pub fn GetView(&self) -> Option<@mut WindowProxy> {
self.view
}
pub fn Detail(&self) -> i32 {
self.detail
}
pub fn InitUIEvent(&mut self,
type_: DOMString,
can_bubble: bool,
cancelable: bool,
view: Option<@mut WindowProxy>,
detail: i32) {
let mut rv = Ok(());
self.parent.InitEvent(type_, can_bubble, cancelable, &mut rv);
self.can_bubble = can_bubble;
self.cancelable = cancelable;
self.view = view;
self.detail = detail;
}
pub fn LayerX(&self) -> i32 {
//TODO
0
}
pub fn LayerY(&self) -> i32 {
//TODO
0
}
pub fn PageX(&self) -> i32 {
//TODO
0
}
pub fn PageY(&self) -> i32 {
//TODO
0
}
pub fn Which(&self) -> u32 {
//TODO
0
}
pub fn GetRangeParent(&self) -> Option<AbstractNode<ScriptView>> {
//TODO
None
}
pub fn RangeOffset(&self) -> i32 {
//TODO
0
}
pub fn CancelBubble(&self) -> bool {
//TODO
false
}
pub fn SetCancelBubble(&mut self, _val: bool) {
//TODO
}
pub fn IsChar(&self) -> bool {
//TODO
false
}
}
impl CacheableWrapper for UIEvent {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.parent.get_wrappercache()
}
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
let mut unused = false;
UIEventBinding::Wrap(cx, scope, self, &mut unused)
}
}
impl BindingObject for UIEvent {
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
self.parent.GetParentObject(cx)
}
}
impl DerivedWrapper for UIEvent {
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
fail!(~"nyi")
}
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
let obj = self.wrap_object_shared(cx, scope);
if obj.is_null() {
return 0;
} else {
unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
return 1;
}
}
}

View file

@ -0,0 +1,39 @@
/* 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/. */
use dom::bindings::utils::{CacheableWrapper, WrapperCache};
use script_task::global_script_context;
use js::jsapi::{JSContext, JSObject};
pub struct WindowProxy {
wrapper: WrapperCache
}
impl WindowProxy {
pub fn new() -> @mut WindowProxy {
@mut WindowProxy {
wrapper: WrapperCache::new()
}
}
pub fn init_wrapper(@mut self) {
let script_context = global_script_context();
let cx = script_context.js_compartment.cx.ptr;
let owner = script_context.root_frame.get_ref().window;
let cache = owner.get_wrappercache();
let scope = cache.get_wrapper();
self.wrap_object_shared(cx, scope);
}
}
impl CacheableWrapper for WindowProxy {
fn get_wrappercache(&mut self) -> &mut WrapperCache {
return self.get_wrappercache()
}
fn wrap_object_shared(@mut self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!("not yet implemented")
}
}

View file

@ -39,8 +39,10 @@ pub mod dom {
pub mod DOMParserBinding; pub mod DOMParserBinding;
pub mod EventBinding; pub mod EventBinding;
pub mod EventTargetBinding; pub mod EventTargetBinding;
pub mod HTMLCollectionBinding;
pub mod FormDataBinding; pub mod FormDataBinding;
pub mod HTMLCollectionBinding;
pub mod MouseEventBinding;
pub mod UIEventBinding;
} }
} }
pub mod blob; pub mod blob;
@ -54,8 +56,11 @@ pub mod dom {
pub mod eventtarget; pub mod eventtarget;
pub mod formdata; pub mod formdata;
pub mod htmlcollection; pub mod htmlcollection;
pub mod mouseevent;
pub mod node; pub mod node;
pub mod uievent;
pub mod window; pub mod window;
pub mod windowproxy;
} }
pub mod html { pub mod html {

@ -1 +1 @@
Subproject commit 26dc2e896a57a28f03be43df46868e1a41a15807 Subproject commit 372622906d112ae28825be1d5fcd8737cd03ae58

View file

@ -57,3 +57,22 @@ window.alert(ev.type);
window.alert(ev.defaultPrevented); window.alert(ev.defaultPrevented);
ev.preventDefault(); ev.preventDefault();
window.alert(ev.defaultPrevented); window.alert(ev.defaultPrevented);
window.alert("MouseEvent:");
window.alert(MouseEvent);
let ev2 = new MouseEvent("press", {bubbles: true, screenX: 150, detail: 100});
window.alert(ev2);
window.alert(ev2.screenX);
window.alert(ev2.detail);
window.alert(ev2.getModifierState("ctrl"));
window.alert(ev2 instanceof Event);
window.alert(ev2 instanceof UIEvent);
//TODO: Doesn't work until we throw proper exceptions instead of returning 0 on
// unwrap failure.
/*try {
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(rects), "length").get.call(window);
window.alert("hmm?");
} catch (x) {
window.alert("ok");
}*/