From d42e413f8ab8e49573c5be1b749537b073761ca5 Mon Sep 17 00:00:00 2001 From: HalidOdat Date: Tue, 26 May 2020 13:19:56 +0200 Subject: [PATCH] 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 --- boa/src/builtins/array/mod.rs | 2 +- boa/src/builtins/bigint/mod.rs | 18 +- boa/src/builtins/boolean/mod.rs | 9 +- boa/src/builtins/error/mod.rs | 5 +- boa/src/builtins/error/range.rs | 5 +- boa/src/builtins/function/mod.rs | 304 +++++++++++++++++-------------- boa/src/builtins/mod.rs | 2 +- boa/src/builtins/number/mod.rs | 17 +- boa/src/builtins/object/mod.rs | 14 +- boa/src/builtins/regexp/mod.rs | 2 +- boa/src/builtins/string/mod.rs | 2 +- boa/src/builtins/symbol/mod.rs | 3 +- boa/src/builtins/value/mod.rs | 2 +- boa/src/exec/declaration/mod.rs | 6 + boa/src/exec/mod.rs | 17 +- boa/src/realm.rs | 7 +- 16 files changed, 227 insertions(+), 188 deletions(-) diff --git a/boa/src/builtins/array/mod.rs b/boa/src/builtins/array/mod.rs index e41ce0c03f..4cf03d3790 100644 --- a/boa/src/builtins/array/mod.rs +++ b/boa/src/builtins/array/mod.rs @@ -1031,7 +1031,7 @@ impl Array { make_builtin_fn(Self::slice, "slice", &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 make_builtin_fn(Self::is_array, "isArray", &array, 1); diff --git a/boa/src/builtins/bigint/mod.rs b/boa/src/builtins/bigint/mod.rs index 7ff326915c..f01b4573c6 100644 --- a/boa/src/builtins/bigint/mod.rs +++ b/boa/src/builtins/bigint/mod.rs @@ -96,14 +96,14 @@ impl BigInt { )) } - // /// `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(crate) fn value_of( @@ -124,7 +124,7 @@ impl BigInt { make_builtin_fn(Self::to_string, "toString", &prototype, 1); 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. diff --git a/boa/src/builtins/boolean/mod.rs b/boa/src/builtins/boolean/mod.rs index f70ae4b742..40b7de056d 100644 --- a/boa/src/builtins/boolean/mod.rs +++ b/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::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. diff --git a/boa/src/builtins/error/mod.rs b/boa/src/builtins/error/mod.rs index d430330fc3..328edc50bf 100644 --- a/boa/src/builtins/error/mod.rs +++ b/boa/src/builtins/error/mod.rs @@ -72,9 +72,10 @@ impl Error { pub(crate) fn create(global: &Value) -> Value { let prototype = Value::new_object(Some(global)); prototype.set_field("message", Value::from("")); - prototype.set_field("name", Value::from("Error")); + 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. diff --git a/boa/src/builtins/error/range.rs b/boa/src/builtins/error/range.rs index fb71ead366..34e4c88ff7 100644 --- a/boa/src/builtins/error/range.rs +++ b/boa/src/builtins/error/range.rs @@ -63,9 +63,10 @@ impl RangeError { pub(crate) fn create(global: &Value) -> Value { let prototype = Value::new_object(Some(global)); prototype.set_field("message", Value::from("")); - prototype.set_field("name", Value::from("RangeError")); + 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)`. diff --git a/boa/src/builtins/function/mod.rs b/boa/src/builtins/function/mod.rs index 92bd850e34..2886b97051 100644 --- a/boa/src/builtins/function/mod.rs +++ b/boa/src/builtins/function/mod.rs @@ -14,7 +14,7 @@ use crate::{ builtins::{ array::Array, - object::{Object, ObjectInternalMethods, ObjectKind, PROTOTYPE}, + object::{Object, ObjectInternalMethods, ObjectKind, INSTANCE_PROTOTYPE, PROTOTYPE}, property::Property, value::{ResultValue, Value}, }, @@ -72,18 +72,6 @@ unsafe impl Trace for FunctionBody { unsafe_empty_trace!(); } -/// Signal what sort of function this is -#[derive(Clone, Debug, Copy, Finalize)] -pub enum FunctionKind { - BuiltIn, - Ordinary, -} - -/// Waiting on until we can derive Copy -unsafe impl Trace for FunctionKind { - unsafe_empty_trace!(); -} - /// Boa representation of a Function Object. /// /// @@ -95,48 +83,73 @@ pub struct Function { pub params: Box<[FormalParameter]>, /// This Mode pub this_mode: ThisMode, - /// Function kind - pub kind: FunctionKind, // Environment, built-in functions don't need Environments pub environment: Option, + /// Is it constructable + constructable: bool, + /// Is it callable. + callable: bool, } impl Function { - /// This will create an ordinary function object - /// - /// - pub fn create_ordinary

( + pub fn new

( parameter_list: P, - scope: Environment, + scope: Option, body: FunctionBody, this_mode: ThisMode, + constructable: bool, + callable: bool, ) -> Self where P: Into>, { Self { body, - environment: Some(scope), + environment: scope, params: parameter_list.into(), - kind: FunctionKind::Ordinary, this_mode, + constructable, + callable, } } + /// This will create an ordinary function object + /// + /// + pub fn ordinary

( + parameter_list: P, + scope: Environment, + body: StatementList, + this_mode: ThisMode, + ) -> Self + where + P: Into>, + { + Self::new( + parameter_list.into(), + Some(scope), + FunctionBody::Ordinary(body), + this_mode, + true, + true, + ) + } + /// This will create a built-in function object /// /// - pub fn create_builtin

(parameter_list: P, body: FunctionBody) -> Self + pub fn builtin

(parameter_list: P, body: NativeFunctionData) -> Self where P: Into>, { - Self { - body, - params: parameter_list.into(), - this_mode: ThisMode::NonLexical, - kind: FunctionKind::BuiltIn, - environment: None, - } + Self::new( + parameter_list.into(), + None, + FunctionBody::BuiltIn(body), + ThisMode::NonLexical, + false, + true, + ) } /// This will handle calls for both ordinary and built-in functions @@ -150,57 +163,53 @@ impl Function { interpreter: &mut Interpreter, this_obj: &mut Value, ) -> ResultValue { - match self.kind { - FunctionKind::BuiltIn => match &self.body { + if self.callable { + 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) - // - 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; + FunctionBody::Ordinary(ref body) => { + // Create a new Function environment who's parent is set to the scope of the function declaration (self.environment) + // + 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); - // 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) => body.run(interpreter), - _ => panic!("Ordinary function should not have BuiltIn Function body"), - }; - - // local_env gets dropped here, its no longer needed - interpreter.realm.environment.pop(); - result + // Call body should be set before reaching here + let result = body.run(interpreter); + + // local_env gets dropped here, its no longer needed + interpreter.realm.environment.pop(); + result + } } + } else { + panic!("TypeError: class constructors must be invoked with 'new'"); } } @@ -212,59 +221,56 @@ impl Function { interpreter: &mut Interpreter, this_obj: &mut Value, ) -> ResultValue { - match self.kind { - FunctionKind::BuiltIn => match &self.body { + if self.constructable { + 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) - // - 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; + FunctionBody::Ordinary(ref body) => { + // Create a new Function environment who's parent is set to the scope of the function declaration (self.environment) + // + 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 _ = body.run(interpreter); - // 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) => body.run(interpreter), - _ => 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) + // local_env gets dropped here, its no longer needed + let binding = interpreter.realm.environment.get_this_binding(); + Ok(binding) + } } + } else { + let name = this.get_field("name").to_string(); + panic!("TypeError: {} is not a constructor", name); } } @@ -309,6 +315,16 @@ impl Function { .borrow_mut() .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 { @@ -319,16 +335,6 @@ impl Debug for Function { } } -/// Function Prototype. -/// -/// -pub fn create_function_prototype() { - let mut function_prototype: Object = Object::default(); - // Set Kind to function (for historical & compatibility reasons) - // - function_prototype.kind = ObjectKind::Function; -} - /// Arguments. /// /// @@ -369,19 +375,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("Function", 1, make_function, global, prototype, 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( + name: &str, + length: i32, + body: NativeFunctionData, + global: &Value, + proto: Value, + constructable: 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::builtin(Vec::new(), body); + + constructor_fn.constructable = constructable; // Get reference to Function.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(); 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); // Set proto.constructor -> constructor_obj proto.set_field("constructor", constructor_val.clone()); 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 } @@ -407,7 +433,7 @@ pub fn make_builtin_fn(function: NativeFunctionData, name: N, parent: &Value, where N: Into, { - let func = Function::create_builtin(vec![], FunctionBody::BuiltIn(function)); + let func = Function::builtin(Vec::new(), function); let mut new_func = Object::function(); new_func.set_func(func); diff --git a/boa/src/builtins/mod.rs b/boa/src/builtins/mod.rs index c8a0b64d20..60a93cc9eb 100644 --- a/boa/src/builtins/mod.rs +++ b/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 bigint; diff --git a/boa/src/builtins/number/mod.rs b/boa/src/builtins/number/mod.rs index 6cf2f2ee77..e3dae7bf89 100644 --- a/boa/src/builtins/number/mod.rs +++ b/boa/src/builtins/number/mod.rs @@ -89,21 +89,6 @@ impl Number { 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] )` /// /// 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::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. diff --git a/boa/src/builtins/object/mod.rs b/boa/src/builtins/object/mod.rs index c2ec7df9ff..912d15203c 100644 --- a/boa/src/builtins/object/mod.rs +++ b/boa/src/builtins/object/mod.rs @@ -471,7 +471,10 @@ impl Object { /// /// [spec]: https://tc39.es/ecma262/#sec-iscallable 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. @@ -480,8 +483,11 @@ impl Object { /// - [EcmaScript reference][spec] /// /// [spec]: https://tc39.es/ecma262/#sec-isconstructor - pub fn is_constructor(&self) -> bool { - self.func.is_some() + pub fn is_constructable(&self) -> bool { + 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(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)); make_builtin_fn(set_prototype_of, "setPrototypeOf", &object, 2); diff --git a/boa/src/builtins/regexp/mod.rs b/boa/src/builtins/regexp/mod.rs index 53de4cf4dd..af82d3bfe8 100644 --- a/boa/src/builtins/regexp/mod.rs +++ b/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_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. diff --git a/boa/src/builtins/string/mod.rs b/boa/src/builtins/string/mod.rs index dc4da87832..06ba55460b 100644 --- a/boa/src/builtins/string/mod.rs +++ b/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::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. diff --git a/boa/src/builtins/symbol/mod.rs b/boa/src/builtins/symbol/mod.rs index 7e9f5f1ed1..e71a5dc09c 100644 --- a/boa/src/builtins/symbol/mod.rs +++ b/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 { // Create prototype object let prototype = Value::new_object(Some(global)); + 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. diff --git a/boa/src/builtins/value/mod.rs b/boa/src/builtins/value/mod.rs index 2bdb186037..0d3f86672c 100644 --- a/boa/src/builtins/value/mod.rs +++ b/boa/src/builtins/value/mod.rs @@ -217,7 +217,7 @@ impl ValueData { match *self { Self::Object(ref o) => { let borrowed_obj = o.borrow(); - borrowed_obj.is_callable() || borrowed_obj.is_constructor() + borrowed_obj.is_callable() || borrowed_obj.is_constructable() } _ => false, } diff --git a/boa/src/exec/declaration/mod.rs b/boa/src/exec/declaration/mod.rs index 3a2af605df..0ab755872e 100644 --- a/boa/src/exec/declaration/mod.rs +++ b/boa/src/exec/declaration/mod.rs @@ -18,6 +18,8 @@ impl Executable for FunctionDecl { self.parameters().to_vec(), self.body().to_vec(), ThisMode::NonLexical, + true, + true, ); // Set the name and assign it in the current environment @@ -43,6 +45,8 @@ impl Executable for FunctionExpr { self.parameters().to_vec(), self.body().to_vec(), ThisMode::NonLexical, + true, + true, ); if let Some(name) = self.name() { @@ -125,6 +129,8 @@ impl Executable for ArrowFunctionDecl { self.params().to_vec(), self.body().to_vec(), ThisMode::Lexical, + false, + true, )) } } diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index f7db20501c..4f0c826681 100644 --- a/boa/src/exec/mod.rs +++ b/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 - pub(crate) fn create_function(&mut self, params: P, body: B, this_mode: ThisMode) -> Value + pub(crate) fn create_function( + &mut self, + params: P, + body: B, + this_mode: ThisMode, + constructable: bool, + callable: bool, + ) -> Value where P: Into>, B: Into, @@ -69,7 +76,7 @@ impl Interpreter { .get_global_object() .expect("Could not get the global object") .get_field("Function") - .get_field("Prototype"); + .get_field(PROTOTYPE); // Every new function has a prototype property pre-made let global_val = &self @@ -81,11 +88,13 @@ impl Interpreter { let params = params.into(); let params_len = params.len(); - let func = FunctionObject::create_ordinary( + let func = FunctionObject::new( params, - self.realm.environment.get_current_environment().clone(), + Some(self.realm.environment.get_current_environment().clone()), FunctionBody::Ordinary(body.into()), this_mode, + constructable, + callable, ); let mut new_func = Object::function(); diff --git a/boa/src/realm.rs b/boa/src/realm.rs index ba044f4645..44c9ac952a 100644 --- a/boa/src/realm.rs +++ b/boa/src/realm.rs @@ -7,7 +7,7 @@ use crate::{ builtins::{ self, - function::NativeFunctionData, + function::{Function, NativeFunctionData}, value::{Value, ValueData}, }, environment::{ @@ -60,10 +60,7 @@ impl Realm { /// Utility to add a function to the global object pub fn register_global_func(self, func_name: &str, func: NativeFunctionData) -> Self { - let func = crate::builtins::function::Function::create_builtin( - vec![], - crate::builtins::function::FunctionBody::BuiltIn(func), - ); + let func = Function::builtin(Vec::new(), func); self.global_obj .set_field(Value::from(func_name), ValueData::from_func(func));