From 9e8cf19e51d5ff1f7c8aa8d5c2f8ccc5d74531ca Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 4 May 2016 18:42:57 -0400 Subject: [PATCH] Add timeline markers for HTTP requests, JS evaluation, and HTML parsing. --- components/net/Cargo.toml | 1 + components/net/http_loader.rs | 26 +++++++---- components/net/lib.rs | 1 + components/net/resource_thread.rs | 12 +++-- components/profile/time.rs | 3 ++ components/profile_traits/time.rs | 3 ++ components/script/dom/bindings/global.rs | 10 +++- components/script/dom/servohtmlparser.rs | 14 ++++++ components/script/dom/window.rs | 54 ++++++++++++++++------ components/script/dom/worker.rs | 1 + components/script/dom/workerglobalscope.rs | 10 +++- components/script/script_thread.rs | 1 + components/servo/Cargo.lock | 2 + components/servo/lib.rs | 4 +- ports/cef/Cargo.lock | 1 + ports/gonk/Cargo.lock | 1 + tests/unit/net/Cargo.toml | 1 + tests/unit/net/lib.rs | 1 + tests/unit/net/resource_thread.rs | 10 ++-- 19 files changed, 126 insertions(+), 30 deletions(-) diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index edab633ab83..2d69776c08d 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -27,6 +27,7 @@ net_traits = {path = "../net_traits"} openssl = "0.7.6" openssl-verify = "0.1" plugins = {path = "../plugins"} +profile_traits = {path = "../profile_traits"} rustc-serialize = "0.3" threadpool = "1.0" time = "0.1.17" diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 41fb9027945..477872f3ef1 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -31,6 +31,8 @@ use net_traits::response::HttpsState; use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData}; use net_traits::{Metadata, NetworkError}; use openssl::ssl::error::{SslError, OpensslError}; +use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata}; +use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType}; use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt, AuthCache, AuthCacheEntry}; use std::borrow::ToOwned; use std::boxed::FnBox; @@ -52,6 +54,7 @@ use uuid; pub fn factory(user_agent: String, http_state: HttpState, devtools_chan: Option>, + profiler_chan: ProfilerChan, connector: Arc>) -> Box { box move |load_data: LoadData, senders, classifier, cancel_listener| { spawn_named(format!("http_loader for {}", load_data.url), move || { - load_for_consumer(load_data, - senders, - classifier, - connector, - http_state, - devtools_chan, - cancel_listener, - user_agent) + let metadata = TimerMetadata { + url: load_data.url.as_str().into(), + iframe: TimerMetadataFrameType::RootWindow, + incremental: TimerMetadataReflowType::FirstReflow, + }; + profile(ProfilerCategory::NetHTTPRequestResponse, Some(metadata), profiler_chan, || { + load_for_consumer(load_data, + senders, + classifier, + connector, + http_state, + devtools_chan, + cancel_listener, + user_agent) + }) }) } } diff --git a/components/net/lib.rs b/components/net/lib.rs index c03dc394e96..91b3066d111 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -31,6 +31,7 @@ extern crate msg; extern crate net_traits; extern crate openssl; extern crate openssl_verify; +extern crate profile_traits; extern crate rustc_serialize; extern crate threadpool; extern crate time; diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index ad7238e2ea3..5f3de8f6f69 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -23,6 +23,7 @@ use net_traits::ProgressMsg::Done; use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResourceThread, ResponseAction}; use net_traits::{ControlMsg, CookieSource, LoadConsumer, LoadData, LoadResponse, ResourceId}; use net_traits::{NetworkError, WebSocketCommunicate, WebSocketConnectData}; +use profile_traits::time::ProfilerChan; use rustc_serialize::json; use rustc_serialize::{Decodable, Encodable}; use std::borrow::ToOwned; @@ -150,13 +151,14 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata, /// Create a ResourceThread pub fn new_resource_thread(user_agent: String, - devtools_chan: Option>) -> ResourceThread { + devtools_chan: Option>, + profiler_chan: ProfilerChan) -> ResourceThread { let hsts_preload = HstsList::from_servo_preload(); let (setup_chan, setup_port) = ipc::channel().unwrap(); let setup_chan_clone = setup_chan.clone(); spawn_named("ResourceManager".to_owned(), move || { let resource_manager = ResourceManager::new( - user_agent, hsts_preload, devtools_chan + user_agent, hsts_preload, devtools_chan, profiler_chan ); let mut channel_manager = ResourceChannelManager { @@ -364,6 +366,7 @@ pub struct ResourceManager { auth_cache: Arc>, mime_classifier: Arc, devtools_chan: Option>, + profiler_chan: ProfilerChan, hsts_list: Arc>, connector: Arc>, cancel_load_map: HashMap>, @@ -373,7 +376,8 @@ pub struct ResourceManager { impl ResourceManager { pub fn new(user_agent: String, mut hsts_list: HstsList, - devtools_channel: Option>) -> ResourceManager { + devtools_channel: Option>, + profiler_chan: ProfilerChan) -> ResourceManager { let mut auth_cache = AuthCache::new(); let mut cookie_jar = CookieStorage::new(); if let Some(ref profile_dir) = opts::get().profile_dir { @@ -387,6 +391,7 @@ impl ResourceManager { auth_cache: Arc::new(RwLock::new(auth_cache)), mime_classifier: Arc::new(MIMEClassifier::new()), devtools_chan: devtools_channel, + profiler_chan: profiler_chan, hsts_list: Arc::new(RwLock::new(hsts_list)), connector: create_http_connector(), cancel_load_map: HashMap::new(), @@ -445,6 +450,7 @@ impl ResourceManager { http_loader::factory(self.user_agent.clone(), http_state, self.devtools_chan.clone(), + self.profiler_chan.clone(), self.connector.clone()) }, "data" => from_factory(data_loader::factory), diff --git a/components/profile/time.rs b/components/profile/time.rs index 3713a048b5b..487b9d8905b 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -122,6 +122,7 @@ impl Formattable for ProfilerCategory { ProfilerCategory::LayoutStoreOverflow => "Store Overflow", ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup", ProfilerCategory::LayoutDispListBuild => "Display List Construction", + ProfilerCategory::NetHTTPRequestResponse => "Network HTTP Request/Response", ProfilerCategory::PaintingPerTile => "Painting Per Tile", ProfilerCategory::PaintingPrepBuff => "Buffer Prep", ProfilerCategory::Painting => "Painting", @@ -132,10 +133,12 @@ impl Formattable for ProfilerCategory { ProfilerCategory::ScriptDevtoolsMsg => "Script Devtools Msg", ProfilerCategory::ScriptDocumentEvent => "Script Document Event", ProfilerCategory::ScriptDomEvent => "Script Dom Event", + ProfilerCategory::ScriptEvaluate => "Script JS Evaluate", ProfilerCategory::ScriptFileRead => "Script File Read", ProfilerCategory::ScriptImageCacheMsg => "Script Image Cache Msg", ProfilerCategory::ScriptInputEvent => "Script Input Event", ProfilerCategory::ScriptNetworkEvent => "Script Network Event", + ProfilerCategory::ScriptParseHTML => "Script Parse HTML", ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation", ProfilerCategory::ScriptResize => "Script Resize", ProfilerCategory::ScriptEvent => "Script Event", diff --git a/components/profile_traits/time.rs b/components/profile_traits/time.rs index 0fe89ac99d3..5d9a95ddd60 100644 --- a/components/profile_traits/time.rs +++ b/components/profile_traits/time.rs @@ -53,6 +53,7 @@ pub enum ProfilerCategory { LayoutStoreOverflow, LayoutParallelWarmup, LayoutDispListBuild, + NetHTTPRequestResponse, PaintingPerTile, PaintingPrepBuff, Painting, @@ -63,11 +64,13 @@ pub enum ProfilerCategory { ScriptDevtoolsMsg, ScriptDocumentEvent, ScriptDomEvent, + ScriptEvaluate, ScriptEvent, ScriptFileRead, ScriptImageCacheMsg, ScriptInputEvent, ScriptNetworkEvent, + ScriptParseHTML, ScriptPlannedNavigation, ScriptResize, ScriptSetViewport, diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index 7dea10fd0a0..8a8aadeaec9 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -20,7 +20,7 @@ use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue}; use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL}; use msg::constellation_msg::{ConstellationChan, PipelineId}; use net_traits::ResourceThread; -use profile_traits::mem; +use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_thread::{MainThreadScriptChan, ScriptThread}; use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest}; @@ -81,6 +81,14 @@ impl<'a> GlobalRef<'a> { } } + /// Get a `time::ProfilerChan` to send messages to the time profiler thread. + pub fn time_profiler_chan(&self) -> &time::ProfilerChan { + match *self { + GlobalRef::Window(window) => window.time_profiler_chan(), + GlobalRef::Worker(worker) => worker.time_profiler_chan(), + } + } + /// Get a `ConstellationChan` to send messages to the constellation channel when available. pub fn constellation_chan(&self) -> &ConstellationChan { match *self { diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 8c12c34ffa1..92658189dc0 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -28,6 +28,8 @@ use msg::constellation_msg::{PipelineId, SubpageId}; use net_traits::{AsyncResponseListener, Metadata, NetworkError}; use network_listener::PreInvoke; use parse::{TrustedParser, ParserRef, Parser}; +use profile_traits::time::ProfilerCategory; +use profile_traits::time::{profile, TimerMetadata, TimerMetadataReflowType, TimerMetadataFrameType}; use script_thread::ScriptThread; use std::cell::Cell; use std::default::Default; @@ -315,6 +317,18 @@ impl ServoHTMLParser { impl ServoHTMLParser { pub fn parse_sync(&self) { + let metadata = TimerMetadata { + url: self.document.url().as_str().into(), + iframe: TimerMetadataFrameType::RootWindow, + incremental: TimerMetadataReflowType::FirstReflow, + }; + profile(ProfilerCategory::ScriptParseHTML, + Some(metadata), + self.document.window().time_profiler_chan().clone(), + || self.do_parse_sync()) + } + + fn do_parse_sync(&self) { // This parser will continue to parse while there is either pending input or // the parser remains unsuspended. loop { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 46e07794dfd..e7d9cbf6057 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -51,6 +51,8 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::storage_thread::{StorageThread, StorageType}; use num_traits::ToPrimitive; use profile_traits::mem; +use profile_traits::time::{ProfilerCategory, TimerMetadata, TimerMetadataFrameType}; +use profile_traits::time::{ProfilerChan, TimerMetadataReflowType, profile}; use reporter::CSSErrorReporter; use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64}; use script_runtime::{ScriptChan, ScriptPort}; @@ -165,6 +167,10 @@ pub struct Window { #[ignore_heap_size_of = "channels are hard"] mem_profiler_chan: mem::ProfilerChan, + /// For sending messages to the memory profiler. + #[ignore_heap_size_of = "channels are hard"] + time_profiler_chan: ProfilerChan, + /// For providing instructions to an optional devtools server. #[ignore_heap_size_of = "channels are hard"] devtools_chan: Option>, @@ -841,21 +847,37 @@ impl<'a, T: Reflectable> ScriptHelpers for &'a T { fn evaluate_script_on_global_with_result(self, code: &str, filename: &str, rval: MutableHandleValue) { let global = self.global(); - 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 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(), 0); - 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, globalhandle.get()); + let _ac = JSAutoCompartment::new(cx, globalhandle.get()); + let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 0); + 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, globalhandle.get()); + } + } } - } + ) } } @@ -1259,6 +1281,10 @@ impl Window { &self.mem_profiler_chan } + pub fn time_profiler_chan(&self) -> &ProfilerChan { + &self.time_profiler_chan + } + pub fn devtools_chan(&self) -> Option> { self.devtools_chan.clone() } @@ -1424,6 +1450,7 @@ impl Window { bluetooth_thread: IpcSender, storage_thread: StorageThread, mem_profiler_chan: mem::ProfilerChan, + time_profiler_chan: ProfilerChan, devtools_chan: Option>, constellation_chan: ConstellationChan, control_chan: IpcSender, @@ -1460,6 +1487,7 @@ impl Window { navigator: Default::default(), image_cache_thread: image_cache_thread, mem_profiler_chan: mem_profiler_chan, + time_profiler_chan: time_profiler_chan, devtools_chan: devtools_chan, browsing_context: Default::default(), performance: Default::default(), diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 1c7fc6def0d..1f66625b7b9 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -102,6 +102,7 @@ impl Worker { let init = WorkerGlobalScopeInit { resource_thread: resource_thread, mem_profiler_chan: global.mem_profiler_chan().clone(), + time_profiler_chan: global.time_profiler_chan().clone(), to_devtools_sender: global.devtools_chan(), from_devtools_sender: optional_sender, constellation_chan: constellation_chan, diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index f518c22890e..c6cbfbe8922 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -23,7 +23,7 @@ use js::jsval::UndefinedValue; use js::rust::Runtime; use msg::constellation_msg::{ConstellationChan, PipelineId}; use net_traits::{LoadContext, ResourceThread, load_whole_resource}; -use profile_traits::mem; +use profile_traits::{mem, time}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort}; use script_traits::ScriptMsg as ConstellationMsg; use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource}; @@ -45,6 +45,7 @@ pub enum WorkerGlobalScopeTypeId { pub struct WorkerGlobalScopeInit { pub resource_thread: ResourceThread, pub mem_profiler_chan: mem::ProfilerChan, + pub time_profiler_chan: time::ProfilerChan, pub to_devtools_sender: Option>, pub from_devtools_sender: Option>, pub constellation_chan: ConstellationChan, @@ -72,6 +73,8 @@ pub struct WorkerGlobalScope { timers: OneshotTimers, #[ignore_heap_size_of = "Defined in std"] mem_profiler_chan: mem::ProfilerChan, + #[ignore_heap_size_of = "Defined in std"] + time_profiler_chan: time::ProfilerChan, #[ignore_heap_size_of = "Defined in ipc-channel"] to_devtools_sender: Option>, @@ -118,6 +121,7 @@ impl WorkerGlobalScope { crypto: Default::default(), timers: OneshotTimers::new(timer_event_chan, init.scheduler_chan.clone()), mem_profiler_chan: init.mem_profiler_chan, + time_profiler_chan: init.time_profiler_chan, to_devtools_sender: init.to_devtools_sender, from_devtools_sender: init.from_devtools_sender, from_devtools_receiver: from_devtools_receiver, @@ -131,6 +135,10 @@ impl WorkerGlobalScope { &self.mem_profiler_chan } + pub fn time_profiler_chan(&self) -> &time::ProfilerChan { + &self.time_profiler_chan + } + pub fn devtools_chan(&self) -> Option> { self.to_devtools_sender.clone() } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 73350bed207..8ebb5ac017b 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1446,6 +1446,7 @@ impl ScriptThread { self.bluetooth_thread.clone(), self.storage_thread.clone(), self.mem_profiler_chan.clone(), + self.time_profiler_chan.clone(), self.devtools_chan.clone(), self.constellation_chan.clone(), self.control_chan.clone(), diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 503a8a4c628..8c8b05f5ed6 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1342,6 +1342,7 @@ dependencies = [ "openssl 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", + "profile_traits 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1379,6 +1380,7 @@ dependencies = [ "net 0.0.1", "net_traits 0.0.1", "plugins 0.0.1", + "profile_traits 0.0.1", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 416be542144..b37222ef199 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -210,7 +210,9 @@ fn create_constellation(opts: opts::Opts, supports_clipboard: bool, webrender_api_sender: Option) -> Sender { let bluetooth_thread: IpcSender = BluetoothThreadFactory::new(); - let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone()); + let resource_thread = new_resource_thread(opts.user_agent.clone(), + devtools_chan.clone(), + time_profiler_chan.clone()); let image_cache_thread = new_image_cache_thread(resource_thread.clone(), webrender_api_sender.as_ref().map(|wr| wr.create_api())); let font_cache_thread = FontCacheThread::new(resource_thread.clone(), diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index f4ce61f2d42..e43f7544323 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -1248,6 +1248,7 @@ dependencies = [ "openssl 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", + "profile_traits 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index c589816ed5b..5830ec85985 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -1240,6 +1240,7 @@ dependencies = [ "openssl 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", + "profile_traits 0.0.1", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/tests/unit/net/Cargo.toml b/tests/unit/net/Cargo.toml index 78d38c9c0e7..9644b7ce883 100644 --- a/tests/unit/net/Cargo.toml +++ b/tests/unit/net/Cargo.toml @@ -14,6 +14,7 @@ net_traits = {path = "../../../components/net_traits"} util = {path = "../../../components/util"} msg = {path = "../../../components/msg"} plugins = {path = "../../../components/plugins"} +profile_traits = {path = "../../../components/profile_traits"} devtools_traits = {path = "../../../components/devtools_traits"} ipc-channel = {git = "https://github.com/servo/ipc-channel"} cookie = "0.2" diff --git a/tests/unit/net/lib.rs b/tests/unit/net/lib.rs index 9a260a6f455..ac06bc1f1c0 100644 --- a/tests/unit/net/lib.rs +++ b/tests/unit/net/lib.rs @@ -13,6 +13,7 @@ extern crate ipc_channel; extern crate msg; extern crate net; extern crate net_traits; +extern crate profile_traits; extern crate time; extern crate unicase; extern crate url; diff --git a/tests/unit/net/resource_thread.rs b/tests/unit/net/resource_thread.rs index 25d455a23a0..941419c3428 100644 --- a/tests/unit/net/resource_thread.rs +++ b/tests/unit/net/resource_thread.rs @@ -6,6 +6,7 @@ use ipc_channel::ipc; use net::resource_thread::new_resource_thread; use net_traits::hosts::{parse_hostsfile, host_replacement}; use net_traits::{ControlMsg, LoadData, LoadConsumer, LoadContext, NetworkError, ProgressMsg}; +use profile_traits::time::ProfilerChan; use std::borrow::ToOwned; use std::collections::HashMap; use std::net::IpAddr; @@ -18,13 +19,15 @@ fn ip(s: &str) -> IpAddr { #[test] fn test_exit() { - let resource_thread = new_resource_thread("".to_owned(), None); + let (tx, _rx) = ipc::channel().unwrap(); + let resource_thread = new_resource_thread("".to_owned(), None, ProfilerChan(tx)); resource_thread.send(ControlMsg::Exit).unwrap(); } #[test] fn test_bad_scheme() { - let resource_thread = new_resource_thread("".to_owned(), None); + let (tx, _rx) = ipc::channel().unwrap(); + let resource_thread = new_resource_thread("".to_owned(), None, ProfilerChan(tx)); let (start_chan, start) = ipc::channel().unwrap(); let url = Url::parse("bogus://whatever").unwrap(); resource_thread.send(ControlMsg::Load(LoadData::new(LoadContext::Browsing, url, None, None, None), @@ -200,7 +203,8 @@ fn test_cancelled_listener() { } }); - let resource_thread = new_resource_thread("".to_owned(), None); + let (tx, _rx) = ipc::channel().unwrap(); + let resource_thread = new_resource_thread("".to_owned(), None, ProfilerChan(tx)); let (sender, receiver) = ipc::channel().unwrap(); let (id_sender, id_receiver) = ipc::channel().unwrap(); let (sync_sender, sync_receiver) = ipc::channel().unwrap();