auto merge of #4594 : evilpie/servo/window-proxy, r=jdm

After this patch somebody just needs to implement the new IndexedGetter (and probably frames/length) on window to fix #4589.
This commit is contained in:
bors-servo 2015-01-12 09:45:47 -07:00
commit a227faa416
5 changed files with 145 additions and 14 deletions

View file

@ -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 dom::window::WindowHelpers;
use js::jsapi::JSObject;
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;
@ -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,

View file

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

View file

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

View file

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

View file

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