mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Fill out various proxy binding traps as part of making setters work. Add named getter and setter and indexed getter support, as well as proxy object expandos. Fixes #660.
This commit is contained in:
parent
a4baa7fc6b
commit
c9bc2046f6
10 changed files with 376 additions and 48 deletions
|
@ -2,10 +2,15 @@
|
|||
* 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::is_dom_proxy;
|
||||
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
|
||||
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
|
||||
use js::glue::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra};
|
||||
use js::glue::{GetObjectProto};
|
||||
use js::jsapi::{JSBool, JS_DefinePropertyById, JS_NewObjectWithGivenProto};
|
||||
use js::glue::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra, RUST_OBJECT_TO_JSVAL};
|
||||
use js::glue::{GetObjectProto, GetObjectParent, SetProxyExtra, GetProxyHandler};
|
||||
use js::glue::InvokeGetOwnPropertyDescriptor;
|
||||
use js::crust::{JS_StrictPropertyStub};
|
||||
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY, JSRESOLVE_QUALIFIED};
|
||||
|
||||
use std::cast;
|
||||
use std::libc;
|
||||
|
@ -15,10 +20,13 @@ use std::sys::size_of;
|
|||
|
||||
type c_bool = libc::c_int;
|
||||
|
||||
static JSPROXYSLOT_EXPANDO: u32 = 0;
|
||||
|
||||
pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
||||
unsafe {
|
||||
if _getOwnPropertyDescriptor(cx, proxy, id, set, desc) == 0 {
|
||||
let handler = GetProxyHandler(proxy);
|
||||
if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, set, desc) == 0 {
|
||||
return 0;
|
||||
}
|
||||
if (*desc).obj.is_not_null() {
|
||||
|
@ -32,34 +40,30 @@ pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
|||
return 1;
|
||||
}
|
||||
|
||||
JS_GetPropertyDescriptorById(cx, proto, id, 0x01 /*JSRESOLVE_QUALIFIED*/,
|
||||
cast::transmute(desc))
|
||||
JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, cast::transmute(desc))
|
||||
}
|
||||
}
|
||||
|
||||
fn _getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||
_set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
||||
unsafe {
|
||||
let v = GetProxyExtra(proxy, 0 /*JSPROXYSLOT_EXPANDO*/);
|
||||
if RUST_JSVAL_IS_VOID(v) == 0 {
|
||||
let expando = RUST_JSVAL_TO_OBJECT(v);
|
||||
if JS_GetPropertyDescriptorById(cx, expando, id, 0x01 /*JSRESOLVE_QUALIFIED*/,
|
||||
cast::transmute(desc)) == 0 {
|
||||
pub extern fn defineProperty(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||
desc: *JSPropertyDescriptor) -> JSBool {
|
||||
unsafe {
|
||||
if ((*desc).attrs & JSPROP_GETTER) != 0 && (*desc).setter == JS_StrictPropertyStub {
|
||||
/*return JS_ReportErrorFlagsAndNumber(cx,
|
||||
JSREPORT_WARNING | JSREPORT_STRICT |
|
||||
JSREPORT_STRICT_MODE_ERROR,
|
||||
js_GetErrorMessage, NULL,
|
||||
JSMSG_GETTER_ONLY);*/
|
||||
return 0;
|
||||
}
|
||||
if (*desc).obj.is_not_null() {
|
||||
(*desc).obj = proxy;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
(*desc).obj = ptr::null();
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
pub extern fn getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
|
||||
_getOwnPropertyDescriptor(cx, proxy, id, set, desc)
|
||||
let expando = EnsureExpandoObject(cx, proxy);
|
||||
if expando.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return JS_DefinePropertyById(cx, expando, id, (*desc).value, (*desc).getter,
|
||||
(*desc).setter, (*desc).attrs);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||
|
@ -84,6 +88,39 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn GetExpandoObject(_proxy: *JSObject) -> *JSObject {
|
||||
ptr::null()
|
||||
pub fn GetExpandoObject(obj: *JSObject) -> *JSObject {
|
||||
unsafe {
|
||||
assert!(is_dom_proxy(obj));
|
||||
let val = GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
|
||||
if RUST_JSVAL_IS_VOID(val) == 1 {
|
||||
ptr::null()
|
||||
} else {
|
||||
RUST_JSVAL_TO_OBJECT(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn EnsureExpandoObject(cx: *JSContext, obj: *JSObject) -> *JSObject {
|
||||
unsafe {
|
||||
assert!(is_dom_proxy(obj));
|
||||
let mut expando = GetExpandoObject(obj);
|
||||
if expando.is_null() {
|
||||
expando = JS_NewObjectWithGivenProto(cx, ptr::null(), ptr::null(),
|
||||
GetObjectParent(obj));
|
||||
if expando.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, RUST_OBJECT_TO_JSVAL(expando));
|
||||
}
|
||||
return expando;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FillPropertyDescriptor(desc: &mut JSPropertyDescriptor, obj: *JSObject, readonly: bool) {
|
||||
desc.obj = obj;
|
||||
desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
|
||||
desc.getter = ptr::null();
|
||||
desc.setter = ptr::null();
|
||||
desc.shortid = 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue