Skip to content

Commit

Permalink
Store active runnable and active function in CallFrame (#3197)
Browse files Browse the repository at this point in the history
* Move acrive runnable to CallFrame

* Move active function to CallFrame

* Add some code doc

* Fix doc link

* Apply review
  • Loading branch information
HalidOdat authored Sep 16, 2023
1 parent 21d2afe commit 6a91a85
Show file tree
Hide file tree
Showing 30 changed files with 184 additions and 194 deletions.
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,7 @@ impl BuiltInConstructor for Array {
// If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| context.intrinsics().constructors().array().constructor())
.into()
} else {
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/async_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl BuiltInConstructor for AsyncFunction {
args: &[JsValue],
context: &mut Context<'_>,
) -> JsResult<JsValue> {
let active_function = context.vm.active_function.clone().unwrap_or_else(|| {
let active_function = context.active_function_object().unwrap_or_else(|| {
context
.intrinsics()
.constructors()
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/async_generator_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl BuiltInConstructor for AsyncGeneratorFunction {
args: &[JsValue],
context: &mut Context<'_>,
) -> JsResult<JsValue> {
let active_function = context.vm.active_function.clone().unwrap_or_else(|| {
let active_function = context.active_function_object().unwrap_or_else(|| {
context
.intrinsics()
.constructors()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ impl BuiltInConstructor for AggregateError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ impl BuiltInConstructor for EvalError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,7 @@ impl BuiltInConstructor for Error {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| context.intrinsics().constructors().error().constructor())
.into()
} else {
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ impl BuiltInConstructor for RangeError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ impl BuiltInConstructor for ReferenceError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ impl BuiltInConstructor for SyntaxError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,7 @@ impl BuiltInConstructor for TypeError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/error/uri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ impl BuiltInConstructor for UriError {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl Eval {
let env_fp = context.vm.environments.len() as u32;
context
.vm
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
.push_frame(CallFrame::new(code_block, None, None).with_env_fp(env_fp));
context.realm().resize_global_env();

let record = context.run();
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,7 @@ impl BuiltInConstructor for BuiltInFunctionObject {
context: &mut Context<'_>,
) -> JsResult<JsValue> {
let active_function = context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| context.intrinsics().constructors().function().constructor());
Self::create_dynamic_function(active_function, new_target, args, false, false, context)
.map(Into::into)
Expand Down
6 changes: 0 additions & 6 deletions boa_engine/src/builtins/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ unsafe impl Trace for GeneratorState {
pub(crate) struct GeneratorContext {
pub(crate) environments: EnvironmentStack,
pub(crate) stack: Vec<JsValue>,
pub(crate) active_function: Option<JsObject>,
pub(crate) call_frame: Option<CallFrame>,
pub(crate) realm: Realm,
}
Expand All @@ -70,14 +69,12 @@ impl GeneratorContext {
pub(crate) fn new(
environments: EnvironmentStack,
stack: Vec<JsValue>,
active_function: Option<JsObject>,
call_frame: CallFrame,
realm: Realm,
) -> Self {
Self {
environments,
stack,
active_function,
call_frame: Some(call_frame),
realm,
}
Expand All @@ -90,7 +87,6 @@ impl GeneratorContext {
environments: context.vm.environments.clone(),
call_frame: Some(context.vm.frame().clone()),
stack: context.vm.stack[fp..].to_vec(),
active_function: context.vm.active_function.clone(),
realm: context.realm().clone(),
};

Expand All @@ -108,7 +104,6 @@ impl GeneratorContext {
) -> CompletionRecord {
std::mem::swap(&mut context.vm.environments, &mut self.environments);
std::mem::swap(&mut context.vm.stack, &mut self.stack);
std::mem::swap(&mut context.vm.active_function, &mut self.active_function);
context.swap_realm(&mut self.realm);
context
.vm
Expand All @@ -125,7 +120,6 @@ impl GeneratorContext {

std::mem::swap(&mut context.vm.environments, &mut self.environments);
std::mem::swap(&mut context.vm.stack, &mut self.stack);
std::mem::swap(&mut context.vm.active_function, &mut self.active_function);
context.swap_realm(&mut self.realm);
self.call_frame = context.vm.pop_frame();
assert!(self.call_frame.is_some());
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/generator_function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl BuiltInConstructor for GeneratorFunction {
args: &[JsValue],
context: &mut Context<'_>,
) -> JsResult<JsValue> {
let active_function = context.vm.active_function.clone().unwrap_or_else(|| {
let active_function = context.active_function_object().unwrap_or_else(|| {
context
.intrinsics()
.constructors()
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/intl/collator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,7 @@ impl BuiltInConstructor for Collator {
// 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| context.intrinsics().constructors().collator().constructor())
.into()
} else {
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/intl/date_time_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ impl BuiltInConstructor for DateTimeFormat {
// 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
let new_target = &if new_target.is_undefined() {
context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| {
context
.intrinsics()
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl Json {
let env_fp = context.vm.environments.len() as u32;
context
.vm
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
.push_frame(CallFrame::new(code_block, None, None).with_env_fp(env_fp));
context.realm().resize_global_env();
let record = context.run();
context.vm.pop_frame();
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ impl BuiltInConstructor for Object {
if !new_target.is_undefined()
&& new_target
!= &context
.vm
.active_function
.clone()
.active_function_object()
.unwrap_or_else(|| context.intrinsics().constructors().object().constructor())
.into()
{
Expand Down
4 changes: 1 addition & 3 deletions boa_engine/src/builtins/regexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,7 @@ impl BuiltInConstructor for RegExp {
if new_target.is_undefined() {
// a. Let newTarget be the active function object.
let new_target = context
.vm
.active_function
.clone()
.active_function_object()
.map_or(JsValue::undefined(), JsValue::new);

// b. If patternIsRegExp is true and flags is undefined, then
Expand Down
37 changes: 36 additions & 1 deletion boa_engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
property::{Attribute, PropertyDescriptor, PropertyKey},
realm::Realm,
script::Script,
vm::{CallFrame, Vm},
vm::{ActiveRunnable, CallFrame, Vm},
JsResult, JsValue, Source,
};
use boa_ast::{expression::Identifier, StatementList};
Expand Down Expand Up @@ -706,6 +706,41 @@ impl Context<'_> {
pub(crate) const fn is_strict(&self) -> bool {
self.strict
}

/// `9.4.1 GetActiveScriptOrModule ( )`
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-getactivescriptormodule
pub(crate) fn get_active_script_or_module(&self) -> Option<ActiveRunnable> {
// 1. If the execution context stack is empty, return null.
// 2. Let ec be the topmost execution context on the execution context stack whose ScriptOrModule component is not null.
// 3. If no such execution context exists, return null. Otherwise, return ec's ScriptOrModule.
self.vm
.frames
.iter()
.rev()
.find_map(|frame| frame.active_runnable.clone())
}

/// Get `active function object`
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#active-function-object
pub(crate) fn active_function_object(&self) -> Option<JsObject> {
if self.vm.native_active_function.is_some() {
return self.vm.native_active_function.clone();
}

if let Some(frame) = self.vm.frames.last() {
return frame.active_function.clone();
}

None
}
}

impl<'host> Context<'host> {
Expand Down
11 changes: 2 additions & 9 deletions boa_engine/src/job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ 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 @@ -69,7 +68,6 @@ 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 @@ -87,19 +85,17 @@ 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, context: &mut Context<'_>) -> 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 @@ -115,7 +111,7 @@ 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(mut self, context: &mut Context<'_>) -> JsResult<JsValue> {
pub fn call(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.
Expand All @@ -126,12 +122,9 @@ impl NativeJob {
// 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 {
Expand Down
Loading

0 comments on commit 6a91a85

Please sign in to comment.