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 -->
This commit is contained in:
bors-servo 2015-06-25 02:18:06 -06:00
commit 57cc84b293
8 changed files with 160 additions and 81 deletions

View file

@ -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`.