Browse Source

Create a unique `PromiseCapability` on each async function call (#2846)

This Pull Request changes the following:

- Creates a new `PromiseCapability` after every async function call instead of sharing the same capability for all calls of the same async function.
pull/2858/head
José Julián Espina 2 years ago
parent
commit
338f6f8176
  1. 15
      boa_engine/src/builtins/function/mod.rs
  2. 29
      boa_engine/src/vm/code_block.rs

15
boa_engine/src/builtins/function/mod.rs

@ -42,7 +42,7 @@ use thin_vec::ThinVec;
use std::{fmt, io::Read}; use std::{fmt, io::Read};
use super::{promise::PromiseCapability, BuiltInBuilder, BuiltInConstructor, IntrinsicObject}; use super::{BuiltInBuilder, BuiltInConstructor, IntrinsicObject};
pub(crate) mod arguments; pub(crate) mod arguments;
#[cfg(test)] #[cfg(test)]
@ -189,9 +189,6 @@ pub(crate) enum FunctionKind {
/// The `[[HomeObject]]` internal slot. /// The `[[HomeObject]]` internal slot.
home_object: Option<JsObject>, home_object: Option<JsObject>,
/// The promise capability record of the async function.
promise_capability: PromiseCapability,
/// The class object that this function is associated with. /// The class object that this function is associated with.
class_object: Option<JsObject>, class_object: Option<JsObject>,
}, },
@ -270,14 +267,8 @@ unsafe impl Trace for FunctionKind {
} }
mark(class_object); mark(class_object);
} }
Self::Async { code, environments, home_object, promise_capability, class_object } => { Self::Async { code, environments, home_object, class_object }
mark(code); | Self::Generator { code, environments, home_object, class_object}
mark(environments);
mark(home_object);
mark(promise_capability);
mark(class_object);
}
Self::Generator { code, environments, home_object, class_object}
| Self::AsyncGenerator { code, environments, home_object, class_object} => { | Self::AsyncGenerator { code, environments, home_object, class_object} => {
mark(code); mark(code);
mark(environments); mark(environments);

29
boa_engine/src/vm/code_block.rs

@ -608,18 +608,11 @@ pub(crate) fn create_function_object(
.build(); .build();
let function = if r#async { let function = if r#async {
let promise_capability = PromiseCapability::new(
&context.intrinsics().constructors().promise().constructor(),
context,
)
.expect("cannot fail per spec");
Function::new( Function::new(
FunctionKind::Async { FunctionKind::Async {
code, code,
environments: context.vm.environments.clone(), environments: context.vm.environments.clone(),
home_object: None, home_object: None,
promise_capability,
class_object: None, class_object: None,
}, },
context.realm().clone(), context.realm().clone(),
@ -835,8 +828,7 @@ impl JsObject {
let context = &mut ContextCleanupGuard::new(context, realm, active_function); let context = &mut ContextCleanupGuard::new(context, realm, active_function);
let (code, mut environments, class_object, promise_cap, async_, gen) = let (code, mut environments, class_object, async_, gen) = match function_object.kind() {
match function_object.kind() {
FunctionKind::Native { FunctionKind::Native {
function, function,
constructor, constructor,
@ -869,7 +861,6 @@ impl JsObject {
code, code,
environments.clone(), environments.clone(),
class_object.clone(), class_object.clone(),
None,
false, false,
false, false,
) )
@ -878,14 +869,12 @@ impl JsObject {
FunctionKind::Async { FunctionKind::Async {
code, code,
environments, environments,
promise_capability,
class_object, class_object,
.. ..
} => ( } => (
code.clone(), code.clone(),
environments.clone(), environments.clone(),
class_object.clone(), class_object.clone(),
Some(promise_capability.clone()),
true, true,
false, false,
), ),
@ -898,7 +887,6 @@ impl JsObject {
code.clone(), code.clone(),
environments.clone(), environments.clone(),
class_object.clone(), class_object.clone(),
None,
false, false,
true, true,
), ),
@ -911,7 +899,6 @@ impl JsObject {
code.clone(), code.clone(),
environments.clone(), environments.clone(),
class_object.clone(), class_object.clone(),
None,
true, true,
true, true,
), ),
@ -919,6 +906,14 @@ impl JsObject {
drop(object); drop(object);
let promise_capability = (async_ && !gen).then(|| {
PromiseCapability::new(
&context.intrinsics().constructors().promise().constructor(),
context,
)
.expect("cannot fail per spec")
});
std::mem::swap(&mut environments, &mut context.vm.environments); std::mem::swap(&mut environments, &mut context.vm.environments);
let lexical_this_mode = code.this_mode == ThisMode::Lexical; let lexical_this_mode = code.this_mode == ThisMode::Lexical;
@ -1023,7 +1018,7 @@ impl JsObject {
let mut frame = CallFrame::new(code) let mut frame = CallFrame::new(code)
.with_param_count(param_count) .with_param_count(param_count)
.with_arg_count(arg_count); .with_arg_count(arg_count);
frame.promise_capability = promise_cap.clone(); frame.promise_capability = promise_capability.clone();
context.vm.push_frame(frame); context.vm.push_frame(frame);
@ -1036,8 +1031,8 @@ impl JsObject {
std::mem::swap(&mut environments, &mut context.vm.environments); std::mem::swap(&mut environments, &mut context.vm.environments);
std::mem::swap(&mut context.vm.stack, &mut stack); std::mem::swap(&mut context.vm.stack, &mut stack);
if let Some(promise_cap) = promise_cap { if let Some(promise_capability) = promise_capability {
Ok(promise_cap.promise().clone().into()) Ok(promise_capability.promise().clone().into())
} else if gen { } else if gen {
result?; result?;
let proto = this_function_object let proto = this_function_object

Loading…
Cancel
Save