@ -1,8 +1,10 @@
use std ::cell ::Cell ;
use crate ::{
environments ::CompileTimeEnvironment , error ::JsNativeError , object ::JsObject ,
syntax ::ast ::expression ::Identifier , Context , JsValue ,
} ;
use boa_gc ::{ Cell , Finalize , Gc , Trace } ;
use boa_gc ::{ Cell as GcCell , Finalize , Gc , Trace } ;
use rustc_hash ::FxHashSet ;
@ -28,8 +30,9 @@ use rustc_hash::FxHashSet;
/// All poisoned environments have to be checked for added bindings.
#[ derive(Debug, Trace, Finalize) ]
pub ( crate ) struct DeclarativeEnvironment {
bindings : Cell < Vec < Option < JsValue > > > ,
compile : Gc < Cell < CompileTimeEnvironment > > ,
bindings : GcCell < Vec < Option < JsValue > > > ,
compile : Gc < GcCell < CompileTimeEnvironment > > ,
#[ unsafe_ignore_trace ]
poisoned : Cell < bool > ,
slots : Option < EnvironmentSlots > ,
}
@ -37,13 +40,13 @@ pub(crate) struct DeclarativeEnvironment {
/// Describes the different types of internal slot data that an environment can hold.
#[ derive(Clone, Debug, Trace, Finalize) ]
pub ( crate ) enum EnvironmentSlots {
Function ( Cell < FunctionSlots > ) ,
Function ( Gc Cell< FunctionSlots > ) ,
Global ,
}
impl EnvironmentSlots {
/// Return the slots if they are part of a function environment.
pub ( crate ) fn as_function_slots ( & self ) -> Option < & Cell < FunctionSlots > > {
pub ( crate ) fn as_function_slots ( & self ) -> Option < & Gc Cell< FunctionSlots > > {
if let Self ::Function ( env ) = & self {
Some ( env )
} else {
@ -227,10 +230,10 @@ pub struct DeclarativeEnvironmentStack {
impl DeclarativeEnvironmentStack {
/// Create a new environment stack with the most outer declarative environment.
#[ inline ]
pub ( crate ) fn new ( global_compile_environment : Gc < Cell < CompileTimeEnvironment > > ) -> Self {
pub ( crate ) fn new ( global_compile_environment : Gc < Gc Cell< CompileTimeEnvironment > > ) -> Self {
Self {
stack : vec ! [ Gc ::new ( DeclarativeEnvironment {
bindings : Cell ::new ( Vec ::new ( ) ) ,
bindings : Gc Cell ::new ( Vec ::new ( ) ) ,
compile : global_compile_environment ,
poisoned : Cell ::new ( false ) ,
slots : Some ( EnvironmentSlots ::Global ) ,
@ -354,18 +357,17 @@ impl DeclarativeEnvironmentStack {
pub ( crate ) fn push_declarative (
& mut self ,
num_bindings : usize ,
compile_environment : Gc < Cell < CompileTimeEnvironment > > ,
compile_environment : Gc < Gc Cell< CompileTimeEnvironment > > ,
) {
let poisoned = self
. stack
. last ( )
. expect ( "global environment must always exist" )
. poisoned
. borrow ( )
. to_owned ( ) ;
. get ( ) ;
self . stack . push ( Gc ::new ( DeclarativeEnvironment {
bindings : Cell ::new ( vec! [ None ; num_bindings ] ) ,
bindings : Gc Cell ::new ( vec! [ None ; num_bindings ] ) ,
compile : compile_environment ,
poisoned : Cell ::new ( poisoned ) ,
slots : None ,
@ -381,7 +383,7 @@ impl DeclarativeEnvironmentStack {
pub ( crate ) fn push_function (
& mut self ,
num_bindings : usize ,
compile_environment : Gc < Cell < CompileTimeEnvironment > > ,
compile_environment : Gc < Gc Cell< CompileTimeEnvironment > > ,
this : Option < JsValue > ,
function_object : JsObject ,
new_target : Option < JsObject > ,
@ -392,7 +394,7 @@ impl DeclarativeEnvironmentStack {
. last ( )
. expect ( "global environment must always exist" ) ;
let poisoned = outer . poisoned . borrow ( ) . to_owned ( ) ;
let poisoned = outer . poisoned . get ( ) ;
let this_binding_status = if lexical {
ThisBindingStatus ::Lexical
@ -409,10 +411,10 @@ impl DeclarativeEnvironmentStack {
} ;
self . stack . push ( Gc ::new ( DeclarativeEnvironment {
bindings : Cell ::new ( vec! [ None ; num_bindings ] ) ,
bindings : Gc Cell ::new ( vec! [ None ; num_bindings ] ) ,
compile : compile_environment ,
poisoned : Cell ::new ( poisoned ) ,
slots : Some ( EnvironmentSlots ::Function ( Cell ::new ( FunctionSlots {
slots : Some ( EnvironmentSlots ::Function ( Gc Cell ::new ( FunctionSlots {
this ,
this_binding_status ,
function_object ,
@ -429,18 +431,18 @@ impl DeclarativeEnvironmentStack {
pub ( crate ) fn push_function_inherit (
& mut self ,
num_bindings : usize ,
compile_environment : Gc < Cell < CompileTimeEnvironment > > ,
compile_environment : Gc < Gc Cell< CompileTimeEnvironment > > ,
) {
let outer = self
. stack
. last ( )
. expect ( "global environment must always exist" ) ;
let poisoned = outer . poisoned . borrow ( ) . to_owned ( ) ;
let poisoned = outer . poisoned . get ( ) ;
let slots = outer . slots . clone ( ) ;
self . stack . push ( Gc ::new ( DeclarativeEnvironment {
bindings : Cell ::new ( vec! [ None ; num_bindings ] ) ,
bindings : Gc Cell ::new ( vec! [ None ; num_bindings ] ) ,
compile : compile_environment ,
poisoned : Cell ::new ( poisoned ) ,
slots ,
@ -474,7 +476,7 @@ impl DeclarativeEnvironmentStack {
/// # Panics
///
/// Panics if no environment exists on the stack.
pub ( crate ) fn current_compile_environment ( & self ) -> Gc < Cell < CompileTimeEnvironment > > {
pub ( crate ) fn current_compile_environment ( & self ) -> Gc < Gc Cell< CompileTimeEnvironment > > {
self . stack
. last ( )
. expect ( "global environment must always exist" )
@ -489,24 +491,21 @@ impl DeclarativeEnvironmentStack {
/// Panics if no environment exists on the stack.
#[ inline ]
pub ( crate ) fn poison_current ( & mut self ) {
let mut poisoned = self
. stack
self . stack
. last ( )
. expect ( "global environment must always exist" )
. poisoned
. borrow_mut ( ) ;
* poisoned = true ;
. set ( true ) ;
}
/// Mark that there may be added binding in all environments.
#[ inline ]
pub ( crate ) fn poison_all ( & mut self ) {
for env in & mut self . stack {
let mut poisoned = env . poisoned . borrow_mut ( ) ;
if * poisoned {
if env . poisoned . get ( ) {
return ;
}
* poisoned = true ;
env . poisoned . set ( true ) ;
}
}
@ -528,7 +527,7 @@ impl DeclarativeEnvironmentStack {
. stack
. get ( env_index )
. expect ( "environment index must be in range" ) ;
if ! * env . poisoned . borrow ( ) {
if ! env . poisoned . get ( ) {
break ;
}
let compile = env . compile . borrow ( ) ;
@ -559,7 +558,7 @@ impl DeclarativeEnvironmentStack {
#[ inline ]
pub ( crate ) fn get_value_global_poisoned ( & self , name : Identifier ) -> Option < JsValue > {
for env in self . stack . iter ( ) . rev ( ) {
if ! * env . poisoned . borrow ( ) {
if ! env . poisoned . get ( ) {
return None ;
}
let compile = env . compile . borrow ( ) ;
@ -624,7 +623,7 @@ impl DeclarativeEnvironmentStack {
. stack
. get ( env_index )
. expect ( "environment index must be in range" ) ;
if ! * env . poisoned . borrow ( ) {
if ! env . poisoned . get ( ) {
break ;
}
let compile = env . compile . borrow ( ) ;
@ -692,7 +691,7 @@ impl DeclarativeEnvironmentStack {
#[ inline ]
pub ( crate ) fn put_value_global_poisoned ( & mut self , name : Identifier , value : & JsValue ) -> bool {
for env in self . stack . iter ( ) . rev ( ) {
if ! * env . poisoned . borrow ( ) {
if ! env . poisoned . get ( ) {
return false ;
}
let compile = env . compile . borrow ( ) ;