Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion core/engine/src/builtins/function/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ impl MappedArguments {
/// [spec]: https://tc39.es/ecma262/#sec-makeargsetter
pub(crate) fn set(&self, index: u32, value: &JsValue) {
if let Some(binding_index) = self.binding_indices.get(index as usize).copied().flatten() {
self.environment.set(binding_index, value.clone());
// Mapped arguments always point to function-scope direct bindings,
// which cannot fail.
drop(self.environment.set(binding_index, value.clone()));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ pub(crate) fn function_call(
BindingLocatorScope::Stack(index),
0,
function_object.clone().into(),
);
)?;
last_env += 1;
}

Expand Down Expand Up @@ -1167,7 +1167,7 @@ fn function_construct(
BindingLocatorScope::Stack(index),
0,
this_function_object.clone().into(),
);
)?;
last_env += 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ impl FunctionEnvironment {
///
/// Panics if the binding value is out of range.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
self.bindings.borrow_mut()[index as usize] = Some(value);
Ok(())
}

/// Gets the bindings of this poisonable environment.
Expand Down
5 changes: 3 additions & 2 deletions core/engine/src/environments/runtime/declarative/global.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::JsValue;
use crate::{JsResult, JsValue};
use boa_gc::{Finalize, GcRefCell, Trace};

#[derive(Debug, Trace, Finalize)]
Expand Down Expand Up @@ -30,8 +30,9 @@ impl GlobalEnvironment {
///
/// Panics if the binding value is out of range.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
self.bindings.borrow_mut()[index as usize] = Some(value);
Ok(())
}

/// Gets the bindings of this poisonable environment.
Expand Down
5 changes: 3 additions & 2 deletions core/engine/src/environments/runtime/declarative/lexical.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use boa_gc::{Finalize, GcRefCell, Trace};

use crate::JsValue;
use crate::{JsResult, JsValue};

#[derive(Debug, Trace, Finalize)]
pub(crate) struct LexicalEnvironment {
Expand Down Expand Up @@ -31,8 +31,9 @@ impl LexicalEnvironment {
///
/// Panics if the binding value is out of range.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
self.bindings.borrow_mut()[index as usize] = Some(value);
Ok(())
}

/// Gets the bindings of this poisonable environment.
Expand Down
14 changes: 11 additions & 3 deletions core/engine/src/environments/runtime/declarative/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,16 @@ impl DeclarativeEnvironment {

/// Sets the binding value from the environment by index.
///
/// # Errors
///
/// Returns an error if the binding is an indirect module reference.
///
/// # Panics
///
/// Panics if the binding value is out of range.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
self.kind.set(index, value);
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
self.kind.set(index, value)
}

/// `GetThisBinding`
Expand Down Expand Up @@ -199,11 +203,15 @@ impl DeclarativeEnvironmentKind {

/// Sets the binding value from the environment by index.
///
/// # Errors
///
/// Returns an error if the binding is an indirect module reference.
///
/// # Panics
///
/// Panics if the binding value is out of range.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
match self {
Self::Lexical(inner) => inner.set(index, value),
Self::Global(inner) => inner.set(index, value),
Expand Down
18 changes: 11 additions & 7 deletions core/engine/src/environments/runtime/declarative/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::cell::RefCell;
use boa_ast::scope::Scope;
use boa_gc::{Finalize, GcRefCell, Trace};

use crate::{JsString, JsValue, module::Module};
use crate::{JsResult, JsString, JsValue, error::PanicError, module::Module};

/// Type of accessor used to access an indirect binding.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -95,18 +95,22 @@ impl ModuleEnvironment {

/// Sets the binding value from the environment by index.
///
/// # Panics
/// # Errors
///
/// Panics if the binding value is out of range.
/// Returns a `TypeError` if the binding is an indirect reference to another environment.
#[track_caller]
pub(crate) fn set(&self, index: u32, value: JsValue) {
pub(crate) fn set(&self, index: u32, value: JsValue) -> JsResult<()> {
let mut bindings = self.bindings.borrow_mut();

match &mut bindings[index as usize] {
BindingType::Direct(v) => *v = Some(value),
BindingType::Indirect(_) => {
panic!("cannot modify indirect references to other environments")
BindingType::Direct(v) => {
*v = Some(value);
Ok(())
}
BindingType::Indirect(_) => Err(PanicError::new(
"cannot modify indirect references to other environments",
)
.into()),
}
}

Expand Down
21 changes: 15 additions & 6 deletions core/engine/src/environments/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ impl EnvironmentStack {

/// Set the value of a lexical binding.
///
/// # Errors
///
/// Returns an error if the binding is an indirect module reference.
///
/// # Panics
///
/// Panics if the environment or binding index are out of range.
Expand All @@ -276,7 +280,7 @@ impl EnvironmentStack {
environment: BindingLocatorScope,
binding_index: u32,
value: JsValue,
) {
) -> JsResult<()> {
let env = match environment {
BindingLocatorScope::GlobalObject | BindingLocatorScope::GlobalDeclarative => {
self.global()
Expand All @@ -287,11 +291,15 @@ impl EnvironmentStack {
.and_then(Environment::as_declarative)
.expect("must be declarative environment"),
};
env.set(binding_index, value);
env.set(binding_index, value)
}

/// Set the value of a binding if it is uninitialized.
///
/// # Errors
///
/// Returns an error if the binding is an indirect module reference.
///
/// # Panics
///
/// Panics if the environment or binding index are out of range.
Expand All @@ -301,7 +309,7 @@ impl EnvironmentStack {
environment: BindingLocatorScope,
binding_index: u32,
value: JsValue,
) {
) -> JsResult<()> {
let env = match environment {
BindingLocatorScope::GlobalObject | BindingLocatorScope::GlobalDeclarative => {
self.global()
Expand All @@ -313,8 +321,9 @@ impl EnvironmentStack {
.expect("must be declarative environment"),
};
if env.get(binding_index).is_none() {
env.set(binding_index, value);
env.set(binding_index, value)?;
}
Ok(())
}

/// Push a private environment to the private environment stack.
Expand Down Expand Up @@ -559,11 +568,11 @@ impl Context {
}
BindingLocatorScope::GlobalDeclarative => {
let env = self.vm.frame().environments.global();
env.set(locator.binding_index(), value);
env.set(locator.binding_index(), value)?;
}
BindingLocatorScope::Stack(index) => match self.environment_expect(index) {
Environment::Declarative(decl) => {
decl.set(locator.binding_index(), value);
decl.set(locator.binding_index(), value)?;
}
Environment::Object(obj) => {
let key = locator.name().clone();
Expand Down
6 changes: 3 additions & 3 deletions core/engine/src/module/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1790,7 +1790,7 @@ impl SourceTextModule {
locator.scope(),
locator.binding_index(),
namespace.into(),
);
)?;
}
ImportBinding::Single {
locator,
Expand All @@ -1816,7 +1816,7 @@ impl SourceTextModule {
locator.scope(),
locator.binding_index(),
namespace.into(),
);
)?;
}
},
}
Expand All @@ -1832,7 +1832,7 @@ impl SourceTextModule {
locator.scope(),
locator.binding_index(),
function.into(),
);
)?;
}

// 25. Remove moduleContext from the execution context stack.
Expand Down
5 changes: 3 additions & 2 deletions core/engine/src/module/synthetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ impl SyntheticModule {
export_name.to_std_string_escaped()
))
})?;
env.set(locator.binding_index(), export_value);
env.set(locator.binding_index(), export_value)?;

Ok(())
}
Expand Down Expand Up @@ -346,7 +346,8 @@ impl SyntheticModule {
locator.scope(),
locator.binding_index(),
JsValue::undefined(),
);
)
.expect("synthetic module bindings are always direct");
}

let env = envs
Expand Down
4 changes: 3 additions & 1 deletion core/engine/src/vm/opcode/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,9 @@ async fn load_dyn_import(
match referrer {
Referrer::Module(mod_ref) => {
let ModuleKind::SourceText(src) = mod_ref.kind() else {
panic!("referrer cannot be a synthetic module");
return Err(JsNativeError::typ()
.with_message("referrer cannot be a synthetic module")
.into());
};

let mut loaded_modules = src.loaded_modules().borrow_mut();
Expand Down
8 changes: 4 additions & 4 deletions core/engine/src/vm/opcode/define/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) struct DefVar;

impl DefVar {
#[inline(always)]
pub(super) fn operation(index: IndexOperand, context: &mut Context) {
pub(super) fn operation(index: IndexOperand, context: &mut Context) -> JsResult<()> {
// TODO: spec specifies to return `empty` on empty vars, but we're trying to initialize.
let binding_locator = context.vm.frame().code_block.bindings[usize::from(index)].clone();

Expand All @@ -28,7 +28,7 @@ impl DefVar {
binding_locator.scope(),
binding_locator.binding_index(),
JsValue::undefined(),
);
)
}
}

Expand Down Expand Up @@ -80,14 +80,14 @@ impl PutLexicalValue {
pub(super) fn operation(
(value, index): (RegisterOperand, IndexOperand),
context: &mut Context,
) {
) -> JsResult<()> {
let value = context.vm.get_register(value.into()).clone();
let binding_locator = context.vm.frame().code_block.bindings[usize::from(index)].clone();
context.vm.frame_mut().environments.put_lexical_value(
binding_locator.scope(),
binding_locator.binding_index(),
value,
);
)
}
}

Expand Down
Loading