Browse Source

Fixed function object constructable/callable (#409)

- Maded arrow functions non-constructable
 - Simplified Function object and removed FunctionKind
 - Rnamed create_ordinary -> ordinary, create_builtin -> builtin
 - Added name and length properties in global objects
pull/424/head
HalidOdat 5 years ago committed by GitHub
parent
commit
d42e413f8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      boa/src/builtins/array/mod.rs
  2. 18
      boa/src/builtins/bigint/mod.rs
  3. 9
      boa/src/builtins/boolean/mod.rs
  4. 5
      boa/src/builtins/error/mod.rs
  5. 5
      boa/src/builtins/error/range.rs
  6. 166
      boa/src/builtins/function/mod.rs
  7. 2
      boa/src/builtins/mod.rs
  8. 17
      boa/src/builtins/number/mod.rs
  9. 14
      boa/src/builtins/object/mod.rs
  10. 2
      boa/src/builtins/regexp/mod.rs
  11. 2
      boa/src/builtins/string/mod.rs
  12. 3
      boa/src/builtins/symbol/mod.rs
  13. 2
      boa/src/builtins/value/mod.rs
  14. 6
      boa/src/exec/declaration/mod.rs
  15. 17
      boa/src/exec/mod.rs
  16. 7
      boa/src/realm.rs

2
boa/src/builtins/array/mod.rs

@ -1031,7 +1031,7 @@ impl Array {
make_builtin_fn(Self::slice, "slice", &prototype, 2); make_builtin_fn(Self::slice, "slice", &prototype, 2);
make_builtin_fn(Self::some, "some", &prototype, 2); make_builtin_fn(Self::some, "some", &prototype, 2);
let array = make_constructor_fn(Self::make_array, global, prototype); let array = make_constructor_fn("Array", 1, Self::make_array, global, prototype, true);
// Static Methods // Static Methods
make_builtin_fn(Self::is_array, "isArray", &array, 1); make_builtin_fn(Self::is_array, "isArray", &array, 1);

18
boa/src/builtins/bigint/mod.rs

@ -96,14 +96,14 @@ impl BigInt {
)) ))
} }
// /// `BigInt.prototype.valueOf()` /// `BigInt.prototype.valueOf()`
// /// ///
// /// The `valueOf()` method returns the wrapped primitive value of a Number object. /// The `valueOf()` method returns the wrapped primitive value of a Number object.
// /// ///
// /// More information: /// More information:
// /// - [ECMAScript reference][spec] /// - [ECMAScript reference][spec]
// /// - [MDN documentation][mdn] /// - [MDN documentation][mdn]
// /// ///
/// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof /// [spec]: https://tc39.es/ecma262/#sec-bigint.prototype.valueof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt/valueOf
pub(crate) fn value_of( pub(crate) fn value_of(
@ -124,7 +124,7 @@ impl BigInt {
make_builtin_fn(Self::to_string, "toString", &prototype, 1); make_builtin_fn(Self::to_string, "toString", &prototype, 1);
make_builtin_fn(Self::value_of, "valueOf", &prototype, 0); make_builtin_fn(Self::value_of, "valueOf", &prototype, 0);
make_constructor_fn(Self::make_bigint, global, prototype) make_constructor_fn("BigInt", 1, Self::make_bigint, global, prototype, false)
} }
/// Initialise the `BigInt` object on the global object. /// Initialise the `BigInt` object on the global object.

9
boa/src/builtins/boolean/mod.rs

@ -115,7 +115,14 @@ impl Boolean {
make_builtin_fn(Self::to_string, "toString", &prototype, 0); make_builtin_fn(Self::to_string, "toString", &prototype, 0);
make_builtin_fn(Self::value_of, "valueOf", &prototype, 0); make_builtin_fn(Self::value_of, "valueOf", &prototype, 0);
make_constructor_fn(Self::construct_boolean, global, prototype) make_constructor_fn(
"Boolean",
1,
Self::construct_boolean,
global,
prototype,
true,
)
} }
/// Initialise the `Boolean` object on the global object. /// Initialise the `Boolean` object on the global object.

5
boa/src/builtins/error/mod.rs

@ -72,9 +72,10 @@ impl Error {
pub(crate) fn create(global: &Value) -> Value { pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global)); let prototype = Value::new_object(Some(global));
prototype.set_field("message", Value::from("")); prototype.set_field("message", Value::from(""));
prototype.set_field("name", Value::from("Error"));
make_builtin_fn(Self::to_string, "toString", &prototype, 0); make_builtin_fn(Self::to_string, "toString", &prototype, 0);
make_constructor_fn(Self::make_error, global, prototype)
make_constructor_fn("Error", 1, Self::make_error, global, prototype, true)
} }
/// Initialise the global object with the `Error` object. /// Initialise the global object with the `Error` object.

5
boa/src/builtins/error/range.rs

@ -63,9 +63,10 @@ impl RangeError {
pub(crate) fn create(global: &Value) -> Value { pub(crate) fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global)); let prototype = Value::new_object(Some(global));
prototype.set_field("message", Value::from("")); prototype.set_field("message", Value::from(""));
prototype.set_field("name", Value::from("RangeError"));
make_builtin_fn(Self::to_string, "toString", &prototype, 0); make_builtin_fn(Self::to_string, "toString", &prototype, 0);
make_constructor_fn(Self::make_error, global, prototype)
make_constructor_fn("RangeError", 1, Self::make_error, global, prototype, true)
} }
/// Runs a `new RangeError(message)`. /// Runs a `new RangeError(message)`.

166
boa/src/builtins/function/mod.rs

@ -14,7 +14,7 @@
use crate::{ use crate::{
builtins::{ builtins::{
array::Array, array::Array,
object::{Object, ObjectInternalMethods, ObjectKind, PROTOTYPE}, object::{Object, ObjectInternalMethods, ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE},
property::Property, property::Property,
value::{ResultValue, Value}, value::{ResultValue, Value},
}, },
@ -72,18 +72,6 @@ unsafe impl Trace for FunctionBody {
unsafe_empty_trace!(); unsafe_empty_trace!();
} }
/// Signal what sort of function this is
#[derive(Clone, Debug, Copy, Finalize)]
pub enum FunctionKind {
BuiltIn,
Ordinary,
}
/// Waiting on <https://github.com/Manishearth/rust-gc/issues/87> until we can derive Copy
unsafe impl Trace for FunctionKind {
unsafe_empty_trace!();
}
/// Boa representation of a Function Object. /// Boa representation of a Function Object.
/// ///
/// <https://tc39.es/ecma262/#sec-ecmascript-function-objects> /// <https://tc39.es/ecma262/#sec-ecmascript-function-objects>
@ -95,48 +83,73 @@ pub struct Function {
pub params: Box<[FormalParameter]>, pub params: Box<[FormalParameter]>,
/// This Mode /// This Mode
pub this_mode: ThisMode, pub this_mode: ThisMode,
/// Function kind
pub kind: FunctionKind,
// Environment, built-in functions don't need Environments // Environment, built-in functions don't need Environments
pub environment: Option<Environment>, pub environment: Option<Environment>,
/// Is it constructable
constructable: bool,
/// Is it callable.
callable: bool,
} }
impl Function { impl Function {
/// This will create an ordinary function object pub fn new<P>(
///
/// <https://tc39.es/ecma262/#sec-ordinaryfunctioncreate>
pub fn create_ordinary<P>(
parameter_list: P, parameter_list: P,
scope: Environment, scope: Option<Environment>,
body: FunctionBody, body: FunctionBody,
this_mode: ThisMode, this_mode: ThisMode,
constructable: bool,
callable: bool,
) -> Self ) -> Self
where where
P: Into<Box<[FormalParameter]>>, P: Into<Box<[FormalParameter]>>,
{ {
Self { Self {
body, body,
environment: Some(scope), environment: scope,
params: parameter_list.into(), params: parameter_list.into(),
kind: FunctionKind::Ordinary,
this_mode, this_mode,
constructable,
callable,
} }
} }
/// This will create an ordinary function object
///
/// <https://tc39.es/ecma262/#sec-ordinaryfunctioncreate>
pub fn ordinary<P>(
parameter_list: P,
scope: Environment,
body: StatementList,
this_mode: ThisMode,
) -> Self
where
P: Into<Box<[FormalParameter]>>,
{
Self::new(
parameter_list.into(),
Some(scope),
FunctionBody::Ordinary(body),
this_mode,
true,
true,
)
}
/// This will create a built-in function object /// This will create a built-in function object
/// ///
/// <https://tc39.es/ecma262/#sec-createbuiltinfunction> /// <https://tc39.es/ecma262/#sec-createbuiltinfunction>
pub fn create_builtin<P>(parameter_list: P, body: FunctionBody) -> Self pub fn builtin<P>(parameter_list: P, body: NativeFunctionData) -> Self
where where
P: Into<Box<[FormalParameter]>>, P: Into<Box<[FormalParameter]>>,
{ {
Self { Self::new(
body, parameter_list.into(),
params: parameter_list.into(), None,
this_mode: ThisMode::NonLexical, FunctionBody::BuiltIn(body),
kind: FunctionKind::BuiltIn, ThisMode::NonLexical,
environment: None, false,
} true,
)
} }
/// This will handle calls for both ordinary and built-in functions /// This will handle calls for both ordinary and built-in functions
@ -150,14 +163,10 @@ impl Function {
interpreter: &mut Interpreter, interpreter: &mut Interpreter,
this_obj: &mut Value, this_obj: &mut Value,
) -> ResultValue { ) -> ResultValue {
match self.kind { if self.callable {
FunctionKind::BuiltIn => match &self.body { match self.body {
FunctionBody::BuiltIn(func) => func(this_obj, args_list, interpreter), FunctionBody::BuiltIn(func) => func(this_obj, args_list, interpreter),
FunctionBody::Ordinary(_) => { FunctionBody::Ordinary(ref body) => {
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) // 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> // <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment( let local_env = new_function_environment(
@ -192,16 +201,16 @@ impl Function {
interpreter.realm.environment.push(local_env); interpreter.realm.environment.push(local_env);
// Call body should be set before reaching here // Call body should be set before reaching here
let result = match &self.body { let result = body.run(interpreter);
FunctionBody::Ordinary(ref body) => body.run(interpreter),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};
// local_env gets dropped here, its no longer needed // local_env gets dropped here, its no longer needed
interpreter.realm.environment.pop(); interpreter.realm.environment.pop();
result result
} }
} }
} else {
panic!("TypeError: class constructors must be invoked with 'new'");
}
} }
/// <https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget> /// <https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget>
@ -212,17 +221,13 @@ impl Function {
interpreter: &mut Interpreter, interpreter: &mut Interpreter,
this_obj: &mut Value, this_obj: &mut Value,
) -> ResultValue { ) -> ResultValue {
match self.kind { if self.constructable {
FunctionKind::BuiltIn => match &self.body { match self.body {
FunctionBody::BuiltIn(func) => { FunctionBody::BuiltIn(func) => {
func(this_obj, args_list, interpreter).unwrap(); func(this_obj, args_list, interpreter).unwrap();
Ok(this_obj.clone()) Ok(this_obj.clone())
} }
FunctionBody::Ordinary(_) => { FunctionBody::Ordinary(ref body) => {
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) // 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> // <https://tc39.es/ecma262/#sec-prepareforordinarycall>
let local_env = new_function_environment( let local_env = new_function_environment(
@ -256,16 +261,17 @@ impl Function {
interpreter.realm.environment.push(local_env); interpreter.realm.environment.push(local_env);
// Call body should be set before reaching here // Call body should be set before reaching here
let _ = match &self.body { let _ = body.run(interpreter);
FunctionBody::Ordinary(ref body) => body.run(interpreter),
_ => panic!("Ordinary function should not have BuiltIn Function body"),
};
// local_env gets dropped here, its no longer needed // local_env gets dropped here, its no longer needed
let binding = interpreter.realm.environment.get_this_binding(); let binding = interpreter.realm.environment.get_this_binding();
Ok(binding) Ok(binding)
} }
} }
} else {
let name = this.get_field("name").to_string();
panic!("TypeError: {} is not a constructor", name);
}
} }
// Adds the final rest parameters to the Environment as an array // Adds the final rest parameters to the Environment as an array
@ -309,6 +315,16 @@ impl Function {
.borrow_mut() .borrow_mut()
.initialize_binding(param.name(), value); .initialize_binding(param.name(), value);
} }
/// Returns true if the function object is callable.
pub fn is_callable(&self) -> bool {
self.callable
}
/// Returns true if the function object is constructable.
pub fn is_constructable(&self) -> bool {
self.constructable
}
} }
impl Debug for Function { impl Debug for Function {
@ -319,16 +335,6 @@ impl Debug for Function {
} }
} }
/// Function Prototype.
///
/// <https://tc39.es/ecma262/#sec-properties-of-the-function-prototype-object>
pub fn create_function_prototype() {
let mut function_prototype: Object = Object::default();
// Set Kind to function (for historical & compatibility reasons)
// <https://tc39.es/ecma262/#sec-properties-of-the-function-prototype-object>
function_prototype.kind = ObjectKind::Function;
}
/// Arguments. /// Arguments.
/// ///
/// <https://tc39.es/ecma262/#sec-createunmappedargumentsobject> /// <https://tc39.es/ecma262/#sec-createunmappedargumentsobject>
@ -369,19 +375,25 @@ pub fn make_function(this: &mut Value, _: &[Value], _: &mut Interpreter) -> Resu
pub fn create(global: &Value) -> Value { pub fn create(global: &Value) -> Value {
let prototype = Value::new_object(Some(global)); let prototype = Value::new_object(Some(global));
make_constructor_fn(make_function, global, prototype) make_constructor_fn("Function", 1, make_function, global, prototype, true)
} }
/// Creates a new constructor function /// Creates a new constructor function
/// ///
/// This utility function handling linking the new Constructor to the prototype. /// This utility function handling linking the new Constructor to the prototype.
/// So far this is only used by internal functions /// 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(
name: &str,
length: i32,
body: NativeFunctionData,
global: &Value,
proto: Value,
constructable: bool,
) -> Value {
// Create the native function // Create the native function
let constructor_fn = crate::builtins::function::Function::create_builtin( let mut constructor_fn = Function::builtin(Vec::new(), body);
vec![],
crate::builtins::function::FunctionBody::BuiltIn(body), constructor_fn.constructable = constructable;
);
// Get reference to Function.prototype // Get reference to Function.prototype
let func_prototype = global.get_field("Function").get_field(PROTOTYPE); let func_prototype = global.get_field("Function").get_field(PROTOTYPE);
@ -390,13 +402,27 @@ pub fn make_constructor_fn(body: NativeFunctionData, global: &Value, proto: Valu
let mut constructor_obj = Object::function(); let mut constructor_obj = Object::function();
constructor_obj.set_func(constructor_fn); constructor_obj.set_func(constructor_fn);
constructor_obj.set_internal_slot("__proto__", func_prototype); constructor_obj.set_internal_slot(INSTANCE_PROTOTYPE, func_prototype);
let constructor_val = Value::from(constructor_obj); let constructor_val = Value::from(constructor_obj);
// Set proto.constructor -> constructor_obj // Set proto.constructor -> constructor_obj
proto.set_field("constructor", constructor_val.clone()); proto.set_field("constructor", constructor_val.clone());
constructor_val.set_field(PROTOTYPE, proto); constructor_val.set_field(PROTOTYPE, proto);
let length = Property::new()
.value(Value::from(length))
.writable(false)
.configurable(false)
.enumerable(false);
constructor_val.set_property_slice("length", length);
let name = Property::new()
.value(Value::from(name))
.writable(false)
.configurable(false)
.enumerable(false);
constructor_val.set_property_slice("name", name);
constructor_val constructor_val
} }
@ -407,7 +433,7 @@ pub fn make_builtin_fn<N>(function: NativeFunctionData, name: N, parent: &Value,
where where
N: Into<String>, N: Into<String>,
{ {
let func = Function::create_builtin(vec![], FunctionBody::BuiltIn(function)); let func = Function::builtin(Vec::new(), function);
let mut new_func = Object::function(); let mut new_func = Object::function();
new_func.set_func(func); new_func.set_func(func);

2
boa/src/builtins/mod.rs

@ -1,4 +1,4 @@
//! Builtins live here, such as Object, String, Math etc //! Builtins live here, such as Object, String, Math, etc.
pub mod array; pub mod array;
pub mod bigint; pub mod bigint;

17
boa/src/builtins/number/mod.rs

@ -89,21 +89,6 @@ impl Number {
Ok(data) Ok(data)
} }
/// `Number()` function.
///
/// More Information https://tc39.es/ecma262/#sec-number-constructor-number-value
pub(crate) fn call_number(
_this: &mut Value,
args: &[Value],
_ctx: &mut Interpreter,
) -> ResultValue {
let data = match args.get(0) {
Some(ref value) => Self::to_number(value),
None => Self::to_number(&Value::from(0)),
};
Ok(data)
}
/// `Number.prototype.toExponential( [fractionDigits] )` /// `Number.prototype.toExponential( [fractionDigits] )`
/// ///
/// The `toExponential()` method returns a string representing the Number object in exponential notation. /// The `toExponential()` method returns a string representing the Number object in exponential notation.
@ -417,7 +402,7 @@ impl Number {
make_builtin_fn(Self::to_string, "toString", &prototype, 1); make_builtin_fn(Self::to_string, "toString", &prototype, 1);
make_builtin_fn(Self::value_of, "valueOf", &prototype, 0); make_builtin_fn(Self::value_of, "valueOf", &prototype, 0);
make_constructor_fn(Self::make_number, global, prototype) make_constructor_fn("Number", 1, Self::make_number, global, prototype, true)
} }
/// Initialise the `Number` object on the global object. /// Initialise the `Number` object on the global object.

14
boa/src/builtins/object/mod.rs

@ -471,7 +471,10 @@ impl Object {
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-iscallable /// [spec]: https://tc39.es/ecma262/#sec-iscallable
pub fn is_callable(&self) -> bool { pub fn is_callable(&self) -> bool {
self.func.is_some() match self.func {
Some(ref function) => function.is_callable(),
None => false,
}
} }
/// It determines if Object is a function object with a [[Construct]] internal method. /// It determines if Object is a function object with a [[Construct]] internal method.
@ -480,8 +483,11 @@ impl Object {
/// - [EcmaScript reference][spec] /// - [EcmaScript reference][spec]
/// ///
/// [spec]: https://tc39.es/ecma262/#sec-isconstructor /// [spec]: https://tc39.es/ecma262/#sec-isconstructor
pub fn is_constructor(&self) -> bool { pub fn is_constructable(&self) -> bool {
self.func.is_some() match self.func {
Some(ref function) => function.is_constructable(),
None => false,
}
} }
} }
@ -614,7 +620,7 @@ pub fn create(global: &Value) -> Value {
make_builtin_fn(has_own_property, "hasOwnProperty", &prototype, 0); make_builtin_fn(has_own_property, "hasOwnProperty", &prototype, 0);
make_builtin_fn(to_string, "toString", &prototype, 0); make_builtin_fn(to_string, "toString", &prototype, 0);
let object = make_constructor_fn(make_object, global, prototype); let object = make_constructor_fn("Object", 1, make_object, global, prototype, true);
object.set_field("length", Value::from(1)); object.set_field("length", Value::from(1));
make_builtin_fn(set_prototype_of, "setPrototypeOf", &object, 2); make_builtin_fn(set_prototype_of, "setPrototypeOf", &object, 2);

2
boa/src/builtins/regexp/mod.rs

@ -485,7 +485,7 @@ impl RegExp {
make_builtin_fn(Self::get_sticky, "sticky", &prototype, 0); make_builtin_fn(Self::get_sticky, "sticky", &prototype, 0);
make_builtin_fn(Self::get_unicode, "unicode", &prototype, 0); make_builtin_fn(Self::get_unicode, "unicode", &prototype, 0);
make_constructor_fn(Self::make_regexp, global, prototype) make_constructor_fn("RegExp", 1, Self::make_regexp, global, prototype, true)
} }
/// Initialise the `RegExp` object on the global object. /// Initialise the `RegExp` object on the global object.

2
boa/src/builtins/string/mod.rs

@ -1071,7 +1071,7 @@ impl String {
make_builtin_fn(Self::match_all, "matchAll", &prototype, 1); make_builtin_fn(Self::match_all, "matchAll", &prototype, 1);
make_builtin_fn(Self::replace, "replace", &prototype, 2); make_builtin_fn(Self::replace, "replace", &prototype, 2);
make_constructor_fn(Self::make_string, global, prototype) make_constructor_fn("String", 1, Self::make_string, global, prototype, true)
} }
/// Initialise the `String` object on the global object. /// Initialise the `String` object on the global object.

3
boa/src/builtins/symbol/mod.rs

@ -92,8 +92,9 @@ pub fn to_string(this: &mut Value, _: &[Value], _: &mut Interpreter) -> ResultVa
pub fn create(global: &Value) -> Value { pub fn create(global: &Value) -> Value {
// Create prototype object // Create prototype object
let prototype = Value::new_object(Some(global)); let prototype = Value::new_object(Some(global));
make_builtin_fn(to_string, "toString", &prototype, 0); make_builtin_fn(to_string, "toString", &prototype, 0);
make_constructor_fn(call_symbol, global, prototype) make_constructor_fn("Symbol", 1, call_symbol, global, prototype, false)
} }
/// Initialise the `Symbol` object on the global object. /// Initialise the `Symbol` object on the global object.

2
boa/src/builtins/value/mod.rs

@ -217,7 +217,7 @@ impl ValueData {
match *self { match *self {
Self::Object(ref o) => { Self::Object(ref o) => {
let borrowed_obj = o.borrow(); let borrowed_obj = o.borrow();
borrowed_obj.is_callable() || borrowed_obj.is_constructor() borrowed_obj.is_callable() || borrowed_obj.is_constructable()
} }
_ => false, _ => false,
} }

6
boa/src/exec/declaration/mod.rs

@ -18,6 +18,8 @@ impl Executable for FunctionDecl {
self.parameters().to_vec(), self.parameters().to_vec(),
self.body().to_vec(), self.body().to_vec(),
ThisMode::NonLexical, ThisMode::NonLexical,
true,
true,
); );
// Set the name and assign it in the current environment // Set the name and assign it in the current environment
@ -43,6 +45,8 @@ impl Executable for FunctionExpr {
self.parameters().to_vec(), self.parameters().to_vec(),
self.body().to_vec(), self.body().to_vec(),
ThisMode::NonLexical, ThisMode::NonLexical,
true,
true,
); );
if let Some(name) = self.name() { if let Some(name) = self.name() {
@ -125,6 +129,8 @@ impl Executable for ArrowFunctionDecl {
self.params().to_vec(), self.params().to_vec(),
self.body().to_vec(), self.body().to_vec(),
ThisMode::Lexical, ThisMode::Lexical,
false,
true,
)) ))
} }
} }

17
boa/src/exec/mod.rs

@ -58,7 +58,14 @@ impl Interpreter {
} }
/// Utility to create a function Value for Function Declarations, Arrow Functions or Function Expressions /// Utility to create a function Value for Function Declarations, Arrow Functions or Function Expressions
pub(crate) fn create_function<P, B>(&mut self, params: P, body: B, this_mode: ThisMode) -> Value pub(crate) fn create_function<P, B>(
&mut self,
params: P,
body: B,
this_mode: ThisMode,
constructable: bool,
callable: bool,
) -> Value
where where
P: Into<Box<[FormalParameter]>>, P: Into<Box<[FormalParameter]>>,
B: Into<StatementList>, B: Into<StatementList>,
@ -69,7 +76,7 @@ impl Interpreter {
.get_global_object() .get_global_object()
.expect("Could not get the global object") .expect("Could not get the global object")
.get_field("Function") .get_field("Function")
.get_field("Prototype"); .get_field(PROTOTYPE);
// Every new function has a prototype property pre-made // Every new function has a prototype property pre-made
let global_val = &self let global_val = &self
@ -81,11 +88,13 @@ impl Interpreter {
let params = params.into(); let params = params.into();
let params_len = params.len(); let params_len = params.len();
let func = FunctionObject::create_ordinary( let func = FunctionObject::new(
params, params,
self.realm.environment.get_current_environment().clone(), Some(self.realm.environment.get_current_environment().clone()),
FunctionBody::Ordinary(body.into()), FunctionBody::Ordinary(body.into()),
this_mode, this_mode,
constructable,
callable,
); );
let mut new_func = Object::function(); let mut new_func = Object::function();

7
boa/src/realm.rs

@ -7,7 +7,7 @@
use crate::{ use crate::{
builtins::{ builtins::{
self, self,
function::NativeFunctionData, function::{Function, NativeFunctionData},
value::{Value, ValueData}, value::{Value, ValueData},
}, },
environment::{ environment::{
@ -60,10 +60,7 @@ impl Realm {
/// Utility to add a function to the global object /// Utility to add a function to the global object
pub fn register_global_func(self, func_name: &str, func: NativeFunctionData) -> Self { pub fn register_global_func(self, func_name: &str, func: NativeFunctionData) -> Self {
let func = crate::builtins::function::Function::create_builtin( let func = Function::builtin(Vec::new(), func);
vec![],
crate::builtins::function::FunctionBody::BuiltIn(func),
);
self.global_obj self.global_obj
.set_field(Value::from(func_name), ValueData::from_func(func)); .set_field(Value::from(func_name), ValueData::from_func(func));

Loading…
Cancel
Save