aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/global.rs31
-rw-r--r--components/script/dom/bindings/trace.rs2
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs38
-rw-r--r--components/script/dom/webidls/Worker.webidl2
-rw-r--r--components/script/dom/worker.rs78
-rw-r--r--components/script/dom/workerglobalscope.rs29
-rw-r--r--tests/html/worker/worker_post_block.js9
-rw-r--r--tests/html/worker/worker_post_interval.js6
-rw-r--r--tests/html/worker/worker_terminate.html48
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini3
-rw-r--r--tests/wpt/metadata/workers/Worker_terminate_event_queue.htm.ini3
-rw-r--r--tests/wpt/metadata/workers/constructors/Worker/terminate.html.ini5
-rw-r--r--tests/wpt/metadata/workers/nested_worker.worker.js.ini9
13 files changed, 216 insertions, 47 deletions
diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs
index 8cb8c54b426..9cac7d9b940 100644
--- a/components/script/dom/bindings/global.rs
+++ b/components/script/dom/bindings/global.rs
@@ -15,7 +15,7 @@ use dom::bindings::reflector::{Reflectable, Reflector};
use dom::window::{self, ScriptHelpers};
use dom::workerglobalscope::WorkerGlobalScope;
use ipc_channel::ipc::IpcSender;
-use js::jsapi::GetGlobalForObjectCrossCompartment;
+use js::jsapi::{CurrentGlobalOrNull, GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{ConstellationChan, PipelineId};
@@ -147,9 +147,8 @@ impl<'a> GlobalRef<'a> {
/// thread.
pub fn script_chan(&self) -> Box<ScriptChan + Send> {
match *self {
- GlobalRef::Window(ref window) => {
- MainThreadScriptChan(window.main_thread_script_chan().clone()).clone()
- }
+ GlobalRef::Window(ref window) =>
+ MainThreadScriptChan(window.main_thread_script_chan().clone()).clone(),
GlobalRef::Worker(ref worker) => worker.script_chan(),
}
}
@@ -280,11 +279,10 @@ pub fn global_root_from_reflector<T: Reflectable>(reflector: &T) -> GlobalRoot {
global_root_from_object(*reflector.reflector().get_jsobject())
}
-/// Returns the global object of the realm that the given JS object was created in.
+/// Returns the Rust global object from a JS global object.
#[allow(unrooted_must_root)]
-pub fn global_root_from_object(obj: *mut JSObject) -> GlobalRoot {
+pub fn global_root_from_global(global: *mut JSObject) -> GlobalRoot {
unsafe {
- let global = GetGlobalForObjectCrossCompartment(obj);
let clasp = JS_GetClass(global);
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
match root_from_object(global) {
@@ -300,3 +298,22 @@ pub fn global_root_from_object(obj: *mut JSObject) -> GlobalRoot {
panic!("found DOM global that doesn't unwrap to Window or WorkerGlobalScope")
}
}
+
+/// Returns the global object of the realm that the given JS object was created in.
+#[allow(unrooted_must_root)]
+pub fn global_root_from_object(obj: *mut JSObject) -> GlobalRoot {
+ unsafe {
+ let global = GetGlobalForObjectCrossCompartment(obj);
+ global_root_from_global(global)
+ }
+}
+
+/// Returns the global object for the given JSContext
+#[allow(unrooted_must_root)]
+pub fn global_root_from_context(cx: *mut JSContext) -> GlobalRoot {
+ unsafe {
+ let global = CurrentGlobalOrNull(cx);
+ assert!(!global.is_null());
+ global_root_from_global(global)
+ }
+}
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index cf831f2a226..9cc2d13fb77 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -38,6 +38,7 @@ use dom::bindings::js::{JS, Root};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, Reflector};
use dom::bindings::utils::WindowProxyHandler;
+use dom::worker::SharedRt;
use encoding::types::EncodingRef;
use euclid::length::Length as EuclidLength;
use euclid::matrix2d::Matrix2D;
@@ -319,6 +320,7 @@ no_jsmanaged_fields!(AttrIdentifier);
no_jsmanaged_fields!(AttrValue);
no_jsmanaged_fields!(ElementSnapshot);
no_jsmanaged_fields!(HttpsState);
+no_jsmanaged_fields!(SharedRt);
no_jsmanaged_fields!(TouchpadPressurePhase);
impl JSTraceable for ConstellationChan<ScriptMsg> {
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 32ec841fc08..1b2d18b18b3 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -9,20 +9,21 @@ use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::error::ErrorResult;
-use dom::bindings::global::GlobalRef;
+use dom::bindings::global::{GlobalRef, global_root_from_context};
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootCollection};
use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::reflector::Reflectable;
use dom::bindings::structuredclone::StructuredCloneData;
+use dom::bindings::trace::JSTraceable;
use dom::messageevent::MessageEvent;
-use dom::worker::{SimpleWorkerErrorHandler, TrustedWorkerAddress, WorkerMessageHandler};
+use dom::worker::{SimpleWorkerErrorHandler, SharedRt, TrustedWorkerAddress, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
-use js::jsapi::{HandleValue, JSContext, RootedValue};
-use js::jsapi::{JSAutoCompartment, JSAutoRequest};
+use js::jsapi::{HandleValue, JS_SetInterruptCallback};
+use js::jsapi::{JSAutoCompartment, JSAutoRequest, JSContext, RootedValue};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::PipelineId;
@@ -33,6 +34,7 @@ use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort, StackRootTLS, get_
use script_traits::{TimerEvent, TimerSource};
use std::mem::replace;
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
+use std::sync::{Arc, Mutex};
use url::Url;
use util::str::DOMString;
use util::thread::spawn_named;
@@ -206,10 +208,12 @@ impl DedicatedWorkerGlobalScope {
DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope)
}
+ #[allow(unsafe_code)]
pub fn run_worker_scope(init: WorkerGlobalScopeInit,
worker_url: Url,
id: PipelineId,
from_devtools_receiver: IpcReceiver<DevtoolScriptControlMsg>,
+ main_thread_rt: Arc<Mutex<Option<SharedRt>>>,
worker: TrustedWorkerAddress,
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
@@ -237,6 +241,7 @@ impl DedicatedWorkerGlobalScope {
};
let runtime = new_rt_and_cx();
+ *main_thread_rt.lock().unwrap() = Some(SharedRt::new(&runtime));
let (devtools_mpsc_chan, devtools_mpsc_port) = channel();
ROUTER.route_ipc_receiver_to_mpsc_sender(from_devtools_receiver, devtools_mpsc_chan);
@@ -257,6 +262,15 @@ impl DedicatedWorkerGlobalScope {
// registration (#6631), so we instead use a random number and cross our fingers.
let scope = global.upcast::<WorkerGlobalScope>();
+ unsafe {
+ // Handle interrupt requests
+ JS_SetInterruptCallback(scope.runtime(), Some(interrupt_callback));
+ }
+
+ if scope.is_closing() {
+ return;
+ }
+
{
let _ar = AutoWorkerReset::new(global.r(), worker);
scope.execute_script(DOMString::from(source));
@@ -265,6 +279,9 @@ impl DedicatedWorkerGlobalScope {
let reporter_name = format!("worker-reporter-{}", random::<u64>());
scope.mem_profiler_chan().run_with_memory_reporting(|| {
while let Ok(event) = global.receive_event() {
+ if scope.is_closing() {
+ break;
+ }
global.handle_event(event);
}
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
@@ -387,6 +404,19 @@ impl DedicatedWorkerGlobalScope {
}
}
+#[allow(unsafe_code)]
+unsafe extern "C" fn interrupt_callback(cx: *mut JSContext) -> bool {
+ let global = global_root_from_context(cx);
+ let worker = match global.r() {
+ GlobalRef::Worker(w) => w,
+ _ => panic!("global for worker is not a worker scope")
+ };
+ assert!(worker.is::<DedicatedWorkerGlobalScope>());
+
+ // A false response causes the script to terminate
+ !worker.is_closing()
+}
+
impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
diff --git a/components/script/dom/webidls/Worker.webidl b/components/script/dom/webidls/Worker.webidl
index 62cd5c89f92..5331d6fdc36 100644
--- a/components/script/dom/webidls/Worker.webidl
+++ b/components/script/dom/webidls/Worker.webidl
@@ -12,7 +12,7 @@ interface AbstractWorker {
// https://html.spec.whatwg.org/multipage/#worker
[Constructor(DOMString scriptURL)/*, Exposed=Window,Worker*/]
interface Worker : EventTarget {
- //void terminate();
+ void terminate();
[Throws]
void postMessage(any message/*, optional sequence<Transferable> transfer*/);
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index f1f15c3c8f9..f6cf53b801e 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -21,12 +21,15 @@ use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent;
use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc;
-use js::jsapi::{HandleValue, JSContext, RootedValue};
-use js::jsapi::{JSAutoCompartment, JSAutoRequest};
+use js::jsapi::{HandleValue, JSContext, JSRuntime, RootedValue};
+use js::jsapi::{JSAutoCompartment, JSAutoRequest, JS_RequestInterruptCallback};
use js::jsval::UndefinedValue;
+use js::rust::Runtime;
use script_runtime::ScriptChan;
use script_thread::Runnable;
+use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel};
+use std::sync::{Arc, Mutex};
use util::str::DOMString;
pub type TrustedWorkerAddress = Trusted<Worker>;
@@ -39,21 +42,26 @@ pub struct Worker {
/// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
/// this Worker created.
sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
+ closing: Arc<AtomicBool>,
+ #[ignore_heap_size_of = "Defined in rust-mozjs"]
+ runtime: Arc<Mutex<Option<SharedRt>>>
}
impl Worker {
- fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>)
- -> Worker {
+ fn new_inherited(sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
+ closing: Arc<AtomicBool>) -> Worker {
Worker {
eventtarget: EventTarget::new_inherited(),
sender: sender,
+ closing: closing,
+ runtime: Arc::new(Mutex::new(None))
}
}
pub fn new(global: GlobalRef,
- sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>)
- -> Root<Worker> {
- reflect_dom_object(box Worker::new_inherited(sender),
+ sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
+ closing: Arc<AtomicBool>) -> Root<Worker> {
+ reflect_dom_object(box Worker::new_inherited(sender, closing),
global,
WorkerBinding::Wrap)
}
@@ -71,7 +79,8 @@ impl Worker {
let scheduler_chan = global.scheduler_chan();
let (sender, receiver) = channel();
- let worker = Worker::new(global, sender.clone());
+ let closing = Arc::new(AtomicBool::new(false));
+ let worker = Worker::new(global, sender.clone(), closing.clone());
let worker_ref = Trusted::new(worker.r(), global.script_chan());
let worker_id = global.get_next_worker_id();
@@ -100,18 +109,28 @@ impl Worker {
constellation_chan: constellation_chan,
scheduler_chan: scheduler_chan,
worker_id: worker_id,
+ closing: closing,
};
+
DedicatedWorkerGlobalScope::run_worker_scope(
- init, worker_url, global.pipeline(), devtools_receiver, worker_ref,
+ init, worker_url, global.pipeline(), devtools_receiver, worker.runtime.clone(), worker_ref,
global.script_chan(), sender, receiver);
Ok(worker)
}
+ pub fn is_closing(&self) -> bool {
+ self.closing.load(Ordering::SeqCst)
+ }
+
pub fn handle_message(address: TrustedWorkerAddress,
data: StructuredCloneData) {
let worker = address.root();
+ if worker.is_closing() {
+ return;
+ }
+
let global = worker.r().global();
let target = worker.upcast();
let _ar = JSAutoRequest::new(global.r().get_cx());
@@ -129,6 +148,11 @@ impl Worker {
pub fn handle_error_message(address: TrustedWorkerAddress, message: DOMString,
filename: DOMString, lineno: u32, colno: u32) {
let worker = address.root();
+
+ if worker.is_closing() {
+ return;
+ }
+
let global = worker.r().global();
let error = RootedValue::new(global.r().get_cx(), UndefinedValue());
let errorevent = ErrorEvent::new(global.r(), atom!("error"),
@@ -147,6 +171,19 @@ impl WorkerMethods for Worker {
Ok(())
}
+ // https://html.spec.whatwg.org/multipage/#terminate-a-worker
+ fn Terminate(&self) {
+ // Step 1
+ if self.closing.swap(true, Ordering::SeqCst) {
+ return;
+ }
+
+ // Step 4
+ if let Some(runtime) = *self.runtime.lock().unwrap() {
+ runtime.request_interrupt();
+ }
+ }
+
// https://html.spec.whatwg.org/multipage/#handler-worker-onmessage
event_handler!(message, GetOnmessage, SetOnmessage);
@@ -221,3 +258,26 @@ impl Runnable for WorkerErrorHandler {
Worker::handle_error_message(this.addr, this.msg, this.file_name, this.line_num, this.col_num);
}
}
+
+#[derive(Copy, Clone)]
+pub struct SharedRt {
+ rt: *mut JSRuntime
+}
+
+impl SharedRt {
+ pub fn new(rt: &Runtime) -> SharedRt {
+ SharedRt {
+ rt: rt.rt()
+ }
+ }
+
+ #[allow(unsafe_code)]
+ pub fn request_interrupt(&self) {
+ unsafe {
+ JS_RequestInterruptCallback(self.rt);
+ }
+ }
+}
+
+#[allow(unsafe_code)]
+unsafe impl Send for SharedRt {}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 51180fe10c2..a0a73c0d993 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -18,7 +18,7 @@ use dom::window::{base64_atob, base64_btoa};
use dom::workerlocation::WorkerLocation;
use dom::workernavigator::WorkerNavigator;
use ipc_channel::ipc::IpcSender;
-use js::jsapi::{HandleValue, JSAutoRequest, JSContext};
+use js::jsapi::{HandleValue, JSAutoRequest, JSContext, JSRuntime};
use js::rust::Runtime;
use msg::constellation_msg::{ConstellationChan, PipelineId};
use net_traits::{LoadContext, ResourceThread, load_whole_resource};
@@ -29,6 +29,8 @@ use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, Tim
use std::cell::Cell;
use std::default::Default;
use std::rc::Rc;
+use std::sync::Arc;
+use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle, OneshotTimers, TimerCallback};
use url::Url;
@@ -47,6 +49,7 @@ pub struct WorkerGlobalScopeInit {
pub constellation_chan: ConstellationChan<ConstellationMsg>,
pub scheduler_chan: IpcSender<TimerEventRequest>,
pub worker_id: WorkerId,
+ pub closing: Arc<AtomicBool>,
}
// https://html.spec.whatwg.org/multipage/#the-workerglobalscope-common-interface
@@ -55,6 +58,7 @@ pub struct WorkerGlobalScope {
eventtarget: EventTarget,
worker_id: WorkerId,
worker_url: Url,
+ closing: Arc<AtomicBool>,
#[ignore_heap_size_of = "Defined in js"]
runtime: Runtime,
next_worker_id: Cell<WorkerId>,
@@ -104,6 +108,7 @@ impl WorkerGlobalScope {
next_worker_id: Cell::new(WorkerId(0)),
worker_id: init.worker_id,
worker_url: worker_url,
+ closing: init.closing,
runtime: runtime,
resource_thread: init.resource_thread,
location: Default::default(),
@@ -155,10 +160,18 @@ impl WorkerGlobalScope {
self.timers.unschedule_callback(handle);
}
+ pub fn runtime(&self) -> *mut JSRuntime {
+ self.runtime.rt()
+ }
+
pub fn get_cx(&self) -> *mut JSContext {
self.runtime.cx()
}
+ pub fn is_closing(&self) -> bool {
+ self.closing.load(Ordering::SeqCst)
+ }
+
pub fn resource_thread(&self) -> &ResourceThread {
&self.resource_thread
}
@@ -307,11 +320,15 @@ impl WorkerGlobalScope {
self.reflector().get_jsobject(), String::from(source), self.worker_url.serialize(), 1) {
Ok(_) => (),
Err(_) => {
- // TODO: An error needs to be dispatched to the parent.
- // https://github.com/servo/servo/issues/6422
- println!("evaluate_script failed");
- let _ar = JSAutoRequest::new(self.runtime.cx());
- report_pending_exception(self.runtime.cx(), self.reflector().get_jsobject().get());
+ if self.is_closing() {
+ println!("evaluate_script failed (terminated)");
+ } else {
+ // TODO: An error needs to be dispatched to the parent.
+ // https://github.com/servo/servo/issues/6422
+ println!("evaluate_script failed");
+ let _ar = JSAutoRequest::new(self.runtime.cx());
+ report_pending_exception(self.runtime.cx(), self.reflector().get_jsobject().get());
+ }
}
}
}
diff --git a/tests/html/worker/worker_post_block.js b/tests/html/worker/worker_post_block.js
new file mode 100644
index 00000000000..a9837b71afd
--- /dev/null
+++ b/tests/html/worker/worker_post_block.js
@@ -0,0 +1,9 @@
+var prev = Date.now()
+for (var i=0; true; i++) {
+
+ if (i % 100000000 == 0) {
+ var now = Date.now();
+ postMessage(now - prev);
+ prev = now;
+ }
+}
diff --git a/tests/html/worker/worker_post_interval.js b/tests/html/worker/worker_post_interval.js
new file mode 100644
index 00000000000..ce1126136fa
--- /dev/null
+++ b/tests/html/worker/worker_post_interval.js
@@ -0,0 +1,6 @@
+var prev = Date.now()
+setInterval(function () {
+ var now = Date.now();
+ postMessage(now - prev);
+ prev = now;
+}, 500);
diff --git a/tests/html/worker/worker_terminate.html b/tests/html/worker/worker_terminate.html
new file mode 100644
index 00000000000..d6c40a5c69d
--- /dev/null
+++ b/tests/html/worker/worker_terminate.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Worker Test</title>
+</head>
+<body>
+<script>
+var workerPath = (function () {
+ var workerType;
+ switch (window.location.search.match(/worker=(\w+)/)[1]) {
+ case 'block':
+ workerType = 'block';
+ break;
+ default:
+ workerType = 'interval';
+ break;
+ }
+
+ return './worker_post_' + workerType + '.js';
+})();
+
+function startWorker() {
+ window.w = new Worker(workerPath);
+ w.onmessage = function(m) {
+ var p = document.createElement('p');
+ p.innerHTML = JSON.stringify(m.data);
+ document.body.appendChild(p);
+ };
+
+ var ps = document.getElementsByTagName('p');
+ while (ps.length) {
+ document.body.removeChild(ps[0]);
+ }
+}
+
+function stopWorker() {
+ if (w) {
+ w.terminate();
+ }
+
+ window.w = null;
+}
+</script>
+ <button onclick="startWorker()">Start Worker</button>
+ <button onclick="stopWorker()">Stop Worker</button>
+</body>
+</html>
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index 5df3f0cc1ac..b28e62669b5 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -7458,9 +7458,6 @@
[SharedWorkerGlobalScope interface: attribute onconnect]
expected: FAIL
- [Worker interface: operation terminate()]
- expected: FAIL
-
[SharedWorker interface: existence and properties of interface object]
expected: FAIL
diff --git a/tests/wpt/metadata/workers/Worker_terminate_event_queue.htm.ini b/tests/wpt/metadata/workers/Worker_terminate_event_queue.htm.ini
deleted file mode 100644
index bef6cb90a7b..00000000000
--- a/tests/wpt/metadata/workers/Worker_terminate_event_queue.htm.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[Worker_terminate_event_queue.htm]
- type: testharness
- disabled: too much output
diff --git a/tests/wpt/metadata/workers/constructors/Worker/terminate.html.ini b/tests/wpt/metadata/workers/constructors/Worker/terminate.html.ini
deleted file mode 100644
index 0f57531e41e..00000000000
--- a/tests/wpt/metadata/workers/constructors/Worker/terminate.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[terminate.html]
- type: testharness
- [terminate()]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/workers/nested_worker.worker.js.ini b/tests/wpt/metadata/workers/nested_worker.worker.js.ini
deleted file mode 100644
index 4a839a55bca..00000000000
--- a/tests/wpt/metadata/workers/nested_worker.worker.js.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[nested_worker.worker]
- type: testharness
- expected: TIMEOUT
- [Nested worker]
- expected: FAIL
-
- [Checking contents for text file]
- expected: FAIL
-