Skip to content

Commit

Permalink
auto merge of #3941 : mukilan/servo/timeout-arguments, r=Ms2ger
Browse files Browse the repository at this point in the history
  • Loading branch information
bors-servo committed Nov 15, 2014
2 parents 443b1b9 + 4b2b0d0 commit 4901c72
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 376 deletions.
407 changes: 76 additions & 331 deletions components/script/dom/bindings/codegen/CodegenRust.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/script/dom/dedicatedworkerglobalscope.rs
Expand Up @@ -146,7 +146,7 @@ impl DedicatedWorkerGlobalScope {
Worker::handle_release(addr)
},
Ok(FireTimerMsg(FromWorker, timer_id)) => {
scope.handle_fire_timer(timer_id, js_context.ptr);
scope.handle_fire_timer(timer_id);
}
Ok(_) => panic!("Unexpected message"),
Err(_) => break,
Expand Down
12 changes: 12 additions & 0 deletions components/script/dom/testbinding.rs
Expand Up @@ -5,6 +5,8 @@
use dom::bindings::codegen::Bindings::TestBindingBinding::TestBindingMethods;
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnum;
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnumValues::_empty;
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::UnionTypes::BlobOrString::BlobOrString;
use dom::bindings::codegen::UnionTypes::EventOrString::{EventOrString, eString};
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::{HTMLElementOrLong, eLong};
Expand Down Expand Up @@ -164,6 +166,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn PassUnion2(self, _: EventOrString) {}
fn PassUnion3(self, _: BlobOrString) {}
fn PassAny(self, _: *mut JSContext, _: JSVal) {}
fn PassCallbackFunction(self, _: Function) {}
fn PassCallbackInterface(self, _: EventListener) {}

fn PassNullableBoolean(self, _: Option<bool>) {}
fn PassNullableByte(self, _: Option<i8>) {}
Expand All @@ -182,6 +186,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn PassNullableInterface(self, _: Option<JSRef<Blob>>) {}
fn PassNullableUnion(self, _: Option<HTMLElementOrLong>) {}
fn PassNullableUnion2(self, _: Option<EventOrString>) {}
fn PassNullableCallbackFunction(self, _: Option<Function>) {}
fn PassNullableCallbackInterface(self, _: Option<EventListener>) {}

fn PassOptionalBoolean(self, _: Option<bool>) {}
fn PassOptionalByte(self, _: Option<i8>) {}
Expand All @@ -201,6 +207,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn PassOptionalUnion(self, _: Option<HTMLElementOrLong>) {}
fn PassOptionalUnion2(self, _: Option<EventOrString>) {}
fn PassOptionalAny(self, _: *mut JSContext, _: JSVal) {}
fn PassOptionalCallbackFunction(self, _: Option<Function>) {}
fn PassOptionalCallbackInterface(self, _: Option<EventListener>) {}

fn PassOptionalNullableBoolean(self, _: Option<Option<bool>>) {}
fn PassOptionalNullableByte(self, _: Option<Option<i8>>) {}
Expand All @@ -219,6 +227,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn PassOptionalNullableInterface(self, _: Option<Option<JSRef<Blob>>>) {}
fn PassOptionalNullableUnion(self, _: Option<Option<HTMLElementOrLong>>) {}
fn PassOptionalNullableUnion2(self, _: Option<Option<EventOrString>>) {}
fn PassOptionalNullableCallbackFunction(self, _: Option<Option<Function>>) {}
fn PassOptionalNullableCallbackInterface(self, _: Option<Option<EventListener>>) {}

fn PassOptionalBooleanWithDefault(self, _: bool) {}
fn PassOptionalByteWithDefault(self, _: i8) {}
Expand Down Expand Up @@ -249,6 +259,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
fn PassOptionalNullableInterfaceWithDefault(self, _: Option<JSRef<Blob>>) {}
fn PassOptionalNullableUnionWithDefault(self, _: Option<HTMLElementOrLong>) {}
fn PassOptionalNullableUnion2WithDefault(self, _: Option<EventOrString>) {}
// fn PassOptionalNullableCallbackFunctionWithDefault(self, _: Option<Function>) {}
fn PassOptionalNullableCallbackInterfaceWithDefault(self, _: Option<EventListener>) {}
fn PassOptionalAnyWithDefault(self, _: *mut JSContext, _: JSVal) {}

fn PassOptionalNullableBooleanWithNonNullDefault(self, _: Option<bool>) {}
Expand Down
14 changes: 14 additions & 0 deletions components/script/dom/webidls/Function.webidl
@@ -0,0 +1,14 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* http://www.whatwg.org/specs/web-apps/current-work/#functiocn
*
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
* Opera Software ASA. You are granted a license to use, reproduce
* and create derivative works of this document.
*/

callback Function = any(any... arguments);
10 changes: 10 additions & 0 deletions components/script/dom/webidls/TestBinding.webidl
Expand Up @@ -148,6 +148,8 @@ interface TestBinding {
void passUnion2((Event or DOMString) data);
void passUnion3((Blob or DOMString) data);
void passAny(any arg);
void passCallbackFunction(Function fun);
void passCallbackInterface(EventListener listener);

void passNullableBoolean(boolean? arg);
void passNullableByte(byte? arg);
Expand All @@ -166,6 +168,8 @@ interface TestBinding {
void passNullableInterface(Blob? arg);
void passNullableUnion((HTMLElement or long)? arg);
void passNullableUnion2((Event or DOMString)? data);
void passNullableCallbackFunction(Function? fun);
void passNullableCallbackInterface(EventListener? listener);

void passOptionalBoolean(optional boolean arg);
void passOptionalByte(optional byte arg);
Expand All @@ -185,6 +189,8 @@ interface TestBinding {
void passOptionalUnion(optional (HTMLElement or long) arg);
void passOptionalUnion2(optional (Event or DOMString) data);
void passOptionalAny(optional any arg);
void passOptionalCallbackFunction(optional Function fun);
void passOptionalCallbackInterface(optional EventListener listener);

void passOptionalNullableBoolean(optional boolean? arg);
void passOptionalNullableByte(optional byte? arg);
Expand All @@ -203,6 +209,8 @@ interface TestBinding {
void passOptionalNullableInterface(optional Blob? arg);
void passOptionalNullableUnion(optional (HTMLElement or long)? arg);
void passOptionalNullableUnion2(optional (Event or DOMString)? data);
void passOptionalNullableCallbackFunction(optional Function? fun);
void passOptionalNullableCallbackInterface(optional EventListener? listener);

void passOptionalBooleanWithDefault(optional boolean arg = false);
void passOptionalByteWithDefault(optional byte arg = 0);
Expand Down Expand Up @@ -233,6 +241,8 @@ interface TestBinding {
void passOptionalNullableInterfaceWithDefault(optional Blob? arg = null);
void passOptionalNullableUnionWithDefault(optional (HTMLElement or long)? arg = null);
void passOptionalNullableUnion2WithDefault(optional (Event or DOMString)? data = null);
// void passOptionalNullableCallbackFunctionWithDefault(optional Function? fun = null);
void passOptionalNullableCallbackInterfaceWithDefault(optional EventListener? listener = null);
void passOptionalAnyWithDefault(optional any arg = null);

void passOptionalNullableBooleanWithNonNullDefault(optional boolean? arg = false);
Expand Down
6 changes: 2 additions & 4 deletions components/script/dom/webidls/Window.webidl
Expand Up @@ -64,13 +64,11 @@ Window implements WindowEventHandlers;
// http://www.whatwg.org/html/#windowtimers
[NoInterfaceObject/*, Exposed=Window,Worker*/]
interface WindowTimers {
//long setTimeout(Function handler, optional long timeout = 0, any... arguments);
long setTimeout(Function handler, optional long timeout = 0, any... arguments);
//long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
long setTimeout(any handler, optional long timeout = 0);
void clearTimeout(optional long handle = 0);
//long setInterval(Function handler, optional long timeout = 0, any... arguments);
long setInterval(Function handler, optional long timeout = 0, any... arguments);
//long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
long setInterval(any handler, optional long timeout = 0);
void clearInterval(optional long handle = 0);
};
Window implements WindowTimers;
Expand Down
14 changes: 8 additions & 6 deletions components/script/dom/window.rs
Expand Up @@ -4,6 +4,7 @@

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::codegen::Bindings::WindowBinding;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
Expand Down Expand Up @@ -223,8 +224,9 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
self.navigator.get().unwrap()
}

fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
fn SetTimeout(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
self.timers.set_timeout_or_interval(callback,
args,
timeout,
false, // is_interval
FromWindow(self.page.id.clone()),
Expand All @@ -235,8 +237,9 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
self.timers.clear_timeout_or_interval(handle);
}

fn SetInterval(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
fn SetInterval(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
self.timers.set_timeout_or_interval(callback,
args,
timeout,
true, // is_interval
FromWindow(self.page.id.clone()),
Expand Down Expand Up @@ -317,7 +320,7 @@ pub trait WindowHelpers {
fn wait_until_safe_to_modify_dom(self);
fn init_browser_context(self, doc: JSRef<Document>);
fn load_url(self, href: DOMString);
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
fn handle_fire_timer(self, timer_id: TimerId);
fn evaluate_js_with_result(self, code: &str) -> JSVal;
fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal;
}
Expand Down Expand Up @@ -380,9 +383,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
}
}

fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
let this_value = self.reflector().get_jsobject();
self.timers.fire_timer(timer_id, this_value, cx);
fn handle_fire_timer(self, timer_id: TimerId) {
self.timers.fire_timer(timer_id, self.clone());
self.flush_layout();
}
}
Expand Down
18 changes: 10 additions & 8 deletions components/script/dom/workerglobalscope.rs
Expand Up @@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
Expand Down Expand Up @@ -155,8 +156,9 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
base64_atob(atob)
}

fn SetTimeout(self, _cx: *mut JSContext, handler: JSVal, timeout: i32) -> i32 {
self.timers.set_timeout_or_interval(handler,
fn SetTimeout(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
self.timers.set_timeout_or_interval(callback,
args,
timeout,
false, // is_interval
FromWorker,
Expand All @@ -167,8 +169,9 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
self.timers.clear_timeout_or_interval(handle);
}

fn SetInterval(self, _cx: *mut JSContext, handler: JSVal, timeout: i32) -> i32 {
self.timers.set_timeout_or_interval(handler,
fn SetInterval(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
self.timers.set_timeout_or_interval(callback,
args,
timeout,
true, // is_interval
FromWorker,
Expand All @@ -181,14 +184,13 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
}

pub trait WorkerGlobalScopeHelpers {
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
fn handle_fire_timer(self, timer_id: TimerId);
}

impl<'a> WorkerGlobalScopeHelpers for JSRef<'a, WorkerGlobalScope> {

fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
let this_value = self.reflector().get_jsobject();
self.timers.fire_timer(timer_id, this_value, cx);
fn handle_fire_timer(self, timer_id: TimerId) {
self.timers.fire_timer(timer_id, self.clone());
}

}
Expand Down
2 changes: 1 addition & 1 deletion components/script/script_task.rs
Expand Up @@ -665,7 +665,7 @@ impl ScriptTask {
pipeline ID not associated with this script task. This is a bug.");
let frame = page.frame();
let window = frame.as_ref().unwrap().window.root();
window.handle_fire_timer(timer_id, self.get_cx());
window.handle_fire_timer(timer_id);
}

/// Handles a notification that reflow completed.
Expand Down
33 changes: 16 additions & 17 deletions components/script/timers.rs
Expand Up @@ -3,16 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::callback::ReportExceptions;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable;

use script_task::{FireTimerMsg, ScriptChan};
use script_task::{TimerSource, FromWindow, FromWorker};

use servo_util::task::spawn_named;

use js::jsapi::JS_CallFunctionValue;
use js::jsapi::{JSContext, JSObject};
use js::jsval::{JSVal, NullValue};
use js::rust::with_compartment;
use js::jsval::JSVal;

use std::cell::Cell;
use std::cmp;
Expand All @@ -21,7 +22,6 @@ use std::comm::{channel, Sender};
use std::comm::Select;
use std::hash::{Hash, sip};
use std::io::timer::Timer;
use std::ptr;
use std::time::duration::Duration;

#[deriving(PartialEq, Eq)]
Expand Down Expand Up @@ -69,11 +69,14 @@ impl Drop for TimerManager {
// Holder for the various JS values associated with setTimeout
// (ie. function value to invoke and all arguments to pass
// to the function when calling it)
// TODO: Handle rooting during fire_timer when movable GC is turned on
#[jstraceable]
#[privatize]
#[deriving(Clone)]
struct TimerData {
is_interval: bool,
funval: JSVal,
funval: Function,
args: Vec<JSVal>
}

impl TimerManager {
Expand All @@ -85,7 +88,8 @@ impl TimerManager {
}

pub fn set_timeout_or_interval(&self,
callback: JSVal,
callback: Function,
arguments: Vec<JSVal>,
timeout: i32,
is_interval: bool,
source: TimerSource,
Expand Down Expand Up @@ -142,6 +146,7 @@ impl TimerManager {
data: TimerData {
is_interval: is_interval,
funval: callback,
args: arguments
}
};
self.active_timers.borrow_mut().insert(timer_id, timer);
Expand All @@ -156,21 +161,15 @@ impl TimerManager {
}
}

pub fn fire_timer(&self, timer_id: TimerId, this: *mut JSObject, cx: *mut JSContext) {
pub fn fire_timer<T: Reflectable>(&self, timer_id: TimerId, this: JSRef<T>) {

let data = match self.active_timers.borrow().get(&timer_id) {
None => return,
Some(timer_handle) => timer_handle.data,
Some(timer_handle) => timer_handle.data.clone(),
};

// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
with_compartment(cx, this, || {
let mut rval = NullValue();
unsafe {
JS_CallFunctionValue(cx, this, data.funval,
0, ptr::null_mut(), &mut rval);
}
});
// TODO: Must handle rooting of funval and args when movable GC is turned on
let _ = data.funval.Call_(this, data.args, ReportExceptions);

if !data.is_interval {
self.active_timers.borrow_mut().remove(&timer_id);
Expand Down
24 changes: 24 additions & 0 deletions tests/wpt/metadata/html/dom/interfaces.html.ini
Expand Up @@ -9948,3 +9948,27 @@
[HTMLFontElement interface: document.createElement("font") must inherit property "size" with the proper type (2)]
expected: FAIL
[Window interface: operation setTimeout(Function,long,any)]
expected: FAIL
[Window interface: operation setTimeout(DOMString,long,any)]
expected: FAIL
[Window interface: operation setInterval(Function,long,any)]
expected: FAIL
[Window interface: operation setInterval(DOMString,long,any)]
expected: FAIL
[WorkerGlobalScope interface: operation setTimeout(Function,long,any)]
expected: FAIL
[WorkerGlobalScope interface: operation setTimeout(DOMString,long,any)]
expected: FAIL
[WorkerGlobalScope interface: operation setInterval(Function,long,any)]
expected: FAIL
[WorkerGlobalScope interface: operation setInterval(DOMString,long,any)]
expected: FAIL
@@ -1,8 +1,9 @@
[compile-error-in-setInterval.html]
type: testharness
expected: TIMEOUT
[window.onerror - compile error in setInterval]
expected: FAIL
expected: NOTRUN

[window.onerror - compile error in setInterval (column)]
expected: FAIL
expected: NOTRUN

@@ -1,8 +1,9 @@
[compile-error-in-setTimeout.html]
type: testharness
expected: TIMEOUT
[window.onerror - compile error in setTimeout]
expected: FAIL
expected: NOTRUN

[window.onerror - compile error in setTimeout (column)]
expected: FAIL
expected: NOTRUN

0 comments on commit 4901c72

Please sign in to comment.