Remove all traces of WindowProxy. Implement basic browser context concept and outerizing of inner windows.

This commit is contained in:
Josh Matthews 2013-10-21 08:11:18 +01:00
parent c760577aee
commit 94dffca1e1
24 changed files with 354 additions and 155 deletions

View file

@ -12,6 +12,8 @@
# * needsAbstract: a list of members that require a JS<>-wrapped version of
# self to be passed to the native code.
# * createGlobal: True for global objects.
# * outerObjectHook: string to use in place of default value for outerObject and thisObject
# JS class hooks
DOMInterfaces = {
@ -112,15 +114,16 @@ DOMInterfaces = {
'ValidityState': {},
'Window': {
'createGlobal': True,
'outerObjectHook': 'Some(bindings::utils::outerize_global)',
'needsAbstract': [
'console',
'location',
'navigator',
'self',
'window',
],
},
'WindowProxy': {},
'TestBinding': {},
}
@ -129,7 +132,6 @@ DOMInterfaces = {
def addHTMLElement(element, concrete=None, needsAbstract=[]):
DOMInterfaces[element] = {
'nativeType': 'JS<%s>' % element,
'pointerType': '',
'concreteType': concrete if concrete else element,
'needsAbstract': needsAbstract
}

View file

@ -1496,7 +1496,8 @@ class CGDOMJSClass(CGThing):
return """
static Class_name: [u8, ..%i] = %s;
static Class: DOMJSClass = DOMJSClass {
base: JSClass { name: &Class_name as *u8 as *libc::c_char,
base: js::Class {
name: &Class_name as *u8 as *libc::c_char,
flags: JSCLASS_IS_DOMJSCLASS | %s | (((%s) & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(%s),
addProperty: Some(JS_PropertyStub),
delProperty: Some(JS_PropertyStub),
@ -1511,14 +1512,51 @@ static Class: DOMJSClass = DOMJSClass {
hasInstance: None,
construct: None,
trace: %s,
reserved: (0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 05
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 10
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 15
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 20
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 25
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 30
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, // 35
0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void, 0 as *libc::c_void) // 40
ext: js::ClassExtension {
equality: 0 as *u8,
outerObject: %s,
innerObject: None,
iteratorObject: 0 as *u8,
unused: 0 as *u8,
isWrappedNative: 0 as *u8,
},
ops: js::ObjectOps {
lookupGeneric: 0 as *u8,
lookupProperty: 0 as *u8,
lookupElement: 0 as *u8,
lookupSpecial: 0 as *u8,
defineGeneric: 0 as *u8,
defineProperty: 0 as *u8,
defineElement: 0 as *u8,
defineSpecial: 0 as *u8,
getGeneric: 0 as *u8,
getProperty: 0 as *u8,
getElement: 0 as *u8,
getElementIfPresent: 0 as *u8,
getSpecial: 0 as *u8,
setGeneric: 0 as *u8,
setProperty: 0 as *u8,
setElement: 0 as *u8,
setSpecial: 0 as *u8,
getGenericAttributes: 0 as *u8,
getPropertyAttributes: 0 as *u8,
getElementAttributes: 0 as *u8,
getSpecialAttributes: 0 as *u8,
setGenericAttributes: 0 as *u8,
setPropertyAttributes: 0 as *u8,
setElementAttributes: 0 as *u8,
setSpecialAttributes: 0 as *u8,
deleteProperty: 0 as *u8,
deleteElement: 0 as *u8,
deleteSpecial: 0 as *u8,
enumerate: 0 as *u8,
typeOf: 0 as *u8,
thisObject: %s,
clear: 0 as *u8,
},
},
dom_class: %s
};
@ -1526,6 +1564,8 @@ static Class: DOMJSClass = DOMJSClass {
str_to_const_array(self.descriptor.interface.identifier.name),
flags, slots, slots,
FINALIZE_HOOK_NAME, traceHook,
self.descriptor.outerObjectHook,
self.descriptor.outerObjectHook,
CGIndenter(CGGeneric(DOMClass(self.descriptor))).define())
def str_to_const_array(s):
@ -1844,9 +1884,9 @@ def CreateBindingJSObject(descriptor, parent=None):
""" % (parent)
else:
if descriptor.createGlobal:
create += " let obj = CreateDOMGlobal(aCx, &Class.base);\n"
create += " let obj = CreateDOMGlobal(aCx, &Class.base as *js::Class as *JSClass);\n"
else:
create += " let obj = JS_NewObject(aCx, &Class.base, proto, %s);\n" % parent
create += " let obj = JS_NewObject(aCx, &Class.base as *js::Class as *JSClass, proto, %s);\n" % parent
create += """ assert!(obj.is_not_null());
JS_SetReservedSlot(obj, DOM_OBJECT_SLOT as u32,
@ -2139,41 +2179,41 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
#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(),
delete_: None,
enumerate: ptr::null(),
has: ptr::null(),
hasOwn: hasOwn,
get: get,
set: ptr::null(),
has: None,
hasOwn: Some(hasOwn),
get: Some(get),
set: None,
keys: ptr::null(),
iterate: ptr::null(),
iterate: None,
call: ptr::null(),
construct: ptr::null(),
call: None,
construct: None,
nativeCall: ptr::null(),
hasInstance: ptr::null(),
typeOf: ptr::null(),
objectClassIs: ptr::null(),
obj_toString: obj_toString,
fun_toString: ptr::null(),
hasInstance: None,
typeOf: None,
objectClassIs: None,
obj_toString: Some(obj_toString),
fun_toString: None,
//regexp_toShared: ptr::null(),
defaultValue: ptr::null(),
iteratorNext: ptr::null(),
finalize: %s,
getElementIfPresent: ptr::null(),
getPrototypeOf: ptr::null(),
trace: %s
defaultValue: None,
iteratorNext: None,
finalize: Some(%s),
getElementIfPresent: None,
getPrototypeOf: None,
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).ptr;
@ -4390,6 +4430,7 @@ class CGBindingRoot(CGThing):
#XXXjdm This should only import the namespace for the current binding,
# not every binding ever.
curr = CGImports(curr, [
'js',
'js::{JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}',
'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}',
@ -4415,6 +4456,7 @@ class CGBindingRoot(CGThing):
'js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO}',
'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING}',
'dom::types::*',
'dom::bindings',
'dom::bindings::js::JS',
'dom::bindings::utils::{CreateDOMGlobal, CreateInterfaceObjects2}',
'dom::bindings::utils::{ConstantSpec, cx_for_dom_object, Default}',

View file

@ -138,6 +138,7 @@ class Descriptor(DescriptorProvider):
self.needsAbstract = desc.get('needsAbstract', [])
self.createGlobal = desc.get('createGlobal', False)
self.register = desc.get('register', True)
self.outerObjectHook = desc.get('outerObjectHook', 'None')
# If we're concrete, we need to crawl our ancestor interfaces and mark
# them as having a concrete descendant.

View file

@ -5,7 +5,7 @@
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector};
use js::jsapi::{JSTracer, JS_CallTracer, JSTRACE_OBJECT};
use js::jsapi::{JSObject, JSTracer, JS_CallTracer, JSTRACE_OBJECT};
use std::cast;
use std::cell::RefCell;
@ -19,10 +19,15 @@ use serialize::{Encodable, Encoder};
// we are unfortunately required to use generic types everywhere and
// unsafely cast to the concrete JSTracer we actually require.
fn get_jstracer<'a, S: Encoder>(s: &'a mut S) -> &'a mut JSTracer {
unsafe {
cast::transmute(s)
}
}
impl<T: Reflectable+Encodable<S>, S: Encoder> Encodable<S> for JS<T> {
fn encode(&self, s: &mut S) {
let s: &mut JSTracer = unsafe { cast::transmute(s) };
trace_reflector(s, "", self.reflector());
trace_reflector(get_jstracer(s), "", self.reflector());
}
}
@ -36,14 +41,17 @@ pub trait JSTraceable {
}
pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) {
trace_object(tracer, description, reflector.get_jsobject())
}
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *JSObject) {
unsafe {
description.to_c_str().with_ref(|name| {
(*tracer).debugPrinter = ptr::null();
(*tracer).debugPrintIndex = -1;
(*tracer).debugPrintArg = name as *libc::c_void;
debug!("tracing {:s}", description);
JS_CallTracer(tracer as *JSTracer, reflector.get_jsobject(),
JSTRACE_OBJECT as u32);
JS_CallTracer(tracer as *JSTracer, obj, JSTRACE_OBJECT as u32);
});
}
}
@ -113,3 +121,9 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Traceable<RefCell<T>> {
self.borrow().encode(s)
}
}
impl<S: Encoder> Encodable<S> for Traceable<*JSObject> {
fn encode(&self, s: &mut S) {
trace_object(get_jstracer(s), "object", **self)
}
}

View file

@ -4,9 +4,10 @@
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::{FromJSValConvertible, IDLInterface};
use dom::bindings::js::JS;
use dom::bindings::trace::Untraceable;
use dom::browsercontext;
use dom::window;
use servo_util::str::DOMString;
@ -19,12 +20,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_GetProperty, JS_HasProperty};
@ -46,12 +49,14 @@ use js;
#[deriving(Encodable)]
pub struct GlobalStaticData {
proxy_handlers: Untraceable<HashMap<uint, *libc::c_void>>
proxy_handlers: Untraceable<HashMap<uint, *libc::c_void>>,
windowproxy_handler: Untraceable<*libc::c_void>,
}
pub fn GlobalStaticData() -> GlobalStaticData {
GlobalStaticData {
proxy_handlers: Untraceable::new(HashMap::new())
proxy_handlers: Untraceable::new(HashMap::new()),
windowproxy_handler: Untraceable::new(browsercontext::new_window_proxy_handler()),
}
}
@ -100,11 +105,29 @@ pub unsafe fn get_dom_class(obj: *JSObject) -> Result<DOMClass, ()> {
return Err(());
}
pub fn unwrap_jsmanaged<T: Reflectable>(obj: *JSObject,
pub fn unwrap_jsmanaged<T: Reflectable>(mut obj: *JSObject,
proto_id: PrototypeList::id::ID,
proto_depth: uint) -> Result<JS<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, /* stopAtOuter = */ 0, ptr::null());
if obj.is_null() {
debug!("unwrapping security wrapper 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(JS::from_raw(unwrap(obj)))
@ -178,7 +201,7 @@ pub struct DOMClass {
}
pub struct DOMJSClass {
base: JSClass,
base: js::Class,
dom_class: DOMClass
}
@ -560,6 +583,36 @@ pub fn CreateDOMGlobal(cx: *JSContext, class: *JSClass) -> *JSObject {
}
}
pub extern fn wrap_for_same_compartment(cx: *JSContext, obj: *JSObject) -> *JSObject {
unsafe {
let clasp = JS_GetClass(obj);
let clasp = clasp as *js::Class;
match (*clasp).ext.outerObject {
Some(outerize) => {
debug!("found an outerize hook");
let obj = JSHandleObject { unnamed: &obj };
outerize(cx, obj)
}
None => {
debug!("no outerize hook found");
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,
IDLInterface::get_prototype_id(None::<window::Window>),
IDLInterface::get_prototype_depth(None::<window::Window>)).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 {
@ -580,11 +633,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())
}

View file

@ -0,0 +1,118 @@
/* 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::trace::Traceable;
use dom::bindings::utils::Reflectable;
use dom::document::Document;
use dom::window::Window;
use js::jsapi::JSObject;
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use std::libc::c_void;
use std::ptr;
#[deriving(Encodable)]
pub struct BrowserContext {
priv history: Vec<SessionHistoryEntry>,
priv active_index: uint,
priv window_proxy: Traceable<*JSObject>,
}
impl BrowserContext {
pub fn new(document: &JS<Document>) -> BrowserContext {
let mut context = BrowserContext {
history: vec!(SessionHistoryEntry::new(document)),
active_index: 0,
window_proxy: Traceable::new(ptr::null()),
};
context.window_proxy = Traceable::new(context.create_window_proxy());
context
}
pub fn active_document(&self) -> JS<Document> {
self.history.get(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) -> *JSObject {
assert!(self.window_proxy.deref().is_not_null());
*self.window_proxy
}
pub fn create_window_proxy(&self) -> *JSObject {
let win = self.active_window();
let page = win.get().page();
let js_info = page.js_info();
let handler = js_info.get_ref().dom_static.windowproxy_handler;
assert!(handler.deref().is_not_null());
let parent = win.get().reflector().get_jsobject();
let cx = js_info.get_ref().js_context.deref().deref().ptr;
let wrapper = unsafe {
WrapperNew(cx, parent, *handler.deref())
};
assert!(wrapper.is_not_null());
wrapper
}
}
#[deriving(Encodable)]
pub struct SessionHistoryEntry {
priv document: JS<Document>,
priv children: Vec<BrowserContext>
}
impl SessionHistoryEntry {
fn new(document: &JS<Document>) -> SessionHistoryEntry {
SessionHistoryEntry {
document: document.clone(),
children: vec!()
}
}
}
static proxy_handler: ProxyTraps = ProxyTraps {
getPropertyDescriptor: None,
getOwnPropertyDescriptor: None,
defineProperty: None,
getOwnPropertyNames: 0 as *u8,
delete_: None,
enumerate: 0 as *u8,
has: None,
hasOwn: None,
get: None,
set: None,
keys: 0 as *u8,
iterate: None,
call: None,
construct: None,
nativeCall: 0 as *u8,
hasInstance: None,
typeOf: None,
objectClassIs: None,
obj_toString: None,
fun_toString: None,
//regexp_toShared: 0 as *u8,
defaultValue: None,
iteratorNext: None,
finalize: None,
getElementIfPresent: None,
getPrototypeOf: None,
trace: None
};
pub fn new_window_proxy_handler() -> *c_void {
unsafe {
CreateWrapperProxyHandler(&proxy_handler)
}
}

View file

@ -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;

View file

@ -11,7 +11,7 @@ use dom::element::HTMLFrameElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::windowproxy::WindowProxy;
use dom::window::Window;
use servo_util::str::DOMString;
#[deriving(Encodable)]
@ -94,7 +94,7 @@ impl HTMLFrameElement {
None
}
pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> {
pub fn GetContentWindow(&self) -> Option<JS<Window>> {
None
}

View file

@ -14,7 +14,7 @@ use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use dom::virtualmethods::VirtualMethods;
use dom::windowproxy::WindowProxy;
use dom::window::Window;
use servo_util::str::DOMString;
use servo_msg::constellation_msg::{PipelineId, SubpageId};
@ -143,7 +143,7 @@ impl HTMLIFrameElement {
None
}
pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> {
pub fn GetContentWindow(&self) -> Option<JS<Window>> {
None
}

View file

@ -16,7 +16,7 @@ use dom::htmlformelement::HTMLFormElement;
use dom::node::{Node, ElementNodeTypeId, NodeHelpers, window_from_node};
use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods;
use dom::windowproxy::WindowProxy;
use dom::window::Window;
use servo_util::str::DOMString;
use servo_net::image_cache_task;
@ -135,7 +135,7 @@ impl HTMLObjectElement {
None
}
pub fn GetContentWindow(&self) -> Option<JS<WindowProxy>> {
pub fn GetContentWindow(&self) -> Option<JS<Window>> {
None
}

View file

@ -11,7 +11,6 @@ use dom::event::{Event, MouseEventTypeId};
use dom::eventtarget::EventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use servo_util::str::DOMString;
#[deriving(Encodable)]
@ -124,7 +123,7 @@ impl MouseEvent {
typeArg: DOMString,
canBubbleArg: bool,
cancelableArg: bool,
viewArg: Option<JS<WindowProxy>>,
viewArg: Option<JS<Window>>,
detailArg: i32,
screenXArg: i32,
screenYArg: i32,

View file

@ -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;

View file

@ -10,13 +10,14 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, EventTypeId, UIEventTypeId};
use dom::node::Node;
use dom::window::Window;
use dom::windowproxy::WindowProxy;
use servo_util::str::DOMString;
use serialize::{Encoder, Encodable};
#[deriving(Encodable)]
pub struct UIEvent {
event: Event,
view: Option<JS<WindowProxy>>,
view: Option<JS<Window>>,
detail: i32
}
@ -50,7 +51,7 @@ impl UIEvent {
Ok(ev)
}
pub fn GetView(&self) -> Option<JS<WindowProxy>> {
pub fn GetView(&self) -> Option<JS<Window>> {
self.view.clone()
}
@ -62,7 +63,7 @@ impl UIEvent {
type_: DOMString,
can_bubble: bool,
cancelable: bool,
view: Option<JS<WindowProxy>>,
view: Option<JS<Window>>,
detail: i32) {
self.event.InitEvent(type_, can_bubble, cancelable);
self.view = view;

View file

@ -25,7 +25,7 @@ interface HTMLFrameElement : HTMLElement {
[SetterThrows]
attribute boolean noResize;
readonly attribute Document? contentDocument;
readonly attribute WindowProxy? contentWindow;
readonly attribute Window? contentWindow;
[TreatNullAs=EmptyString, SetterThrows] attribute DOMString marginHeight;
[TreatNullAs=EmptyString, SetterThrows] attribute DOMString marginWidth;

View file

@ -27,7 +27,7 @@ interface HTMLIFrameElement : HTMLElement {
[SetterThrows, Pure]
attribute DOMString height;
readonly attribute Document? contentDocument;
readonly attribute WindowProxy? contentWindow;
readonly attribute Window? contentWindow;
};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis

View file

@ -32,7 +32,7 @@ interface HTMLObjectElement : HTMLElement {
// Not pure: can trigger about:blank instantiation
readonly attribute Document? contentDocument;
// Not pure: can trigger about:blank instantiation
readonly attribute WindowProxy? contentWindow;
readonly attribute Window? contentWindow;
readonly attribute boolean willValidate;
readonly attribute ValidityState validity;

View file

@ -26,7 +26,7 @@ interface MouseEvent : UIEvent {
void initMouseEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
WindowProxy? viewArg,
Window? viewArg,
long detailArg,
long screenXArg,
long screenYArg,
@ -56,7 +56,7 @@ dictionary MouseEventInit {
boolean cancelable = false;
// Attributes from UIEvent:
WindowProxy? view = null;
Window? view = null;
long detail = 0;
// Attributes for MouseEvent:

View file

@ -13,12 +13,12 @@
[Constructor(DOMString type, optional UIEventInit eventInitDict)]
interface UIEvent : Event
{
readonly attribute WindowProxy? view;
readonly attribute Window? view;
readonly attribute long detail;
void initUIEvent(DOMString aType,
boolean aCanBubble,
boolean aCancelable,
WindowProxy? aView,
Window? aView,
long aDetail);
};
@ -40,6 +40,6 @@ partial interface UIEvent {
dictionary UIEventInit : EventInit
{
WindowProxy? view = null;
Window? view = null;
long detail = 0;
};

View file

@ -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 Window window;
[Replaceable] readonly attribute Window self;
[Unforgeable] readonly attribute Document document;
attribute DOMString name;
/* [PutForwards=href, Unforgeable] */ readonly attribute Location location;
@ -30,14 +30,14 @@
void blur();
// other browsing contexts
/*[Replaceable] readonly attribute WindowProxy frames;
/*[Replaceable] readonly attribute Window frames;
[Replaceable] readonly attribute unsigned long length;
[Unforgeable] readonly attribute WindowProxy top;
attribute WindowProxy? opener;
readonly attribute WindowProxy parent;*/
[Unforgeable] readonly attribute Window top;
attribute Window? opener;
readonly attribute Window parent;*/
readonly attribute Element? frameElement;
/*WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank", optional DOMString features = "", optional boolean replace = false);
getter WindowProxy (unsigned long index);*/
/*Window open(optional DOMString url = "about:blank", optional DOMString target = "_blank", optional DOMString features = "", optional boolean replace = false);
getter Window (unsigned long index);*/
//getter object (DOMString name);
// the user agent

View file

@ -6,6 +6,7 @@ use dom::bindings::codegen::WindowBinding;
use dom::bindings::js::JS;
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::browsercontext::BrowserContext;
use dom::document::Document;
use dom::element::Element;
use dom::eventtarget::{EventTarget, WindowTypeId};
@ -20,9 +21,8 @@ use servo_net::image_cache_task::ImageCacheTask;
use servo_util::str::DOMString;
use servo_util::task::{spawn_named};
use js::jsapi::{JSContext, JS_DefineProperty, JS_PropertyStub, JS_StrictPropertyStub};
use js::jsval::{NullValue, ObjectValue, JSVal};
use js::JSPROP_ENUMERATE;
use js::jsapi::JSContext;
use js::jsval::{NullValue, JSVal};
use collections::hashmap::HashMap;
use std::cmp;
@ -87,6 +87,7 @@ pub struct Window {
next_timer_handle: i32,
compositor: Untraceable<~ScriptListener>,
timer_chan: Untraceable<Sender<TimerControlMsg>>,
browser_context: Option<BrowserContext>,
page: Rc<Page>,
}
@ -290,6 +291,14 @@ impl Window {
self.ClearTimeout(handle);
}
pub fn Window(&self, abstract_self: &JS<Window>) -> JS<Window> {
abstract_self.clone()
}
pub fn Self(&self, abstract_self: &JS<Window>) -> JS<Window> {
self.Window(abstract_self)
}
pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
// FIXME This should probably be ReflowForQuery, not Display. All queries currently
// currently rely on the display list, which means we can't destroy it by
@ -304,6 +313,10 @@ impl Window {
self.page().join_layout();
}
pub fn init_browser_context(&mut self, doc: &JS<Document>) {
self.browser_context = Some(BrowserContext::new(doc));
}
pub fn new(cx: *JSContext,
page: Rc<Page>,
script_chan: ScriptChan,
@ -335,25 +348,10 @@ impl Window {
navigator: None,
image_cache_task: image_cache_task,
active_timers: ~HashMap::new(),
next_timer_handle: 0
next_timer_handle: 0,
browser_context: None,
};
let global = WindowBinding::Wrap(cx, win);
let fn_names = ["window", "self"];
for str in fn_names.iter() {
(*str).to_c_str().with_ref(|name| {
let object = global.reflector().get_jsobject();
assert!(object.is_not_null());
unsafe {
JS_DefineProperty(cx, object, name,
ObjectValue(&*object),
Some(JS_PropertyStub),
Some(JS_StrictPropertyStub),
JSPROP_ENUMERATE);
}
})
}
global
WindowBinding::Wrap(cx, win)
}
}

View file

@ -1,32 +0,0 @@
/* 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::codegen::WindowProxyBinding;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::window::Window;
#[deriving(Encodable)]
pub struct WindowProxy {
reflector_: Reflector
}
impl WindowProxy {
pub fn new(owner: &JS<Window>) -> JS<WindowProxy> {
let proxy = ~WindowProxy {
reflector_: Reflector::new()
};
reflect_dom_object(proxy, owner, WindowProxyBinding::Wrap)
}
}
impl Reflectable for WindowProxy {
fn reflector<'a>(&'a self) -> &'a Reflector {
&self.reflector_
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
&mut self.reflector_
}
}

View file

@ -59,6 +59,7 @@ pub mod dom {
pub mod attr;
pub mod attrlist;
pub mod blob;
pub mod browsercontext;
pub mod characterdata;
pub mod clientrect;
pub mod clientrectlist;
@ -157,7 +158,6 @@ pub mod dom {
pub mod validitystate;
pub mod virtualmethods;
pub mod window;
pub mod windowproxy;
pub mod testbinding;
}

View file

@ -9,7 +9,7 @@ use dom::bindings::codegen::RegisterBindings;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, ElementCast, EventCast};
use dom::bindings::js::JS;
use dom::bindings::trace::{Traceable, Untraceable};
use dom::bindings::utils::{Reflectable, GlobalStaticData, with_gc_enabled};
use dom::bindings::utils::{Reflectable, GlobalStaticData, with_gc_enabled, wrap_for_same_compartment};
use dom::document::{Document, HTMLDocument};
use dom::element::{Element, AttributeHandlers};
use dom::event::{Event_, ResizeEvent, ReflowEvent, ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
@ -18,7 +18,6 @@ use dom::uievent::UIEvent;
use dom::eventtarget::EventTarget;
use dom::node::{Node, NodeHelpers};
use dom::window::{TimerData, Window};
use dom::windowproxy::WindowProxy;
use html::hubbub_html_parser::HtmlParserResult;
use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript};
use html::hubbub_html_parser;
@ -34,6 +33,7 @@ use geom::point::Point2D;
use geom::size::Size2D;
use js::global::DEBUG_FNS;
use js::jsapi::{JSObject, JS_InhibitGC, JS_AllowGC, JS_CallFunctionValue, JS_DefineFunctions};
use js::jsapi::JS_SetWrapObjectCallbacks;
use js::jsval::NullValue;
use js::rust::{Cx, RtUtils};
use js;
@ -499,6 +499,13 @@ impl ScriptTask {
-> Rc<ScriptTask> {
let js_runtime = js::rust::rt();
unsafe {
JS_SetWrapObjectCallbacks(js_runtime.deref().ptr,
ptr::null(),
wrap_for_same_compartment,
ptr::null());
}
Rc::new(ScriptTask {
page_tree: RefCell::new(PageTree::new(id, layout_chan, window_size)),
@ -785,12 +792,14 @@ impl ScriptTask {
let cx = self.js_runtime.cx();
// Create the window and document objects.
let window = Window::new(cx.deref().ptr,
let mut window = Window::new(cx.deref().ptr,
page_tree.page.clone(),
self.chan.clone(),
self.compositor.dup(),
self.image_cache_task.clone());
page.initialize_js_info(cx.clone(), window.reflector().get_jsobject());
let mut document = Document::new(&window, Some(url.clone()), HTMLDocument, None);
window.get_mut().init_browser_context(&document);
{
let mut js_info = page.mut_js_info();
@ -801,7 +810,6 @@ impl ScriptTask {
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
let mut document = Document::new(&window, Some(url.clone()), HTMLDocument, None);
let html_parsing_result = hubbub_html_parser::parse_html(page,
&mut document,
url.clone(),
@ -958,12 +966,10 @@ impl ScriptTask {
Some(ref frame) => {
// http://dev.w3.org/csswg/cssom-view/#resizing-viewports
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-resize
let window_proxy: JS<WindowProxy> = WindowProxy::new(&frame.window);
let mut uievent = UIEvent::new(&frame.window);
uievent.get_mut().InitUIEvent(~"resize", false, false, Some(window_proxy), 0i32);
uievent.get_mut().InitUIEvent(~"resize", false, false, Some(frame.window.clone()), 0i32);
let event: &mut JS<Event> = &mut EventCast::from(&uievent);
// FIXME: this event should be dispatch on WindowProxy. See #1715
let mut wintarget: JS<EventTarget> = EventTargetCast::from(&frame.window);
let winclone = wintarget.clone();
let _ = wintarget.get_mut().dispatch_event_with_target(&winclone, None, event);

@ -1 +1 @@
Subproject commit 9f0ae0ab33f786c9d2d5e1a9fdfdc6c07fa98033
Subproject commit 70d3c9c7071053a8c497ef4d4fdc24bf95ec9f10