Browse Source

Allow passing owned `HostHooks` and `JobQueues` to `Context` (#2811)

This allows `thread_local` contexts to have owned `HostHooks` and `JobQueues`.

It changes the following:

- Creates a new `MaybeShared` struct that can hold either a reference or an `Rc`.
- Changes the `job_queue` and `host_hooks` parameters of `Context` to use `MaybeShared`.

This PR also allows us to make `SimpleJobQueue` the default promise runner, which I think it's pretty cool :)

cc @lastmjs
pull/2814/head
José Julián Espina 2 years ago
parent
commit
0d6ba53ff2
  1. 4
      boa_cli/src/main.rs
  2. 4
      boa_engine/src/builtins/intl/locale/tests.rs
  3. 4
      boa_engine/src/builtins/intl/locale/utils.rs
  4. 21
      boa_engine/src/builtins/promise/tests.rs
  5. 4
      boa_engine/src/context/hooks.rs
  6. 9
      boa_engine/src/context/icu.rs
  7. 42
      boa_engine/src/context/maybe_shared.rs
  8. 71
      boa_engine/src/context/mod.rs
  9. 25
      boa_engine/src/job.rs
  10. 3
      boa_engine/src/lib.rs
  11. 37
      boa_engine/src/object/builtins/jspromise.rs
  12. 27
      boa_engine/src/tests/promise.rs
  13. 4
      boa_examples/src/bin/futures.rs
  14. 11
      boa_tester/src/exec/mod.rs

4
boa_cli/src/main.rs

@ -302,9 +302,9 @@ fn evaluate_files(args: &Opt, context: &mut Context<'_>) -> Result<(), io::Error
fn main() -> Result<(), io::Error> {
let args = Opt::parse();
let queue = Jobs::default();
let queue: &dyn JobQueue = &Jobs::default();
let mut context = ContextBuilder::new()
.job_queue(&queue)
.job_queue(queue)
.build()
.expect("cannot fail with default global object");

4
boa_engine/src/builtins/intl/locale/tests.rs

@ -7,7 +7,7 @@ use icu_locid::{
locale, Locale,
};
use icu_plurals::provider::CardinalV1Marker;
use icu_provider::{DataLocale, DataProvider, DataRequest, DataRequestMetadata};
use icu_provider::{BufferProvider, DataLocale, DataProvider, DataRequest, DataRequestMetadata};
use crate::{
builtins::intl::{
@ -73,7 +73,7 @@ impl Service for TestService {
#[test]
fn locale_resolution() {
let provider = boa_icu_provider::buffer();
let provider: &dyn BufferProvider = boa_icu_provider::buffer();
let icu = Icu::new(BoaProvider::Buffer(provider)).unwrap();
let mut default = default_locale(icu.locale_canonicalizer());
default

4
boa_engine/src/builtins/intl/locale/utils.rs

@ -547,7 +547,7 @@ pub(in crate::builtins::intl) fn validate_extension<M: KeyedDataMarker>(
mod tests {
use icu_locid::{langid, locale, Locale};
use icu_plurals::provider::CardinalV1Marker;
use icu_provider::AsDeserializingBufferProvider;
use icu_provider::{AsDeserializingBufferProvider, BufferProvider};
use crate::{
builtins::intl::locale::utils::{
@ -579,7 +579,7 @@ mod tests {
#[test]
fn lookup_match() {
let provider = boa_icu_provider::buffer();
let provider: &dyn BufferProvider = boa_icu_provider::buffer();
let icu = Icu::new(BoaProvider::Buffer(provider)).unwrap();
// requested: []

21
boa_engine/src/builtins/promise/tests.rs

@ -1,13 +1,10 @@
use crate::{context::ContextBuilder, job::SimpleJobQueue, run_test_actions_with, TestAction};
use crate::{run_test_actions, TestAction};
use indoc::indoc;
#[test]
fn promise() {
let queue = SimpleJobQueue::new();
let context = &mut ContextBuilder::new().job_queue(&queue).build().unwrap();
run_test_actions_with(
[
TestAction::run(indoc! {r#"
run_test_actions([
TestAction::run(indoc! {r#"
let count = 0;
const promise = new Promise((resolve, reject) => {
count += 1;
@ -15,11 +12,9 @@ fn promise() {
}).then((_) => (count += 1));
count += 1;
"#}),
TestAction::assert_eq("count", 2),
#[allow(clippy::redundant_closure_for_method_calls)]
TestAction::inspect_context(|ctx| ctx.run_jobs()),
TestAction::assert_eq("count", 3),
],
context,
);
TestAction::assert_eq("count", 2),
#[allow(clippy::redundant_closure_for_method_calls)]
TestAction::inspect_context(|ctx| ctx.run_jobs()),
TestAction::assert_eq("count", 3),
]);
}

4
boa_engine/src/context/hooks.rs

@ -38,8 +38,8 @@ use super::intrinsics::Intrinsics;
/// Err(JsNativeError::typ().with_message("eval calls not available").into())
/// }
/// }
/// let hooks = Hooks; // Can have additional state.
/// let context = &mut ContextBuilder::new().host_hooks(&hooks).build().unwrap();
/// let hooks: &dyn HostHooks = &Hooks; // Can have additional state.
/// let context = &mut ContextBuilder::new().host_hooks(hooks).build().unwrap();
/// let result = context.eval_script(Source::from_bytes(r#"eval("let a = 5")"#));
/// assert_eq!(result.unwrap_err().to_string(), "TypeError: eval calls not available");
/// ```

9
boa_engine/src/context/icu.rs

@ -43,7 +43,7 @@ where
M::Yokeable: ZeroFrom<'static, M::Yokeable> + MaybeSendSync,
{
fn load(&self, req: DataRequest<'_>) -> Result<DataResponse<M>, DataError> {
match *self {
match self {
BoaProvider::Buffer(provider) => provider.as_deserializing().load(req),
BoaProvider::Any(provider) => provider.as_downcasting().load(req),
}
@ -125,8 +125,8 @@ impl BoaProvider<'_> {
}
}
/// Collection of tools initialized from a [`DataProvider`] that are used
/// for the functionality of `Intl`.
/// Collection of tools initialized from a [`DataProvider`] that are used for the functionality of
/// `Intl`.
pub(crate) struct Icu<'provider> {
provider: BoaProvider<'provider>,
locale_canonicalizer: LocaleCanonicalizer,
@ -148,8 +148,7 @@ impl<'provider> Icu<'provider> {
///
/// # Errors
///
/// This method will return an error if any of the tools
/// required cannot be constructed.
/// Returns an error if any of the tools required cannot be constructed.
pub(crate) fn new(
provider: BoaProvider<'provider>,
) -> Result<Icu<'provider>, LocaleTransformError> {

42
boa_engine/src/context/maybe_shared.rs

@ -0,0 +1,42 @@
use std::{ops::Deref, rc::Rc};
/// A [`Cow`][std::borrow::Cow]-like pointer where the `Owned` variant is an [`Rc`].
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum MaybeShared<'a, T: ?Sized> {
/// Borrowed data.
Borrowed(&'a T),
/// `Rc` shared data.
Shared(Rc<T>),
}
impl<T: ?Sized> Clone for MaybeShared<'_, T> {
fn clone(&self) -> Self {
match self {
Self::Borrowed(b) => Self::Borrowed(b),
Self::Shared(sh) => Self::Shared(sh.clone()),
}
}
}
impl<T: ?Sized> Deref for MaybeShared<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
MaybeShared::Borrowed(b) => b,
MaybeShared::Shared(sh) => sh,
}
}
}
impl<'a, T: ?Sized> From<&'a T> for MaybeShared<'a, T> {
fn from(value: &'a T) -> Self {
Self::Borrowed(value)
}
}
impl<T: ?Sized> From<Rc<T>> for MaybeShared<'static, T> {
fn from(value: Rc<T>) -> Self {
Self::Shared(value)
}
}

71
boa_engine/src/context/mod.rs

@ -1,26 +1,26 @@
//! The ECMAScript context.
mod hooks;
pub mod intrinsics;
pub use hooks::{DefaultHooks, HostHooks};
#[cfg(feature = "intl")]
pub(crate) mod icu;
pub mod intrinsics;
mod maybe_shared;
pub use hooks::{DefaultHooks, HostHooks};
#[cfg(feature = "intl")]
pub use icu::BoaProvider;
use intrinsics::Intrinsics;
pub use maybe_shared::MaybeShared;
use std::io::Read;
#[cfg(not(feature = "intl"))]
pub use std::marker::PhantomData;
use std::{io::Read, rc::Rc};
use crate::{
builtins,
bytecompiler::ByteCompiler,
class::{Class, ClassBuilder},
job::{IdleJobQueue, JobQueue, NativeJob},
job::{JobQueue, NativeJob, SimpleJobQueue},
native_function::NativeFunction,
object::{FunctionObjectBuilder, JsObject},
optimizer::{Optimizer, OptimizerOptions, OptimizerStatistics},
@ -99,9 +99,9 @@ pub struct Context<'host> {
#[cfg(feature = "intl")]
icu: icu::Icu<'host>,
host_hooks: &'host dyn HostHooks,
host_hooks: MaybeShared<'host, dyn HostHooks>,
job_queue: &'host dyn JobQueue,
job_queue: MaybeShared<'host, dyn JobQueue>,
optimizer_options: OptimizerOptions,
}
@ -494,12 +494,12 @@ impl<'host> Context<'host> {
/// Enqueues a [`NativeJob`] on the [`JobQueue`].
pub fn enqueue_job(&mut self, job: NativeJob) {
self.job_queue.enqueue_promise_job(job, self);
self.job_queue().enqueue_promise_job(job, self);
}
/// Runs all the jobs in the job queue.
pub fn run_jobs(&mut self) {
self.job_queue.run_jobs(self);
self.job_queue().run_jobs(self);
self.clear_kept_objects();
}
@ -524,13 +524,13 @@ impl<'host> Context<'host> {
}
/// Gets the host hooks.
pub fn host_hooks(&self) -> &'host dyn HostHooks {
self.host_hooks
pub fn host_hooks(&self) -> MaybeShared<'host, dyn HostHooks> {
self.host_hooks.clone()
}
/// Gets the job queue.
pub fn job_queue(&mut self) -> &'host dyn JobQueue {
self.job_queue
pub fn job_queue(&self) -> MaybeShared<'host, dyn JobQueue> {
self.job_queue.clone()
}
}
@ -558,8 +558,8 @@ impl<'host> Context<'host> {
#[derive(Default)]
pub struct ContextBuilder<'icu, 'hooks, 'queue> {
interner: Option<Interner>,
host_hooks: Option<&'hooks dyn HostHooks>,
job_queue: Option<&'queue dyn JobQueue>,
host_hooks: Option<MaybeShared<'hooks, dyn HostHooks>>,
job_queue: Option<MaybeShared<'queue, dyn JobQueue>>,
#[cfg(feature = "intl")]
icu: Option<icu::Icu<'icu>>,
#[cfg(not(feature = "intl"))]
@ -570,10 +570,15 @@ pub struct ContextBuilder<'icu, 'hooks, 'queue> {
impl std::fmt::Debug for ContextBuilder<'_, '_, '_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[derive(Clone, Copy, Debug)]
struct JobQueue;
#[derive(Clone, Copy, Debug)]
struct HostHooks;
let mut out = f.debug_struct("ContextBuilder");
out.field("interner", &self.interner)
.field("host_hooks", &"HostHooks");
.field("host_hooks", &self.host_hooks.as_ref().map(|_| HostHooks))
.field("job_queue", &self.job_queue.as_ref().map(|_| JobQueue));
#[cfg(feature = "intl")]
out.field("icu", &self.icu);
@ -632,18 +637,27 @@ impl<'icu, 'hooks, 'queue> ContextBuilder<'icu, 'hooks, 'queue> {
///
/// [`Host Hooks`]: https://tc39.es/ecma262/#sec-host-hooks-summary
#[must_use]
pub fn host_hooks(self, host_hooks: &dyn HostHooks) -> ContextBuilder<'icu, '_, 'queue> {
pub fn host_hooks<'new_hooks, H>(
self,
host_hooks: H,
) -> ContextBuilder<'icu, 'new_hooks, 'queue>
where
H: Into<MaybeShared<'new_hooks, dyn HostHooks>>,
{
ContextBuilder {
host_hooks: Some(host_hooks),
host_hooks: Some(host_hooks.into()),
..self
}
}
/// Initializes the [`JobQueue`] for the context.
#[must_use]
pub fn job_queue(self, job_queue: &dyn JobQueue) -> ContextBuilder<'icu, 'hooks, '_> {
pub fn job_queue<'new_queue, Q>(self, job_queue: Q) -> ContextBuilder<'icu, 'hooks, 'new_queue>
where
Q: Into<MaybeShared<'new_queue, dyn JobQueue>>,
{
ContextBuilder {
job_queue: Some(job_queue),
job_queue: Some(job_queue.into()),
..self
}
}
@ -666,8 +680,11 @@ impl<'icu, 'hooks, 'queue> ContextBuilder<'icu, 'hooks, 'queue> {
'hooks: 'host,
'queue: 'host,
{
let host_hooks = self.host_hooks.unwrap_or(&DefaultHooks);
let realm = Realm::create(host_hooks);
let host_hooks = self.host_hooks.unwrap_or_else(|| {
let hooks: &dyn HostHooks = &DefaultHooks;
hooks.into()
});
let realm = Realm::create(&*host_hooks);
let vm = Vm::new(realm.environment().clone());
let mut context = Context {
@ -677,14 +694,18 @@ impl<'icu, 'hooks, 'queue> ContextBuilder<'icu, 'hooks, 'queue> {
strict: false,
#[cfg(feature = "intl")]
icu: self.icu.unwrap_or_else(|| {
let provider = BoaProvider::Buffer(boa_icu_provider::buffer());
let buffer: &dyn icu_provider::BufferProvider = boa_icu_provider::buffer();
let provider = BoaProvider::Buffer(buffer);
icu::Icu::new(provider).expect("Failed to initialize default icu data.")
}),
#[cfg(feature = "fuzz")]
instructions_remaining: self.instructions_remaining,
kept_alive: Vec::new(),
host_hooks,
job_queue: self.job_queue.unwrap_or(&IdleJobQueue),
job_queue: self.job_queue.unwrap_or_else(|| {
let queue: Rc<dyn JobQueue> = Rc::new(SimpleJobQueue::new());
queue.into()
}),
optimizer_options: OptimizerOptions::OPTIMIZE_ALL,
};

25
boa_engine/src/job.rs

@ -198,10 +198,17 @@ pub trait JobQueue {
/// A job queue that does nothing.
///
/// This is the default job queue for the [`Context`], and is useful if you want to disable
/// the promise capabilities of the engine.
/// This queue is mostly useful if you want to disable the promise capabilities of the engine. This
/// can be done by passing a reference to it to the [`ContextBuilder`]:
///
/// If you want to enable running promise jobs, see [`SimpleJobQueue`].
/// ```
/// use boa_engine::{context::ContextBuilder, job::{JobQueue, IdleJobQueue}};
///
/// let queue: &dyn JobQueue = &IdleJobQueue;
/// let context = ContextBuilder::new().job_queue(queue).build();
/// ```
///
/// [`ContextBuilder`]: crate::context::ContextBuilder
#[derive(Debug, Clone, Copy)]
pub struct IdleJobQueue;
@ -215,16 +222,10 @@ impl JobQueue for IdleJobQueue {
/// A simple FIFO job queue that bails on the first error.
///
/// To enable running promise jobs on the engine, you need to pass it to the [`ContextBuilder`]:
/// This is the default job queue for the [`Context`], but it is mostly pretty limited for
/// custom event queues.
///
/// ```
/// use boa_engine::{context::ContextBuilder, job::SimpleJobQueue};
///
/// let queue = SimpleJobQueue::new();
/// let context = ContextBuilder::new().job_queue(&queue).build();
/// ```
///
/// [`ContextBuilder`]: crate::context::ContextBuilder
/// To disable running promise jobs on the engine, see [`IdleJobQueue`].
#[derive(Default)]
pub struct SimpleJobQueue(RefCell<VecDeque<NativeJob>>);

3
boa_engine/src/lib.rs

@ -151,6 +151,7 @@ pub mod error;
pub mod job;
pub mod native_function;
pub mod object;
pub mod optimizer;
pub mod property;
pub mod realm;
pub mod string;
@ -158,8 +159,6 @@ pub mod symbol;
pub mod value;
pub mod vm;
pub mod optimizer;
#[cfg(feature = "console")]
pub mod console;

37
boa_engine/src/object/builtins/jspromise.rs

@ -27,7 +27,6 @@ use super::{JsArray, JsFunction};
/// ```
/// # use boa_engine::{
/// # builtins::promise::PromiseState,
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::{builtins::JsPromise, FunctionObjectBuilder},
/// # property::Attribute,
@ -35,8 +34,7 @@ use super::{JsArray, JsFunction};
/// # };
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// context.register_global_property("finally", false, Attribute::all());
///
@ -131,14 +129,12 @@ impl JsPromise {
/// ```
/// # use std::error::Error;
/// # use boa_engine::{
/// # job::SimpleJobQueue,
/// # object::builtins::JsPromise,
/// # builtins::promise::PromiseState,
/// # Context, JsValue, js_string
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// let promise = JsPromise::new(|resolvers, context| {
/// let result = js_string!("hello world").into();
@ -393,14 +389,12 @@ impl JsPromise {
/// # use std::error::Error;
/// # use boa_engine::{
/// # builtins::promise::PromiseState,
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::{builtins::JsPromise, FunctionObjectBuilder},
/// # Context, JsArgs, JsError, JsValue, NativeFunction,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// let promise = JsPromise::new(
/// |resolvers, context| {
@ -461,13 +455,11 @@ impl JsPromise {
/// # use boa_engine::{
/// # js_string,
/// # builtins::promise::PromiseState,
/// # job::SimpleJobQueue,
/// # object::{builtins::JsPromise, FunctionObjectBuilder},
/// # Context, JsArgs, JsNativeError, JsValue, NativeFunction,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// let promise = JsPromise::new(
/// |resolvers, context| {
@ -524,14 +516,12 @@ impl JsPromise {
/// ```
/// # use std::error::Error;
/// # use boa_engine::{
/// # job::SimpleJobQueue,
/// # object::{builtins::JsPromise, FunctionObjectBuilder},
/// # property::Attribute,
/// # Context, JsNativeError, JsValue, NativeFunction,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// context.register_global_property("finally", false, Attribute::all());
///
@ -594,14 +584,12 @@ impl JsPromise {
/// ```
/// # use std::error::Error;
/// # use boa_engine::{
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::builtins::{JsArray, JsPromise},
/// # Context, JsNativeError, JsValue,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// let promise1 = JsPromise::all(
/// [
@ -668,15 +656,12 @@ impl JsPromise {
/// ```
/// # use std::error::Error;
/// # use boa_engine::{
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::builtins::{JsArray, JsPromise},
/// # Context, JsNativeError, JsValue,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
///
/// let context = &mut Context::default();
///
/// let promise = JsPromise::all_settled(
/// [
@ -744,14 +729,12 @@ impl JsPromise {
/// # use std::error::Error;
/// # use boa_engine::{
/// # builtins::promise::PromiseState,
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::builtins::JsPromise,
/// # Context, JsNativeError,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
///
/// let promise = JsPromise::any(
@ -807,14 +790,12 @@ impl JsPromise {
/// # use std::error::Error;
/// # use boa_engine::{
/// # builtins::promise::PromiseState,
/// # job::SimpleJobQueue,
/// # js_string,
/// # object::builtins::JsPromise,
/// # Context, JsValue,
/// # };
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let queue = &SimpleJobQueue::new();
/// let context = &mut Context::builder().job_queue(queue).build()?;
/// let context = &mut Context::default();
///
/// let (a, resolvers_a) = JsPromise::new_pending(context);
/// let (b, resolvers_b) = JsPromise::new_pending(context);

27
boa_engine/src/tests/promise.rs

@ -1,16 +1,13 @@
use indoc::indoc;
use crate::{job::SimpleJobQueue, run_test_actions_with, Context, TestAction};
use crate::{run_test_actions, TestAction};
#[test]
#[allow(clippy::redundant_closure_for_method_calls)]
fn issue_2658() {
let queue = &SimpleJobQueue::new();
let context = &mut Context::builder().job_queue(queue).build().unwrap();
run_test_actions_with(
[
TestAction::run(indoc! {
r#"
run_test_actions([
TestAction::run(indoc! {
r#"
let result1;
let result2;
async function* agf(a) {
@ -33,13 +30,11 @@ fn issue_2658() {
genTwo.next().then(v => { result1 = v; });
genTwo.next().then(v => { result2 = v; });
"#
}),
TestAction::inspect_context(|ctx| ctx.run_jobs()),
TestAction::assert("!result1.done"),
TestAction::assert_eq("result1.value", 5),
TestAction::assert("!result2.done"),
TestAction::assert_eq("result2.value", 5),
],
context,
);
}),
TestAction::inspect_context(|ctx| ctx.run_jobs()),
TestAction::assert("!result1.done"),
TestAction::assert_eq("result1.value", 5),
TestAction::assert("!result2.done"),
TestAction::assert_eq("result2.value", 5),
]);
}

4
boa_examples/src/bin/futures.rs

@ -131,8 +131,8 @@ fn delay(
fn main() {
// Initialize the required executors and the context
let executor = LocalExecutor::new();
let queue = Queue::new(executor);
let context = &mut ContextBuilder::new().job_queue(&queue).build().unwrap();
let queue: &dyn JobQueue = &Queue::new(executor);
let context = &mut ContextBuilder::new().job_queue(queue).build().unwrap();
// Bind the defined async function to the ECMAScript function "delay".
context

11
boa_tester/src/exec/mod.rs

@ -7,9 +7,8 @@ use crate::{
TestFlags, TestOutcomeResult, TestResult, TestSuite, VersionedStats,
};
use boa_engine::{
context::ContextBuilder, job::SimpleJobQueue, native_function::NativeFunction,
object::FunctionObjectBuilder, optimizer::OptimizerOptions, property::Attribute, Context,
JsArgs, JsNativeErrorKind, JsValue, Source,
native_function::NativeFunction, object::FunctionObjectBuilder, optimizer::OptimizerOptions,
property::Attribute, Context, JsArgs, JsNativeErrorKind, JsValue, Source,
};
use colored::Colorize;
use fxhash::FxHashSet;
@ -210,11 +209,7 @@ impl Test {
let result = std::panic::catch_unwind(|| match self.expected_outcome {
Outcome::Positive => {
let async_result = AsyncResult::default();
let queue = SimpleJobQueue::new();
let context = &mut ContextBuilder::new()
.job_queue(&queue)
.build()
.expect("cannot fail with default global");
let context = &mut Context::default();
if let Err(e) = self.set_up_env(harness, context, async_result.clone()) {
return (false, e);

Loading…
Cancel
Save