Skip to content

Commit

Permalink
Merge e9f61a0 into 323f486
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored May 22, 2020
2 parents 323f486 + e9f61a0 commit a0da1a2
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 119 deletions.
2 changes: 1 addition & 1 deletion boa/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(slice, named "slice", with length 2, of prototype);
make_builtin_fn!(some, named "some", with length 2, of prototype);

let array = make_constructor_fn(make_array, global, prototype);
let array = make_constructor_fn(make_array, global, prototype, true, true);

// Static Methods
make_builtin_fn!(is_array, named "isArray", with length 1, of array);
Expand Down
18 changes: 9 additions & 9 deletions boa/src/builtins/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,14 @@ pub fn to_string(this: &mut Value, args: &[Value], _ctx: &mut Interpreter) -> Re
))
}

// /// `BigInt.prototype.valueOf()`
// ///
// /// The `valueOf()` method returns the wrapped primitive value of a Number object.
// ///
// /// More information:
// /// - [ECMAScript reference][spec]
// /// - [MDN documentation][mdn]
// ///
/// `BigInt.prototype.valueOf()`
///
/// The `valueOf()` method returns the wrapped primitive value of a Number object.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf
pub fn value_of(this: &mut Value, _args: &[Value], _ctx: &mut Interpreter) -> ResultValue {
Expand All @@ -96,7 +96,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(to_string, named "toString", with length 1, of prototype);
make_builtin_fn!(value_of, named "valueOf", of prototype);

make_constructor_fn(make_bigint, global, prototype)
make_constructor_fn(make_bigint, global, prototype, false, true)
}

/// Initialise the `BigInt` object on the global object.
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/boolean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(to_string, named "toString", of prototype);
make_builtin_fn!(value_of, named "valueOf", of prototype);

make_constructor_fn(construct_boolean, global, prototype)
make_constructor_fn(construct_boolean, global, prototype, true, true)
}

/// Initialise the `Boolean` object on the global object.
Expand Down
3 changes: 2 additions & 1 deletion boa/src/builtins/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ pub fn create(global: &Value) -> Value {
prototype.set_field_slice("message", Value::from(""));
prototype.set_field_slice("name", Value::from("Error"));
make_builtin_fn!(to_string, named "toString", of prototype);
make_constructor_fn(make_error, global, prototype)

make_constructor_fn(make_error, global, prototype, true, true)
}

/// Initialise the global object with the `Error` object.
Expand Down
226 changes: 124 additions & 102 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ pub struct Function {
pub kind: FunctionKind,
// Environment, built-in functions don't need Environments
pub environment: Option<Environment>,
/// Is it constructable
constructable: bool,
/// Is it callable.
callable: bool,
}

impl Function {
Expand All @@ -123,6 +127,8 @@ impl Function {
params: parameter_list.into(),
kind: FunctionKind::Ordinary,
this_mode,
constructable: true,
callable: true,
}
}

Expand All @@ -139,6 +145,8 @@ impl Function {
this_mode: ThisMode::NonLexical,
kind: FunctionKind::BuiltIn,
environment: None,
constructable: false,
callable: true,
}
}

Expand All @@ -153,57 +161,61 @@ impl Function {
interpreter: &mut Interpreter,
this_obj: &mut Value,
) -> ResultValue {
match self.kind {
FunctionKind::BuiltIn => match &self.body {
FunctionBody::BuiltIn(func) => func(this_obj, args_list, interpreter),
FunctionBody::Ordinary(_) => {
panic!("Builtin function should not have Ordinary Function body")
}
},
FunctionKind::Ordinary => {
// Create a new Function environment who's parent is set to the scope of the function declaration (self.environment)
// <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment(
this.clone(),
None,
Some(self.environment.as_ref().unwrap().clone()),
BindingStatus::Uninitialized,
);

// Add argument bindings to the function environment
for i in 0..self.params.len() {
let param = self.params.get(i).expect("Could not get param");
// Rest Parameters
if param.is_rest_param {
self.add_rest_param(param, i, args_list, interpreter, &local_env);
break;
if self.callable {
match self.kind {
FunctionKind::BuiltIn => match &self.body {
FunctionBody::BuiltIn(func) => func(this_obj, args_list, interpreter),
FunctionBody::Ordinary(_) => {
panic!("Builtin function should not have Ordinary Function body")
}
},
FunctionKind::Ordinary => {
// Create a new Function environment who's parent is set to the scope of the function declaration (self.environment)
// <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment(
this.clone(),
None,
Some(self.environment.as_ref().unwrap().clone()),
BindingStatus::Uninitialized,
);

// Add argument bindings to the function environment
for i in 0..self.params.len() {
let param = self.params.get(i).expect("Could not get param");
// Rest Parameters
if param.is_rest_param {
self.add_rest_param(param, i, args_list, interpreter, &local_env);
break;
}

let value = args_list.get(i).expect("Could not get value");
self.add_arguments_to_environment(param, value.clone(), &local_env);
}

let value = args_list.get(i).expect("Could not get value");
self.add_arguments_to_environment(param, value.clone(), &local_env);
// Add arguments object
let arguments_obj = create_unmapped_arguments_object(args_list);
local_env
.borrow_mut()
.create_mutable_binding("arguments".to_string(), false);
local_env
.borrow_mut()
.initialize_binding("arguments", arguments_obj);

interpreter.realm.environment.push(local_env);

// Call body should be set before reaching here
let result = match &self.body {
FunctionBody::Ordinary(ref body) => interpreter.run(body),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};

// local_env gets dropped here, its no longer needed
interpreter.realm.environment.pop();
result
}

// Add arguments object
let arguments_obj = create_unmapped_arguments_object(args_list);
local_env
.borrow_mut()
.create_mutable_binding("arguments".to_string(), false);
local_env
.borrow_mut()
.initialize_binding("arguments", arguments_obj);

interpreter.realm.environment.push(local_env);

// Call body should be set before reaching here
let result = match &self.body {
FunctionBody::Ordinary(ref body) => interpreter.run(body),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};

// local_env gets dropped here, its no longer needed
interpreter.realm.environment.pop();
result
}
} else {
panic!("not callable");
}
}

Expand All @@ -215,59 +227,63 @@ impl Function {
interpreter: &mut Interpreter,
this_obj: &mut Value,
) -> ResultValue {
match self.kind {
FunctionKind::BuiltIn => match &self.body {
FunctionBody::BuiltIn(func) => {
func(this_obj, args_list, interpreter).unwrap();
Ok(this_obj.clone())
}
FunctionBody::Ordinary(_) => {
panic!("Builtin function should not have Ordinary Function body")
}
},
FunctionKind::Ordinary => {
// Create a new Function environment who's parent is set to the scope of the function declaration (self.environment)
// <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment(
this.clone(),
Some(this_obj.clone()),
Some(self.environment.as_ref().unwrap().clone()),
BindingStatus::Initialized,
);

// Add argument bindings to the function environment
for (i, param) in self.params.iter().enumerate() {
// Rest Parameters
if param.is_rest_param {
self.add_rest_param(param, i, args_list, interpreter, &local_env);
break;
if self.constructable {
match self.kind {
FunctionKind::BuiltIn => match &self.body {
FunctionBody::BuiltIn(func) => {
func(this_obj, args_list, interpreter).unwrap();
Ok(this_obj.clone())
}
FunctionBody::Ordinary(_) => {
panic!("Builtin function should not have Ordinary Function body")
}
},
FunctionKind::Ordinary => {
// Create a new Function environment who's parent is set to the scope of the function declaration (self.environment)
// <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment(
this.clone(),
Some(this_obj.clone()),
Some(self.environment.as_ref().unwrap().clone()),
BindingStatus::Initialized,
);

// Add argument bindings to the function environment
for (i, param) in self.params.iter().enumerate() {
// Rest Parameters
if param.is_rest_param {
self.add_rest_param(param, i, args_list, interpreter, &local_env);
break;
}

let value = args_list.get(i).expect("Could not get value");
self.add_arguments_to_environment(param, value.clone(), &local_env);
}

let value = args_list.get(i).expect("Could not get value");
self.add_arguments_to_environment(param, value.clone(), &local_env);
// Add arguments object
let arguments_obj = create_unmapped_arguments_object(args_list);
local_env
.borrow_mut()
.create_mutable_binding("arguments".to_string(), false);
local_env
.borrow_mut()
.initialize_binding("arguments", arguments_obj);

interpreter.realm.environment.push(local_env);

// Call body should be set before reaching here
let _ = match &self.body {
FunctionBody::Ordinary(ref body) => interpreter.run(body),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};

// local_env gets dropped here, its no longer needed
let binding = interpreter.realm.environment.get_this_binding();
Ok(binding)
}

// Add arguments object
let arguments_obj = create_unmapped_arguments_object(args_list);
local_env
.borrow_mut()
.create_mutable_binding("arguments".to_string(), false);
local_env
.borrow_mut()
.initialize_binding("arguments", arguments_obj);

interpreter.realm.environment.push(local_env);

// Call body should be set before reaching here
let _ = match &self.body {
FunctionBody::Ordinary(ref body) => interpreter.run(body),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};

// local_env gets dropped here, its no longer needed
let binding = interpreter.realm.environment.get_this_binding();
Ok(binding)
}
} else {
panic!("not constructable")
}
}

Expand Down Expand Up @@ -372,19 +388,25 @@ pub fn make_function(this: &mut Value, _: &[Value], _: &mut Interpreter) -> Resu
pub fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global));

make_constructor_fn(make_function, global, prototype)
make_constructor_fn(make_function, global, prototype, true, true)
}

/// Creates a new constructor function
///
/// This utility function handling linking the new Constructor to the prototype.
/// So far this is only used by internal functions
pub fn make_constructor_fn(body: NativeFunctionData, global: &Value, proto: Value) -> Value {
pub fn make_constructor_fn(
body: NativeFunctionData,
global: &Value,
proto: Value,
constructable: bool,
callable: bool,
) -> Value {
// Create the native function
let constructor_fn = crate::builtins::function::Function::create_builtin(
vec![],
crate::builtins::function::FunctionBody::BuiltIn(body),
);
let mut constructor_fn = Function::create_builtin(Vec::new(), FunctionBody::BuiltIn(body));

constructor_fn.constructable = constructable;
constructor_fn.callable = callable;

// Get reference to Function.prototype
let func_prototype = global
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/number/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(to_string, named "toString", with length 1, of prototype);
make_builtin_fn!(value_of, named "valueOf", of prototype);

make_constructor_fn(make_number, global, prototype)
make_constructor_fn(make_number, global, prototype, true, true)
}

/// Initialise the `Number` object on the global object.
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 @@ -614,7 +614,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(has_own_property, named "hasOwnProperty", of prototype);
make_builtin_fn!(to_string, named "toString", of prototype);

let object = make_constructor_fn(make_object, global, prototype);
let object = make_constructor_fn(make_object, global, prototype, true, true);

object.set_field_slice("length", Value::from(1));
make_builtin_fn!(set_prototype_of, named "setPrototypeOf", with length 2, of object);
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/regexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(get_sticky, named "sticky", of prototype);
make_builtin_fn!(get_unicode, named "unicode", of prototype);

make_constructor_fn(make_regexp, global, prototype)
make_constructor_fn(make_regexp, global, prototype, true, true)
}

/// Initialise the `RegExp` object on the global object.
Expand Down
2 changes: 1 addition & 1 deletion boa/src/builtins/string/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn!(match_all, named "matchAll", with length 1, of prototype);
make_builtin_fn!(replace, named "replace", with length 2, of prototype);

make_constructor_fn(make_string, global, prototype)
make_constructor_fn(make_string, global, prototype, true, true)
}

/// Initialise the `String` object on the global object.
Expand Down
3 changes: 2 additions & 1 deletion boa/src/builtins/symbol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ pub fn create(global: &Value) -> Value {
// Create prototype object
let prototype = Value::new_object(Some(global));
make_builtin_fn!(to_string, named "toString", of prototype);
make_constructor_fn(call_symbol, global, prototype)

make_constructor_fn(call_symbol, global, prototype, true, true)
}

/// Initialise the `Symbol` object on the global object.
Expand Down

0 comments on commit a0da1a2

Please sign in to comment.