From 012be81eaba1c6328b25a9558ef7d76f25f7439c Mon Sep 17 00:00:00 2001 From: Joel Teichroeb Date: Sun, 17 May 2015 23:47:15 +0000 Subject: [PATCH 1/2] Add support for NamedConstructor in webidls --- .../dom/bindings/codegen/CodegenRust.py | 40 ++++++++ components/script/dom/bindings/utils.rs | 95 +++++++++++++------ 2 files changed, 107 insertions(+), 28 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 c57de127dfc..0dd9d922b71 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) { + let constructor = RootedObject::new(cx, create_constructor(cx, constructor_native, ctor_nargs, name)); + assert!(!constructor.ptr.is_null()); + + 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(constants) = members.consts { + define_constants(cx, constructor.handle(), constants); + } + unsafe { - let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs, - JSFUN_CONSTRUCTOR, name); - assert!(!fun.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_properties) = members.static_attrs { - define_properties(cx, constructor.handle(), static_properties); - } - - if let Some(constants) = members.consts { - define_constants(cx, constructor.handle(), constants); - } - 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`. From d33579183a19796b702576a9eb99805f20a608b1 Mon Sep 17 00:00:00 2001 From: Joel Teichroeb Date: Sun, 17 May 2015 23:47:35 +0000 Subject: [PATCH 2/2] Implement the Image NamedConstructor for HTMLImageElement --- components/script/dom/htmlimageelement.rs | 17 +++++++ .../dom/webidls/HTMLImageElement.webidl | 2 +- tests/wpt/metadata/MANIFEST.json | 6 ++- .../wpt/metadata/html/dom/interfaces.html.ini | 51 ------------------- .../wpt/mozilla/tests/mozilla/interfaces.html | 1 + .../the-img-element/Image-constructor.html | 29 +++++++++++ 6 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/Image-constructor.html 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, + height: Option) -> Fallible> { + 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 @@ -14117,6 +14117,10 @@ "path": "html/semantics/embedded-content/the-img-element/img.complete.html", "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 @@ + +DOM Image constructor Test + + + + + + + +
+