Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WindowProxy support and basic browsing context concept. #1818

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Implement extremely basic browsing context concept, along with proper…

… WindowProxy.
  • Loading branch information
jdm committed Apr 14, 2014
commit ab2955e8c993522d9e040f14db4977d3b86ababd
@@ -584,8 +584,7 @@ def handleJSObjectType(type, isMember, failureCode):
declArgs = None
templateBody = "${declName} = Some(${val}.to_object());"
setToNullCode = "${declName} = None;"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
template = wrapObjectTemplate(templateBody, False, type, failureCode)
return (template, declType, None, isOptional, None) #XXX declArgs

assert not (isEnforceRange and isClamp) # These are mutually exclusive
@@ -2160,16 +2159,16 @@ def definition_body(self):
#XXXjdm This self.descriptor.concrete check shouldn't be necessary
if not self.descriptor.concrete or self.descriptor.proxy:
body += """ let traps = ProxyTraps {
getPropertyDescriptor: getPropertyDescriptor,
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
defineProperty: defineProperty,
getPropertyDescriptor: Some(getPropertyDescriptor),
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
defineProperty: Some(defineProperty),
getOwnPropertyNames: ptr::null(),
delete_: ptr::null(),
enumerate: ptr::null(),
has: ptr::null(),
hasOwn: hasOwn,
get: get,
has: None,
hasOwn: Some(hasOwn),
get: Some(get),
set: ptr::null(),
keys: ptr::null(),
iterate: ptr::null(),
@@ -2180,21 +2179,21 @@ def definition_body(self):
hasInstance: ptr::null(),
typeOf: ptr::null(),
objectClassIs: ptr::null(),
obj_toString: obj_toString,
obj_toString: Some(obj_toString),
fun_toString: ptr::null(),
//regexp_toShared: ptr::null(),
defaultValue: ptr::null(),
iteratorNext: ptr::null(),
finalize: %s,
finalize: Some(%s),
getElementIfPresent: ptr::null(),
getPrototypeOf: ptr::null(),
trace: %s
trace: Some(%s)
};
js_info.dom_static.proxy_handlers.insert(PrototypeList::id::%s as uint,
CreateProxyHandler(&traps, cast::transmute(&Class)));
""" % (FINALIZE_HOOK_NAME,
('Some(%s)' % TRACE_HOOK_NAME),
TRACE_HOOK_NAME,
self.descriptor.name)

return (body + """ let cx = js_info.js_context.deref().ptr;
@@ -17,12 +17,14 @@ use std::ptr;
use std::ptr::null;
use std::slice;
use std::str;
use js::glue::*;
use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily};
use js::glue::{GetGlobalForObjectCrossCompartment, UnwrapObject, GetProxyHandlerExtra};
use js::glue::{IsWrapper, RUST_JSID_TO_STRING, RUST_JSID_IS_INT, RUST_INTERNED_STRING_TO_JSID};
use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_INT};
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction};
use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength};
use js::jsapi::{JS_ObjectIsRegExp, JS_ObjectIsDate};
use js::jsapi::{JS_ObjectIsRegExp, JS_ObjectIsDate, JSHandleObject};
use js::jsapi::{JS_InternString, JS_GetFunctionObject};
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype};
use js::jsapi::{JS_DefineFunctions, JS_DefineProperty};
@@ -96,9 +98,29 @@ pub unsafe fn get_dom_class(obj: *JSObject) -> Result<DOMClass, ()> {
return Err(());
}

pub fn unwrap_object<T>(obj: *JSObject, proto_id: PrototypeList::id::ID, proto_depth: uint) -> Result<*mut T, ()> {
pub fn unwrap_object<T>(mut obj: *JSObject,
proto_id: PrototypeList::id::ID,
proto_depth: uint) -> Result<*mut T, ()> {
unsafe {
get_dom_class(obj).and_then(|dom_class| {
let dom_class = get_dom_class(obj).or_else(|_| {
if IsWrapper(obj) == 1 {
debug!("found wrapper");
obj = UnwrapObject(obj, 0, ptr::null());
if obj.is_null() {
debug!("unwrapping failed");
Err(())
} else {
assert!(IsWrapper(obj) == 0);
debug!("unwrapped successfully");
get_dom_class(obj)
}
} else {
debug!("not a dom wrapper");
Err(())
}
});

dom_class.and_then(|dom_class| {
if dom_class.interface_chain[proto_depth] == proto_id {
debug!("good prototype");
Ok(unwrap(obj))
@@ -526,6 +548,30 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
}
}

pub extern fn wrap_for_same_compartment(cx: *JSContext, obj: *JSObject) -> *JSObject {
unsafe {
let class = JS_GetClass(obj);
let clazz: *js::Class = cast::transmute(class);
match (*clazz).ext.outerObject {
Some(outerize) => {
debug!("found an outerize hook");
let obj = JSHandleObject { unnamed: &obj };
outerize(cx, obj)
}
None => obj
}
}
}

pub extern fn outerize_global(_cx: *JSContext, obj: JSHandleObject) -> *JSObject {
unsafe {
debug!("outerizing");
let obj = *obj.unnamed;
let win: JS<window::Window> = unwrap_jsmanaged(obj, PrototypeList::id::Window, 1).unwrap();
win.get().browser_context.get_ref().window_proxy()
}
}

/// Returns the global object of the realm that the given JS object was created in.
pub fn global_object_for_js_object(obj: *JSObject) -> JS<window::Window> {
unsafe {
@@ -549,11 +595,6 @@ fn cx_for_dom_reflector(obj: *JSObject) -> *JSContext {
}
}

/// Returns the global object of the realm that the given DOM object was created in.
pub fn global_object_for_dom_object<T: Reflectable>(obj: &T) -> JS<window::Window> {
global_object_for_js_object(obj.reflector().get_jsobject())
}

pub fn cx_for_dom_object<T: Reflectable>(obj: &T) -> *JSContext {
cx_for_dom_reflector(obj.reflector().get_jsobject())
}
@@ -0,0 +1,139 @@
/* 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 dom::bindings::js::JS;
use dom::bindings::proxyhandler::_obj_toString;
use dom::bindings::trace::trace_object;
use dom::bindings::utils::Reflectable;
use dom::document::Document;
use dom::window::Window;
use dom::windowproxy::WindowProxy;

use js::jsapi::{JSContext, JSObject, JSString, JSTracer};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};

use std::cast;
use std::libc::c_void;
use std::ptr;
use serialize::{Encoder, Encodable};

#[deriving(Encodable)]
pub struct BrowserContext {
history: ~[SessionHistoryEntry],
active_index: uint,
priv extra: Untraceable,
}

struct Untraceable {
proxy_handler: *c_void,
window_proxy: *JSObject,
}

impl<S: Encoder> Encodable<S> for Untraceable {
fn encode(&self, tracer: &mut S) {
let tracer: &mut JSTracer = unsafe { cast::transmute(tracer) };
trace_object(tracer, "proxy", self.window_proxy);
}
}

impl BrowserContext {
pub fn new(document: JS<Document>) -> BrowserContext {
let mut context = BrowserContext {
history: ~[SessionHistoryEntry::new(document)],
active_index: 0,
extra: Untraceable {
proxy_handler: new_window_proxy_handler(),
window_proxy: ptr::null(),
},
};
context.extra.window_proxy = context.create_window_proxy();
context
}

pub fn active_document(&self) -> JS<Document> {
self.history[self.active_index].document.clone()
}

pub fn active_window(&self) -> JS<Window> {
let doc = self.active_document();
doc.get().window.clone()
}

pub fn window_proxy(&self) -> WindowProxy {
assert!(self.extra.window_proxy.is_not_null());
self.extra.window_proxy
}

pub fn create_window_proxy(&self) -> WindowProxy {
assert!(self.extra.proxy_handler.is_not_null());

let win = self.active_window();
let page = win.get().page();
let js_info = page.js_info();

let parent = win.get().reflector().get_jsobject();
let cx = js_info.get_ref().js_context.deref().ptr;
unsafe {
WrapperNew(cx, parent, self.extra.proxy_handler)
}
}
}

#[deriving(Encodable)]
pub struct SessionHistoryEntry {
document: JS<Document>,
children: ~[BrowserContext]
}

impl SessionHistoryEntry {
fn new(document: JS<Document>) -> SessionHistoryEntry {
SessionHistoryEntry {
document: document,
children: ~[]
}
}
}

extern fn obj_toString(cx: *JSContext, _proxy: *JSObject) -> *JSString {
"Window".to_c_str().with_ref(|s| {
_obj_toString(cx, s)
})
}

fn new_window_proxy_handler() -> *c_void {
let traps = ProxyTraps {
getPropertyDescriptor: None,
getOwnPropertyDescriptor: None,
defineProperty: None,
getOwnPropertyNames: ptr::null(),
delete_: ptr::null(),
enumerate: ptr::null(),

has: None,
hasOwn: None,
get: None,
set: ptr::null(),
keys: ptr::null(),
iterate: ptr::null(),

call: ptr::null(),
construct: ptr::null(),
nativeCall: ptr::null(),
hasInstance: ptr::null(),
typeOf: ptr::null(),
objectClassIs: ptr::null(),
obj_toString: Some(obj_toString),
fun_toString: ptr::null(),
//regexp_toShared: ptr::null(),
defaultValue: ptr::null(),
iteratorNext: ptr::null(),
finalize: None,
getElementIfPresent: ptr::null(),
getPrototypeOf: ptr::null(),
trace: None
};
unsafe {
CreateWrapperProxyHandler(&traps)
}
}
@@ -5,7 +5,8 @@
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::error::{Fallible, InvalidState};
use dom::bindings::codegen::EventListenerBinding::EventListener;
use dom::bindings::codegen::EventListenerBinding;
use self::EventListenerBinding::EventListener;
use dom::event::Event;
use dom::eventdispatcher::dispatch_event;
use dom::node::NodeTypeId;
@@ -4,8 +4,9 @@

use dom::bindings::js::JS;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::bindings::codegen::TestBindingBinding::TestEnum;
use dom::bindings::codegen::TestBindingBinding::TestEnumValues::_empty;
use dom::bindings::codegen::TestBindingBinding;
use self::TestBindingBinding::TestEnum;
use self::TestBindingBinding::TestEnumValues::_empty;
use dom::blob::Blob;
use dom::window::Window;
use servo_util::str::DOMString;
@@ -10,8 +10,8 @@
[NamedPropertiesObject]
/*sealed*/ interface Window : EventTarget {
// the current browsing context
/*[Unforgeable] readonly attribute WindowProxy window;
[Replaceable] readonly attribute WindowProxy self;*/
[Unforgeable] readonly attribute WindowProxy window;
[Replaceable] readonly attribute WindowProxy self;
[Unforgeable] readonly attribute Document document;
attribute DOMString name;
/* [PutForwards=href, Unforgeable] */ readonly attribute Location location;
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.