Skip to content

Commit

Permalink
Expand ActiveRunnable to missing places
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed May 16, 2023
1 parent d1399d9 commit 6627500
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 79 deletions.
21 changes: 17 additions & 4 deletions boa_engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
string::utf16,
symbol::JsSymbol,
value::IntegerOrInfinity,
vm::CodeBlock,
vm::{ActiveRunnable, CodeBlock},
Context, JsArgs, JsResult, JsString, JsValue,
};
use boa_ast::{
Expand Down Expand Up @@ -176,6 +176,9 @@ pub(crate) enum FunctionKind {

/// The class object that this function is associated with.
class_object: Option<JsObject>,

/// The `[[ScriptOrModule]]` internal slot.
script_or_module: Option<ActiveRunnable>,
},

/// A bytecode async function.
Expand All @@ -191,6 +194,9 @@ pub(crate) enum FunctionKind {

/// The class object that this function is associated with.
class_object: Option<JsObject>,

/// The `[[ScriptOrModule]]` internal slot.
script_or_module: Option<ActiveRunnable>,
},

/// A bytecode generator function.
Expand All @@ -206,6 +212,9 @@ pub(crate) enum FunctionKind {

/// The class object that this function is associated with.
class_object: Option<JsObject>,

/// The `[[ScriptOrModule]]` internal slot.
script_or_module: Option<ActiveRunnable>,
},

/// A bytecode async generator function.
Expand All @@ -221,6 +230,9 @@ pub(crate) enum FunctionKind {

/// The class object that this function is associated with.
class_object: Option<JsObject>,

/// The `[[ScriptOrModule]]` internal slot.
script_or_module: Option<ActiveRunnable>,
},
}

Expand Down Expand Up @@ -267,13 +279,14 @@ unsafe impl Trace for FunctionKind {
}
mark(class_object);
}
Self::Async { code, environments, home_object, class_object }
| Self::Generator { code, environments, home_object, class_object}
| Self::AsyncGenerator { code, environments, home_object, class_object} => {
Self::Async { code, environments, home_object, class_object, script_or_module }
| Self::Generator { code, environments, home_object, class_object, script_or_module}
| Self::AsyncGenerator { code, environments, home_object, class_object, script_or_module} => {
mark(code);
mark(environments);
mark(home_object);
mark(class_object);
mark(script_or_module);
}
}
}}
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/builtins/promise/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2333,7 +2333,7 @@ fn new_promise_reaction_job(
};

// 4. Return the Record { [[Job]]: job, [[Realm]]: handlerRealm }.
NativeJob::with_realm(job, realm)
NativeJob::with_realm(job, realm, context)
}

/// More information:
Expand Down Expand Up @@ -2387,5 +2387,5 @@ fn new_promise_resolve_thenable_job(
};

// 6. Return the Record { [[Job]]: job, [[Realm]]: thenRealm }.
NativeJob::with_realm(job, realm)
NativeJob::with_realm(job, realm, context)
}
39 changes: 35 additions & 4 deletions boa_engine/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::{any::Any, cell::RefCell, collections::VecDeque, fmt::Debug, future::Fu
use crate::{
object::{JsFunction, NativeObject},
realm::Realm,
vm::ActiveRunnable,
Context, JsResult, JsValue,
};
use boa_gc::{Finalize, Trace};
Expand Down Expand Up @@ -68,6 +69,7 @@ pub struct NativeJob {
#[allow(clippy::type_complexity)]
f: Box<dyn FnOnce(&mut Context<'_>) -> JsResult<JsValue>>,
realm: Option<Realm>,
active_runnable: Option<ActiveRunnable>,
}

impl Debug for NativeJob {
Expand All @@ -85,17 +87,19 @@ impl NativeJob {
Self {
f: Box::new(f),
realm: None,
active_runnable: None,
}
}

/// Creates a new `NativeJob` from a closure and an execution realm.
pub fn with_realm<F>(f: F, realm: Realm) -> Self
pub fn with_realm<F>(f: F, realm: Realm, context: &mut Context<'_>) -> Self
where
F: FnOnce(&mut Context<'_>) -> JsResult<JsValue> + 'static,
{
Self {
f: Box::new(f),
realm: Some(realm),
active_runnable: context.vm.active_runnable.clone(),
}
}

Expand All @@ -110,11 +114,24 @@ impl NativeJob {
///
/// If the native job has an execution realm defined, this sets the running execution
/// context to the realm's before calling the inner closure, and resets it after execution.
pub fn call(self, context: &mut Context<'_>) -> JsResult<JsValue> {
pub fn call(mut self, context: &mut Context<'_>) -> JsResult<JsValue> {
// If realm is not null, each time job is invoked the implementation must perform
// implementation-defined steps such that execution is prepared to evaluate ECMAScript
// code at the time of job's invocation.
if let Some(realm) = self.realm {
let old_realm = context.enter_realm(realm);

// Let scriptOrModule be GetActiveScriptOrModule() at the time HostEnqueuePromiseJob is
// invoked. If realm is not null, each time job is invoked the implementation must
// perform implementation-defined steps such that scriptOrModule is the active script or
// module at the time of job's invocation.
std::mem::swap(&mut context.vm.active_runnable, &mut self.active_runnable);

let result = (self.f)(context);

context.enter_realm(old_realm);
std::mem::swap(&mut context.vm.active_runnable, &mut self.active_runnable);

result
} else {
(self.f)(context)
Expand Down Expand Up @@ -173,8 +190,22 @@ impl JobCallback {
pub trait JobQueue {
/// [`HostEnqueuePromiseJob ( job, realm )`][spec].
///
/// Enqueues a [`NativeJob`] on the job queue. Note that host-defined [Jobs] need to satisfy
/// a set of requirements for them to be spec-compliant.
/// Enqueues a [`NativeJob`] on the job queue.
///
/// # Requirements
///
/// Per the [spec]:
/// > An implementation of `HostEnqueuePromiseJob` must conform to the requirements in [9.5][Jobs] as well as the
/// following:
/// > - If `realm` is not null, each time `job` is invoked the implementation must perform implementation-defined steps
/// such that execution is prepared to evaluate ECMAScript code at the time of job's invocation.
/// > - Let `scriptOrModule` be `GetActiveScriptOrModule()` at the time `HostEnqueuePromiseJob` is invoked. If realm
/// is not null, each time job is invoked the implementation must perform implementation-defined steps such that
/// scriptOrModule is the active script or module at the time of job's invocation.
/// > - Jobs must run in the same order as the `HostEnqueuePromiseJob` invocations that scheduled them.
///
/// Of all the requirements, Boa guarantees the first two by its internal implementation of `NativeJob`, meaning
/// the implementer must only guarantee that jobs are run in the same order as they're enqueued.
///
/// [spec]: https://tc39.es/ecma262/#sec-hostenqueuepromisejob
/// [Jobs]: https://tc39.es/ecma262/#sec-jobs
Expand Down
Loading

0 comments on commit 6627500

Please sign in to comment.