Skip to content

Commit

Permalink
Implement most of the important WindowProxy traps
Browse files Browse the repository at this point in the history
  • Loading branch information
evilpie committed Jan 12, 2015
1 parent b020a01 commit d54a45a
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 15 deletions.
125 changes: 116 additions & 9 deletions components/script/dom/browsercontext.rs
Expand Up @@ -2,14 +2,27 @@
* 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, JSRef, Temporary};
use dom::bindings::conversions::unwrap_jsmanaged;
use dom::bindings::conversions::{ToJSValConvertible};
use dom::bindings::js::{JS, JSRef, Temporary, Root};
use dom::bindings::js::{OptionalRootable, OptionalRootedRootable, ResultRootable};
use dom::bindings::js::{OptionalRootedReference, OptionalOptionalRootedRootable};
use dom::bindings::proxyhandler::{getPropertyDescriptor, FillPropertyDescriptor};
use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::bindings::utils::{GetArrayIndexFromId};
use dom::document::{Document, DocumentHelpers};
use dom::window::Window;

use js::jsapi::JSObject;
use dom::window::WindowHelpers;

use js::jsapi::{JSContext, JSObject, jsid, JSPropertyDescriptor};
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_DefinePropertyById};
use js::jsapi::{JS_SetPropertyById};
use js::jsval::JSVal;
use js::glue::{GetProxyPrivate};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::rust::with_compartment;
use js::{JSRESOLVE_QUALIFIED, JSRESOLVE_ASSIGNING};

use std::ptr;

Expand Down Expand Up @@ -86,18 +99,112 @@ impl SessionHistoryEntry {
}
}

unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: *mut JSObject, id: jsid) -> Option<Temporary<Window>> {
let index = GetArrayIndexFromId(cx, id);
if let Some(index) = index {
let target = GetProxyPrivate(proxy).to_object();
let win: Root<Window> = unwrap_jsmanaged(target).unwrap().root();
let mut found = false;
return win.r().IndexedGetter(index, &mut found);
}

None
}

unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, set: bool, desc: *mut JSPropertyDescriptor) -> bool {
let window = GetSubframeWindow(cx, proxy, id);
if let Some(window) = window {
let window = window.root();
(*desc).value = window.to_jsval(cx);
FillPropertyDescriptor(&mut *desc, proxy, true);
return true;
}

let target = GetProxyPrivate(proxy).to_object();
let flags = if set { JSRESOLVE_ASSIGNING } else { 0 } | JSRESOLVE_QUALIFIED;
// XXX This should be JS_GetOwnPropertyDescriptorById
if JS_GetPropertyDescriptorById(cx, target, id, flags, desc) == 0 {
return false;
}

if (*desc).obj != target {
// Not an own property
(*desc).obj = ptr::null_mut();
} else {
(*desc).obj = proxy;
}

true
}


unsafe extern fn defineProperty(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, desc: *mut JSPropertyDescriptor) -> bool {
if GetArrayIndexFromId(cx, id).is_some() {
// Spec says to Reject whether this is a supported index or not,
// since we have no indexed setter or indexed creator. That means
// throwing in strict mode (FIXME: Bug 828137), doing nothing in
// non-strict mode.
return true;
}

let target = GetProxyPrivate(proxy).to_object();
JS_DefinePropertyById(cx, target, id, (*desc).value, (*desc).getter,
(*desc).setter, (*desc).attrs) != 0
}

unsafe extern fn hasOwn(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, bp: *mut bool) -> bool {
let window = GetSubframeWindow(cx, proxy, id);
if window.is_some() {
*bp = true;
return true;
}

let target = GetProxyPrivate(proxy).to_object();
let mut found = 0;
if JS_AlreadyHasOwnPropertyById(cx, target, id, &mut found) == 0 {
return false;
}

*bp = found != 0;
return true;
}

unsafe extern fn get(cx: *mut JSContext, proxy: *mut JSObject, receiver: *mut JSObject, id: jsid, vp: *mut JSVal) -> bool {
let window = GetSubframeWindow(cx, proxy, id);
if let Some(window) = window {
let window = window.root();
*vp = window.to_jsval(cx);
return true;
}

let target = GetProxyPrivate(proxy).to_object();
JS_ForwardGetPropertyTo(cx, target, id, receiver, vp) != 0
}

unsafe extern fn set(cx: *mut JSContext, proxy: *mut JSObject, _receiver: *mut JSObject, id: jsid, _strict: bool, vp: *mut JSVal) -> bool {
if GetArrayIndexFromId(cx, id).is_some() {
// Reject (which means throw if and only if strict) the set.
// FIXME: Throw
return true;
}

// FIXME: The receiver should be used, we need something like JS_ForwardSetPropertyTo.
let target = GetProxyPrivate(proxy).to_object();
JS_SetPropertyById(cx, target, id, vp) != 0
}

static PROXY_HANDLER: ProxyTraps = ProxyTraps {
getPropertyDescriptor: None,
getOwnPropertyDescriptor: None,
defineProperty: None,
getPropertyDescriptor: Some(getPropertyDescriptor),
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
defineProperty: Some(defineProperty),
getOwnPropertyNames: None,
delete_: None,
enumerate: None,

has: None,
hasOwn: None,
get: None,
set: None,
hasOwn: Some(hasOwn),
get: Some(get),
set: Some(set),
keys: None,
iterate: None,

Expand Down
7 changes: 6 additions & 1 deletion components/script/dom/window.rs
Expand Up @@ -311,12 +311,12 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
}
}


pub trait WindowHelpers {
fn flush_layout(self, goal: ReflowGoal, query: ReflowQueryType);
fn init_browser_context(self, doc: JSRef<Document>);
fn load_url(self, href: DOMString);
fn handle_fire_timer(self, timer_id: TimerId);
fn IndexedGetter(self, _index: u32, _found: &mut bool) -> Option<Temporary<Window>>;
}

pub trait ScriptHelpers {
Expand Down Expand Up @@ -378,6 +378,11 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
self.timers.fire_timer(timer_id, self);
self.flush_layout(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery);
}

// https://html.spec.whatwg.org/multipage/browsers.html#accessing-other-browsing-contexts
fn IndexedGetter(self, _index: u32, _found: &mut bool) -> Option<Temporary<Window>> {
None
}
}

impl Window {
Expand Down
2 changes: 1 addition & 1 deletion components/script/lib.rs
Expand Up @@ -62,7 +62,7 @@ pub mod dom {
pub mod callback;
pub mod error;
pub mod conversions;
mod proxyhandler;
pub mod proxyhandler;
pub mod str;
pub mod structuredclone;
pub mod trace;
Expand Down
23 changes: 23 additions & 0 deletions tests/content/test_windowproxy.html
@@ -0,0 +1,23 @@
<html>
<head id="foo">
<script src="harness.js"></script>
</head>
<body>
<div></div>
<script>
window.abcd = 15;
is(window.abcd, 15);
is(Object.getOwnPropertyDescriptor(window, 'abcd').value, 15);
is(window.hasOwnProperty('abcd'), true);

is('location' in window, true);
// FIXME: https://github.com/servo/servo/issues/4593
is(Object.hasOwnProperty('location'), false)

// Can't set indexed properties
window[100] = "abc";
is(window[100], undefined);
is(Object.getOwnPropertyDescriptor(window, 1000), undefined);
</script>
</body>
</html>
Expand Up @@ -2,7 +2,3 @@
type: testharness
[Indexed properties of the window object (non-strict mode) 1]
expected: FAIL

[Indexed properties of the window object (non-strict mode) 2]
expected: FAIL

5 comments on commit d54a45a

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from jdm
at evilpie@d54a45a

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging evilpie/servo/window-proxy = d54a45a into auto

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

evilpie/servo/window-proxy = d54a45a merged ok, testing candidate = a227faa

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = a227faa

Please sign in to comment.