2020-03-13 10:08:52 +01:00
/*
2021-05-29 12:38:28 +02:00
* Copyright ( c ) 2020 , Stephan Unverwerth < s . unverwerth @ serenityos . org >
2020-03-13 10:08:52 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-03-13 10:08:52 +01:00
*/
2021-06-07 15:17:37 +02:00
# include <AK/Debug.h>
2020-04-04 14:34:27 +01:00
# include <AK/Function.h>
2020-03-18 11:23:53 +01:00
# include <LibJS/AST.h>
2021-06-09 06:49:58 +04:30
# include <LibJS/Bytecode/BasicBlock.h>
2021-06-05 15:53:36 +02:00
# include <LibJS/Bytecode/Generator.h>
# include <LibJS/Bytecode/Interpreter.h>
2020-03-13 10:08:52 +01:00
# include <LibJS/Interpreter.h>
2021-09-22 12:44:56 +02:00
# include <LibJS/Runtime/AbstractOperations.h>
2020-05-04 16:05:13 +01:00
# include <LibJS/Runtime/Array.h>
2021-09-24 22:40:38 +02:00
# include <LibJS/Runtime/ECMAScriptFunctionObject.h>
2020-04-04 14:34:27 +01:00
# include <LibJS/Runtime/Error.h>
2021-07-01 12:24:46 +02:00
# include <LibJS/Runtime/FunctionEnvironment.h>
2021-06-11 01:38:30 +04:30
# include <LibJS/Runtime/GeneratorObject.h>
2021-06-15 00:04:08 -07:00
# include <LibJS/Runtime/GeneratorObjectPrototype.h>
2020-04-17 19:59:32 +02:00
# include <LibJS/Runtime/GlobalObject.h>
2021-06-11 01:38:30 +04:30
# include <LibJS/Runtime/NativeFunction.h>
2020-03-16 14:20:30 +01:00
# include <LibJS/Runtime/Value.h>
2020-03-13 10:08:52 +01:00
namespace JS {
2021-09-24 23:10:21 +02:00
ECMAScriptFunctionObject * ECMAScriptFunctionObject : : create ( GlobalObject & global_object , FlyString name , Statement const & ecmascript_code , Vector < FunctionNode : : Parameter > parameters , i32 m_function_length , Environment * parent_scope , FunctionKind kind , bool is_strict , bool is_arrow_function )
2020-04-17 19:59:32 +02:00
{
2021-06-15 00:04:08 -07:00
Object * prototype = nullptr ;
switch ( kind ) {
case FunctionKind : : Regular :
prototype = global_object . function_prototype ( ) ;
break ;
case FunctionKind : : Generator :
prototype = global_object . generator_function_prototype ( ) ;
break ;
}
2021-09-25 00:38:23 +02:00
return global_object . heap ( ) . allocate < ECMAScriptFunctionObject > ( global_object , move ( name ) , ecmascript_code , move ( parameters ) , m_function_length , parent_scope , * prototype , kind , is_strict , is_arrow_function ) ;
2020-04-17 19:59:32 +02:00
}
2021-09-25 00:38:23 +02:00
ECMAScriptFunctionObject : : ECMAScriptFunctionObject ( FlyString name , Statement const & ecmascript_code , Vector < FunctionNode : : Parameter > formal_parameters , i32 function_length , Environment * parent_scope , Object & prototype , FunctionKind kind , bool strict , bool is_arrow_function )
: FunctionObject ( prototype )
2021-06-25 21:22:37 +02:00
, m_environment ( parent_scope )
2021-09-24 23:10:21 +02:00
, m_formal_parameters ( move ( formal_parameters ) )
, m_ecmascript_code ( ecmascript_code )
2021-09-12 23:10:16 +01:00
, m_realm ( vm ( ) . interpreter_if_exists ( ) ? & vm ( ) . interpreter ( ) . realm ( ) : nullptr )
2021-09-24 23:10:21 +02:00
, m_strict ( strict )
, m_name ( move ( name ) )
2021-06-24 13:29:25 +02:00
, m_function_length ( function_length )
2021-06-11 03:38:05 +04:30
, m_kind ( kind )
2020-05-30 00:10:42 -05:00
, m_is_arrow_function ( is_arrow_function )
2020-03-13 10:08:52 +01:00
{
2021-06-25 20:53:17 +02:00
// NOTE: This logic is from OrdinaryFunctionCreate, https://tc39.es/ecma262/#sec-ordinaryfunctioncreate
if ( m_is_arrow_function )
2021-09-24 23:19:36 +02:00
m_this_mode = ThisMode : : Lexical ;
2021-09-24 23:10:21 +02:00
else if ( m_strict )
2021-09-24 23:19:36 +02:00
m_this_mode = ThisMode : : Strict ;
2021-06-25 20:53:17 +02:00
else
2021-09-24 23:19:36 +02:00
m_this_mode = ThisMode : : Global ;
2021-06-28 11:18:32 +02:00
// 15.1.3 Static Semantics: IsSimpleParameterList, https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist
2021-09-25 00:10:09 +02:00
m_has_simple_parameter_list = all_of ( m_formal_parameters , [ & ] ( auto & parameter ) {
2021-06-28 11:18:32 +02:00
if ( parameter . is_rest )
return false ;
if ( parameter . default_value )
return false ;
if ( ! parameter . binding . template has < FlyString > ( ) )
return false ;
return true ;
2021-09-25 00:10:09 +02:00
} ) ;
2020-06-20 17:11:11 +02:00
}
2021-09-24 22:40:38 +02:00
void ECMAScriptFunctionObject : : initialize ( GlobalObject & global_object )
2020-06-20 17:11:11 +02:00
{
2020-10-13 23:49:19 +02:00
auto & vm = this - > vm ( ) ;
2021-06-27 21:48:34 +02:00
Base : : initialize ( global_object ) ;
2020-06-08 13:31:21 -05:00
if ( ! m_is_arrow_function ) {
2021-06-27 22:15:58 +02:00
auto * prototype = vm . heap ( ) . allocate < Object > ( global_object , * global_object . new_ordinary_function_prototype_object_shape ( ) ) ;
2021-06-15 00:04:08 -07:00
switch ( m_kind ) {
case FunctionKind : : Regular :
2021-07-06 02:15:08 +03:00
prototype - > define_property_or_throw ( vm . names . constructor , { . value = this , . writable = true , . enumerable = false , . configurable = true } ) ;
2021-06-15 00:04:08 -07:00
break ;
case FunctionKind : : Generator :
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
2021-10-02 14:32:37 +01:00
set_prototype ( global_object . generator_object_prototype ( ) ) ;
2021-06-15 00:04:08 -07:00
break ;
}
2021-07-06 02:15:08 +03:00
define_direct_property ( vm . names . prototype , prototype , Attribute : : Writable ) ;
2020-06-08 13:24:15 -05:00
}
2021-07-05 18:02:27 +03:00
define_property_or_throw ( vm . names . length , { . value = Value ( m_function_length ) , . writable = false , . enumerable = false , . configurable = true } ) ;
define_property_or_throw ( vm . names . name , { . value = js_string ( vm , m_name . is_null ( ) ? " " : m_name ) , . writable = false , . enumerable = false , . configurable = true } ) ;
2020-03-13 10:08:52 +01:00
}
2021-09-24 22:40:38 +02:00
ECMAScriptFunctionObject : : ~ ECMAScriptFunctionObject ( )
2020-03-13 10:08:52 +01:00
{
}
2021-09-24 22:40:38 +02:00
void ECMAScriptFunctionObject : : visit_edges ( Visitor & visitor )
2020-04-15 21:58:22 +02:00
{
2021-06-27 21:48:34 +02:00
Base : : visit_edges ( visitor ) ;
2021-06-25 21:22:37 +02:00
visitor . visit ( m_environment ) ;
2021-09-11 19:19:08 +03:00
visitor . visit ( m_realm ) ;
2021-09-24 23:49:24 +02:00
visitor . visit ( m_home_object ) ;
2021-09-25 00:01:09 +02:00
for ( auto & field : m_fields ) {
field . name . visit_edges ( visitor ) ;
visitor . visit ( field . initializer ) ;
}
2020-04-15 21:58:22 +02:00
}
2021-09-22 12:44:56 +02:00
// 9.1.2.4 NewFunctionEnvironment ( F, newTarget ), https://tc39.es/ecma262/#sec-newfunctionenvironment
FunctionEnvironment * ECMAScriptFunctionObject : : new_function_environment ( Object * new_target )
2020-04-15 21:58:22 +02:00
{
2021-09-22 12:44:56 +02:00
auto * environment = heap ( ) . allocate < FunctionEnvironment > ( global_object ( ) , m_environment ) ;
environment - > set_function_object ( * this ) ;
if ( this_mode ( ) = = ThisMode : : Lexical ) {
environment - > set_this_binding_status ( FunctionEnvironment : : ThisBindingStatus : : Lexical ) ;
}
environment - > set_new_target ( new_target ? new_target : js_undefined ( ) ) ;
return environment ;
}
// 10.2.11 FunctionDeclarationInstantiation ( func, argumentsList ), https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
ThrowCompletionOr < void > ECMAScriptFunctionObject : : function_declaration_instantiation ( Interpreter * interpreter )
{
auto & vm = this - > vm ( ) ;
auto & callee_context = vm . running_execution_context ( ) ;
// Needed to extract declarations and functions
ScopeNode const * scope_body = nullptr ;
if ( is < ScopeNode > ( * m_ecmascript_code ) )
scope_body = static_cast < ScopeNode const * > ( m_ecmascript_code . ptr ( ) ) ;
bool has_parameter_expressions = false ;
// FIXME: Maybe compute has duplicates at parse time? (We need to anyway since it's an error in some cases)
bool has_duplicates = false ;
HashTable < FlyString > parameter_names ;
2021-09-24 23:10:21 +02:00
for ( auto & parameter : m_formal_parameters ) {
2021-09-22 12:44:56 +02:00
if ( parameter . default_value )
has_parameter_expressions = true ;
2021-05-29 16:03:19 +04:30
parameter . binding . visit (
2021-09-22 12:44:56 +02:00
[ & ] ( FlyString const & name ) {
if ( parameter_names . set ( name ) ! = AK : : HashSetResult : : InsertedNewEntry )
has_duplicates = true ;
} ,
[ & ] ( NonnullRefPtr < BindingPattern > const & pattern ) {
if ( pattern - > contains_expression ( ) )
has_parameter_expressions = true ;
pattern - > for_each_bound_name ( [ & ] ( auto & name ) {
if ( parameter_names . set ( name ) ! = AK : : HashSetResult : : InsertedNewEntry )
has_duplicates = true ;
2021-05-29 16:03:19 +04:30
} ) ;
} ) ;
2020-04-15 21:58:22 +02:00
}
2021-09-22 12:44:56 +02:00
auto needs_argument_object = this_mode ( ) ! = ThisMode : : Lexical ;
if ( parameter_names . contains ( vm . names . arguments . as_string ( ) ) )
needs_argument_object = false ;
HashTable < FlyString > function_names ;
Vector < FunctionDeclaration const & > functions_to_initialize ;
if ( scope_body ) {
scope_body - > for_each_var_function_declaration_in_reverse_order ( [ & ] ( FunctionDeclaration const & function ) {
if ( function_names . set ( function . name ( ) ) = = AK : : HashSetResult : : InsertedNewEntry )
functions_to_initialize . append ( function ) ;
} ) ;
auto arguments_name = vm . names . arguments . as_string ( ) ;
if ( ! has_parameter_expressions & & function_names . contains ( arguments_name ) )
needs_argument_object = false ;
if ( ! has_parameter_expressions & & needs_argument_object ) {
scope_body - > for_each_lexically_declared_name ( [ & ] ( auto const & name ) {
if ( name = = arguments_name )
needs_argument_object = false ;
return IterationDecision : : Continue ;
} ) ;
2020-04-15 21:58:22 +02:00
}
}
2020-06-08 13:31:21 -05:00
2021-09-22 12:44:56 +02:00
Environment * environment ;
if ( is_strict_mode ( ) | | ! has_parameter_expressions ) {
environment = callee_context . lexical_environment ;
} else {
environment = new_declarative_environment ( * callee_context . lexical_environment ) ;
VERIFY ( callee_context . variable_environment = = callee_context . lexical_environment ) ;
callee_context . lexical_environment = environment ;
2020-11-28 16:02:27 +01:00
}
2021-09-22 12:44:56 +02:00
for ( auto const & parameter_name : parameter_names ) {
if ( environment - > has_binding ( parameter_name ) )
continue ;
environment - > create_mutable_binding ( global_object ( ) , parameter_name , false ) ;
if ( has_duplicates )
environment - > initialize_binding ( global_object ( ) , parameter_name , js_undefined ( ) ) ;
VERIFY ( ! vm . exception ( ) ) ;
}
if ( needs_argument_object ) {
Object * arguments_object ;
if ( is_strict_mode ( ) | | ! has_simple_parameter_list ( ) )
arguments_object = create_unmapped_arguments_object ( global_object ( ) , vm . running_execution_context ( ) . arguments ) ;
else
arguments_object = create_mapped_arguments_object ( global_object ( ) , * this , formal_parameters ( ) , vm . running_execution_context ( ) . arguments , * environment ) ;
if ( is_strict_mode ( ) )
environment - > create_immutable_binding ( global_object ( ) , vm . names . arguments . as_string ( ) , false ) ;
else
environment - > create_mutable_binding ( global_object ( ) , vm . names . arguments . as_string ( ) , false ) ;
environment - > initialize_binding ( global_object ( ) , vm . names . arguments . as_string ( ) , arguments_object ) ;
parameter_names . set ( vm . names . arguments . as_string ( ) ) ;
}
// We now treat parameterBindings as parameterNames.
// The spec makes an iterator here to do IteratorBindingInitialization but we just do it manually
auto & execution_context_arguments = vm . running_execution_context ( ) . arguments ;
for ( size_t i = 0 ; i < m_formal_parameters . size ( ) ; + + i ) {
auto & parameter = m_formal_parameters [ i ] ;
parameter . binding . visit (
[ & ] ( auto const & param ) {
Value argument_value ;
if ( parameter . is_rest ) {
auto * array = Array : : create ( global_object ( ) , 0 ) ;
for ( size_t rest_index = i ; rest_index < execution_context_arguments . size ( ) ; + + rest_index )
array - > indexed_properties ( ) . append ( execution_context_arguments [ rest_index ] ) ;
argument_value = move ( array ) ;
} else if ( i < execution_context_arguments . size ( ) & & ! execution_context_arguments [ i ] . is_undefined ( ) ) {
argument_value = execution_context_arguments [ i ] ;
} else if ( parameter . default_value ) {
// FIXME: Support default arguments in the bytecode world!
if ( interpreter )
argument_value = parameter . default_value - > execute ( * interpreter , global_object ( ) ) ;
if ( vm . exception ( ) )
return ;
} else {
argument_value = js_undefined ( ) ;
}
Environment * used_environment = has_duplicates ? nullptr : environment ;
if constexpr ( IsSame < FlyString const & , decltype ( param ) > ) {
Reference reference = vm . resolve_binding ( param , used_environment ) ;
if ( vm . exception ( ) )
return ;
// Here the difference from hasDuplicates is important
if ( has_duplicates )
reference . put_value ( global_object ( ) , argument_value ) ;
else
reference . initialize_referenced_binding ( global_object ( ) , argument_value ) ;
} else if ( IsSame < NonnullRefPtr < BindingPattern > const & , decltype ( param ) > ) {
// Here the difference from hasDuplicates is important
auto result = vm . binding_initialization ( param , argument_value , used_environment , global_object ( ) ) ;
if ( result . is_error ( ) )
return ;
}
if ( vm . exception ( ) )
return ;
} ) ;
if ( auto * exception = vm . exception ( ) )
return throw_completion ( exception - > value ( ) ) ;
}
Environment * var_environment ;
HashTable < FlyString > instantiated_var_names ;
if ( ! has_parameter_expressions ) {
if ( scope_body ) {
scope_body - > for_each_var_declared_name ( [ & ] ( auto const & name ) {
if ( ! parameter_names . contains ( name ) & & instantiated_var_names . set ( name ) = = AK : : HashSetResult : : InsertedNewEntry ) {
environment - > create_mutable_binding ( global_object ( ) , name , false ) ;
environment - > initialize_binding ( global_object ( ) , name , js_undefined ( ) ) ;
}
} ) ;
}
var_environment = environment ;
} else {
var_environment = new_declarative_environment ( * environment ) ;
callee_context . variable_environment = var_environment ;
if ( scope_body ) {
scope_body - > for_each_var_declared_name ( [ & ] ( auto const & name ) {
if ( instantiated_var_names . set ( name ) ! = AK : : HashSetResult : : InsertedNewEntry )
return IterationDecision : : Continue ;
var_environment - > create_mutable_binding ( global_object ( ) , name , false ) ;
Value initial_value ;
if ( ! parameter_names . contains ( name ) | | function_names . contains ( name ) )
initial_value = js_undefined ( ) ;
else
initial_value = environment - > get_binding_value ( global_object ( ) , name , false ) ;
var_environment - > initialize_binding ( global_object ( ) , name , initial_value ) ;
return IterationDecision : : Continue ;
} ) ;
}
}
// B.3.2.1 Changes to FunctionDeclarationInstantiation, https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
if ( ! m_strict & & scope_body ) {
scope_body - > for_each_function_hoistable_with_annexB_extension ( [ & ] ( FunctionDeclaration & function_declaration ) {
auto & function_name = function_declaration . name ( ) ;
if ( parameter_names . contains ( function_name ) )
return IterationDecision : : Continue ;
// The spec says 'initializedBindings' here but that does not exist and it then adds it to 'instantiatedVarNames' so it probably means 'instantiatedVarNames'.
if ( ! instantiated_var_names . contains ( function_name ) & & function_name ! = vm . names . arguments . as_string ( ) ) {
var_environment - > create_mutable_binding ( global_object ( ) , function_name , false ) ;
VERIFY ( ! vm . exception ( ) ) ;
var_environment - > initialize_binding ( global_object ( ) , function_name , js_undefined ( ) ) ;
instantiated_var_names . set ( function_name ) ;
}
function_declaration . set_should_do_additional_annexB_steps ( ) ;
return IterationDecision : : Continue ;
} ) ;
}
Environment * lex_environment ;
if ( ! is_strict_mode ( ) )
lex_environment = new_declarative_environment ( * var_environment ) ;
else
lex_environment = var_environment ;
callee_context . lexical_environment = lex_environment ;
if ( ! scope_body )
return { } ;
scope_body - > for_each_lexically_scoped_declaration ( [ & ] ( Declaration const & declaration ) {
declaration . for_each_bound_name ( [ & ] ( auto const & name ) {
if ( declaration . is_constant_declaration ( ) )
lex_environment - > create_immutable_binding ( global_object ( ) , name , true ) ;
else
lex_environment - > create_mutable_binding ( global_object ( ) , name , false ) ;
return IterationDecision : : Continue ;
} ) ;
} ) ;
VERIFY ( ! vm . exception ( ) ) ;
for ( auto & declaration : functions_to_initialize ) {
auto * function = ECMAScriptFunctionObject : : create ( global_object ( ) , declaration . name ( ) , declaration . body ( ) , declaration . parameters ( ) , declaration . function_length ( ) , lex_environment , declaration . kind ( ) , declaration . is_strict_mode ( ) ) ;
var_environment - > set_mutable_binding ( global_object ( ) , declaration . name ( ) , function , false ) ;
}
return { } ;
2020-04-15 21:58:22 +02:00
}
2021-09-24 22:40:38 +02:00
Value ECMAScriptFunctionObject : : execute_function_body ( )
2020-03-13 10:08:52 +01:00
{
2020-11-11 21:37:23 +00:00
auto & vm = this - > vm ( ) ;
2021-06-05 15:53:36 +02:00
auto * bytecode_interpreter = Bytecode : : Interpreter : : current ( ) ;
if ( bytecode_interpreter ) {
2021-09-22 12:44:56 +02:00
// FIXME: pass something to evaluate default arguments with
TRY_OR_DISCARD ( function_declaration_instantiation ( nullptr ) ) ;
2021-06-09 09:11:20 +02:00
if ( ! m_bytecode_executable . has_value ( ) ) {
2021-09-24 23:10:21 +02:00
m_bytecode_executable = Bytecode : : Generator : : generate ( m_ecmascript_code , m_kind = = FunctionKind : : Generator ) ;
2021-06-13 20:40:20 +04:30
auto & passes = JS : : Bytecode : : Interpreter : : optimization_pipeline ( ) ;
passes . perform ( * m_bytecode_executable ) ;
2021-06-07 15:19:48 +02:00
if constexpr ( JS_BYTECODE_DEBUG ) {
2021-06-13 20:40:20 +04:30
dbgln ( " Optimisation passes took {}us " , passes . elapsed ( ) ) ;
2021-06-07 15:19:48 +02:00
dbgln ( " Compiled Bytecode::Block for function '{}': " , m_name ) ;
2021-06-09 09:11:20 +02:00
for ( auto & block : m_bytecode_executable - > basic_blocks )
2021-06-09 10:02:01 +02:00
block . dump ( * m_bytecode_executable ) ;
2021-06-07 15:19:48 +02:00
}
2021-06-07 15:17:37 +02:00
}
2021-06-11 01:38:30 +04:30
auto result = bytecode_interpreter - > run ( * m_bytecode_executable ) ;
2021-06-11 03:38:05 +04:30
if ( m_kind ! = FunctionKind : : Generator )
2021-06-11 01:38:30 +04:30
return result ;
2021-06-24 19:17:45 +02:00
return GeneratorObject : : create ( global_object ( ) , result , this , vm . running_execution_context ( ) . lexical_environment , bytecode_interpreter - > snapshot_frame ( ) ) ;
2021-06-05 15:53:36 +02:00
} else {
2021-06-11 03:38:05 +04:30
VERIFY ( m_kind ! = FunctionKind : : Generator ) ;
2021-06-05 15:53:36 +02:00
OwnPtr < Interpreter > local_interpreter ;
2021-09-22 12:44:56 +02:00
Interpreter * ast_interpreter = vm . interpreter_if_exists ( ) ;
2021-06-05 15:53:36 +02:00
if ( ! ast_interpreter ) {
2021-09-12 12:33:54 +01:00
local_interpreter = Interpreter : : create_with_existing_realm ( * realm ( ) ) ;
2021-06-05 15:53:36 +02:00
ast_interpreter = local_interpreter . ptr ( ) ;
}
2020-09-27 17:24:14 +02:00
2021-06-05 15:53:36 +02:00
VM : : InterpreterExecutionScope scope ( * ast_interpreter ) ;
2021-05-29 16:03:19 +04:30
2021-09-22 12:44:56 +02:00
TRY_OR_DISCARD ( function_declaration_instantiation ( ast_interpreter ) ) ;
2020-10-04 13:54:44 +02:00
2021-09-22 12:44:56 +02:00
return m_ecmascript_code - > execute ( * ast_interpreter , global_object ( ) ) ;
2021-06-05 15:53:36 +02:00
}
2020-03-13 10:08:52 +01:00
}
2021-09-24 22:40:38 +02:00
Value ECMAScriptFunctionObject : : call ( )
2020-11-11 21:37:40 +00:00
{
if ( m_is_class_constructor ) {
vm ( ) . throw_exception < TypeError > ( global_object ( ) , ErrorType : : ClassConstructorWithoutNew , m_name ) ;
return { } ;
}
return execute_function_body ( ) ;
}
2021-09-24 22:40:38 +02:00
Value ECMAScriptFunctionObject : : construct ( FunctionObject & )
2020-04-01 18:31:24 +01:00
{
2021-06-15 00:04:08 -07:00
if ( m_is_arrow_function | | m_kind = = FunctionKind : : Generator ) {
2020-10-04 13:55:20 +01:00
vm ( ) . throw_exception < TypeError > ( global_object ( ) , ErrorType : : NotAConstructor , m_name ) ;
2020-08-25 12:52:32 +02:00
return { } ;
}
2020-11-11 21:37:40 +00:00
return execute_function_body ( ) ;
2020-04-01 18:31:24 +01:00
}
2021-09-24 22:40:38 +02:00
void ECMAScriptFunctionObject : : set_name ( const FlyString & name )
2020-04-04 14:34:27 +01:00
{
2021-07-05 18:02:27 +03:00
VERIFY ( ! name . is_null ( ) ) ;
auto & vm = this - > vm ( ) ;
m_name = name ;
auto success = define_property_or_throw ( vm . names . name , { . value = js_string ( vm , m_name ) , . writable = false , . enumerable = false , . configurable = true } ) ;
VERIFY ( success ) ;
2020-04-04 14:34:27 +01:00
}
2021-09-25 00:01:09 +02:00
// 7.3.31 DefineField ( receiver, fieldRecord ), https://tc39.es/ecma262/#sec-definefield
void ECMAScriptFunctionObject : : InstanceField : : define_field ( VM & vm , Object & receiver ) const
{
Value init_value = js_undefined ( ) ;
if ( initializer ) {
auto init_value_or_error = vm . call ( * initializer , receiver . value_of ( ) ) ;
if ( init_value_or_error . is_error ( ) )
return ;
init_value = init_value_or_error . release_value ( ) ;
}
receiver . create_data_property_or_throw ( name , init_value ) ;
}
2020-03-13 10:08:52 +01:00
}