mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
apply pylbrecht/servo/named.window.getter (closes #27952)
This commit is contained in:
parent
be6e25a1b2
commit
fd1de05592
16 changed files with 611 additions and 292 deletions
220
components/script/window_named_properties.rs
Normal file
220
components/script/window_named_properties.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::proxyhandler::set_property_descriptor;
|
||||
use crate::dom::bindings::root::Root;
|
||||
use crate::dom::bindings::utils::has_property_on_prototype;
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::window::Window;
|
||||
use crate::js::conversions::ToJSValConvertible;
|
||||
use crate::script_runtime::JSContext as SafeJSContext;
|
||||
use js::conversions::jsstr_to_string;
|
||||
use js::error::throw_type_error;
|
||||
use js::glue::RUST_JSID_TO_STRING;
|
||||
use js::glue::{CreateProxyHandler, NewProxyObject, ProxyTraps, RUST_JSID_IS_STRING};
|
||||
use js::jsapi::JS_SetImmutablePrototype;
|
||||
use js::jsapi::{Handle, HandleObject, JSClass, JSContext, JSErrNum, UndefinedHandleValue};
|
||||
use js::jsapi::{
|
||||
HandleId, JSClass_NON_NATIVE, MutableHandle, MutableHandleIdVector, ObjectOpResult,
|
||||
PropertyDescriptor, ProxyClassExtension, ProxyClassOps, ProxyObjectOps,
|
||||
JSCLASS_DELAY_METADATA_BUILDER, JSCLASS_IS_PROXY, JSCLASS_RESERVED_SLOTS_MASK,
|
||||
JSCLASS_RESERVED_SLOTS_SHIFT,
|
||||
};
|
||||
use js::jsval::UndefinedValue;
|
||||
use js::rust::IntoHandle;
|
||||
use js::rust::{Handle as RustHandle, MutableHandle as RustMutableHandle};
|
||||
use js::rust::{HandleObject as RustHandleObject, MutableHandleObject as RustMutableHandleObject};
|
||||
use libc;
|
||||
use std::ptr;
|
||||
|
||||
struct SyncWrapper(*const libc::c_void);
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Sync for SyncWrapper {}
|
||||
|
||||
lazy_static! {
|
||||
static ref HANDLER: SyncWrapper = {
|
||||
let traps = ProxyTraps {
|
||||
enter: None,
|
||||
getOwnPropertyDescriptor: Some(get_own_property_descriptor),
|
||||
defineProperty: Some(define_property),
|
||||
ownPropertyKeys: Some(own_property_keys),
|
||||
delete_: Some(delete),
|
||||
enumerate: None,
|
||||
getPrototypeIfOrdinary: None,
|
||||
getPrototype: None,
|
||||
setPrototype: None,
|
||||
setImmutablePrototype: None,
|
||||
preventExtensions: Some(prevent_extensions),
|
||||
isExtensible: Some(is_extensible),
|
||||
has: None,
|
||||
get: None,
|
||||
set: None,
|
||||
call: None,
|
||||
construct: None,
|
||||
hasOwn: None,
|
||||
getOwnEnumerablePropertyKeys: None,
|
||||
nativeCall: None,
|
||||
objectClassIs: None,
|
||||
className: Some(class_name),
|
||||
fun_toString: None,
|
||||
boxedValue_unbox: None,
|
||||
defaultValue: None,
|
||||
trace: None,
|
||||
finalize: None,
|
||||
objectMoved: None,
|
||||
isCallable: None,
|
||||
isConstructor: None,
|
||||
};
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe {
|
||||
SyncWrapper(CreateProxyHandler(&traps, ptr::null()))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn get_own_property_descriptor(
|
||||
cx: *mut JSContext,
|
||||
proxy: HandleObject,
|
||||
id: HandleId,
|
||||
desc: MutableHandle<PropertyDescriptor>,
|
||||
is_none: *mut bool,
|
||||
) -> bool {
|
||||
let cx = SafeJSContext::from_ptr(cx);
|
||||
if !RUST_JSID_IS_STRING(id) {
|
||||
// Nothing to do if we're resolving a non-string property.
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut found = false;
|
||||
if !has_property_on_prototype(
|
||||
*cx,
|
||||
RustHandle::from_raw(proxy),
|
||||
RustHandle::from_raw(id),
|
||||
&mut found,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if found {
|
||||
return true;
|
||||
}
|
||||
|
||||
let s = jsstr_to_string(*cx, RUST_JSID_TO_STRING(id));
|
||||
if s.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let window = Root::downcast::<Window>(GlobalScope::from_object(proxy.get()))
|
||||
.expect("global is not a window");
|
||||
if let Some(obj) = window.NamedGetter(cx, s.into()) {
|
||||
rooted!(in(*cx) let mut rval = UndefinedValue());
|
||||
obj.to_jsval(*cx, rval.handle_mut());
|
||||
set_property_descriptor(RustMutableHandle::from_raw(desc), rval.handle(), 0, &mut *is_none);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn own_property_keys(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
_props: MutableHandleIdVector,
|
||||
) -> bool {
|
||||
// FIXME(pylbrecht): dummy implementation
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn define_property(
|
||||
cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
_id: HandleId,
|
||||
_desc: Handle<PropertyDescriptor>,
|
||||
_result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
throw_type_error(
|
||||
cx,
|
||||
"Not allowed to define a property on the named properties object.",
|
||||
);
|
||||
false
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn delete(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
_id: HandleId,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY as usize;
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn prevent_extensions(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
result: *mut ObjectOpResult,
|
||||
) -> bool {
|
||||
(*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as usize;
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn is_extensible(
|
||||
_cx: *mut JSContext,
|
||||
_proxy: HandleObject,
|
||||
extensible: *mut bool,
|
||||
) -> bool {
|
||||
*extensible = true;
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn class_name(_cx: *mut JSContext, _proxy: HandleObject) -> *const i8 {
|
||||
&b"WindowProperties\0" as *const _ as *const i8
|
||||
}
|
||||
|
||||
// Maybe this should be a DOMJSClass. See https://bugzilla.mozilla.org/show_bug.cgi?id=787070
|
||||
#[allow(unsafe_code)]
|
||||
static CLASS: JSClass = JSClass {
|
||||
name: b"WindowProperties\0" as *const u8 as *const libc::c_char,
|
||||
flags: JSClass_NON_NATIVE |
|
||||
JSCLASS_IS_PROXY |
|
||||
JSCLASS_DELAY_METADATA_BUILDER |
|
||||
((1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), /* JSCLASS_HAS_RESERVED_SLOTS(1) */
|
||||
cOps: unsafe { &ProxyClassOps },
|
||||
spec: ptr::null(),
|
||||
ext: unsafe { &ProxyClassExtension },
|
||||
oOps: unsafe { &ProxyObjectOps },
|
||||
};
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn create(
|
||||
cx: SafeJSContext,
|
||||
proto: RustHandleObject,
|
||||
mut properties_obj: RustMutableHandleObject,
|
||||
) {
|
||||
unsafe {
|
||||
properties_obj.set(NewProxyObject(
|
||||
*cx,
|
||||
HANDLER.0,
|
||||
UndefinedHandleValue,
|
||||
proto.get(),
|
||||
// TODO: pass proper clasp
|
||||
&CLASS,
|
||||
false,
|
||||
));
|
||||
assert!(!properties_obj.get().is_null());
|
||||
let mut succeeded = false;
|
||||
assert!(JS_SetImmutablePrototype(
|
||||
*cx,
|
||||
properties_obj.handle().into_handle(),
|
||||
&mut succeeded
|
||||
));
|
||||
assert!(succeeded);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue