Skip to content

Commit

Permalink
Merge df32ca7 into ad7306d
Browse files Browse the repository at this point in the history
  • Loading branch information
0x7D2B authored Jun 2, 2021
2 parents ad7306d + df32ca7 commit a559070
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 177 deletions.
4 changes: 0 additions & 4 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,12 @@ impl Function {

// Create binding
local_env
.borrow_mut()
// Function parameters can share names in JavaScript...
.create_mutable_binding(param.name().to_owned(), false, true, context)
.expect("Failed to create binding for rest param");

// Set Binding to value
local_env
.borrow_mut()
.initialize_binding(param.name(), array, context)
.expect("Failed to initialize rest param");
}
Expand All @@ -147,13 +145,11 @@ impl Function {
) {
// Create binding
local_env
.borrow_mut()
.create_mutable_binding(param.name().to_owned(), false, true, context)
.expect("Failed to create binding");

// Set Binding to value
local_env
.borrow_mut()
.initialize_binding(param.name(), value, context)
.expect("Failed to intialize binding");
}
Expand Down
68 changes: 36 additions & 32 deletions boa/src/environment/declarative_environment_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,44 +34,41 @@ pub struct DeclarativeEnvironmentRecordBinding {
/// declarations contained within its scope.
#[derive(Debug, Trace, Finalize, Clone)]
pub struct DeclarativeEnvironmentRecord {
pub env_rec: FxHashMap<Box<str>, DeclarativeEnvironmentRecordBinding>,
pub env_rec: GcCell<FxHashMap<Box<str>, DeclarativeEnvironmentRecordBinding>>,
pub outer_env: Option<Environment>,
}

impl DeclarativeEnvironmentRecord {
#[allow(clippy::new_ret_no_self)]
pub fn new(env: Option<Environment>) -> Environment {
pub fn new(env: Option<Environment>) -> DeclarativeEnvironmentRecord {
let _timer = BoaProfiler::global().start_event("new_declarative_environment", "env");
let boxed_env = Box::new(DeclarativeEnvironmentRecord {
env_rec: FxHashMap::default(),
DeclarativeEnvironmentRecord {
env_rec: GcCell::new(FxHashMap::default()),
outer_env: env,
});

Gc::new(GcCell::new(boxed_env))
}
}
}

impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
fn has_binding(&self, name: &str) -> bool {
self.env_rec.contains_key(name)
self.env_rec.borrow().contains_key(name)
}

fn create_mutable_binding(
&mut self,
&self,
name: String,
deletion: bool,
allow_name_reuse: bool,
_context: &mut Context,
) -> Result<()> {
if !allow_name_reuse {
assert!(
!self.env_rec.contains_key(name.as_str()),
!self.env_rec.borrow().contains_key(name.as_str()),
"Identifier {} has already been declared",
name
);
}

self.env_rec.insert(
self.env_rec.borrow_mut().insert(
name.into_boxed_str(),
DeclarativeEnvironmentRecordBinding {
value: None,
Expand All @@ -84,18 +81,18 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
}

fn create_immutable_binding(
&mut self,
&self,
name: String,
strict: bool,
_context: &mut Context,
) -> Result<()> {
assert!(
!self.env_rec.contains_key(name.as_str()),
!self.env_rec.borrow().contains_key(name.as_str()),
"Identifier {} has already been declared",
name
);

self.env_rec.insert(
self.env_rec.borrow_mut().insert(
name.into_boxed_str(),
DeclarativeEnvironmentRecordBinding {
value: None,
Expand All @@ -107,13 +104,8 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}

fn initialize_binding(
&mut self,
name: &str,
value: Value,
_context: &mut Context,
) -> Result<()> {
if let Some(ref mut record) = self.env_rec.get_mut(name) {
fn initialize_binding(&self, name: &str, value: Value, _context: &mut Context) -> Result<()> {
if let Some(ref mut record) = self.env_rec.borrow_mut().get_mut(name) {
if record.value.is_none() {
record.value = Some(value);
return Ok(());
Expand All @@ -124,13 +116,13 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {

#[allow(clippy::else_if_without_else)]
fn set_mutable_binding(
&mut self,
&self,
name: &str,
value: Value,
mut strict: bool,
context: &mut Context,
) -> Result<()> {
if self.env_rec.get(name).is_none() {
if self.env_rec.borrow().get(name).is_none() {
if strict {
return Err(context.construct_reference_error(format!("{} not found", name)));
}
Expand All @@ -140,16 +132,22 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
return Ok(());
}

let record: &mut DeclarativeEnvironmentRecordBinding = self.env_rec.get_mut(name).unwrap();
if record.strict {
let (record_strict, record_has_no_value, record_mutable) = {
let env_rec = self.env_rec.borrow();
let record = env_rec.get(name).unwrap();
(record.strict, record.value.is_none(), record.mutable)
};
if record_strict {
strict = true
}
if record.value.is_none() {
if record_has_no_value {
return Err(
context.construct_reference_error(format!("{} has not been initialized", name))
);
}
if record.mutable {
if record_mutable {
let mut env_rec = self.env_rec.borrow_mut();
let record = env_rec.get_mut(name).unwrap();
record.value = Some(value);
} else if strict {
return Err(context.construct_reference_error(format!(
Expand All @@ -162,7 +160,7 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
}

fn get_binding_value(&self, name: &str, _strict: bool, context: &mut Context) -> Result<Value> {
if let Some(binding) = self.env_rec.get(name) {
if let Some(binding) = self.env_rec.borrow().get(name) {
if let Some(ref val) = binding.value {
Ok(val.clone())
} else {
Expand All @@ -173,11 +171,11 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
}
}

fn delete_binding(&mut self, name: &str) -> bool {
match self.env_rec.get(name) {
fn delete_binding(&self, name: &str) -> bool {
match self.env_rec.borrow().get(name) {
Some(binding) => {
if binding.can_delete {
self.env_rec.remove(name);
self.env_rec.borrow_mut().remove(name);
true
} else {
false
Expand Down Expand Up @@ -215,3 +213,9 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
EnvironmentType::Declarative
}
}

impl From<DeclarativeEnvironmentRecord> for Environment {
fn from(env: DeclarativeEnvironmentRecord) -> Environment {
Gc::new(Box::new(env))
}
}
29 changes: 12 additions & 17 deletions boa/src/environment/environment_record_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// Most variable names cannot be reused, but functions in JavaScript are allowed to have multiple
/// paraments with the same name.
fn create_mutable_binding(
&mut self,
&self,
name: String,
deletion: bool,
allow_name_reuse: bool,
Expand All @@ -46,7 +46,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// If strict is true then attempts to set it after it has been initialized will always throw an exception,
/// regardless of the strict mode setting of operations that reference that binding.
fn create_immutable_binding(
&mut self,
&self,
name: String,
strict: bool,
context: &mut Context,
Expand All @@ -55,15 +55,14 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// Set the value of an already existing but uninitialized binding in an Environment Record.
/// The String value N is the text of the bound name.
/// V is the value for the binding and is a value of any ECMAScript language type.
fn initialize_binding(&mut self, name: &str, value: Value, context: &mut Context)
-> Result<()>;
fn initialize_binding(&self, name: &str, value: Value, context: &mut Context) -> Result<()>;

/// Set the value of an already existing mutable binding in an Environment Record.
/// The String value `name` is the text of the bound name.
/// value is the `value` for the binding and may be a value of any ECMAScript language type. S is a Boolean flag.
/// If `strict` is true and the binding cannot be set throw a TypeError exception.
fn set_mutable_binding(
&mut self,
&self,
name: &str,
value: Value,
strict: bool,
Expand All @@ -80,7 +79,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
/// The String value name is the text of the bound name.
/// If a binding for name exists, remove the binding and return true.
/// If the binding exists but cannot be removed return false. If the binding does not exist return true.
fn delete_binding(&mut self, name: &str) -> bool;
fn delete_binding(&self, name: &str) -> bool;

/// Determine if an Environment Record establishes a this binding.
/// Return true if it does and false if it does not.
Expand Down Expand Up @@ -115,15 +114,15 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
self.get_this_binding(context)
} else {
match self.get_outer_environment_ref() {
Some(outer) => outer.borrow().recursive_get_this_binding(context),
Some(outer) => outer.recursive_get_this_binding(context),
None => Ok(Value::Undefined),
}
}
}

/// Create mutable binding while handling outer environments
fn recursive_create_mutable_binding(
&mut self,
&self,
name: String,
deletion: bool,
scope: VariableScope,
Expand All @@ -134,14 +133,13 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
VariableScope::Function => self
.get_outer_environment_ref()
.expect("No function or global environment")
.borrow_mut()
.recursive_create_mutable_binding(name, deletion, scope, context),
}
}

/// Create immutable binding while handling outer environments
fn recursive_create_immutable_binding(
&mut self,
&self,
name: String,
deletion: bool,
scope: VariableScope,
Expand All @@ -152,14 +150,13 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
VariableScope::Function => self
.get_outer_environment_ref()
.expect("No function or global environment")
.borrow_mut()
.recursive_create_immutable_binding(name, deletion, scope, context),
}
}

/// Set mutable binding while handling outer environments
fn recursive_set_mutable_binding(
&mut self,
&self,
name: &str,
value: Value,
strict: bool,
Expand All @@ -170,14 +167,13 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
} else {
self.get_outer_environment_ref()
.expect("Environment stack underflow")
.borrow_mut()
.recursive_set_mutable_binding(name, value, strict, context)
}
}

/// Initialize binding while handling outer environments
fn recursive_initialize_binding(
&mut self,
&self,
name: &str,
value: Value,
context: &mut Context,
Expand All @@ -187,7 +183,6 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
} else {
self.get_outer_environment_ref()
.expect("Environment stack underflow")
.borrow_mut()
.recursive_initialize_binding(name, value, context)
}
}
Expand All @@ -196,7 +191,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
fn recursive_has_binding(&self, name: &str) -> bool {
self.has_binding(name)
|| match self.get_outer_environment_ref() {
Some(outer) => outer.borrow().recursive_has_binding(name),
Some(outer) => outer.recursive_has_binding(name),
None => false,
}
}
Expand All @@ -207,7 +202,7 @@ pub trait EnvironmentRecordTrait: Debug + Trace + Finalize {
self.get_binding_value(name, false, context)
} else {
match self.get_outer_environment_ref() {
Some(outer) => outer.borrow().recursive_get_binding_value(name, context),
Some(outer) => outer.recursive_get_binding_value(name, context),
None => context.throw_reference_error(format!("{} is not defined", name)),
}
}
Expand Down
Loading

0 comments on commit a559070

Please sign in to comment.