Hook up interface and prototype object creation.

This commit is contained in:
Josh Matthews 2013-02-14 20:43:53 -05:00
parent e333e5d4c3
commit 7c435f5dcb

View file

@ -1,13 +1,18 @@
use js;
use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
JS_THIS_OBJECT, JS_SET_RVAL};
JS_THIS_OBJECT, JS_SET_RVAL, JSFUN_CONSTRUCTOR, JS_CALLEE};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSNative,
JSFunctionSpec, JSPropertySpec, JSVal};
JSFunctionSpec, JSPropertySpec, JSVal, JSString};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
JS_GetClass, JS_GetPrototype};
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate,
JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype,
JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction,
JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject,
JS_GetInternedStringCharsAndLength};
use js::jsfriendapi::bindgen::{DefineFunctionWithReserved, GetObjectJSClass,
JS_NewObjectWithUniqueType};
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB,
RESOLVE_STUB};
use js::glue::bindgen::*;
@ -15,6 +20,43 @@ use core::ptr::null;
use core::cast;
use content::content_task::{Content, task_from_context};
const TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
const TOSTRING_NAME_RESERVED_SLOT: u64 = 1;
extern fn InterfaceObjectToString(cx: *JSContext, argc: uint, vp: *mut JSVal) -> JSBool {
unsafe {
let callee = RUST_JSVAL_TO_OBJECT(*JS_CALLEE(cx, cast::transmute(&vp)));
let obj = JS_THIS_OBJECT(cx, cast::transmute(&vp));
if obj.is_null() {
//XXXjdm figure out JSMSG madness
/*JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
"null", "object");*/
return 0;
}
let v = GetFunctionNativeReserved(callee, TOSTRING_CLASS_RESERVED_SLOT);
let clasp: *JSClass = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(*v));
let v = GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
let jsname: *JSString = RUST_JSVAL_TO_STRING(*v);
let length = 0;
let name = JS_GetInternedStringCharsAndLength(jsname, &length);
if GetObjectJSClass(obj) != clasp {
//XXXjdm figure out JSMSG madness
/*JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
NS_ConvertUTF16toUTF8(name).get(), "toString",
"object");*/
return 0;
}
let name = jsval_to_str(cx, *v).get();
let retval = str(~"function " + name + ~"() {\n [native code]\n}");
*vp = domstring_to_jsval(cx, &retval);
return 1;
}
}
pub enum DOMString {
str(~str),
null_string
@ -285,7 +327,7 @@ mod prototypes {
pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSObject,
protoProto: *JSObject, protoClass: *JSClass,
constructorClass: *JSClass, constructor: JSNative,
ctorNargs: uint,
ctorNargs: u32,
domClass: *DOMClass,
methods: *JSFunctionSpec,
properties: *JSPropertySpec,
@ -295,10 +337,9 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO
unsafe {
let mut proto = ptr::null();
if protoClass.is_not_null() {
proto = /*CreateInterfacePrototypeObject(cx, global, protoProto,
protoClass,
regularProperties,
chromeOnlyProperties);*/ptr::null();
proto = CreateInterfacePrototypeObject(cx, global, protoProto,
protoClass, methods,
properties, constants);
if proto.is_null() {
return ptr::null();
}
@ -310,9 +351,9 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO
let mut interface = ptr::null();
if constructorClass.is_not_null() || constructor.is_not_null() {
interface = do str::as_c_str(name) |s| {
/*CreateInterfaceObject(cx, global, constructorClass, constructor,
ctorNargs, proto, properties,
chromeOnlyProperties, s)*/ptr::null()
CreateInterfaceObject(cx, global, receiver, constructorClass,
constructor, ctorNargs, proto,
staticMethods, constants, s)
};
if interface.is_null() {
return ptr::null();
@ -327,6 +368,110 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO
}
}
fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject,
constructorClass: *JSClass, constructorNative: JSNative,
ctorNargs: u32, proto: *JSObject,
staticMethods: *JSFunctionSpec,
constants: *ConstantSpec,
name: *libc::c_char) -> *JSObject {
unsafe {
let constructor = if constructorClass.is_not_null() {
let functionProto = JS_GetFunctionPrototype(cx, global);
if functionProto.is_null() {
ptr::null()
} else {
JS_NewObject(cx, constructorClass, functionProto, global)
}
} else {
assert constructorNative.is_not_null();
let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
JSFUN_CONSTRUCTOR, global, name);
if fun.is_null() {
ptr::null()
} else {
JS_GetFunctionObject(fun)
}
};
if constructor.is_null() {
return ptr::null();
}
if staticMethods.is_not_null() /*&&
!DefinePrefable(cx, constructor, staticMethods)*/ {
return ptr::null();
}
if constructorClass.is_not_null() {
let toString = do str::as_c_str("toString") |s| {
DefineFunctionWithReserved(cx, constructor, s,
InterfaceObjectToString,
0, 0)
};
if toString.is_null() {
return ptr::null();
}
let toStringObj = JS_GetFunctionObject(toString);
SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
&RUST_PRIVATE_TO_JSVAL(constructorClass as *libc::c_void));
let s = JS_InternString(cx, name);
if s.is_null() {
return ptr::null();
}
SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
&RUST_STRING_TO_JSVAL(s));
}
if constants.is_not_null() /*&&
!DefinePrefable(cx, constructor, constants)*/ {
return ptr::null();
}
if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
return ptr::null();
}
let alreadyDefined = 0;
if JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined) == 0 {
return ptr::null();
}
if alreadyDefined == 0 &&
JS_DefineProperty(cx, receiver, name, RUST_OBJECT_TO_JSVAL(constructor),
ptr::null(), ptr::null(), 0) == 0 {
return ptr::null();
}
return constructor;
}
}
fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
parentProto: *JSObject, protoClass: *JSClass,
methods: *JSFunctionSpec,
properties: *JSPropertySpec,
constants: *ConstantSpec) -> *JSObject {
let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
if ourProto.is_null() {
return ptr::null();
}
if methods.is_not_null() /*&& !DefinePrefable(cx, ourProto, methods)*/ {
return ptr::null();
}
if properties.is_not_null() /*&& !DefinePrefable(cx, ourProto, properties)*/ {
return ptr::null();
}
if constants.is_not_null() /*&& !DefinePrefable(cx, ourProto, constants)*/ {
return ptr::null();
}
return ourProto;
}
pub extern fn ThrowingConstructor(cx: *JSContext, argc: uint, vp: *JSVal) -> JSBool {
//XXX should trigger exception here
return 0;