diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 0bc978f2088..5d679cce2e9 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -10,24 +10,29 @@ use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId}; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::root_from_object; -use dom::bindings::error::ErrorInfo; +use dom::bindings::error::{ErrorInfo, report_pending_exception}; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflectable, Reflector}; use dom::console::TimerSet; -use dom::window::{self, ScriptHelpers}; +use dom::window; use dom::workerglobalscope::WorkerGlobalScope; use ipc_channel::ipc::IpcSender; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use js::glue::{IsWrapper, UnwrapObject}; -use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment}; -use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue}; -use js::jsapi::HandleValue; +use js::jsapi::{CurrentGlobalOrNull, Evaluate2, GetGlobalForObjectCrossCompartment}; +use js::jsapi::{HandleValue, JS_GetClass, JSAutoCompartment, JSContext}; +use js::jsapi::{JSObject, MutableHandleValue}; +use js::rust::CompileOptionsWrapper; +use libc; use msg::constellation_msg::PipelineId; use net_traits::{CoreResourceThread, IpcSend, ResourceThreads}; use profile_traits::{mem, time}; -use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, EnqueuedPromiseCallback}; +use script_runtime::{CommonScriptMsg, EnqueuedPromiseCallback, ScriptChan}; +use script_runtime::{ScriptPort, maybe_take_panic_result}; use script_thread::{MainThreadScriptChan, RunnableWrapper, ScriptThread}; use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest}; +use std::ffi::CString; +use std::panic; use task_source::file_reading::FileReadingTaskSource; use timers::{OneshotTimerCallback, OneshotTimerHandle}; use url::Url; @@ -217,12 +222,51 @@ impl<'a> GlobalRef<'a> { } } - /// Evaluate the JS messages on the `RootedValue` of this global - pub fn evaluate_js_on_global_with_result(&self, code: &str, rval: MutableHandleValue) { - match *self { - GlobalRef::Window(window) => window.evaluate_js_on_global_with_result(code, rval), - GlobalRef::Worker(worker) => worker.evaluate_js_on_global_with_result(code, rval), - } + /// Evaluate JS code on this global. + pub fn evaluate_js_on_global_with_result( + &self, code: &str, rval: MutableHandleValue) { + self.evaluate_script_on_global_with_result(code, "", rval) + } + + /// Evaluate a JS script on this global. + #[allow(unsafe_code)] + pub fn evaluate_script_on_global_with_result( + &self, code: &str, filename: &str, rval: MutableHandleValue) { + let metadata = time::TimerMetadata { + url: if filename.is_empty() { + self.get_url().as_str().into() + } else { + filename.into() + }, + iframe: time::TimerMetadataFrameType::RootWindow, + incremental: time::TimerMetadataReflowType::FirstReflow, + }; + time::profile( + time::ProfilerCategory::ScriptEvaluate, + Some(metadata), + self.time_profiler_chan().clone(), + || { + let cx = self.get_cx(); + let globalhandle = self.reflector().get_jsobject(); + let code: Vec = code.encode_utf16().collect(); + let filename = CString::new(filename).unwrap(); + + let _ac = JSAutoCompartment::new(cx, globalhandle.get()); + let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 1); + unsafe { + if !Evaluate2(cx, options.ptr, code.as_ptr(), + code.len() as libc::size_t, + rval) { + debug!("error evaluating JS string"); + report_pending_exception(cx, true); + } + } + + if let Some(error) = maybe_take_panic_result() { + panic::resume_unwind(error); + } + } + ) } /// Set the `bool` value to indicate whether developer tools has requested diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 15df6ee4e33..ed550309a3c 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -25,7 +25,6 @@ use dom::htmlelement::HTMLElement; use dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use dom::node::{document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; -use dom::window::ScriptHelpers; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncodingRef}; use html5ever::tree_builder::NextParserState; @@ -507,9 +506,8 @@ impl HTMLScriptElement { // Step 5.a.2. let window = window_from_node(self); rooted!(in(window.get_cx()) let mut rval = UndefinedValue()); - window.evaluate_script_on_global_with_result(&script.text, - script.url.as_str(), - rval.handle_mut()); + GlobalRef::Window(&window).evaluate_script_on_global_with_result( + &script.text, script.url.as_str(), rval.handle_mut()); // Step 6. document.set_current_script(old_script.r()); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 10d47f161be..3ac5c4e37f9 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -16,7 +16,7 @@ use dom::bindings::codegen::Bindings::RequestBinding::RequestInit; use dom::bindings::codegen::Bindings::WindowBinding::{self, FrameRequestCallback, WindowMethods}; use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; use dom::bindings::codegen::UnionTypes::RequestOrUSVString; -use dom::bindings::error::{Error, ErrorInfo, ErrorResult, Fallible, report_pending_exception}; +use dom::bindings::error::{Error, ErrorInfo, ErrorResult, Fallible}; use dom::bindings::global::{GlobalRef, global_root_from_object}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap, Root}; @@ -49,12 +49,10 @@ use euclid::{Point2D, Rect, Size2D}; use fetch; use gfx_traits::LayerId; use ipc_channel::ipc::{self, IpcSender}; -use js::jsapi::{Evaluate2, HandleObject, HandleValue, JSAutoCompartment, JSContext}; -use js::jsapi::{JS_GC, JS_GetRuntime, MutableHandleValue, SetWindowProxy}; +use js::jsapi::{HandleObject, HandleValue, JSAutoCompartment, JSContext}; +use js::jsapi::{JS_GC, JS_GetRuntime, SetWindowProxy}; use js::jsval::UndefinedValue; -use js::rust::CompileOptionsWrapper; use js::rust::Runtime; -use libc; use msg::constellation_msg::{FrameType, LoadData, PipelineId, ReferrerPolicy, WindowSizeType}; use net_traits::ResourceThreads; use net_traits::bluetooth_thread::BluetoothMethodMsg; @@ -64,15 +62,14 @@ use num_traits::ToPrimitive; use open; use origin::Origin; use profile_traits::mem; -use profile_traits::time::{ProfilerCategory, TimerMetadata, TimerMetadataFrameType}; -use profile_traits::time::{ProfilerChan, TimerMetadataReflowType, profile}; +use profile_traits::time::ProfilerChan; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use script_layout_interface::TrustedNodeAddress; use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflow}; use script_layout_interface::reporter::CSSErrorReporter; use script_layout_interface::rpc::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC}; use script_layout_interface::rpc::{MarginStyleResponse, ResolvedStyleResponse}; -use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory, maybe_take_panic_result}; +use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptThreadEventCategory}; use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, Runnable, RunnableWrapper}; use script_thread::SendableMainThreadScriptChan; use script_traits::{ConstellationControlMsg, MozBrowserEvent, UntrustedNodeAddress}; @@ -84,9 +81,7 @@ use std::borrow::ToOwned; use std::cell::Cell; use std::collections::{HashMap, HashSet}; use std::default::Default; -use std::ffi::CString; use std::io::{Write, stderr, stdout}; -use std::panic; use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -913,61 +908,6 @@ impl WindowMethods for Window { } } -pub trait ScriptHelpers { - fn evaluate_js_on_global_with_result(self, code: &str, - rval: MutableHandleValue); - fn evaluate_script_on_global_with_result(self, code: &str, filename: &str, - rval: MutableHandleValue); -} - -impl<'a, T: Reflectable> ScriptHelpers for &'a T { - fn evaluate_js_on_global_with_result(self, code: &str, - rval: MutableHandleValue) { - self.evaluate_script_on_global_with_result(code, "", rval) - } - - #[allow(unsafe_code)] - fn evaluate_script_on_global_with_result(self, code: &str, filename: &str, - rval: MutableHandleValue) { - let global = self.global(); - let metadata = TimerMetadata { - url: if filename.is_empty() { - global.r().get_url().as_str().into() - } else { - filename.into() - }, - iframe: TimerMetadataFrameType::RootWindow, - incremental: TimerMetadataReflowType::FirstReflow, - }; - profile( - ProfilerCategory::ScriptEvaluate, - Some(metadata), - global.r().time_profiler_chan().clone(), - || { - let cx = global.r().get_cx(); - let globalhandle = global.r().reflector().get_jsobject(); - let code: Vec = code.encode_utf16().collect(); - let filename = CString::new(filename).unwrap(); - - let _ac = JSAutoCompartment::new(cx, globalhandle.get()); - let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 1); - unsafe { - if !Evaluate2(cx, options.ptr, code.as_ptr(), - code.len() as libc::size_t, - rval) { - debug!("error evaluating JS string"); - report_pending_exception(cx, true); - } - } - - if let Some(error) = maybe_take_panic_result() { - panic::resume_unwind(error); - } - } - ) - } -} - impl Window { pub fn get_runnable_wrapper(&self) -> RunnableWrapper { RunnableWrapper { diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index f1878501500..282fd90a08b 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -46,7 +46,7 @@ use dom::serviceworker::TrustedServiceWorkerAddress; use dom::serviceworkerregistration::ServiceWorkerRegistration; use dom::servohtmlparser::ParserContext; use dom::uievent::UIEvent; -use dom::window::{ReflowReason, ScriptHelpers, Window}; +use dom::window::{ReflowReason, Window}; use dom::worker::TrustedWorkerAddress; use euclid::Rect; use euclid::point::Point2D; @@ -1775,7 +1775,8 @@ impl ScriptThread { unsafe { let _ac = JSAutoCompartment::new(self.get_cx(), window.reflector().get_jsobject().get()); rooted!(in(self.get_cx()) let mut jsval = UndefinedValue()); - window.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut()); + GlobalRef::Window(&window).evaluate_js_on_global_with_result( + &script_source, jsval.handle_mut()); let strval = DOMString::from_jsval(self.get_cx(), jsval.handle(), StringificationBehavior::Empty); diff --git a/components/script/timers.rs b/components/script/timers.rs index f75ebf907d5..601755c6fc4 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -9,7 +9,6 @@ use dom::bindings::global::GlobalRef; use dom::bindings::reflector::Reflectable; use dom::bindings::str::DOMString; use dom::testbinding::TestBindingCallback; -use dom::window::ScriptHelpers; use dom::xmlhttprequest::XHRTimeoutCallback; use euclid::length::Length; use heapsize::HeapSizeOf; @@ -490,10 +489,12 @@ impl JsTimerTask { // step 4.2 match *&self.callback { InternalTimerCallback::StringTimerCallback(ref code_str) => { - let cx = this.global().r().get_cx(); + let global = this.global(); + let cx = global.r().get_cx(); rooted!(in(cx) let mut rval = UndefinedValue()); - this.evaluate_js_on_global_with_result(code_str, rval.handle_mut()); + global.r().evaluate_js_on_global_with_result( + code_str, rval.handle_mut()); }, InternalTimerCallback::FunctionTimerCallback(ref function, ref arguments) => { let arguments: Vec = arguments.iter().map(|arg| arg.get()).collect(); diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index b4e80bddac7..03281464765 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -13,6 +13,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior}; +use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::str::DOMString; @@ -23,7 +24,6 @@ use dom::htmliframeelement::HTMLIFrameElement; use dom::htmlinputelement::HTMLInputElement; use dom::htmloptionelement::HTMLOptionElement; use dom::node::Node; -use dom::window::ScriptHelpers; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; @@ -92,7 +92,8 @@ pub fn handle_execute_script(context: &BrowsingContext, let result = unsafe { let cx = window.get_cx(); rooted!(in(cx) let mut rval = UndefinedValue()); - window.evaluate_js_on_global_with_result(&eval, rval.handle_mut()); + GlobalRef::Window(&window).evaluate_js_on_global_with_result( + &eval, rval.handle_mut()); jsval_to_webdriver(cx, rval.handle()) }; reply.send(result).unwrap(); @@ -111,7 +112,8 @@ pub fn handle_execute_async_script(context: &BrowsingContext, let cx = window.get_cx(); window.set_webdriver_script_chan(Some(reply)); rooted!(in(cx) let mut rval = UndefinedValue()); - window.evaluate_js_on_global_with_result(&eval, rval.handle_mut()); + GlobalRef::Window(&window).evaluate_js_on_global_with_result( + &eval, rval.handle_mut()); } pub fn handle_get_frame_id(context: &BrowsingContext,