2021-06-03 10:46:30 +02:00
/*
* Copyright ( c ) 2021 , Andreas Kling < kling @ serenityos . org >
2022-01-09 19:12:24 +01:00
* Copyright ( c ) 2021 - 2022 , Linus Groh < linusg @ serenityos . org >
2021-06-09 18:18:56 +02:00
* Copyright ( c ) 2021 , Gunnar Beutner < gbeutner @ serenityos . org >
2021-06-03 10:46:30 +02:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2021-06-13 15:30:32 -07:00
# include <AK/HashTable.h>
2022-11-23 13:41:50 +01:00
# include <LibJS/AST.h>
2021-06-03 10:46:30 +02:00
# include <LibJS/Bytecode/Interpreter.h>
# include <LibJS/Bytecode/Op.h>
2021-10-23 01:49:10 +03:00
# include <LibJS/Runtime/AbstractOperations.h>
2021-06-08 23:06:52 +02:00
# include <LibJS/Runtime/Array.h>
2021-06-08 07:59:25 +02:00
# include <LibJS/Runtime/BigInt.h>
2021-07-01 12:24:46 +02:00
# include <LibJS/Runtime/DeclarativeEnvironment.h>
2021-09-24 22:40:38 +02:00
# include <LibJS/Runtime/ECMAScriptFunctionObject.h>
2021-07-01 12:24:46 +02:00
# include <LibJS/Runtime/Environment.h>
2022-08-30 18:03:02 +02:00
# include <LibJS/Runtime/FunctionEnvironment.h>
2022-07-17 19:06:44 +01:00
# include <LibJS/Runtime/GlobalEnvironment.h>
2021-06-03 18:26:32 +02:00
# include <LibJS/Runtime/GlobalObject.h>
2022-01-09 19:12:24 +01:00
# include <LibJS/Runtime/Iterator.h>
2021-06-13 13:40:48 -07:00
# include <LibJS/Runtime/IteratorOperations.h>
2022-03-18 20:18:19 +03:30
# include <LibJS/Runtime/NativeFunction.h>
2022-03-13 16:01:18 +03:30
# include <LibJS/Runtime/ObjectEnvironment.h>
2022-11-23 13:41:50 +01:00
# include <LibJS/Runtime/Reference.h>
2021-06-19 17:17:40 -07:00
# include <LibJS/Runtime/RegExpObject.h>
2021-06-03 10:46:30 +02:00
# include <LibJS/Runtime/Value.h>
2021-06-07 15:12:43 +02:00
namespace JS : : Bytecode {
2022-12-06 01:12:49 +00:00
DeprecatedString Instruction : : to_deprecated_string ( Bytecode : : Executable const & executable ) const
2021-06-07 15:12:43 +02:00
{
# define __BYTECODE_OP(op) \
case Instruction : : Type : : op : \
2022-12-06 01:12:49 +00:00
return static_cast < Bytecode : : Op : : op const & > ( * this ) . to_deprecated_string_impl ( executable ) ;
2021-06-07 15:12:43 +02:00
switch ( type ( ) ) {
ENUMERATE_BYTECODE_OPS ( __BYTECODE_OP )
default :
VERIFY_NOT_REACHED ( ) ;
}
# undef __BYTECODE_OP
}
}
2021-06-03 10:46:30 +02:00
namespace JS : : Bytecode : : Op {
2022-03-31 00:59:58 +04:30
static ThrowCompletionOr < void > put_by_property_key ( Object * object , Value value , PropertyKey name , Bytecode : : Interpreter & interpreter , PropertyKind kind )
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
2022-03-31 00:59:58 +04:30
if ( kind = = PropertyKind : : Getter | | kind = = PropertyKind : : Setter ) {
// The generator should only pass us functions for getters and setters.
VERIFY ( value . is_function ( ) ) ;
}
switch ( kind ) {
case PropertyKind : : Getter : {
auto & function = value . as_function ( ) ;
if ( function . name ( ) . is_empty ( ) & & is < ECMAScriptFunctionObject > ( function ) )
2022-12-04 18:02:33 +00:00
static_cast < ECMAScriptFunctionObject * > ( & function ) - > set_name ( DeprecatedString : : formatted ( " get {} " , name ) ) ;
2022-03-31 00:59:58 +04:30
object - > define_direct_accessor ( name , & function , nullptr , Attribute : : Configurable | Attribute : : Enumerable ) ;
break ;
}
case PropertyKind : : Setter : {
auto & function = value . as_function ( ) ;
if ( function . name ( ) . is_empty ( ) & & is < ECMAScriptFunctionObject > ( function ) )
2022-12-04 18:02:33 +00:00
static_cast < ECMAScriptFunctionObject * > ( & function ) - > set_name ( DeprecatedString : : formatted ( " set {} " , name ) ) ;
2022-03-31 00:59:58 +04:30
object - > define_direct_accessor ( name , nullptr , & function , Attribute : : Configurable | Attribute : : Enumerable ) ;
break ;
}
2022-07-17 18:58:23 +01:00
case PropertyKind : : KeyValue : {
bool succeeded = TRY ( object - > internal_set ( name , interpreter . accumulator ( ) , object ) ) ;
2022-08-21 14:00:56 +01:00
if ( ! succeeded & & vm . in_strict_mode ( ) )
return vm . throw_completion < TypeError > ( ErrorType : : ReferenceNullishSetProperty , name , interpreter . accumulator ( ) . to_string_without_side_effects ( ) ) ;
2022-03-31 00:59:58 +04:30
break ;
2022-07-17 18:58:23 +01:00
}
2022-03-31 00:59:58 +04:30
case PropertyKind : : Spread :
2022-08-21 14:00:56 +01:00
TRY ( object - > copy_data_properties ( vm , value , { } ) ) ;
2022-03-31 00:59:58 +04:30
break ;
case PropertyKind : : ProtoSetter :
if ( value . is_object ( ) | | value . is_null ( ) )
MUST ( object - > internal_set_prototype_of ( value . is_object ( ) ? & value . as_object ( ) : nullptr ) ) ;
break ;
}
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Load : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-03 10:46:30 +02:00
{
2021-06-07 20:58:36 -07:00
interpreter . accumulator ( ) = interpreter . reg ( m_src ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-03 10:46:30 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > LoadImmediate : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-07 22:05:09 +02:00
{
2021-06-07 20:58:36 -07:00
interpreter . accumulator ( ) = m_value ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-07 20:58:36 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Store : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-07 20:58:36 -07:00
{
interpreter . reg ( m_dst ) = interpreter . accumulator ( ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-07 22:05:09 +02:00
}
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > abstract_inequals ( VM & vm , Value src1 , Value src2 )
2021-06-03 10:46:30 +02:00
{
2022-08-21 14:00:56 +01:00
return Value ( ! TRY ( is_loosely_equal ( vm , src1 , src2 ) ) ) ;
2021-06-03 10:46:30 +02:00
}
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > abstract_equals ( VM & vm , Value src1 , Value src2 )
2021-06-03 18:32:33 +02:00
{
2022-08-21 14:00:56 +01:00
return Value ( TRY ( is_loosely_equal ( vm , src1 , src2 ) ) ) ;
2021-06-03 18:32:33 +02:00
}
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > typed_inequals ( VM & , Value src1 , Value src2 )
2021-06-07 19:17:20 +02:00
{
2021-09-23 23:43:28 +02:00
return Value ( ! is_strictly_equal ( src1 , src2 ) ) ;
2021-06-07 19:17:20 +02:00
}
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > typed_equals ( VM & , Value src1 , Value src2 )
2021-06-07 19:17:20 +02:00
{
2021-09-23 23:43:28 +02:00
return Value ( is_strictly_equal ( src1 , src2 ) ) ;
2021-06-07 19:17:20 +02:00
}
2022-02-07 14:36:45 +01:00
# define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
ThrowCompletionOr < void > OpTitleCase : : execute_impl ( Bytecode : : Interpreter & interpreter ) const \
{ \
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ; \
2022-02-07 14:36:45 +01:00
auto lhs = interpreter . reg ( m_lhs_reg ) ; \
auto rhs = interpreter . accumulator ( ) ; \
2022-08-21 14:00:56 +01:00
interpreter . accumulator ( ) = TRY ( op_snake_case ( vm , lhs , rhs ) ) ; \
2022-02-07 14:36:45 +01:00
return { } ; \
} \
2022-12-06 01:12:49 +00:00
DeprecatedString OpTitleCase : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const \
2022-02-07 14:36:45 +01:00
{ \
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( # OpTitleCase " {} " , m_lhs_reg ) ; \
2021-06-07 23:08:35 +02:00
}
2021-06-07 21:13:37 +01:00
2021-06-07 23:08:35 +02:00
JS_ENUMERATE_COMMON_BINARY_OPS ( JS_DEFINE_COMMON_BINARY_OP )
2021-06-07 21:18:19 +01:00
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > not_ ( VM & , Value value )
2021-06-07 21:13:37 +01:00
{
2021-06-07 23:08:35 +02:00
return Value ( ! value . to_boolean ( ) ) ;
2021-06-07 21:13:37 +01:00
}
2022-08-21 14:00:56 +01:00
static ThrowCompletionOr < Value > typeof_ ( VM & vm , Value value )
2021-06-07 19:53:47 +01:00
{
2022-12-06 22:17:27 +00:00
return Value ( PrimitiveString : : create ( vm , value . typeof ( ) ) ) ;
2021-06-07 19:53:47 +01:00
}
2022-08-21 14:00:56 +01:00
# define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
ThrowCompletionOr < void > OpTitleCase : : execute_impl ( Bytecode : : Interpreter & interpreter ) const \
{ \
auto & vm = interpreter . vm ( ) ; \
interpreter . accumulator ( ) = TRY ( op_snake_case ( vm , interpreter . accumulator ( ) ) ) ; \
return { } ; \
} \
2022-12-06 01:12:49 +00:00
DeprecatedString OpTitleCase : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const \
2022-08-21 14:00:56 +01:00
{ \
return # OpTitleCase ; \
2021-06-07 23:08:35 +02:00
}
2021-06-07 19:53:47 +01:00
2021-06-07 23:08:35 +02:00
JS_ENUMERATE_COMMON_UNARY_OPS ( JS_DEFINE_COMMON_UNARY_OP )
2021-06-07 19:53:47 +01:00
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewBigInt : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-08 07:59:25 +02:00
{
2022-12-06 22:03:52 +00:00
auto & vm = interpreter . vm ( ) ;
interpreter . accumulator ( ) = BigInt : : create ( vm , m_bigint ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-08 07:59:25 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewArray : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-08 23:06:52 +02:00
{
2022-12-13 20:49:49 +00:00
auto array = MUST ( Array : : create ( interpreter . realm ( ) , 0 ) ) ;
2022-03-14 12:44:01 +00:00
for ( size_t i = 0 ; i < m_element_count ; i + + ) {
2022-03-14 14:48:42 +00:00
auto & value = interpreter . reg ( Register ( m_elements [ 0 ] . index ( ) + i ) ) ;
2022-03-14 12:44:01 +00:00
array - > indexed_properties ( ) . put ( i , value , default_attributes ) ;
}
interpreter . accumulator ( ) = array ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-08 23:06:52 +02:00
}
2022-09-09 15:23:02 +02:00
ThrowCompletionOr < void > Append : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-09-09 16:05:40 +02:00
// Note: This OpCode is used to construct array literals and argument arrays for calls,
// containing at least one spread element,
2022-09-09 15:23:02 +02:00
// Iterating over such a spread element to unpack it has to be visible by
// the user courtesy of
2022-09-09 16:05:40 +02:00
// (1) https://tc39.es/ecma262/#sec-runtime-semantics-arrayaccumulation
2022-09-09 15:23:02 +02:00
// SpreadElement : ... AssignmentExpression
// 1. Let spreadRef be ? Evaluation of AssignmentExpression.
// 2. Let spreadObj be ? GetValue(spreadRef).
// 3. Let iteratorRecord be ? GetIterator(spreadObj).
// 4. Repeat,
// a. Let next be ? IteratorStep(iteratorRecord).
// b. If next is false, return nextIndex.
// c. Let nextValue be ? IteratorValue(next).
// d. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽 (nextIndex)), nextValue).
// e. Set nextIndex to nextIndex + 1.
2022-09-09 16:05:40 +02:00
// (2) https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation
// ArgumentList : ... AssignmentExpression
// 1. Let list be a new empty List.
// 2. Let spreadRef be ? Evaluation of AssignmentExpression.
// 3. Let spreadObj be ? GetValue(spreadRef).
// 4. Let iteratorRecord be ? GetIterator(spreadObj).
// 5. Repeat,
// a. Let next be ? IteratorStep(iteratorRecord).
// b. If next is false, return list.
// c. Let nextArg be ? IteratorValue(next).
// d. Append nextArg to list.
// ArgumentList : ArgumentList , ... AssignmentExpression
// 1. Let precedingArgs be ? ArgumentListEvaluation of ArgumentList.
// 2. Let spreadRef be ? Evaluation of AssignmentExpression.
// 3. Let iteratorRecord be ? GetIterator(? GetValue(spreadRef)).
// 4. Repeat,
// a. Let next be ? IteratorStep(iteratorRecord).
// b. If next is false, return precedingArgs.
// c. Let nextArg be ? IteratorValue(next).
// d. Append nextArg to precedingArgs.
2022-09-09 15:23:02 +02:00
auto & vm = interpreter . vm ( ) ;
// Note: We know from codegen, that lhs is a plain array with only indexed properties
auto & lhs = interpreter . reg ( m_lhs ) . as_array ( ) ;
auto lhs_size = lhs . indexed_properties ( ) . array_like_size ( ) ;
auto rhs = interpreter . accumulator ( ) ;
if ( m_is_spread ) {
// ...rhs
size_t i = lhs_size ;
TRY ( get_iterator_values ( vm , rhs , [ & i , & lhs ] ( Value iterator_value ) - > Optional < Completion > {
lhs . indexed_properties ( ) . put ( i , iterator_value , default_attributes ) ;
+ + i ;
return { } ;
} ) ) ;
} else {
lhs . indexed_properties ( ) . put ( lhs_size , rhs , default_attributes ) ;
}
return { } ;
}
2022-01-09 19:12:24 +01:00
// FIXME: Since the accumulator is a Value, we store an object there and have to convert back and forth between that an Iterator records. Not great.
// Make sure to put this into the accumulator before the iterator object disappears from the stack to prevent the members from being GC'd.
2022-08-21 15:56:27 +01:00
static Object * iterator_to_object ( VM & vm , Iterator iterator )
2022-01-09 19:12:24 +01:00
{
2022-08-21 15:56:27 +01:00
auto & realm = * vm . current_realm ( ) ;
2022-12-13 20:49:50 +00:00
auto object = Object : : create ( realm , nullptr ) ;
2022-01-09 19:12:24 +01:00
object - > define_direct_property ( vm . names . iterator , iterator . iterator , 0 ) ;
object - > define_direct_property ( vm . names . next , iterator . next_method , 0 ) ;
object - > define_direct_property ( vm . names . done , Value ( iterator . done ) , 0 ) ;
return object ;
}
2022-08-21 15:56:27 +01:00
static Iterator object_to_iterator ( VM & vm , Object & object )
2022-01-09 19:12:24 +01:00
{
return Iterator {
. iterator = & MUST ( object . get ( vm . names . iterator ) ) . as_object ( ) ,
. next_method = MUST ( object . get ( vm . names . next ) ) ,
. done = MUST ( object . get ( vm . names . done ) ) . as_bool ( )
} ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > IteratorToArray : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 14:06:26 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto iterator_object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2022-08-21 15:56:27 +01:00
auto iterator = object_to_iterator ( vm , * iterator_object ) ;
2021-06-13 14:06:26 -07:00
2022-12-13 20:49:49 +00:00
auto array = MUST ( Array : : create ( interpreter . realm ( ) , 0 ) ) ;
2021-06-13 14:06:26 -07:00
size_t index = 0 ;
while ( true ) {
2022-08-21 15:56:27 +01:00
auto * iterator_result = TRY ( iterator_next ( vm , iterator ) ) ;
2021-06-13 14:06:26 -07:00
2022-08-21 15:56:27 +01:00
auto complete = TRY ( iterator_complete ( vm , * iterator_result ) ) ;
2021-06-13 14:06:26 -07:00
if ( complete ) {
interpreter . accumulator ( ) = array ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 14:06:26 -07:00
}
2022-08-21 15:56:27 +01:00
auto value = TRY ( iterator_value ( vm , * iterator_result ) ) ;
2021-06-13 14:06:26 -07:00
2021-10-03 01:18:46 +01:00
MUST ( array - > create_data_property_or_throw ( index , value ) ) ;
2021-06-13 14:06:26 -07:00
index + + ;
}
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 14:06:26 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewString : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-03 18:26:32 +02:00
{
2022-12-06 22:17:27 +00:00
interpreter . accumulator ( ) = PrimitiveString : : create ( interpreter . vm ( ) , interpreter . current_executable ( ) . get_string ( m_string ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-03 18:26:32 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewObject : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-04 20:30:23 +02:00
{
2022-08-22 19:00:49 +01:00
auto & vm = interpreter . vm ( ) ;
auto & realm = * vm . current_realm ( ) ;
2022-08-27 00:54:55 +01:00
interpreter . accumulator ( ) = Object : : create ( realm , realm . intrinsics ( ) . object_prototype ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-07 20:58:36 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewRegExp : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-19 17:17:40 -07:00
{
2022-08-21 16:14:51 +01:00
auto & vm = interpreter . vm ( ) ;
2021-06-19 17:17:40 -07:00
auto source = interpreter . current_executable ( ) . get_string ( m_source_index ) ;
auto flags = interpreter . current_executable ( ) . get_string ( m_flags_index ) ;
2022-12-06 22:17:27 +00:00
interpreter . accumulator ( ) = TRY ( regexp_create ( vm , PrimitiveString : : create ( vm , source ) , PrimitiveString : : create ( vm , flags ) ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-19 17:17:40 -07:00
}
2022-12-09 18:48:57 +00:00
# define JS_DEFINE_NEW_BUILTIN_ERROR_OP(ErrorName) \
ThrowCompletionOr < void > New # # ErrorName : : execute_impl ( Bytecode : : Interpreter & interpreter ) const \
{ \
auto & vm = interpreter . vm ( ) ; \
auto & realm = * vm . current_realm ( ) ; \
interpreter . accumulator ( ) = ErrorName : : create ( realm , interpreter . current_executable ( ) . get_string ( m_error_string ) ) ; \
return { } ; \
} \
DeprecatedString New # # ErrorName : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const \
{ \
return DeprecatedString : : formatted ( " New " # ErrorName " {} ( \" {} \" ) " , m_error_string , executable . string_table - > get ( m_error_string ) ) ; \
}
JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS ( JS_DEFINE_NEW_BUILTIN_ERROR_OP )
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > CopyObjectExcludingProperties : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 15:30:32 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
2022-08-22 19:00:49 +01:00
auto & realm = * vm . current_realm ( ) ;
2022-08-21 14:00:56 +01:00
auto * from_object = TRY ( interpreter . reg ( m_from_object ) . to_object ( vm ) ) ;
2021-06-13 15:30:32 -07:00
2022-12-13 20:49:50 +00:00
auto to_object = Object : : create ( realm , realm . intrinsics ( ) . object_prototype ( ) ) ;
2021-06-13 15:30:32 -07:00
HashTable < Value , ValueTraits > excluded_names ;
2022-02-07 14:36:45 +01:00
for ( size_t i = 0 ; i < m_excluded_names_count ; + + i )
2021-06-13 15:30:32 -07:00
excluded_names . set ( interpreter . reg ( m_excluded_names [ i ] ) ) ;
2022-02-07 14:36:45 +01:00
auto own_keys = TRY ( from_object - > internal_own_property_keys ( ) ) ;
2021-06-13 15:30:32 -07:00
for ( auto & key : own_keys ) {
if ( ! excluded_names . contains ( key ) ) {
2022-08-21 14:00:56 +01:00
auto property_key = TRY ( key . to_property_key ( vm ) ) ;
2022-02-07 14:36:45 +01:00
auto property_value = TRY ( from_object - > get ( property_key ) ) ;
2022-02-06 15:59:04 +00:00
to_object - > define_direct_property ( property_key , property_value , JS : : default_attributes ) ;
2021-06-13 15:30:32 -07:00
}
}
interpreter . accumulator ( ) = to_object ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 15:30:32 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > ConcatString : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-07 20:58:36 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
interpreter . reg ( m_lhs ) = TRY ( add ( vm , interpreter . reg ( m_lhs ) , interpreter . accumulator ( ) ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-04 20:30:23 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > GetVariable : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-03 18:26:32 +02:00
{
2022-08-21 15:39:13 +01:00
auto & vm = interpreter . vm ( ) ;
2022-02-07 14:36:45 +01:00
auto get_reference = [ & ] ( ) - > ThrowCompletionOr < Reference > {
2021-10-24 15:36:24 +02:00
auto const & string = interpreter . current_executable ( ) . get_identifier ( m_identifier ) ;
if ( m_cached_environment_coordinate . has_value ( ) ) {
2022-11-11 15:24:57 +01:00
Environment * environment = nullptr ;
if ( m_cached_environment_coordinate - > index = = EnvironmentCoordinate : : global_marker ) {
environment = & interpreter . vm ( ) . current_realm ( ) - > global_environment ( ) ;
} else {
environment = vm . running_execution_context ( ) . lexical_environment ;
for ( size_t i = 0 ; i < m_cached_environment_coordinate - > hops ; + + i )
environment = environment - > outer_environment ( ) ;
VERIFY ( environment ) ;
VERIFY ( environment - > is_declarative_environment ( ) ) ;
}
2021-10-24 15:36:24 +02:00
if ( ! environment - > is_permanently_screwed_by_eval ( ) ) {
2022-08-21 15:39:13 +01:00
return Reference { * environment , string , vm . in_strict_mode ( ) , m_cached_environment_coordinate } ;
2021-10-24 15:36:24 +02:00
}
m_cached_environment_coordinate = { } ;
}
2022-08-21 15:39:13 +01:00
auto reference = TRY ( vm . resolve_binding ( string ) ) ;
2021-10-24 15:36:24 +02:00
if ( reference . environment_coordinate ( ) . has_value ( ) )
m_cached_environment_coordinate = reference . environment_coordinate ( ) ;
return reference ;
2022-02-07 14:36:45 +01:00
} ;
auto reference = TRY ( get_reference ( ) ) ;
2022-08-21 15:39:13 +01:00
interpreter . accumulator ( ) = TRY ( reference . get_value ( vm ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-03 18:26:32 +02:00
}
2022-03-27 19:50:09 +01:00
ThrowCompletionOr < void > DeleteVariable : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-08-21 15:39:13 +01:00
auto & vm = interpreter . vm ( ) ;
2022-03-27 19:50:09 +01:00
auto const & string = interpreter . current_executable ( ) . get_identifier ( m_identifier ) ;
2022-08-21 15:39:13 +01:00
auto reference = TRY ( vm . resolve_binding ( string ) ) ;
interpreter . accumulator ( ) = Value ( TRY ( reference . delete_ ( vm ) ) ) ;
2022-03-27 19:50:09 +01:00
return { } ;
}
2022-02-12 19:48:45 +03:30
ThrowCompletionOr < void > CreateEnvironment : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto make_and_swap_envs = [ & ] ( auto * & old_environment ) {
2022-12-15 19:59:47 +00:00
Environment * environment = new_declarative_environment ( * old_environment ) . ptr ( ) ;
2022-02-12 19:48:45 +03:30
swap ( old_environment , environment ) ;
return environment ;
} ;
if ( m_mode = = EnvironmentMode : : Lexical )
interpreter . saved_lexical_environment_stack ( ) . append ( make_and_swap_envs ( interpreter . vm ( ) . running_execution_context ( ) . lexical_environment ) ) ;
else if ( m_mode = = EnvironmentMode : : Var )
interpreter . saved_variable_environment_stack ( ) . append ( make_and_swap_envs ( interpreter . vm ( ) . running_execution_context ( ) . variable_environment ) ) ;
return { } ;
}
2022-03-13 16:01:18 +03:30
ThrowCompletionOr < void > EnterObjectEnvironment : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto & old_environment = vm . running_execution_context ( ) . lexical_environment ;
2022-03-13 16:01:18 +03:30
interpreter . saved_lexical_environment_stack ( ) . append ( old_environment ) ;
2022-08-21 14:00:56 +01:00
auto object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
vm . running_execution_context ( ) . lexical_environment = new_object_environment ( * object , true , old_environment ) ;
2022-03-13 16:01:18 +03:30
return { } ;
}
2022-02-12 19:48:45 +03:30
ThrowCompletionOr < void > CreateVariable : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-03 18:26:32 +02:00
{
2021-09-22 12:44:56 +02:00
auto & vm = interpreter . vm ( ) ;
2022-02-12 19:48:45 +03:30
auto const & name = interpreter . current_executable ( ) . get_identifier ( m_identifier ) ;
2021-09-22 12:44:56 +02:00
2022-02-12 19:48:45 +03:30
if ( m_mode = = EnvironmentMode : : Lexical ) {
2022-07-17 19:06:44 +01:00
VERIFY ( ! m_is_global ) ;
2022-02-12 19:48:45 +03:30
// Note: This is papering over an issue where "FunctionDeclarationInstantiation" creates these bindings for us.
// Instead of crashing in there, we'll just raise an exception here.
if ( TRY ( vm . lexical_environment ( ) - > has_binding ( name ) ) )
2022-12-04 18:02:33 +00:00
return vm . throw_completion < InternalError > ( DeprecatedString : : formatted ( " Lexical environment already has binding '{}' " , name ) ) ;
2022-02-12 19:48:45 +03:30
if ( m_is_immutable )
2022-08-21 15:12:43 +01:00
vm . lexical_environment ( ) - > create_immutable_binding ( vm , name , vm . in_strict_mode ( ) ) ;
2022-02-12 19:48:45 +03:30
else
2022-08-21 15:12:43 +01:00
vm . lexical_environment ( ) - > create_mutable_binding ( vm , name , vm . in_strict_mode ( ) ) ;
2022-02-12 19:48:45 +03:30
} else {
2022-07-17 19:06:44 +01:00
if ( ! m_is_global ) {
if ( m_is_immutable )
2022-08-21 15:12:43 +01:00
vm . variable_environment ( ) - > create_immutable_binding ( vm , name , vm . in_strict_mode ( ) ) ;
2022-07-17 19:06:44 +01:00
else
2022-08-21 15:12:43 +01:00
vm . variable_environment ( ) - > create_mutable_binding ( vm , name , vm . in_strict_mode ( ) ) ;
2022-07-17 19:06:44 +01:00
} else {
// NOTE: CreateVariable with m_is_global set to true is expected to only be used in GlobalDeclarationInstantiation currently, which only uses "false" for "can_be_deleted".
// The only area that sets "can_be_deleted" to true is EvalDeclarationInstantiation, which is currently fully implemented in C++ and not in Bytecode.
verify_cast < GlobalEnvironment > ( vm . variable_environment ( ) ) - > create_global_var_binding ( name , false ) ;
}
2022-02-12 19:48:45 +03:30
}
return { } ;
}
ThrowCompletionOr < void > SetVariable : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto & vm = interpreter . vm ( ) ;
auto const & name = interpreter . current_executable ( ) . get_identifier ( m_identifier ) ;
auto environment = m_mode = = EnvironmentMode : : Lexical ? vm . running_execution_context ( ) . lexical_environment : vm . running_execution_context ( ) . variable_environment ;
auto reference = TRY ( vm . resolve_binding ( name , environment ) ) ;
switch ( m_initialization_mode ) {
case InitializationMode : : Initialize :
2022-08-21 15:39:13 +01:00
TRY ( reference . initialize_referenced_binding ( vm , interpreter . accumulator ( ) ) ) ;
2022-02-12 19:48:45 +03:30
break ;
case InitializationMode : : Set :
2022-08-21 15:39:13 +01:00
TRY ( reference . put_value ( vm , interpreter . accumulator ( ) ) ) ;
2022-02-12 19:48:45 +03:30
break ;
case InitializationMode : : InitializeOrSet :
VERIFY ( reference . is_environment_reference ( ) ) ;
VERIFY ( reference . base_environment ( ) . is_declarative_environment ( ) ) ;
2022-08-21 15:12:43 +01:00
TRY ( static_cast < DeclarativeEnvironment & > ( reference . base_environment ( ) ) . initialize_or_set_mutable_binding ( vm , name , interpreter . accumulator ( ) ) ) ;
2022-02-12 19:48:45 +03:30
break ;
}
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-03 18:26:32 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > GetById : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-04 21:03:53 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2022-02-07 14:36:45 +01:00
interpreter . accumulator ( ) = TRY ( object - > get ( interpreter . current_executable ( ) . get_identifier ( m_property ) ) ) ;
return { } ;
2021-06-04 21:03:53 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > PutById : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-04 20:47:07 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . reg ( m_base ) . to_object ( vm ) ) ;
2022-03-31 00:59:58 +04:30
PropertyKey name = interpreter . current_executable ( ) . get_identifier ( m_property ) ;
auto value = interpreter . accumulator ( ) ;
return put_by_property_key ( object , value , name , interpreter , m_kind ) ;
2021-06-04 20:47:07 +02:00
}
2022-03-27 19:50:09 +01:00
ThrowCompletionOr < void > DeleteById : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2022-03-27 19:50:09 +01:00
auto const & identifier = interpreter . current_executable ( ) . get_identifier ( m_property ) ;
2022-08-21 14:00:56 +01:00
bool strict = vm . in_strict_mode ( ) ;
2022-03-27 19:50:09 +01:00
auto reference = Reference { object , identifier , { } , strict } ;
2022-08-21 15:39:13 +01:00
interpreter . accumulator ( ) = Value ( TRY ( reference . delete_ ( vm ) ) ) ;
2022-03-27 19:50:09 +01:00
return { } ;
} ;
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Jump : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-04 12:07:38 +02:00
{
2021-06-09 06:49:58 +04:30
interpreter . jump ( * m_true_target ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-04 12:07:38 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > ResolveThisBinding : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-10-24 14:43:00 +02:00
{
2022-08-21 15:12:43 +01:00
auto & vm = interpreter . vm ( ) ;
interpreter . accumulator ( ) = TRY ( vm . resolve_this_binding ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-10-24 14:43:00 +02:00
}
2022-03-19 19:40:21 +00:00
ThrowCompletionOr < void > GetNewTarget : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
interpreter . accumulator ( ) = interpreter . vm ( ) . get_new_target ( ) ;
return { } ;
}
2021-06-13 20:40:20 +04:30
void Jump : : replace_references_impl ( BasicBlock const & from , BasicBlock const & to )
{
if ( m_true_target . has_value ( ) & & & m_true_target - > block ( ) = = & from )
m_true_target = Label { to } ;
if ( m_false_target . has_value ( ) & & & m_false_target - > block ( ) = = & from )
m_false_target = Label { to } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > JumpConditional : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-04 12:07:38 +02:00
{
2021-06-09 06:49:58 +04:30
VERIFY ( m_true_target . has_value ( ) ) ;
VERIFY ( m_false_target . has_value ( ) ) ;
2021-06-07 20:58:36 -07:00
auto result = interpreter . accumulator ( ) ;
2021-06-07 22:53:33 +02:00
if ( result . to_boolean ( ) )
2021-06-09 06:49:58 +04:30
interpreter . jump ( m_true_target . value ( ) ) ;
else
interpreter . jump ( m_false_target . value ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-04 12:20:44 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > JumpNullish : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-08 02:18:47 +02:00
{
2021-06-09 06:49:58 +04:30
VERIFY ( m_true_target . has_value ( ) ) ;
VERIFY ( m_false_target . has_value ( ) ) ;
2021-06-07 20:58:36 -07:00
auto result = interpreter . accumulator ( ) ;
2021-06-09 06:49:58 +04:30
if ( result . is_nullish ( ) )
interpreter . jump ( m_true_target . value ( ) ) ;
else
interpreter . jump ( m_false_target . value ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-08 02:18:47 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > JumpUndefined : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 12:24:40 -07:00
{
VERIFY ( m_true_target . has_value ( ) ) ;
VERIFY ( m_false_target . has_value ( ) ) ;
auto result = interpreter . accumulator ( ) ;
if ( result . is_undefined ( ) )
interpreter . jump ( m_true_target . value ( ) ) ;
else
interpreter . jump ( m_false_target . value ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 12:24:40 -07:00
}
2022-09-07 23:39:43 +02:00
// 13.3.8.1 https://tc39.es/ecma262/#sec-runtime-semantics-argumentlistevaluation
static MarkedVector < Value > argument_list_evaluation ( Bytecode : : Interpreter & interpreter )
{
// Note: Any spreading and actual evaluation is handled in preceding opcodes
// Note: The spec uses the concept of a list, while we create a temporary array
// in the preceding opcodes, so we have to convert in a manner that is not
// visible to the user
auto & vm = interpreter . vm ( ) ;
MarkedVector < Value > argument_values { vm . heap ( ) } ;
auto arguments = interpreter . accumulator ( ) ;
2022-10-30 12:32:47 +01:00
if ( ! ( arguments . is_object ( ) & & is < Array > ( arguments . as_object ( ) ) ) ) {
2022-11-08 19:41:23 +01:00
dbgln ( " [{}] Call arguments are not an array, but: {} " , interpreter . debug_position ( ) , arguments . to_string_without_side_effects ( ) ) ;
2022-10-30 12:32:47 +01:00
interpreter . current_executable ( ) . dump ( ) ;
VERIFY_NOT_REACHED ( ) ;
}
2022-09-07 23:39:43 +02:00
auto & argument_array = arguments . as_array ( ) ;
auto array_length = argument_array . indexed_properties ( ) . array_like_size ( ) ;
argument_values . ensure_capacity ( array_length ) ;
for ( size_t i = 0 ; i < array_length ; + + i ) {
if ( auto maybe_value = argument_array . indexed_properties ( ) . get ( i ) ; maybe_value . has_value ( ) )
argument_values . append ( maybe_value . release_value ( ) . value ) ;
else
argument_values . append ( js_undefined ( ) ) ;
}
return argument_values ;
}
2022-10-01 01:36:06 +02:00
Completion Call : : throw_type_error_for_callee ( Bytecode : : Interpreter & interpreter , StringView callee_type ) const
{
auto callee = interpreter . reg ( m_callee ) ;
if ( m_expression_string . has_value ( ) )
return interpreter . vm ( ) . throw_completion < TypeError > ( ErrorType : : IsNotAEvaluatedFrom , callee . to_string_without_side_effects ( ) , callee_type , interpreter . current_executable ( ) . get_string ( m_expression_string - > value ( ) ) ) ;
return interpreter . vm ( ) . throw_completion < TypeError > ( ErrorType : : IsNotA , callee . to_string_without_side_effects ( ) , callee_type ) ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Call : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-05 15:15:30 +02:00
{
2022-08-21 19:24:32 +01:00
auto & vm = interpreter . vm ( ) ;
2021-06-05 15:15:30 +02:00
auto callee = interpreter . reg ( m_callee ) ;
2022-03-19 19:41:15 +00:00
if ( m_type = = CallType : : Call & & ! callee . is_function ( ) )
2022-10-01 01:36:06 +02:00
return throw_type_error_for_callee ( interpreter , " function " sv ) ;
2022-03-19 19:41:15 +00:00
if ( m_type = = CallType : : Construct & & ! callee . is_constructor ( ) )
2022-10-01 01:36:06 +02:00
return throw_type_error_for_callee ( interpreter , " constructor " sv ) ;
2022-03-19 19:41:15 +00:00
2021-06-05 15:15:30 +02:00
auto & function = callee . as_function ( ) ;
auto this_value = interpreter . reg ( m_this_value ) ;
2022-09-07 23:39:43 +02:00
auto argument_values = argument_list_evaluation ( interpreter ) ;
2022-02-07 14:36:45 +01:00
2022-03-13 11:48:50 +03:30
Value return_value ;
if ( m_type = = CallType : : Call )
2022-08-21 19:24:32 +01:00
return_value = TRY ( call ( vm , function , this_value , move ( argument_values ) ) ) ;
2022-03-13 11:48:50 +03:30
else
2022-08-21 19:24:32 +01:00
return_value = TRY ( construct ( vm , function , move ( argument_values ) ) ) ;
2021-06-05 15:15:30 +02:00
2021-06-07 20:58:36 -07:00
interpreter . accumulator ( ) = return_value ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-05 15:15:30 +02:00
}
2022-08-30 18:03:02 +02:00
// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
ThrowCompletionOr < void > SuperCall : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto & vm = interpreter . vm ( ) ;
// 1. Let newTarget be GetNewTarget().
auto new_target = vm . get_new_target ( ) ;
// 2. Assert: Type(newTarget) is Object.
VERIFY ( new_target . is_object ( ) ) ;
// 3. Let func be GetSuperConstructor().
auto * func = get_super_constructor ( vm ) ;
// 4. Let argList be ? ArgumentListEvaluation of Arguments.
MarkedVector < Value > arg_list { vm . heap ( ) } ;
if ( m_is_synthetic ) {
auto const & value = interpreter . accumulator ( ) ;
VERIFY ( value . is_object ( ) & & is < Array > ( value . as_object ( ) ) ) ;
auto const & array_value = static_cast < Array const & > ( value . as_object ( ) ) ;
auto length = MUST ( length_of_array_like ( vm , array_value ) ) ;
for ( size_t i = 0 ; i < length ; + + i )
arg_list . append ( array_value . get_without_side_effects ( PropertyKey { i } ) ) ;
} else {
2022-09-07 23:39:43 +02:00
arg_list = argument_list_evaluation ( interpreter ) ;
2022-08-30 18:03:02 +02:00
}
// 5. If IsConstructor(func) is false, throw a TypeError exception.
if ( ! Value ( func ) . is_constructor ( ) )
return vm . throw_completion < TypeError > ( ErrorType : : NotAConstructor , " Super constructor " ) ;
// 6. Let result be ? Construct(func, argList, newTarget).
2022-12-14 19:35:49 +00:00
auto result = TRY ( construct ( vm , static_cast < FunctionObject & > ( * func ) , move ( arg_list ) , & new_target . as_function ( ) ) ) ;
2022-08-30 18:03:02 +02:00
// 7. Let thisER be GetThisEnvironment().
2022-12-15 20:07:13 +00:00
auto & this_environment = verify_cast < FunctionEnvironment > ( * get_this_environment ( vm ) ) ;
2022-08-30 18:03:02 +02:00
// 8. Perform ? thisER.BindThisValue(result).
TRY ( this_environment . bind_this_value ( vm , result ) ) ;
// 9. Let F be thisER.[[FunctionObject]].
auto & f = this_environment . function_object ( ) ;
// 10. Assert: F is an ECMAScript function object.
// NOTE: This is implied by the strong C++ type.
// 11. Perform ? InitializeInstanceElements(result, F).
2022-12-07 00:22:23 +00:00
TRY ( result - > initialize_instance_elements ( f ) ) ;
2022-08-30 18:03:02 +02:00
// 12. Return result.
interpreter . accumulator ( ) = result ;
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > NewFunction : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-05 15:14:09 +02:00
{
auto & vm = interpreter . vm ( ) ;
2022-08-16 00:20:49 +01:00
interpreter . accumulator ( ) = ECMAScriptFunctionObject : : create ( interpreter . realm ( ) , m_function_node . name ( ) , m_function_node . source_text ( ) , m_function_node . body ( ) , m_function_node . parameters ( ) , m_function_node . function_length ( ) , vm . lexical_environment ( ) , vm . running_execution_context ( ) . private_environment , m_function_node . kind ( ) , m_function_node . is_strict_mode ( ) , m_function_node . might_need_arguments_object ( ) , m_function_node . contains_direct_call_to_eval ( ) , m_function_node . is_arrow_function ( ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-05 15:14:09 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Return : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-05 15:53:36 +02:00
{
2021-06-07 20:58:36 -07:00
interpreter . do_return ( interpreter . accumulator ( ) . value_or ( js_undefined ( ) ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-05 15:53:36 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Increment : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-09 11:40:38 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto old_value = TRY ( interpreter . accumulator ( ) . to_numeric ( vm ) ) ;
2021-06-09 11:40:38 +02:00
if ( old_value . is_number ( ) )
interpreter . accumulator ( ) = Value ( old_value . as_double ( ) + 1 ) ;
else
2022-12-06 22:03:52 +00:00
interpreter . accumulator ( ) = BigInt : : create ( vm , old_value . as_bigint ( ) . big_integer ( ) . plus ( Crypto : : SignedBigInteger { 1 } ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-09 11:40:38 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Decrement : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-09 11:40:38 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto old_value = TRY ( interpreter . accumulator ( ) . to_numeric ( vm ) ) ;
2021-06-09 11:40:38 +02:00
if ( old_value . is_number ( ) )
interpreter . accumulator ( ) = Value ( old_value . as_double ( ) - 1 ) ;
else
2022-12-06 22:03:52 +00:00
interpreter . accumulator ( ) = BigInt : : create ( vm , old_value . as_bigint ( ) . big_integer ( ) . minus ( Crypto : : SignedBigInteger { 1 } ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-09 11:40:38 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Throw : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-09 18:18:56 +02:00
{
2022-02-07 14:36:45 +01:00
return throw_completion ( interpreter . accumulator ( ) ) ;
2021-06-09 18:18:56 +02:00
}
2022-12-09 18:48:57 +00:00
ThrowCompletionOr < void > ThrowIfNotObject : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto & vm = interpreter . vm ( ) ;
if ( ! interpreter . accumulator ( ) . is_object ( ) )
return vm . throw_completion < TypeError > ( ErrorType : : NotAnObject , interpreter . accumulator ( ) . to_string_without_side_effects ( ) ) ;
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > EnterUnwindContext : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-10 15:04:38 +02:00
{
interpreter . enter_unwind_context ( m_handler_target , m_finalizer_target ) ;
2021-06-13 20:39:40 +04:30
interpreter . jump ( m_entry_point ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-10 15:04:38 +02:00
}
2021-06-13 20:40:20 +04:30
void EnterUnwindContext : : replace_references_impl ( BasicBlock const & from , BasicBlock const & to )
{
if ( & m_entry_point . block ( ) = = & from )
m_entry_point = Label { to } ;
if ( m_handler_target . has_value ( ) & & & m_handler_target - > block ( ) = = & from )
m_handler_target = Label { to } ;
if ( m_finalizer_target . has_value ( ) & & & m_finalizer_target - > block ( ) = = & from )
m_finalizer_target = Label { to } ;
}
2022-10-22 20:19:16 +02:00
void CopyObjectExcludingProperties : : replace_references_impl ( Register from , Register to )
{
if ( m_from_object = = from )
m_from_object = to ;
for ( size_t i = 0 ; i < m_excluded_names_count ; + + i ) {
if ( m_excluded_names [ i ] = = from )
m_excluded_names [ i ] = to ;
}
}
void Call : : replace_references_impl ( Register from , Register to )
{
if ( m_callee = = from )
m_callee = to ;
if ( m_this_value = = from )
m_this_value = to ;
}
2022-02-12 19:48:45 +03:30
ThrowCompletionOr < void > LeaveEnvironment : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
if ( m_mode = = EnvironmentMode : : Lexical )
interpreter . vm ( ) . running_execution_context ( ) . lexical_environment = interpreter . saved_lexical_environment_stack ( ) . take_last ( ) ;
if ( m_mode = = EnvironmentMode : : Var )
interpreter . vm ( ) . running_execution_context ( ) . variable_environment = interpreter . saved_variable_environment_stack ( ) . take_last ( ) ;
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > LeaveUnwindContext : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-10 15:04:38 +02:00
{
interpreter . leave_unwind_context ( ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-10 15:04:38 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > ContinuePendingUnwind : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-10 15:04:38 +02:00
{
2022-02-07 14:36:45 +01:00
return interpreter . continue_pending_unwind ( m_resume_target ) ;
2021-06-10 15:04:38 +02:00
}
2021-06-13 20:40:20 +04:30
void ContinuePendingUnwind : : replace_references_impl ( BasicBlock const & from , BasicBlock const & to )
{
if ( & m_resume_target . block ( ) = = & from )
m_resume_target = Label { to } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > PushDeclarativeEnvironment : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-10 22:12:21 +02:00
{
2022-12-14 17:40:33 +00:00
auto environment = interpreter . vm ( ) . heap ( ) . allocate_without_realm < DeclarativeEnvironment > ( interpreter . vm ( ) . lexical_environment ( ) ) ;
2021-07-01 12:24:46 +02:00
interpreter . vm ( ) . running_execution_context ( ) . lexical_environment = environment ;
interpreter . vm ( ) . running_execution_context ( ) . variable_environment = environment ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-10 22:12:21 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > Yield : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-11 01:38:30 +04:30
{
auto yielded_value = interpreter . accumulator ( ) . value_or ( js_undefined ( ) ) ;
2022-08-16 00:20:49 +01:00
auto object = Object : : create ( interpreter . realm ( ) , nullptr ) ;
2021-07-06 01:15:50 +03:00
object - > define_direct_property ( " result " , yielded_value , JS : : default_attributes ) ;
2021-06-11 01:38:30 +04:30
if ( m_continuation_label . has_value ( ) )
2021-07-06 01:15:50 +03:00
object - > define_direct_property ( " continuation " , Value ( static_cast < double > ( reinterpret_cast < u64 > ( & m_continuation_label - > block ( ) ) ) ) , JS : : default_attributes ) ;
2021-06-11 01:38:30 +04:30
else
2021-07-06 01:15:50 +03:00
object - > define_direct_property ( " continuation " , Value ( 0 ) , JS : : default_attributes ) ;
2021-06-11 01:38:30 +04:30
interpreter . do_return ( object ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-11 01:38:30 +04:30
}
2021-06-13 20:40:20 +04:30
void Yield : : replace_references_impl ( BasicBlock const & from , BasicBlock const & to )
{
if ( m_continuation_label . has_value ( ) & & & m_continuation_label - > block ( ) = = & from )
m_continuation_label = Label { to } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > GetByValue : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-11 00:35:25 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . reg ( m_base ) . to_object ( vm ) ) ;
2022-02-07 14:36:45 +01:00
2022-08-21 14:00:56 +01:00
auto property_key = TRY ( interpreter . accumulator ( ) . to_property_key ( vm ) ) ;
2022-02-07 14:36:45 +01:00
interpreter . accumulator ( ) = TRY ( object - > get ( property_key ) ) ;
return { } ;
2021-06-11 00:35:25 +02:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > PutByValue : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-11 00:35:25 +02:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . reg ( m_base ) . to_object ( vm ) ) ;
2022-02-07 14:36:45 +01:00
2022-08-21 14:00:56 +01:00
auto property_key = TRY ( interpreter . reg ( m_property ) . to_property_key ( vm ) ) ;
2022-03-31 00:59:58 +04:30
return put_by_property_key ( object , interpreter . accumulator ( ) , property_key , interpreter , m_kind ) ;
2021-06-11 00:35:25 +02:00
}
2022-03-27 19:50:09 +01:00
ThrowCompletionOr < void > DeleteByValue : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . reg ( m_base ) . to_object ( vm ) ) ;
auto property_key = TRY ( interpreter . accumulator ( ) . to_property_key ( vm ) ) ;
bool strict = vm . in_strict_mode ( ) ;
2022-03-27 19:50:09 +01:00
auto reference = Reference { object , property_key , { } , strict } ;
2022-08-21 15:39:13 +01:00
interpreter . accumulator ( ) = Value ( TRY ( reference . delete_ ( vm ) ) ) ;
2022-03-27 19:50:09 +01:00
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > GetIterator : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 13:40:48 -07:00
{
2022-08-21 15:56:27 +01:00
auto & vm = interpreter . vm ( ) ;
auto iterator = TRY ( get_iterator ( vm , interpreter . accumulator ( ) ) ) ;
interpreter . accumulator ( ) = iterator_to_object ( vm , iterator ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 13:40:48 -07:00
}
2022-12-09 18:48:57 +00:00
ThrowCompletionOr < void > GetMethod : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto & vm = interpreter . vm ( ) ;
auto identifier = interpreter . current_executable ( ) . get_identifier ( m_property ) ;
auto * method = TRY ( interpreter . accumulator ( ) . get_method ( vm , identifier ) ) ;
interpreter . accumulator ( ) = method ? : js_undefined ( ) ;
return { } ;
}
2022-03-18 20:18:19 +03:30
// 14.7.5.9 EnumerateObjectProperties ( O ), https://tc39.es/ecma262/#sec-enumerate-object-properties
ThrowCompletionOr < void > GetObjectPropertyIterator : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
// While the spec does provide an algorithm, it allows us to implement it ourselves so long as we meet the following invariants:
// 1- Returned property keys do not include keys that are Symbols
// 2- Properties of the target object may be deleted during enumeration. A property that is deleted before it is processed by the iterator's next method is ignored
// 3- If new properties are added to the target object during enumeration, the newly added properties are not guaranteed to be processed in the active enumeration
// 4- A property name will be returned by the iterator's next method at most once in any enumeration.
// 5- Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively;
// but a property of a prototype is not processed if it has the same name as a property that has already been processed by the iterator's next method.
// 6- The values of [[Enumerable]] attributes are not considered when determining if a property of a prototype object has already been processed.
// 7- The enumerable property names of prototype objects must be obtained by invoking EnumerateObjectProperties passing the prototype object as the argument.
// 8- EnumerateObjectProperties must obtain the own property keys of the target object by calling its [[OwnPropertyKeys]] internal method.
// 9- Property attributes of the target object must be obtained by calling its [[GetOwnProperty]] internal method
// Invariant 3 effectively allows the implementation to ignore newly added keys, and we do so (similar to other implementations).
// Invariants 1 and 6 through 9 are implemented in `enumerable_own_property_names`, which implements the EnumerableOwnPropertyNames AO.
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2022-03-18 20:18:19 +03:30
// Note: While the spec doesn't explicitly require these to be ordered, it says that the values should be retrieved via OwnPropertyKeys,
// so we just keep the order consistent anyway.
OrderedHashTable < PropertyKey > properties ;
HashTable < Object * > seen_objects ;
// Collect all keys immediately (invariant no. 5)
for ( auto * object_to_check = object ; object_to_check & & ! seen_objects . contains ( object_to_check ) ; object_to_check = TRY ( object_to_check - > internal_get_prototype_of ( ) ) ) {
seen_objects . set ( object_to_check ) ;
for ( auto & key : TRY ( object_to_check - > enumerable_own_property_names ( Object : : PropertyKind : : Key ) ) ) {
2022-08-21 14:00:56 +01:00
properties . set ( TRY ( PropertyKey : : from_value ( vm , key ) ) ) ;
2022-03-18 20:18:19 +03:30
}
}
Iterator iterator {
. iterator = object ,
. next_method = NativeFunction : : create (
2022-08-16 00:20:49 +01:00
interpreter . realm ( ) ,
2022-08-22 11:48:08 +01:00
[ seen_items = HashTable < PropertyKey > ( ) , items = move ( properties ) ] ( VM & vm ) mutable - > ThrowCompletionOr < Value > {
auto & realm = * vm . current_realm ( ) ;
2022-08-20 09:48:43 +01:00
auto iterated_object_value = vm . this_value ( ) ;
2022-03-18 20:18:19 +03:30
if ( ! iterated_object_value . is_object ( ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < InternalError > ( " Invalid state for GetObjectPropertyIterator.next " ) ;
2022-03-18 20:18:19 +03:30
auto & iterated_object = iterated_object_value . as_object ( ) ;
2022-12-13 20:49:50 +00:00
auto result_object = Object : : create ( realm , nullptr ) ;
2022-03-18 20:18:19 +03:30
while ( true ) {
if ( items . is_empty ( ) ) {
result_object - > define_direct_property ( vm . names . done , JS : : Value ( true ) , default_attributes ) ;
return result_object ;
}
auto it = items . begin ( ) ;
auto key = * it ;
items . remove ( it ) ;
// If the key was already seen, skip over it (invariant no. 4)
auto result = seen_items . set ( key ) ;
if ( result ! = AK : : HashSetResult : : InsertedNewEntry )
continue ;
// If the property is deleted, don't include it (invariant no. 2)
if ( ! TRY ( iterated_object . has_property ( key ) ) )
continue ;
result_object - > define_direct_property ( vm . names . done , JS : : Value ( false ) , default_attributes ) ;
if ( key . is_number ( ) )
result_object - > define_direct_property ( vm . names . value , JS : : Value ( key . as_number ( ) ) , default_attributes ) ;
else if ( key . is_string ( ) )
2022-12-06 22:17:27 +00:00
result_object - > define_direct_property ( vm . names . value , PrimitiveString : : create ( vm , key . as_string ( ) ) , default_attributes ) ;
2022-03-18 20:18:19 +03:30
else
VERIFY_NOT_REACHED ( ) ; // We should not have non-string/number keys.
return result_object ;
}
} ,
1 ,
2022-08-21 15:56:27 +01:00
vm . names . next ) ,
2022-03-18 20:18:19 +03:30
. done = false ,
} ;
2022-08-21 15:56:27 +01:00
interpreter . accumulator ( ) = iterator_to_object ( vm , move ( iterator ) ) ;
2022-03-18 20:18:19 +03:30
return { } ;
}
2022-12-09 18:48:57 +00:00
ThrowCompletionOr < void > IteratorClose : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
auto & vm = interpreter . vm ( ) ;
auto * iterator_object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
auto iterator = object_to_iterator ( vm , * iterator_object ) ;
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY ( iterator_close ( vm , iterator , Completion { m_completion_type , m_completion_value , { } } ) ) ;
return { } ;
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > IteratorNext : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 13:40:48 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * iterator_object = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2022-08-21 15:56:27 +01:00
auto iterator = object_to_iterator ( vm , * iterator_object ) ;
2021-10-20 08:44:30 -04:00
2022-08-21 15:56:27 +01:00
interpreter . accumulator ( ) = TRY ( iterator_next ( vm , iterator ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 13:40:48 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > IteratorResultDone : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 13:40:48 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * iterator_result = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2021-10-20 09:00:37 -04:00
2022-08-21 15:56:27 +01:00
auto complete = TRY ( iterator_complete ( vm , * iterator_result ) ) ;
2021-10-20 09:00:37 -04:00
interpreter . accumulator ( ) = Value ( complete ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 13:40:48 -07:00
}
2022-02-07 14:36:45 +01:00
ThrowCompletionOr < void > IteratorResultValue : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-13 13:40:48 -07:00
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
auto * iterator_result = TRY ( interpreter . accumulator ( ) . to_object ( vm ) ) ;
2021-10-20 09:05:52 -04:00
2022-08-21 15:56:27 +01:00
interpreter . accumulator ( ) = TRY ( iterator_value ( vm , * iterator_result ) ) ;
2022-02-07 14:36:45 +01:00
return { } ;
2021-06-13 13:40:48 -07:00
}
2022-02-11 22:38:21 +03:30
ThrowCompletionOr < void > NewClass : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
2021-06-30 15:42:13 -03:00
{
2022-02-11 22:38:21 +03:30
auto name = m_class_expression . name ( ) ;
auto scope = interpreter . ast_interpreter_scope ( ) ;
auto & ast_interpreter = scope . interpreter ( ) ;
2022-10-02 11:50:13 +02:00
auto * class_object = TRY ( m_class_expression . class_definition_evaluation ( ast_interpreter , name , name . is_null ( ) ? " " sv : name ) ) ;
class_object - > set_source_text ( m_class_expression . source_text ( ) ) ;
2022-02-11 22:38:21 +03:30
interpreter . accumulator ( ) = class_object ;
return { } ;
2021-06-30 15:42:13 -03:00
}
2022-06-11 23:12:22 +01:00
// 13.5.3.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-typeof-operator-runtime-semantics-evaluation
ThrowCompletionOr < void > TypeofVariable : : execute_impl ( Bytecode : : Interpreter & interpreter ) const
{
2022-08-21 14:00:56 +01:00
auto & vm = interpreter . vm ( ) ;
2022-06-11 23:12:22 +01:00
// 1. Let val be the result of evaluating UnaryExpression.
auto const & string = interpreter . current_executable ( ) . get_identifier ( m_identifier ) ;
2022-08-21 14:00:56 +01:00
auto reference = TRY ( vm . resolve_binding ( string ) ) ;
2022-06-11 23:12:22 +01:00
// 2. If val is a Reference Record, then
// a. If IsUnresolvableReference(val) is true, return "undefined".
if ( reference . is_unresolvable ( ) ) {
2022-12-06 22:17:27 +00:00
interpreter . accumulator ( ) = PrimitiveString : : create ( vm , " undefined " sv ) ;
2022-06-11 23:12:22 +01:00
return { } ;
}
// 3. Set val to ? GetValue(val).
2022-08-21 15:39:13 +01:00
auto value = TRY ( reference . get_value ( vm ) ) ;
2022-06-11 23:12:22 +01:00
// 4. NOTE: This step is replaced in section B.3.6.3.
// 5. Return a String according to Table 41.
2022-12-06 22:17:27 +00:00
interpreter . accumulator ( ) = PrimitiveString : : create ( vm , value . typeof ( ) ) ;
2022-06-11 23:12:22 +01:00
return { } ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString Load : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-03 10:46:30 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Load {} " , m_src ) ;
2021-06-03 10:46:30 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString LoadImmediate : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-07 22:05:09 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " LoadImmediate {} " , m_value ) ;
2021-06-07 20:58:36 -07:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Store : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-07 20:58:36 -07:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Store {} " , m_dst ) ;
2021-06-07 22:05:09 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewBigInt : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-08 07:59:25 +02:00
{
2023-01-13 10:52:17 -05:00
return DeprecatedString : : formatted ( " NewBigInt \" {} \" " , m_bigint . to_base_deprecated ( 10 ) ) ;
2021-06-08 07:59:25 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewArray : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-08 23:06:52 +02:00
{
StringBuilder builder ;
2022-07-11 17:32:29 +00:00
builder . append ( " NewArray " sv ) ;
2021-06-08 23:06:52 +02:00
if ( m_element_count ! = 0 ) {
2022-03-27 17:49:10 +01:00
builder . appendff ( " [{}-{}] " , m_elements [ 0 ] , m_elements [ 1 ] ) ;
2021-06-08 23:06:52 +02:00
}
2022-12-06 01:12:49 +00:00
return builder . to_deprecated_string ( ) ;
2021-06-08 23:06:52 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Append : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-09-09 15:23:02 +02:00
{
if ( m_is_spread )
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Append lhs: **{} " , m_lhs ) ;
return DeprecatedString : : formatted ( " Append lhs: {} " , m_lhs ) ;
2022-09-09 15:23:02 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString IteratorToArray : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-13 14:06:26 -07:00
{
return " IteratorToArray " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewString : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-03 18:26:32 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " NewString {} ( \" {} \" ) " , m_string , executable . string_table - > get ( m_string ) ) ;
2021-06-03 18:26:32 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewObject : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-04 20:30:23 +02:00
{
2021-06-07 20:58:36 -07:00
return " NewObject " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewRegExp : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-19 17:17:40 -07:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " NewRegExp source:{} ( \" {} \" ) flags:{} ( \" {} \" ) " , m_source_index , executable . get_string ( m_source_index ) , m_flags_index , executable . get_string ( m_flags_index ) ) ;
2021-06-19 17:17:40 -07:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString CopyObjectExcludingProperties : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-13 15:30:32 -07:00
{
StringBuilder builder ;
builder . appendff ( " CopyObjectExcludingProperties from:{} " , m_from_object ) ;
if ( m_excluded_names_count ! = 0 ) {
2022-07-11 17:32:29 +00:00
builder . append ( " excluding:[ " sv ) ;
2022-08-31 14:18:27 +02:00
builder . join ( " , " sv , Span < Register const > ( m_excluded_names , m_excluded_names_count ) ) ;
2021-06-13 15:30:32 -07:00
builder . append ( ' ] ' ) ;
}
2022-12-06 01:12:49 +00:00
return builder . to_deprecated_string ( ) ;
2021-06-13 15:30:32 -07:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString ConcatString : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-07 20:58:36 -07:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " ConcatString {} " , m_lhs ) ;
2021-06-04 20:30:23 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetVariable : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-03 18:26:32 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " GetVariable {} ({}) " , m_identifier , executable . identifier_table - > get ( m_identifier ) ) ;
2021-06-03 18:26:32 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString DeleteVariable : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2022-03-27 19:50:09 +01:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " DeleteVariable {} ({}) " , m_identifier , executable . identifier_table - > get ( m_identifier ) ) ;
2022-03-27 19:50:09 +01:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString CreateEnvironment : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-02-12 19:48:45 +03:30
{
auto mode_string = m_mode = = EnvironmentMode : : Lexical
? " Lexical "
: " Variable " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " CreateEnvironment mode:{} " , mode_string ) ;
2022-02-12 19:48:45 +03:30
}
2022-12-06 01:12:49 +00:00
DeprecatedString CreateVariable : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2022-02-12 19:48:45 +03:30
{
auto mode_string = m_mode = = EnvironmentMode : : Lexical ? " Lexical " : " Variable " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " CreateVariable env:{} immutable:{} global:{} {} ({}) " , mode_string , m_is_immutable , m_is_global , m_identifier , executable . identifier_table - > get ( m_identifier ) ) ;
2022-02-12 19:48:45 +03:30
}
2022-12-06 01:12:49 +00:00
DeprecatedString EnterObjectEnvironment : : to_deprecated_string_impl ( Executable const & ) const
2022-03-13 16:01:18 +03:30
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " EnterObjectEnvironment " ) ;
2022-03-13 16:01:18 +03:30
}
2022-12-06 01:12:49 +00:00
DeprecatedString SetVariable : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-03 18:26:32 +02:00
{
2022-02-12 19:48:45 +03:30
auto initialization_mode_name = m_initialization_mode = = InitializationMode : : Initialize ? " Initialize "
: m_initialization_mode = = InitializationMode : : Set ? " Set "
: " InitializeOrSet " ;
auto mode_string = m_mode = = EnvironmentMode : : Lexical ? " Lexical " : " Variable " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " SetVariable env:{} init:{} {} ({}) " , mode_string , initialization_mode_name , m_identifier , executable . identifier_table - > get ( m_identifier ) ) ;
2021-06-03 18:26:32 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString PutById : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-04 20:47:07 +02:00
{
2022-03-31 00:59:58 +04:30
auto kind = m_kind = = PropertyKind : : Getter
? " getter "
: m_kind = = PropertyKind : : Setter
? " setter "
: " property " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " PutById kind:{} base:{}, property:{} ({}) " , kind , m_base , m_property , executable . identifier_table - > get ( m_property ) ) ;
2021-06-04 20:47:07 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetById : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-04 21:03:53 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " GetById {} ({}) " , m_property , executable . identifier_table - > get ( m_property ) ) ;
2021-06-04 21:03:53 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString DeleteById : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2022-03-27 19:50:09 +01:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " DeleteById {} ({}) " , m_property , executable . identifier_table - > get ( m_property ) ) ;
2022-03-27 19:50:09 +01:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Jump : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-04 12:07:38 +02:00
{
2021-06-09 06:49:58 +04:30
if ( m_true_target . has_value ( ) )
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Jump {} " , * m_true_target ) ;
return DeprecatedString : : formatted ( " Jump <empty> " ) ;
2021-06-04 12:07:38 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString JumpConditional : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-04 12:20:44 +02:00
{
2022-12-04 18:02:33 +00:00
auto true_string = m_true_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_true_target ) : " <empty> " ;
auto false_string = m_false_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_false_target ) : " <empty> " ;
return DeprecatedString : : formatted ( " JumpConditional true:{} false:{} " , true_string , false_string ) ;
2021-06-04 12:20:44 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString JumpNullish : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-08 02:18:47 +02:00
{
2022-12-04 18:02:33 +00:00
auto true_string = m_true_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_true_target ) : " <empty> " ;
auto false_string = m_false_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_false_target ) : " <empty> " ;
return DeprecatedString : : formatted ( " JumpNullish null:{} nonnull:{} " , true_string , false_string ) ;
2021-06-08 02:18:47 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString JumpUndefined : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-13 12:24:40 -07:00
{
2022-12-04 18:02:33 +00:00
auto true_string = m_true_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_true_target ) : " <empty> " ;
auto false_string = m_false_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_false_target ) : " <empty> " ;
return DeprecatedString : : formatted ( " JumpUndefined undefined:{} not undefined:{} " , true_string , false_string ) ;
2021-06-13 12:24:40 -07:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Call : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-05 15:15:30 +02:00
{
2022-10-01 01:36:06 +02:00
if ( m_expression_string . has_value ( ) )
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Call callee:{}, this:{}, arguments:[...acc] ({}) " , m_callee , m_this_value , executable . get_string ( m_expression_string . value ( ) ) ) ;
2022-10-01 01:36:06 +02:00
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Call callee:{}, this:{}, arguments:[...acc] " , m_callee , m_this_value ) ;
2022-08-30 18:03:02 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString SuperCall : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-08-30 18:03:02 +02:00
{
2022-09-07 23:39:43 +02:00
return " SuperCall arguments:[...acc] " sv ;
2021-06-05 15:15:30 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewFunction : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-05 15:14:09 +02:00
{
2021-06-10 00:49:23 +02:00
return " NewFunction " ;
2021-06-05 15:14:09 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString NewClass : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-30 15:42:13 -03:00
{
2022-10-02 11:51:17 +02:00
auto name = m_class_expression . name ( ) ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " NewClass '{}' " , name . is_null ( ) ? " " sv : name ) ;
2021-06-30 15:42:13 -03:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Return : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-05 15:53:36 +02:00
{
return " Return " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString Increment : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-09 11:40:38 +02:00
{
return " Increment " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString Decrement : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-09 11:40:38 +02:00
{
return " Decrement " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString Throw : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-09 18:18:56 +02:00
{
return " Throw " ;
}
2022-12-09 18:48:57 +00:00
DeprecatedString ThrowIfNotObject : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
{
return " ThrowIfNotObject " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString EnterUnwindContext : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-10 15:04:38 +02:00
{
2022-12-04 18:02:33 +00:00
auto handler_string = m_handler_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_handler_target ) : " <empty> " ;
auto finalizer_string = m_finalizer_target . has_value ( ) ? DeprecatedString : : formatted ( " {} " , * m_finalizer_target ) : " <empty> " ;
return DeprecatedString : : formatted ( " EnterUnwindContext handler:{} finalizer:{} entry:{} " , handler_string , finalizer_string , m_entry_point ) ;
2021-06-10 15:04:38 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString LeaveEnvironment : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-02-12 19:48:45 +03:30
{
auto mode_string = m_mode = = EnvironmentMode : : Lexical
? " Lexical "
: " Variable " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " LeaveEnvironment env:{} " , mode_string ) ;
2022-02-12 19:48:45 +03:30
}
2022-12-06 01:12:49 +00:00
DeprecatedString LeaveUnwindContext : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-10 15:04:38 +02:00
{
return " LeaveUnwindContext " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString ContinuePendingUnwind : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-10 15:04:38 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " ContinuePendingUnwind resume:{} " , m_resume_target ) ;
2021-06-10 15:04:38 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString PushDeclarativeEnvironment : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2021-06-10 22:12:21 +02:00
{
StringBuilder builder ;
2022-07-11 17:32:29 +00:00
builder . append ( " PushDeclarativeEnvironment " sv ) ;
2021-06-10 22:12:21 +02:00
if ( ! m_variables . is_empty ( ) ) {
2022-07-11 17:32:29 +00:00
builder . append ( " { " sv ) ;
2022-12-04 18:02:33 +00:00
Vector < DeprecatedString > names ;
2021-06-10 22:12:21 +02:00
for ( auto & it : m_variables )
names . append ( executable . get_string ( it . key ) ) ;
2022-07-11 20:10:18 +00:00
builder . append ( ' } ' ) ;
2022-07-11 17:32:29 +00:00
builder . join ( " , " sv , names ) ;
2021-06-10 22:12:21 +02:00
}
2022-12-06 01:12:49 +00:00
return builder . to_deprecated_string ( ) ;
2021-06-10 22:12:21 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString Yield : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-11 01:38:30 +04:30
{
if ( m_continuation_label . has_value ( ) )
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " Yield continuation:@{} " , m_continuation_label - > block ( ) . name ( ) ) ;
return DeprecatedString : : formatted ( " Yield return " ) ;
2021-06-11 01:38:30 +04:30
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetByValue : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-11 00:35:25 +02:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " GetByValue base:{} " , m_base ) ;
2021-06-11 00:35:25 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString PutByValue : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-06-11 00:35:25 +02:00
{
2022-03-31 00:59:58 +04:30
auto kind = m_kind = = PropertyKind : : Getter
? " getter "
: m_kind = = PropertyKind : : Setter
? " setter "
: " property " ;
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " PutByValue kind:{} base:{}, property:{} " , kind , m_base , m_property ) ;
2021-06-11 00:35:25 +02:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString DeleteByValue : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-03-27 19:50:09 +01:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " DeleteByValue base:{} " , m_base ) ;
2022-03-27 19:50:09 +01:00
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetIterator : : to_deprecated_string_impl ( Executable const & ) const
2021-06-13 13:40:48 -07:00
{
return " GetIterator " ;
}
2022-12-09 18:48:57 +00:00
DeprecatedString GetMethod : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
{
return DeprecatedString : : formatted ( " GetMethod {} ({}) " , m_property , executable . identifier_table - > get ( m_property ) ) ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetObjectPropertyIterator : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-03-18 20:18:19 +03:30
{
return " GetObjectPropertyIterator " ;
}
2022-12-09 18:48:57 +00:00
DeprecatedString IteratorClose : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
{
return DeprecatedString : : formatted ( " IteratorClose completion_type={} completion_value={} " , to_underlying ( m_completion_type ) , m_completion_value . has_value ( ) ? m_completion_value . value ( ) . to_string_without_side_effects ( ) : " <empty> " ) ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString IteratorNext : : to_deprecated_string_impl ( Executable const & ) const
2021-06-13 13:40:48 -07:00
{
return " IteratorNext " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString IteratorResultDone : : to_deprecated_string_impl ( Executable const & ) const
2021-06-13 13:40:48 -07:00
{
return " IteratorResultDone " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString IteratorResultValue : : to_deprecated_string_impl ( Executable const & ) const
2021-06-13 13:40:48 -07:00
{
return " IteratorResultValue " ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString ResolveThisBinding : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2021-10-24 14:43:00 +02:00
{
return " ResolveThisBinding " sv ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString GetNewTarget : : to_deprecated_string_impl ( Bytecode : : Executable const & ) const
2022-03-19 19:40:21 +00:00
{
return " GetNewTarget " sv ;
}
2022-12-06 01:12:49 +00:00
DeprecatedString TypeofVariable : : to_deprecated_string_impl ( Bytecode : : Executable const & executable ) const
2022-06-11 23:12:22 +01:00
{
2022-12-04 18:02:33 +00:00
return DeprecatedString : : formatted ( " TypeofVariable {} ({}) " , m_identifier , executable . identifier_table - > get ( m_identifier ) ) ;
2022-06-11 23:12:22 +01:00
}
2021-06-03 10:46:30 +02:00
}