Skip to content

Commit

Permalink
Merge e47bd59 into 2f4c47d
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored May 10, 2021
2 parents 2f4c47d + e47bd59 commit 247066f
Show file tree
Hide file tree
Showing 29 changed files with 532 additions and 655 deletions.
3 changes: 1 addition & 2 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ use crate::{
builtins::array::array_iterator::{ArrayIterationKind, ArrayIterator},
builtins::BuiltIn,
builtins::Number,
gc::GcObject,
object::{ConstructorBuilder, FunctionBuilder, ObjectData, PROTOTYPE},
object::{ConstructorBuilder, FunctionBuilder, GcObject, ObjectData, PROTOTYPE},
property::{Attribute, DataDescriptor},
value::{same_value_zero, IntegerOrInfinity, Value},
BoaProfiler, Context, Result,
Expand Down
9 changes: 5 additions & 4 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ impl Function {
local_env
.borrow_mut()
// Function parameters can share names in JavaScript...
.create_mutable_binding(param.name().to_owned(), false, true)
.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)
.initialize_binding(param.name(), array, context)
.expect("Failed to initialize rest param");
}

Expand All @@ -142,17 +142,18 @@ impl Function {
param: &FormalParameter,
value: Value,
local_env: &Environment,
context: &mut Context,
) {
// Create binding
local_env
.borrow_mut()
.create_mutable_binding(param.name().to_owned(), false, true)
.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)
.initialize_binding(param.name(), value, context)
.expect("Failed to intialize binding");
}

Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/global_this/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl BuiltIn for GlobalThis {

(
Self::NAME,
context.global_object().clone().into(),
context.global_object().into(),
Self::attribute(),
)
}
Expand Down
7 changes: 1 addition & 6 deletions boa/src/builtins/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,7 @@ impl Map {
}
let map_prototype = context
.global_object()
.clone()
.get(
&"Map".into(),
context.global_object().clone().into(),
context,
)?
.get(&"Map".into(), context.global_object().into(), context)?
.get_field(PROTOTYPE, context)?
.as_object()
.expect("'Map' global property should be an object");
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub fn init(context: &mut Context) {
console::Console::init,
];

let global_object = context.global_object().clone();
let global_object = context.global_object();

for init in &globals {
let (name, value, attribute) = init(context);
Expand Down
29 changes: 8 additions & 21 deletions boa/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ impl StandardObjects {
#[derive(Debug)]
pub struct Context {
/// realm holds both the global object and the environment
realm: Realm,
pub(crate) realm: Realm,

/// The current executor.
executor: Interpreter,
Expand Down Expand Up @@ -270,16 +270,6 @@ impl Context {
Default::default()
}

#[inline]
pub fn realm(&self) -> &Realm {
&self.realm
}

#[inline]
pub fn realm_mut(&mut self) -> &mut Realm {
&mut self.realm
}

#[inline]
pub fn executor(&mut self) -> &mut Interpreter {
&mut self.executor
Expand Down Expand Up @@ -340,8 +330,8 @@ impl Context {

/// Return the global object.
#[inline]
pub fn global_object(&self) -> &GcObject {
&self.realm().global_object
pub fn global_object(&self) -> GcObject {
self.realm.global_object.clone()
}

/// Constructs a `RangeError` with the specified message.
Expand Down Expand Up @@ -503,7 +493,7 @@ impl Context {
flags,
body: RcStatementList::from(body.into()),
params,
environment: self.realm.environment.get_current_environment().clone(),
environment: self.get_current_environment().clone(),
};

let new_func = Object::function(func, function_prototype);
Expand Down Expand Up @@ -555,7 +545,7 @@ impl Context {
body: NativeFunction,
) -> Result<()> {
let function = self.create_builtin_function(name, length, body)?;
let mut global = self.global_object().clone();
let mut global = self.global_object();
global.insert_property(name, function, Attribute::all());
Ok(())
}
Expand All @@ -574,10 +564,7 @@ impl Context {
pub(crate) fn set_value(&mut self, node: &Node, value: Value) -> Result<Value> {
match node {
Node::Identifier(ref name) => {
self.realm
.environment
.set_mutable_binding(name.as_ref(), value.clone(), true)
.map_err(|e| e.to_error(self))?;
self.set_mutable_binding(name.as_ref(), value.clone(), true)?;
Ok(value)
}
Node::GetConstField(ref get_const_field_node) => Ok(get_const_field_node
Expand Down Expand Up @@ -616,7 +603,7 @@ impl Context {

let class = class_builder.build();
let property = DataDescriptor::new(class, T::ATTRIBUTE);
self.global_object().clone().insert(T::NAME, property);
self.global_object().insert(T::NAME, property);
Ok(())
}

Expand All @@ -643,7 +630,7 @@ impl Context {
V: Into<Value>,
{
let property = DataDescriptor::new(value, attribute);
self.global_object().clone().insert(key, property);
self.global_object().insert(key, property);
}

/// Evaluates the given code.
Expand Down
86 changes: 49 additions & 37 deletions boa/src/environment/declarative_environment_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
//! A declarative Environment Record binds the set of identifiers defined by the declarations contained within its scope.
//! More info: [ECMA-262 sec-declarative-environment-records](https://tc39.es/ecma262/#sec-declarative-environment-records)

use super::ErrorKind;
use crate::{
environment::{
environment_record_trait::EnvironmentRecordTrait,
lexical_environment::{Environment, EnvironmentType},
},
gc::{Finalize, Trace},
Value,
object::GcObject,
BoaProfiler, Context, Result, Value,
};
use gc::{Gc, GcCell};
use rustc_hash::FxHashMap;

/// Declarative Bindings have a few properties for book keeping purposes, such as mutability (const vs let).
Expand All @@ -33,10 +34,23 @@ pub struct DeclarativeEnvironmentRecordBinding {
/// declarations contained within its scope.
#[derive(Debug, Trace, Finalize, Clone)]
pub struct DeclarativeEnvironmentRecord {
pub env_rec: FxHashMap<String, DeclarativeEnvironmentRecordBinding>,
pub env_rec: FxHashMap<Box<str>, DeclarativeEnvironmentRecordBinding>,
pub outer_env: Option<Environment>,
}

impl DeclarativeEnvironmentRecord {
#[allow(clippy::new_ret_no_self)]
pub fn new(env: Option<Environment>) -> Environment {
let _timer = BoaProfiler::global().start_event("new_declarative_environment", "env");
let boxed_env = Box::new(DeclarativeEnvironmentRecord {
env_rec: 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)
Expand All @@ -47,17 +61,18 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
name: String,
deletion: bool,
allow_name_reuse: bool,
) -> Result<(), ErrorKind> {
_context: &mut Context,
) -> Result<()> {
if !allow_name_reuse {
assert!(
!self.env_rec.contains_key(&name),
!self.env_rec.contains_key(name.as_str()),
"Identifier {} has already been declared",
name
);
}

self.env_rec.insert(
name,
name.into_boxed_str(),
DeclarativeEnvironmentRecordBinding {
value: None,
can_delete: deletion,
Expand All @@ -68,15 +83,20 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}

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

self.env_rec.insert(
name,
name.into_boxed_str(),
DeclarativeEnvironmentRecordBinding {
value: None,
can_delete: true,
Expand All @@ -87,7 +107,12 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}

fn initialize_binding(&mut self, name: &str, value: Value) -> Result<(), ErrorKind> {
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) {
if record.value.is_none() {
record.value = Some(value);
Expand All @@ -103,17 +128,15 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
name: &str,
value: Value,
mut strict: bool,
) -> Result<(), ErrorKind> {
context: &mut Context,
) -> Result<()> {
if self.env_rec.get(name).is_none() {
if strict {
return Err(ErrorKind::new_reference_error(format!(
"{} not found",
name
)));
return Err(context.construct_reference_error(format!("{} not found", name)));
}

self.create_mutable_binding(name.to_owned(), true, false)?;
self.initialize_binding(name, value)?;
self.create_mutable_binding(name.to_owned(), true, false, context)?;
self.initialize_binding(name, value, context)?;
return Ok(());
}

Expand All @@ -122,15 +145,14 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
strict = true
}
if record.value.is_none() {
return Err(ErrorKind::new_reference_error(format!(
"{} has not been initialized",
name
)));
return Err(
context.construct_reference_error(format!("{} has not been initialized", name))
);
}
if record.mutable {
record.value = Some(value);
} else if strict {
return Err(ErrorKind::new_type_error(format!(
return Err(context.construct_reference_error(format!(
"Cannot mutate an immutable binding {}",
name
)));
Expand All @@ -139,15 +161,12 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
Ok(())
}

fn get_binding_value(&self, name: &str, _strict: bool) -> Result<Value, ErrorKind> {
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(ref val) = binding.value {
Ok(val.clone())
} else {
Err(ErrorKind::new_reference_error(format!(
"{} is an uninitialized binding",
name
)))
context.throw_reference_error(format!("{} is an uninitialized binding", name))
}
} else {
panic!("Cannot get binding value for {}", name);
Expand All @@ -172,16 +191,16 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
false
}

fn get_this_binding(&self) -> Result<Value, ErrorKind> {
fn get_this_binding(&self, _context: &mut Context) -> Result<Value> {
Ok(Value::undefined())
}

fn has_super_binding(&self) -> bool {
false
}

fn with_base_object(&self) -> Value {
Value::undefined()
fn with_base_object(&self) -> Option<GcObject> {
None
}

fn get_outer_environment_ref(&self) -> Option<&Environment> {
Expand All @@ -195,11 +214,4 @@ impl EnvironmentRecordTrait for DeclarativeEnvironmentRecord {
fn get_environment_type(&self) -> EnvironmentType {
EnvironmentType::Declarative
}

fn get_global_object(&self) -> Option<Value> {
match &self.outer_env {
Some(outer) => outer.borrow().get_global_object(),
None => None,
}
}
}
Loading

0 comments on commit 247066f

Please sign in to comment.