Skip to content

Commit

Permalink
Implement arguments exotic object
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Aug 28, 2021
1 parent 57592c0 commit 1f5302e
Show file tree
Hide file tree
Showing 14 changed files with 765 additions and 84 deletions.
2 changes: 1 addition & 1 deletion boa/examples/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use boa::{
//
// The fields of the struct are not accessible by Javascript unless we create accessors for them.
/// Represents a `Person` object.
#[derive(Debug, Trace, Finalize)]
#[derive(Debug, Clone, Trace, Finalize)]
struct Person {
/// The name of the person.
name: String,
Expand Down
20 changes: 2 additions & 18 deletions boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,11 @@ impl BuiltIn for Array {
fn init(context: &mut Context) -> (&'static str, JsValue, Attribute) {
let _timer = BoaProfiler::global().start_event(Self::NAME, "init");

let symbol_iterator = WellKnownSymbols::iterator();

let get_species = FunctionBuilder::native(context, Self::get_species)
.name("get [Symbol.species]")
.constructable(false)
.build();

let values_function = FunctionBuilder::native(context, Self::values)
.name("values")
.length(0)
.constructable(false)
.build();

let array = ConstructorBuilder::with_standard_object(
context,
Self::constructor,
Expand All @@ -70,16 +62,8 @@ impl BuiltIn for Array {
0,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::PERMANENT,
)
.property(
"values",
values_function.clone(),
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.property(
symbol_iterator,
values_function,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.method(Self::values, "values", 0)
.method(Self::values, (WellKnownSymbols::iterator(), "values"), 0)
.method(Self::concat, "concat", 1)
.method(Self::push, "push", 1)
.method(Self::index_of, "indexOf", 1)
Expand Down
47 changes: 7 additions & 40 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
};
use bitflags::bitflags;
use dyn_clone::DynClone;

use sealed::Sealed;
use std::fmt::{self, Debug};

Expand Down Expand Up @@ -51,13 +52,16 @@ pub type NativeFunction = fn(&JsValue, &[JsValue], &mut Context) -> JsResult<JsV
/// be callable from Javascript, but most of the time the compiler
/// is smart enough to correctly infer the types.
pub trait ClosureFunction:
Fn(&JsValue, &[JsValue], &mut Context) -> JsResult<JsValue> + DynCopy + DynClone + 'static
Fn(&JsValue, &[JsValue], &mut Context, &mut JsObject) -> JsResult<JsValue>
+ DynCopy
+ DynClone
+ 'static
{
}

// The `Copy` bound automatically infers `DynCopy` and `DynClone`
impl<T> ClosureFunction for T where
T: Fn(&JsValue, &[JsValue], &mut Context) -> JsResult<JsValue> + Copy + 'static
T: Fn(&JsValue, &[JsValue], &mut Context, &mut JsObject) -> JsResult<JsValue> + Copy + 'static
{
}

Expand Down Expand Up @@ -122,6 +126,7 @@ pub enum Function {
#[unsafe_ignore_trace]
function: Box<dyn ClosureFunction>,
constructable: bool,
captures: JsObject,
},
Ordinary {
flags: FunctionFlags,
Expand Down Expand Up @@ -193,44 +198,6 @@ impl Function {
}
}

/// Arguments.
///
/// <https://tc39.es/ecma262/#sec-createunmappedargumentsobject>
pub fn create_unmapped_arguments_object(
arguments_list: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let len = arguments_list.len();
let obj = JsObject::new(Object::default());
// Set length
let length = PropertyDescriptor::builder()
.value(len)
.writable(true)
.enumerable(false)
.configurable(true);
// Define length as a property
crate::object::internal_methods::ordinary_define_own_property(
&obj,
"length".into(),
length.into(),
context,
)?;
let mut index: usize = 0;
while index < len {
let val = arguments_list.get(index).expect("Could not get argument");
let prop = PropertyDescriptor::builder()
.value(val.clone())
.writable(true)
.enumerable(true)
.configurable(true);

obj.insert(index, prop);
index += 1;
}

Ok(JsValue::new(obj))
}

/// Creates a new member function of a `Object` or `prototype`.
///
/// A function registered using this macro can then be called from Javascript using:
Expand Down
50 changes: 50 additions & 0 deletions boa/src/builtins/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::{
builtins::function::BuiltInFunction,
object::{JsObject, Object},
property::PropertyDescriptor,
Context, JsResult, JsValue,
};

use super::function::Function;

#[derive(Debug, Default)]
pub struct Intrinsics {
throw_type_error: JsObject,
}

impl Intrinsics {
pub fn init(context: &mut Context) -> Intrinsics {
Self {
throw_type_error: create_throw_type_error(context),
}
}

pub fn throw_type_error(&self) -> JsObject {
self.throw_type_error.clone()
}
}

fn create_throw_type_error(context: &mut Context) -> JsObject {
fn throw_type_error(_: &JsValue, _: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
context.throw_type_error("generic type error")
}
let mut function = Object::function(
Function::Native {
function: BuiltInFunction(throw_type_error),
constructable: false,
},
context
.standard_objects()
.function_object()
.prototype()
.into(),
);
let property = PropertyDescriptor::builder()
.writable(false)
.enumerable(false)
.configurable(false);
function.insert_property("name", property.clone().value("ThrowTypeError"));
function.insert_property("length", property.value(0));

JsObject::new(function)
}
1 change: 1 addition & 0 deletions boa/src/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod error;
pub mod function;
pub mod global_this;
pub mod infinity;
pub mod intrinsics;
pub mod iterable;
pub mod json;
pub mod map;
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ impl Object {
let o = o.borrow();
match o.kind() {
ObjectKind::Array => "Array",
// TODO: Arguments Exotic Objects are currently not supported
ObjectKind::Arguments(_) => "Arguments",
ObjectKind::Function(_) => "Function",
ObjectKind::Error => "Error",
ObjectKind::Boolean(_) => "Boolean",
Expand Down
26 changes: 19 additions & 7 deletions boa/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
builtins::{
self,
function::{Function, FunctionFlags, NativeFunction},
intrinsics::Intrinsics,
iterable::IteratorPrototypes,
},
class::{Class, ClassBuilder},
Expand Down Expand Up @@ -86,7 +87,7 @@ pub struct StandardObjects {
symbol: StandardConstructor,
error: StandardConstructor,
type_error: StandardConstructor,
referece_error: StandardConstructor,
reference_error: StandardConstructor,
range_error: StandardConstructor,
syntax_error: StandardConstructor,
eval_error: StandardConstructor,
Expand All @@ -109,7 +110,7 @@ impl Default for StandardObjects {
symbol: StandardConstructor::default(),
error: StandardConstructor::default(),
type_error: StandardConstructor::default(),
referece_error: StandardConstructor::default(),
reference_error: StandardConstructor::default(),
range_error: StandardConstructor::default(),
syntax_error: StandardConstructor::default(),
eval_error: StandardConstructor::default(),
Expand Down Expand Up @@ -173,7 +174,7 @@ impl StandardObjects {

#[inline]
pub fn reference_error_object(&self) -> &StandardConstructor {
&self.referece_error
&self.reference_error
}

#[inline]
Expand Down Expand Up @@ -271,6 +272,9 @@ pub struct Context {
/// Cached standard objects and their prototypes.
standard_objects: StandardObjects,

/// Cached intrinsic objects
intrinsics: Intrinsics,

/// Whether or not to show trace of instructions being ran
pub trace: bool,
}
Expand All @@ -285,15 +289,17 @@ impl Default for Context {
#[cfg(feature = "console")]
console: Console::default(),
iterator_prototypes: IteratorPrototypes::default(),
intrinsics: Intrinsics::default(),
standard_objects: Default::default(),
trace: false,
};

// Add new builtIns to Context Realm
// At a later date this can be removed from here and called explicitly,
// but for now we almost always want these default builtins
context.create_intrinsics();
context.init_builtins();
context.iterator_prototypes = IteratorPrototypes::init(&mut context);
context.intrinsics = Intrinsics::init(&mut context);
context
}
}
Expand Down Expand Up @@ -325,9 +331,9 @@ impl Context {

/// Sets up the default global objects within Global
#[inline]
fn create_intrinsics(&mut self) {
let _timer = BoaProfiler::global().start_event("create_intrinsics", "interpreter");
// Create intrinsics, add global objects here
fn init_builtins(&mut self) {
let _timer = BoaProfiler::global().start_event("init_builtins", "interpreter");
// Create builtin objects, add global objects here
builtins::init(self);
}

Expand Down Expand Up @@ -853,6 +859,12 @@ impl Context {
&self.standard_objects
}

/// Return the intrinsics.
#[inline]
pub fn intrinsics(&self) -> &Intrinsics {
&self.intrinsics
}

/// Set the value of trace on the context
pub fn set_trace(&mut self, trace: bool) {
self.trace = trace;
Expand Down
1 change: 0 additions & 1 deletion boa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ This is an experimental Javascript lexer, parser and compiler written in Rust. C
- **profiler** - Enables profiling with measureme (this is mostly internal).
**/

#![doc(
html_logo_url = "https://raw.githubusercontent.com/jasonwilliams/boa/master/assets/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/jasonwilliams/boa/master/assets/logo.svg"
Expand Down
Loading

0 comments on commit 1f5302e

Please sign in to comment.