mod declarative_environment;
mod function_environment;
mod global_environment;
mod module_environment;
mod object_environment;
mod private_environment;
pub(crate) use declarative_environment::*;
pub(crate) use function_environment::*;
pub(crate) use global_environment::*;
pub(crate) use module_environment::*;
pub(crate) use object_environment::*;
pub(crate) use private_environment::*;
use std::ops::ControlFlow;
use crate::{
ecmascript::{
Agent, InternalMethods, JsResult, Object, PropertyLookupCache, Proxy, Reference, SetResult,
String, TryError, TryHasResult, TryResult, Value, js_result_into_try,
},
engine::{Bindable, GcScope, HeapRootData, NoGcScope, Scopable, bindable_handle},
heap::{CompactionLists, HeapIndexHandle, HeapMarkAndSweep, WorkQueues},
};
pub(crate) type OuterEnv<'a> = Option<Environment<'a>>;
macro_rules! create_environment_index {
($record: ident, $index: ident, $entry: ident) => {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub(crate) struct $index<'a>(crate::heap::BaseIndex<'a, $record>);
crate::heap::index_handle!($index);
impl core::fmt::Debug for $index<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"$index({:?})",
crate::heap::HeapIndexHandle::get_index_u32(*self)
)
}
}
impl<'a> crate::heap::DirectArenaAccess for $index<'a> {
type Data = $record;
type Output = $record;
#[inline]
fn get_direct(self, source: &Vec<Self::Data>) -> &Self::Output {
source
.get(crate::heap::HeapIndexHandle::get_index(self))
.expect("Invalid environment handle")
}
}
impl<'a> crate::heap::DirectArenaAccessMut for $index<'a> {
#[inline]
fn get_direct_mut(self, source: &mut Vec<Self::Data>) -> &mut Self::Output {
source
.get_mut(crate::heap::HeapIndexHandle::get_index(self))
.expect("Invalid environment handle")
}
}
impl AsRef<Vec<$record>> for crate::ecmascript::execution::Agent {
#[inline(always)]
fn as_ref(&self) -> &Vec<$record> {
&self.heap.environments.$entry
}
}
impl AsMut<Vec<$record>> for crate::ecmascript::execution::Agent {
#[inline(always)]
fn as_mut(&mut self) -> &mut Vec<$record> {
&mut self.heap.environments.$entry
}
}
};
}
create_environment_index!(
DeclarativeEnvironmentRecord,
DeclarativeEnvironment,
declarative
);
create_environment_index!(FunctionEnvironmentRecord, FunctionEnvironment, function);
create_environment_index!(GlobalEnvironmentRecord, GlobalEnvironment, global);
create_environment_index!(ObjectEnvironmentRecord, ObjectEnvironment, object);
create_environment_index!(ModuleEnvironmentRecord, ModuleEnvironment, module);
create_environment_index!(PrivateEnvironmentRecord, PrivateEnvironment, private);
impl<'a> From<DeclarativeEnvironment<'a>> for Environment<'a> {
fn from(value: DeclarativeEnvironment<'a>) -> Self {
Environment::Declarative(value)
}
}
impl<'a> From<GlobalEnvironment<'a>> for Environment<'a> {
fn from(value: GlobalEnvironment<'a>) -> Self {
Environment::Global(value)
}
}
impl<'a> From<ModuleEnvironment<'a>> for Environment<'a> {
fn from(value: ModuleEnvironment<'a>) -> Self {
Environment::Module(value)
}
}
impl<'a> From<ObjectEnvironment<'a>> for Environment<'a> {
fn from(value: ObjectEnvironment<'a>) -> Self {
Environment::Object(value)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub(crate) enum Environment<'a> {
Declarative(DeclarativeEnvironment<'a>) = 1,
Function(FunctionEnvironment<'a>),
Global(GlobalEnvironment<'a>),
Module(ModuleEnvironment<'a>),
Object(ObjectEnvironment<'a>),
}
bindable_handle!(Environment);
impl<'e> Environment<'e> {
pub(crate) fn get_outer_env(self, agent: &Agent) -> OuterEnv<'e> {
match self {
Environment::Declarative(e) => e.get_outer_env(agent),
Environment::Function(e) => e.get_outer_env(agent),
Environment::Global(_) => None,
Environment::Module(e) => e.get_outer_env(agent),
Environment::Object(e) => e.get_outer_env(agent),
}
}
pub(crate) fn try_has_binding<'gc>(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
gc: NoGcScope<'gc, '_>,
) -> ControlFlow<TryError<'gc>, TryHasBindingContinue<'gc>> {
match self {
Environment::Declarative(e) => {
TryHasBindingContinue::Result(e.has_binding(agent, name)).into()
}
Environment::Function(e) => {
TryHasBindingContinue::Result(e.has_binding(agent, name)).into()
}
Environment::Global(e) => e.try_has_binding(agent, name, cache, gc),
Environment::Module(e) => {
TryHasBindingContinue::Result(e.has_binding(agent, name)).into()
}
Environment::Object(e) => e.try_has_binding(agent, name, cache, gc),
}
}
pub(crate) fn has_binding<'a>(
self,
agent: &mut Agent,
name: String,
gc: GcScope<'a, '_>,
) -> JsResult<'a, bool> {
match self {
Environment::Declarative(e) => Ok(e.has_binding(agent, name)),
Environment::Function(e) => Ok(e.has_binding(agent, name)),
Environment::Global(e) => e.has_binding(agent, name, gc),
Environment::Module(e) => Ok(e.has_binding(agent, name)),
Environment::Object(e) => e.has_binding(agent, name, gc),
}
}
pub(crate) fn try_create_mutable_binding<'a>(
self,
agent: &mut Agent,
name: String,
is_deletable: bool,
cache: Option<PropertyLookupCache>,
gc: NoGcScope<'a, '_>,
) -> TryResult<'a, ()> {
match self {
Environment::Declarative(e) => {
e.create_mutable_binding(agent, name, is_deletable);
TryResult::Continue(())
}
Environment::Function(e) => {
e.create_mutable_binding(agent, name, is_deletable);
TryResult::Continue(())
}
Environment::Global(e) => {
js_result_into_try(e.create_mutable_binding(agent, name, is_deletable, gc))
}
Environment::Module(e) => {
e.create_mutable_binding(agent, name, is_deletable);
TryResult::Continue(())
}
Environment::Object(e) => {
e.try_create_mutable_binding(agent, name, is_deletable, cache, gc)
}
}
}
pub(crate) fn create_mutable_binding<'a>(
self,
agent: &mut Agent,
name: String,
is_deletable: bool,
gc: GcScope<'a, '_>,
) -> JsResult<'a, ()> {
match self {
Environment::Declarative(e) => {
e.create_mutable_binding(agent, name, is_deletable);
Ok(())
}
Environment::Function(e) => {
e.create_mutable_binding(agent, name, is_deletable);
Ok(())
}
Environment::Global(e) => {
e.create_mutable_binding(agent, name, is_deletable, gc.into_nogc())
}
Environment::Module(e) => {
e.create_mutable_binding(agent, name, is_deletable);
Ok(())
}
Environment::Object(e) => e.create_mutable_binding(agent, name, is_deletable, gc),
}
}
pub(crate) fn create_immutable_binding<'a>(
self,
agent: &mut Agent,
name: String,
is_strict: bool,
gc: NoGcScope<'a, '_>,
) -> JsResult<'a, ()> {
match self {
Environment::Declarative(e) => {
e.create_immutable_binding(agent, name, is_strict);
Ok(())
}
Environment::Function(e) => {
e.create_immutable_binding(agent, name, is_strict);
Ok(())
}
Environment::Global(e) => e.create_immutable_binding(agent, name, is_strict, gc),
Environment::Module(e) => {
debug_assert!(is_strict);
e.create_immutable_binding(agent, name);
Ok(())
}
Environment::Object(e) => {
e.create_immutable_binding(agent, name, is_strict);
Ok(())
}
}
}
pub(crate) fn try_initialize_binding<'gc>(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
value: Value,
gc: NoGcScope<'gc, '_>,
) -> TryResult<'gc, SetResult<'gc>> {
match self {
Environment::Declarative(e) => {
e.initialize_binding(agent, name, value);
SetResult::Done.into()
}
Environment::Function(e) => {
e.initialize_binding(agent, name, value);
SetResult::Done.into()
}
Environment::Global(e) => e.try_initialize_binding(agent, name, cache, value, gc),
Environment::Module(e) => {
e.initialize_binding(agent, name, value);
SetResult::Done.into()
}
Environment::Object(e) => e.try_initialize_binding(agent, name, cache, value, gc),
}
}
pub(crate) fn initialize_binding<'a>(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
value: Value,
gc: GcScope<'a, '_>,
) -> JsResult<'a, ()> {
match self {
Environment::Declarative(e) => {
e.initialize_binding(agent, name, value);
Ok(())
}
Environment::Function(e) => {
e.initialize_binding(agent, name, value);
Ok(())
}
Environment::Global(e) => e.initialize_binding(agent, name, cache, value, gc),
Environment::Module(e) => {
e.initialize_binding(agent, name, value);
Ok(())
}
Environment::Object(e) => e.initialize_binding(agent, name, cache, value, gc),
}
}
pub(crate) fn try_set_mutable_binding<'gc>(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
value: Value,
is_strict: bool,
gc: NoGcScope<'gc, '_>,
) -> TryResult<'gc, SetResult<'gc>> {
match self {
Environment::Declarative(e) => js_result_into_try(
e.set_mutable_binding(agent, name, value, is_strict, gc)
.map(|_| SetResult::Done),
),
Environment::Function(e) => js_result_into_try(
e.set_mutable_binding(agent, name, value, is_strict, gc)
.map(|_| SetResult::Done),
),
Environment::Global(e) => {
e.try_set_mutable_binding(agent, name, cache, value, is_strict, gc)
}
Environment::Module(e) => {
debug_assert!(is_strict);
js_result_into_try(
e.set_mutable_binding(agent, name, value, gc)
.map(|_| SetResult::Done),
)
}
Environment::Object(e) => {
e.try_set_mutable_binding(agent, name, cache, value, is_strict, gc)
}
}
}
pub(crate) fn set_mutable_binding<'a>(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
value: Value,
is_strict: bool,
gc: GcScope<'a, '_>,
) -> JsResult<'a, ()> {
match self {
Environment::Declarative(e) => {
e.set_mutable_binding(agent, name, value, is_strict, gc.into_nogc())
}
Environment::Function(e) => {
e.set_mutable_binding(agent, name, value, is_strict, gc.into_nogc())
}
Environment::Global(e) => {
e.set_mutable_binding(agent, name, cache, value, is_strict, gc)
}
Environment::Module(e) => e.set_mutable_binding(agent, name, value, gc.into_nogc()),
Environment::Object(e) => {
e.set_mutable_binding(agent, name, cache, value, is_strict, gc)
}
}
}
pub(crate) fn try_get_binding_value(
self,
agent: &mut Agent,
name: String,
cache: Option<PropertyLookupCache>,
is_strict: bool,
gc: NoGcScope<'e, '_>,
) -> TryResult<'e, Value<'e>> {
match self {
Environment::Declarative(e) => {
js_result_into_try(e.get_binding_value(agent, name, is_strict, gc))
}
Environment::Function(e) => {
js_result_into_try(e.get_binding_value(agent, name, is_strict, gc))
}
Environment::Global(e) => e.try_get_binding_value(agent, name, cache, is_strict, gc),
Environment::Module(e) => e.try_get_binding_value(agent, name, is_strict, gc),
Environment::Object(e) => e.try_get_binding_value(agent, name, cache, is_strict, gc),
}
}
pub(crate) fn get_binding_value<'a>(
self,
agent: &mut Agent,
name: String,
is_strict: bool,
gc: GcScope<'a, '_>,
) -> JsResult<'a, Value<'a>> {
match self {
Environment::Declarative(e) => {
let gc = gc.into_nogc();
e.bind(gc).get_binding_value(agent, name, is_strict, gc)
}
Environment::Function(e) => {
let gc = gc.into_nogc();
e.bind(gc).get_binding_value(agent, name, is_strict, gc)
}
Environment::Global(e) => e.get_binding_value(agent, name, is_strict, gc),
Environment::Module(e) => {
let gc = gc.into_nogc();
e.bind(gc)
.env_get_binding_value(agent, name, is_strict, gc.into_nogc())
}
Environment::Object(e) => e.get_binding_value(agent, name, is_strict, gc),
}
}
pub(crate) fn try_delete_binding<'a>(
self,
agent: &mut Agent,
name: String,
gc: NoGcScope<'a, '_>,
) -> TryResult<'a, bool> {
match self {
Environment::Declarative(e) => TryResult::Continue(e.delete_binding(agent, name)),
Environment::Function(e) => TryResult::Continue(e.delete_binding(agent, name)),
Environment::Global(e) => e.try_delete_binding(agent, name, gc),
Environment::Module(_) => unreachable!(),
Environment::Object(e) => TryResult::Continue(e.try_delete_binding(agent, name, gc)?),
}
}
pub(crate) fn delete_binding<'a>(
self,
agent: &mut Agent,
name: String,
gc: GcScope<'a, '_>,
) -> JsResult<'a, bool> {
match self {
Environment::Declarative(e) => Ok(e.delete_binding(agent, name)),
Environment::Function(e) => Ok(e.delete_binding(agent, name)),
Environment::Global(e) => e.delete_binding(agent, name, gc),
Environment::Module(_) => unreachable!(),
Environment::Object(e) => e.delete_binding(agent, name, gc),
}
}
pub(crate) fn has_this_binding(self, agent: &Agent) -> bool {
match self {
Environment::Declarative(_) => false,
Environment::Function(e) => e.has_this_binding(agent),
Environment::Global(_) => true,
Environment::Module(_) => true,
Environment::Object(_) => false,
}
}
pub(crate) fn get_this_binding(
self,
agent: &mut Agent,
gc: NoGcScope<'e, '_>,
) -> JsResult<'e, Value<'e>> {
match self {
Environment::Function(e) => e.get_this_binding(agent, gc),
Environment::Global(e) => Ok(e.get_this_binding(agent).into()),
Environment::Module(_) => Ok(Value::Undefined),
_ => unreachable!(),
}
}
pub(crate) fn has_super_binding(self, agent: &mut Agent) -> bool {
match self {
Environment::Function(e) => e.has_super_binding(agent),
_ => false,
}
}
pub(crate) fn with_base_object(self, agent: &mut Agent) -> Option<Object<'e>> {
match self {
Environment::Object(e) => e.with_base_object(agent),
_ => None,
}
}
}
impl core::fmt::Debug for Environment<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Environment::Declarative(d) => {
write!(f, "DeclarativeEnvironment({:?})", d.get_index_u32())
}
Environment::Function(d) => write!(f, "FunctionEnvironment({:?})", d.get_index_u32()),
Environment::Global(d) => write!(f, "GlobalEnvironment({:?})", d.get_index_u32()),
Environment::Module(d) => write!(f, "ModuleEnvironment({:?})", d.get_index_u32()),
Environment::Object(d) => write!(f, "ObjectEnvironment({:?})", d.get_index_u32()),
}
}
}
impl From<Environment<'_>> for HeapRootData {
fn from(value: Environment<'_>) -> Self {
match value {
Environment::Declarative(e) => Self::from(e),
Environment::Function(e) => Self::from(e),
Environment::Global(e) => Self::from(e),
Environment::Module(e) => Self::from(e),
Environment::Object(e) => Self::from(e),
}
}
}
impl TryFrom<HeapRootData> for Environment<'_> {
type Error = ();
fn try_from(value: HeapRootData) -> Result<Self, Self::Error> {
match value {
HeapRootData::DeclarativeEnvironment(e) => Ok(Self::Declarative(e)),
HeapRootData::FunctionEnvironment(e) => Ok(Self::Function(e)),
HeapRootData::GlobalEnvironment(e) => Ok(Self::Global(e)),
HeapRootData::ModuleEnvironment(e) => Ok(Self::Module(e)),
HeapRootData::ObjectEnvironment(e) => Ok(Self::Object(e)),
_ => Err(()),
}
}
}
impl HeapMarkAndSweep for Environment<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
match self {
Environment::Declarative(e) => e.mark_values(queues),
Environment::Function(e) => e.mark_values(queues),
Environment::Global(e) => e.mark_values(queues),
Environment::Module(e) => e.mark_values(queues),
Environment::Object(e) => e.mark_values(queues),
}
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
match self {
Environment::Declarative(e) => e.sweep_values(compactions),
Environment::Function(e) => e.sweep_values(compactions),
Environment::Global(e) => e.sweep_values(compactions),
Environment::Module(e) => e.sweep_values(compactions),
Environment::Object(e) => e.sweep_values(compactions),
}
}
}
#[derive(Debug)]
pub(crate) struct Environments {
pub(crate) declarative: Vec<DeclarativeEnvironmentRecord>,
pub(crate) function: Vec<FunctionEnvironmentRecord>,
pub(crate) global: Vec<GlobalEnvironmentRecord>,
pub(crate) object: Vec<ObjectEnvironmentRecord>,
pub(crate) module: Vec<ModuleEnvironmentRecord>,
pub(crate) private: Vec<PrivateEnvironmentRecord>,
}
impl Default for Environments {
fn default() -> Self {
Self {
declarative: Vec::with_capacity(256),
function: Vec::with_capacity(1024),
global: Vec::with_capacity(1),
object: Vec::with_capacity(1024),
module: Vec::with_capacity(8),
private: Vec::with_capacity(0),
}
}
}
pub(crate) enum TryHasBindingContinue<'a> {
Result(bool),
Proxy(Proxy<'a>),
}
bindable_handle!(TryHasBindingContinue);
impl<'a> TryFrom<TryHasBindingContinue<'a>> for bool {
type Error = Proxy<'a>;
fn try_from(value: TryHasBindingContinue<'a>) -> Result<Self, Self::Error> {
match value {
TryHasBindingContinue::Result(bool) => Ok(bool),
TryHasBindingContinue::Proxy(proxy) => Err(proxy),
}
}
}
impl<'a> From<TryHasResult<'a>> for TryHasBindingContinue<'a> {
fn from(value: TryHasResult<'a>) -> Self {
match value {
TryHasResult::Unset => Self::Result(false),
TryHasResult::Offset(_, _) | TryHasResult::Custom(_, _) => Self::Result(true),
TryHasResult::Proxy(proxy) => Self::Proxy(proxy),
}
}
}
impl<'a> From<TryHasResult<'a>> for TryResult<'a, TryHasBindingContinue<'a>> {
fn from(value: TryHasResult<'a>) -> Self {
Self::Continue(value.into())
}
}
impl<'a> From<TryHasBindingContinue<'a>> for TryResult<'a, TryHasBindingContinue<'a>> {
fn from(value: TryHasBindingContinue<'a>) -> Self {
Self::Continue(value)
}
}
pub(crate) fn try_get_identifier_reference<'a>(
agent: &mut Agent,
env: Environment,
name: String,
cache: Option<PropertyLookupCache>,
strict: bool,
gc: NoGcScope<'a, '_>,
) -> TryResult<'a, Reference<'a>> {
let env = env.bind(gc);
let name = name.bind(gc);
let cache = cache.bind(gc);
let exists = if let ControlFlow::Continue(TryHasBindingContinue::Result(exists)) =
env.try_has_binding(agent, name, cache, gc)
{
exists
} else {
return TryError::GcError.into();
};
if exists {
TryResult::Continue(Reference::new_variable_reference(env, name, cache, strict))
}
else {
let outer = env.get_outer_env(agent);
let Some(outer) = outer else {
return TryResult::Continue(Reference::new_unresolvable_reference(name, strict));
};
try_get_identifier_reference(agent, outer, name, cache, strict, gc)
}
}
pub(crate) fn get_identifier_reference<'a, 'b>(
agent: &mut Agent,
env: Option<Environment>,
name: String,
cache: Option<PropertyLookupCache>,
strict: bool,
mut gc: GcScope<'a, 'b>,
) -> JsResult<'a, Reference<'a>> {
let env = env.bind(gc.nogc());
let mut name = name.bind(gc.nogc());
let mut cache = cache.bind(gc.nogc());
let Some(mut env) = env else {
let name = name.unbind().bind(gc.into_nogc());
return Ok(Reference::new_unresolvable_reference(name, strict));
};
let exists = env.try_has_binding(agent, name, cache, gc.nogc());
let exists = if let ControlFlow::Continue(TryHasBindingContinue::Result(exists)) = exists {
exists
} else {
let env_scoped = env.scope(agent, gc.nogc());
let name_scoped = name.scope(agent, gc.nogc());
let cache_scoped = cache.map(|c| c.scope(agent, gc.nogc()));
let exists = handle_try_has_binding_result_cold(
agent,
env.unbind(),
name.unbind(),
exists.unbind(),
gc.reborrow(),
)
.unbind()?
.bind(gc.nogc());
unsafe {
cache = cache_scoped.map(|c| c.take(agent));
name = name_scoped.take(agent);
env = env_scoped.take(agent);
}
exists
};
if exists {
Ok(Reference::new_variable_reference(env, name, cache, strict).unbind())
}
else {
let outer = env.get_outer_env(agent);
get_identifier_reference(
agent,
outer.unbind(),
name.unbind(),
cache.unbind(),
strict,
gc,
)
}
}
#[cold]
#[inline(never)]
fn handle_try_has_binding_result_cold<'a>(
agent: &mut Agent,
env: Environment,
name: String,
exists: ControlFlow<TryError, TryHasBindingContinue>,
gc: GcScope<'a, '_>,
) -> JsResult<'a, bool> {
match exists {
ControlFlow::Continue(c) => match c {
TryHasBindingContinue::Result(exists) => Ok(exists),
TryHasBindingContinue::Proxy(proxy) => {
proxy
.unbind()
.internal_has_property(agent, name.to_property_key(), gc)
}
},
ControlFlow::Break(b) => match b {
TryError::Err(err) => Err(err.unbind().bind(gc.into_nogc())),
_ => env.unbind().has_binding(agent, name.unbind(), gc),
},
}
}
impl Environments {
pub(crate) fn push_declarative_environment<'a>(
&mut self,
env: DeclarativeEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> DeclarativeEnvironment<'a> {
self.declarative.push(env);
DeclarativeEnvironment::from_index_u32(self.declarative.len() as u32 - 1)
}
pub(crate) fn push_function_environment<'a>(
&mut self,
env: FunctionEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> FunctionEnvironment<'a> {
self.function.push(env);
FunctionEnvironment::from_index_u32(self.function.len() as u32 - 1)
}
pub(crate) fn push_global_environment<'a>(
&mut self,
env: GlobalEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> GlobalEnvironment<'a> {
self.global.push(env);
GlobalEnvironment::from_index_u32(self.global.len() as u32 - 1)
}
pub(crate) fn push_module_environment<'a>(
&mut self,
env: ModuleEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> ModuleEnvironment<'a> {
self.module.push(env);
ModuleEnvironment::from_index_u32(self.module.len() as u32 - 1)
}
pub(crate) fn push_object_environment<'a>(
&mut self,
env: ObjectEnvironmentRecord,
decl_env: DeclarativeEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> (ObjectEnvironment<'a>, DeclarativeEnvironment<'a>) {
self.object.push(env);
self.declarative.push(decl_env);
(
ObjectEnvironment::from_index_u32(self.object.len() as u32 - 1),
DeclarativeEnvironment::from_index_u32(self.declarative.len() as u32 - 1),
)
}
pub(crate) fn push_private_environment<'a>(
&mut self,
env: PrivateEnvironmentRecord,
_: NoGcScope<'a, '_>,
) -> PrivateEnvironment<'a> {
self.private.push(env);
PrivateEnvironment::from_index_u32(self.private.len() as u32 - 1)
}
pub(crate) fn get_declarative_environment(
&self,
index: DeclarativeEnvironment,
) -> &DeclarativeEnvironmentRecord {
self.declarative
.get(index.get_index())
.expect("DeclarativeEnvironment did not match to any vector index")
}
pub(crate) fn get_declarative_environment_mut(
&mut self,
index: DeclarativeEnvironment,
) -> &mut DeclarativeEnvironmentRecord {
self.declarative
.get_mut(index.get_index())
.expect("DeclarativeEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_function_environment(
&self,
index: FunctionEnvironment,
) -> &FunctionEnvironmentRecord {
self.function
.get(index.get_index())
.expect("FunctionEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_function_environment_mut(
&mut self,
index: FunctionEnvironment,
) -> &mut FunctionEnvironmentRecord {
self.function
.get_mut(index.get_index())
.expect("FunctionEnvironment did not match to any vector index")
}
pub(crate) fn get_module_environment(
&self,
index: ModuleEnvironment,
) -> &ModuleEnvironmentRecord {
self.module
.get(index.get_index())
.expect("ModuleEnvironment did not match to any vector index")
}
pub(crate) fn get_module_environment_mut(
&mut self,
index: ModuleEnvironment,
) -> &mut ModuleEnvironmentRecord {
self.module
.get_mut(index.get_index())
.expect("ModuleEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_global_environment(
&self,
index: GlobalEnvironment,
) -> &GlobalEnvironmentRecord {
self.global
.get(index.get_index())
.expect("GlobalEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_global_environment_mut(
&mut self,
index: GlobalEnvironment,
) -> &mut GlobalEnvironmentRecord {
self.global
.get_mut(index.get_index())
.expect("GlobalEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_object_environment(
&self,
index: ObjectEnvironment,
) -> &ObjectEnvironmentRecord {
self.object
.get(index.get_index())
.expect("ObjectEnvironment did not match to any vector index")
}
#[expect(dead_code)]
pub(crate) fn get_object_environment_mut(
&mut self,
index: ObjectEnvironment,
) -> &mut ObjectEnvironmentRecord {
self.object
.get_mut(index.get_index())
.expect("ObjectEnvironment did not match to any vector index")
}
pub(crate) fn get_private_environment(
&self,
index: PrivateEnvironment,
) -> &PrivateEnvironmentRecord {
self.private
.get(index.get_index())
.expect("PrivateEnvironment did not match to any vector index")
}
pub(crate) fn get_private_environment_mut(
&mut self,
index: PrivateEnvironment,
) -> &mut PrivateEnvironmentRecord {
self.private
.get_mut(index.get_index())
.expect("PrivateEnvironment did not match to any vector index")
}
}
pub(crate) fn get_this_environment<'a>(agent: &Agent, gc: NoGcScope<'a, '_>) -> Environment<'a> {
let mut env = agent.current_lexical_environment(gc);
loop {
if env.has_this_binding(agent) {
return env;
}
env = env.get_outer_env(agent).unwrap();
}
}
impl AsRef<Environments> for Environments {
fn as_ref(&self) -> &Environments {
self
}
}
impl AsMut<Environments> for Environments {
fn as_mut(&mut self) -> &mut Environments {
self
}
}
impl AsRef<Environments> for Agent {
fn as_ref(&self) -> &Environments {
&self.heap.environments
}
}
impl AsMut<Environments> for Agent {
fn as_mut(&mut self) -> &mut Environments {
&mut self.heap.environments
}
}