aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-06-25 02:18:06 -0600
committerbors-servo <metajack+bors@gmail.com>2015-06-25 02:18:06 -0600
commit57cc84b2935c429c92774649275625a7fd63973c (patch)
tree90af5b35684d234c9207913d9102d003d0516b95
parent605b83da54dc7c33def4fb1e3162e377e1715d0b (diff)
parentd33579183a19796b702576a9eb99805f20a608b1 (diff)
downloadservo-57cc84b2935c429c92774649275625a7fd63973c.tar.gz
servo-57cc84b2935c429c92774649275625a7fd63973c.zip
Auto merge of #6110 - klusark:NamedConstructor, r=Ms2ger
Implement Named constructors and the Image constructor for HTMLImageElement I'm not sure if I like how I mostly just duplicated the code in CodegenRust.py, so that might need to be refactored. Instead of just calling it Image, we might want to call it ConstructorImage, to make it clear that it's a constructor. Anyone have an opinion on that? There seems to be a bug in the HTMLImageElement getter/setter as the value is 0 regardless of what I do. This seems to be unrelated to my commits, so I'll investigate that separately. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6110) <!-- Reviewable:end -->
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py40
-rw-r--r--components/script/dom/bindings/utils.rs89
-rw-r--r--components/script/dom/htmlimageelement.rs17
-rw-r--r--components/script/dom/webidls/HTMLImageElement.webidl2
-rw-r--r--tests/wpt/metadata/MANIFEST.json6
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini51
-rw-r--r--tests/wpt/mozilla/tests/mozilla/interfaces.html1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/Image-constructor.html29
8 files changed, 157 insertions, 78 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 832dd564736..2847401e65c 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -2286,11 +2286,25 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
call = """\
do_create_interface_objects(cx, receiver, parent_proto.handle(),
%s, %s,
+ &named_constructors,
%s,
&sNativeProperties, rval);""" % (protoClass, constructor, domClass)
+ createArray = """\
+let named_constructors: [(NonNullJSNative, &'static str, u32); %d] = [
+""" % len(self.descriptor.interface.namedConstructors)
+ for ctor in self.descriptor.interface.namedConstructors:
+ constructHook = CONSTRUCT_HOOK_NAME + "_" + ctor.identifier.name;
+ constructArgs = methodLength(ctor)
+ constructor = '(%s as NonNullJSNative, "%s", %d)' % (
+ constructHook, ctor.identifier.name, constructArgs)
+ createArray += constructor
+ createArray += ","
+ createArray += "];"
+
return CGList([
CGGeneric(getParentProto),
+ CGGeneric(createArray),
CGGeneric(call % self.properties.variableNames())
], "\n")
@@ -4422,6 +4436,30 @@ let args = CallArgs::from_vp(vp, argc);
self.descriptor, self._ctor)
return CGList([preamble, callGenerator])
+class CGClassNameConstructHook(CGAbstractExternMethod):
+ """
+ JS-visible named constructor for our objects
+ """
+ def __init__(self, descriptor, ctor):
+ args = [Argument('*mut JSContext', 'cx'), Argument('u32', 'argc'), Argument('*mut JSVal', 'vp')]
+ self._ctor = ctor
+ CGAbstractExternMethod.__init__(self, descriptor,
+ CONSTRUCT_HOOK_NAME + "_" +
+ self._ctor.identifier.name,
+ 'u8', args)
+
+ def definition_body(self):
+ preamble = CGGeneric("""\
+let global = global_object_for_js_object(JS_CALLEE(cx, vp).to_object());
+let args = CallArgs::from_vp(vp, argc);
+""")
+ name = self._ctor.identifier.name
+ nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
+ callGenerator = CGMethodCall(["global.r()"], nativeName, True,
+ self.descriptor, self._ctor)
+ return CGList([preamble, callGenerator])
+
+
class CGClassFinalizeHook(CGAbstractClassHook):
"""
A hook for finalize, used to release our native object.
@@ -4568,6 +4606,8 @@ class CGDescriptor(CGThing):
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGClassConstructHook(descriptor))
+ for ctor in descriptor.interface.namedConstructors:
+ cgThings.append(CGClassNameConstructHook(descriptor, ctor))
cgThings.append(CGInterfaceObjectJSClass(descriptor))
if not descriptor.interface.isCallback():
diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs
index f8df9805ebd..5a2eb51f2ce 100644
--- a/components/script/dom/bindings/utils.rs
+++ b/components/script/dom/bindings/utils.rs
@@ -205,6 +205,7 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
proto_proto: HandleObject,
proto_class: Option<&'static JSClass>,
constructor: Option<(NonNullJSNative, &'static str, u32)>,
+ named_constructors: &[(NonNullJSNative, &'static str, u32)],
dom_class: *const DOMClass,
members: &'static NativeProperties,
rval: MutableHandleObject) {
@@ -226,6 +227,55 @@ pub fn do_create_interface_objects(cx: *mut JSContext,
native, nargs, rval.handle(),
members, s.as_ptr())
}
+
+ for ctor in named_constructors.iter() {
+ let (cnative, cname, cnargs) = *ctor;
+
+ let cs = CString::new(cname).unwrap();
+ let constructor = RootedObject::new(cx, create_constructor(cx, cnative, cnargs, cs.as_ptr()));
+ assert!(!constructor.ptr.is_null());
+ unsafe {
+ assert!(JS_DefineProperty1(cx, constructor.handle(), "prototype".as_ptr() as *const i8,
+ rval.handle(),
+ JSPROP_PERMANENT | JSPROP_READONLY,
+ None, None) != 0);
+ }
+ define_constructor(cx, receiver, cs.as_ptr(), constructor.handle());
+ }
+
+}
+
+fn create_constructor(cx: *mut JSContext,
+ constructor_native: NonNullJSNative,
+ ctor_nargs: u32,
+ name: *const libc::c_char) -> *mut JSObject {
+ unsafe {
+ let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
+ JSFUN_CONSTRUCTOR, name);
+ assert!(!fun.is_null());
+
+ let constructor = JS_GetFunctionObject(fun);
+ assert!(!constructor.is_null());
+
+ constructor
+ }
+}
+
+fn define_constructor(cx: *mut JSContext,
+ receiver: HandleObject,
+ name: *const libc::c_char,
+ constructor: HandleObject) {
+ unsafe {
+ let mut already_defined = 0;
+ assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
+
+ if already_defined == 0 {
+ assert!(JS_DefineProperty1(cx, receiver, name,
+ constructor,
+ 0, None, None) != 0);
+ }
+
+ }
}
/// Creates the *interface object*.
@@ -236,39 +286,28 @@ fn create_interface_object(cx: *mut JSContext,
ctor_nargs: u32, proto: HandleObject,
members: &'static NativeProperties,
name: *const libc::c_char) {
- unsafe {
- let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
- JSFUN_CONSTRUCTOR, name);
- assert!(!fun.is_null());
+ let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name));
+ assert!(!constructor.ptr.is_null());
- let constructor = RootedObject::new(cx, JS_GetFunctionObject(fun));
- assert!(!constructor.ptr.is_null());
-
- if let Some(static_methods) = members.static_methods {
- define_methods(cx, constructor.handle(), static_methods);
- }
+ if let Some(static_methods) = members.static_methods {
+ define_methods(cx, constructor.handle(), static_methods);
+ }
- if let Some(static_properties) = members.static_attrs {
- define_properties(cx, constructor.handle(), static_properties);
- }
+ if let Some(static_properties) = members.static_attrs {
+ define_properties(cx, constructor.handle(), static_properties);
+ }
- if let Some(constants) = members.consts {
- define_constants(cx, constructor.handle(), constants);
- }
+ if let Some(constants) = members.consts {
+ define_constants(cx, constructor.handle(), constants);
+ }
+ unsafe {
if !proto.get().is_null() {
assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto) != 0);
}
-
- let mut already_defined = 0;
- assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
-
- if already_defined == 0 {
- assert!(JS_DefineProperty1(cx, receiver, name,
- constructor.handle(),
- 0, None, None) != 0);
- }
}
+
+ define_constructor(cx, receiver, name, constructor.handle());
}
/// Defines constants on `obj`.
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 2ea5442bff6..6580e4f42a5 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -7,8 +7,10 @@ use dom::attr::{AttrHelpers, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
+use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, HTMLElementCast,
HTMLImageElementDerived};
+use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::refcounted::Trusted;
@@ -151,6 +153,21 @@ impl HTMLImageElement {
let element = HTMLImageElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
}
+
+ pub fn Image(global: GlobalRef,
+ width: Option<u32>,
+ height: Option<u32>) -> Fallible<Root<HTMLImageElement>> {
+ let document = global.as_window().Document();
+ let image = HTMLImageElement::new("img".to_owned(), None, document.r());
+ if let Some(w) = width {
+ image.SetWidth(w);
+ }
+ if let Some(h) = height {
+ image.SetHeight(h);
+ }
+
+ Ok(image)
+ }
}
pub trait LayoutHTMLImageElementHelpers {
diff --git a/components/script/dom/webidls/HTMLImageElement.webidl b/components/script/dom/webidls/HTMLImageElement.webidl
index 71b49229393..defbfb68257 100644
--- a/components/script/dom/webidls/HTMLImageElement.webidl
+++ b/components/script/dom/webidls/HTMLImageElement.webidl
@@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// https://www.whatwg.org/html/#htmlimageelement
-//[NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
+[NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
interface HTMLImageElement : HTMLElement {
attribute DOMString alt;
attribute DOMString src;
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index 5b780fd14da..68e5e677b29 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -14118,6 +14118,10 @@
"url": "/html/semantics/embedded-content/the-img-element/img.complete.html"
},
{
+ "path": "html/semantics/embedded-content/the-img-element/Image-constructor.html",
+ "url": "/html/semantics/embedded-content/the-img-element/Image-constructor.html"
+ },
+ {
"path": "html/semantics/embedded-content/the-img-element/relevant-mutations.html",
"url": "/html/semantics/embedded-content/the-img-element/relevant-mutations.html"
},
@@ -30594,4 +30598,4 @@
"rev": "075802c1d3387d07e31cd5887459d539b1297c8d",
"url_base": "/",
"version": 2
-} \ No newline at end of file
+}
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index 02a810d184b..975b61ab307 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -2745,18 +2745,6 @@
[HTMLImageElement interface: document.createElement("img") must inherit property "lowsrc" with the proper type (14)]
expected: FAIL
- [HTMLImageElement must be primary interface of new Image()]
- expected: FAIL
-
- [Stringification of new Image()]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "alt" with the proper type (0)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "src" with the proper type (1)]
- expected: FAIL
-
[HTMLImageElement interface: new Image() must inherit property "srcset" with the proper type (2)]
expected: FAIL
@@ -2766,51 +2754,12 @@
[HTMLImageElement interface: new Image() must inherit property "crossOrigin" with the proper type (4)]
expected: FAIL
- [HTMLImageElement interface: new Image() must inherit property "useMap" with the proper type (5)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "isMap" with the proper type (6)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "width" with the proper type (7)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "height" with the proper type (8)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "naturalWidth" with the proper type (9)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "naturalHeight" with the proper type (10)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "complete" with the proper type (11)]
- expected: FAIL
-
[HTMLImageElement interface: new Image() must inherit property "currentSrc" with the proper type (12)]
expected: FAIL
- [HTMLImageElement interface: new Image() must inherit property "name" with the proper type (13)]
- expected: FAIL
-
[HTMLImageElement interface: new Image() must inherit property "lowsrc" with the proper type (14)]
expected: FAIL
- [HTMLImageElement interface: new Image() must inherit property "align" with the proper type (15)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "hspace" with the proper type (16)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "vspace" with the proper type (17)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "longDesc" with the proper type (18)]
- expected: FAIL
-
- [HTMLImageElement interface: new Image() must inherit property "border" with the proper type (19)]
- expected: FAIL
-
[HTMLIFrameElement interface: existence and properties of interface object]
expected: FAIL
diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html
index e1933f77c76..effcfdae208 100644
--- a/tests/wpt/mozilla/tests/mozilla/interfaces.html
+++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html
@@ -168,6 +168,7 @@ var interfaceNamesInGlobalScope = [
"HTMLUnknownElement",
"HTMLVideoElement",
"ImageData",
+ "Image",
"KeyboardEvent",
"Location",
"MessageEvent",
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/Image-constructor.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/Image-constructor.html
new file mode 100644
index 00000000000..528d3c80773
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/Image-constructor.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<title>DOM Image constructor Test</title>
+<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element" />
+<meta name="assert" content="Tests the Image constructor for the img-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+
+<div id="log"></div>
+<script>
+ test(function() {
+ var img = new Image();
+ assert_true(img != undefined);
+ }, "Image constructor works");
+
+ test(function() {
+ assert_true(Image.prototype === HTMLImageElement.prototype);
+ }, "Image and HTMLImageElement share a prototype");
+
+ test(function() {
+ assert_true((new Image()).localName === "img");
+ }, "Image localName is img");
+
+ test(function() {
+ assert_true((new Image()).namespaceURI === "http://www.w3.org/1999/xhtml");
+ }, "Image namespace URI is correct");
+
+</script>