@@ -17,15 +17,19 @@ use crate::{
1717 builtins:: {
1818 array_create,
1919 keyed_collections:: map_objects:: map_prototype:: canonicalize_keyed_collection_key,
20- ArgumentsList , Array ,
20+ ArgumentsList , Array , BuiltinConstructorFunction ,
21+ } ,
22+ execution:: {
23+ agent:: ExceptionType , new_class_field_initializer_environment, Agent ,
24+ ECMAScriptCodeEvaluationState , EnvironmentIndex , ExecutionContext , JsResult ,
25+ RealmIdentifier ,
2126 } ,
22- execution:: { agent:: ExceptionType , Agent , JsResult , RealmIdentifier } ,
2327 types:: {
24- Function , InternalMethods , IntoObject , IntoValue , Number , Object , OrdinaryObject ,
25- PropertyDescriptor , PropertyKey , String , Value , BUILTIN_STRING_MEMORY ,
28+ Function , InternalMethods , IntoFunction , IntoObject , IntoValue , Number , Object ,
29+ OrdinaryObject , PropertyDescriptor , PropertyKey , String , Value , BUILTIN_STRING_MEMORY ,
2630 } ,
2731 } ,
28- engine:: instanceof_operator,
32+ engine:: { instanceof_operator, Vm } ,
2933 heap:: { Heap , ObjectEntry } ,
3034 SmallInteger ,
3135} ;
@@ -870,6 +874,63 @@ pub(crate) fn copy_data_properties_into_object(
870874 ) )
871875}
872876
877+ /// [7.3.33 InitializeInstanceElements ( O, constructor )](https://tc39.es/ecma262/#sec-initializeinstanceelements)
878+ ///
879+ /// The abstract operation InitializeInstanceElements takes arguments O (an
880+ /// Object) and constructor (an ECMAScript function object) and returns either
881+ /// a normal completion containing unused or a throw completion.
882+ pub ( crate ) fn initialize_instance_elements (
883+ agent : & mut Agent ,
884+ o : Object ,
885+ constructor : BuiltinConstructorFunction ,
886+ ) -> JsResult < ( ) > {
887+ // 1. Let methods be the value of constructor.[[PrivateMethods]].
888+ // 2. For each PrivateElement method of methods, do
889+ // a. Perform ? PrivateMethodOrAccessorAdd(O, method).
890+ // TODO: Private properties and methods.
891+ // 3. Let fields be the value of constructor.[[Fields]].
892+ // 4. For each element fieldRecord of fields, do
893+ // a. Perform ? DefineField(O, fieldRecord).
894+ // 5. Return unused.
895+ let constructor_data = & agent[ constructor] ;
896+ if let Some ( bytecode) = constructor_data. compiled_initializer_bytecode {
897+ // Note: The code here looks quite a bit different from what the spec
898+ // says. For one, the spec is bugged and doesn't consider default
899+ // constructors at all. Second, we compile field initializers into
900+ // the ECMAScript class constructors directly, so our code only needs
901+ // to work for builtin constructors.
902+ // Third, the spec defines the initializers as individual functions
903+ // run one after the other. Instea we compile all of the initializers
904+ // into a single bytecode executable associated with the constructor.
905+ // The problem then becomes how to run this executable as an ECMAScript
906+ // function.
907+ // To do this, we need a new execution context that points to a new
908+ // Function environment. The function environment should be lexically a
909+ // child of the class constructor's creating environment.
910+ let bytecode = unsafe { bytecode. as_ref ( ) } ;
911+ let f = constructor. into_function ( ) ;
912+ let outer_env = constructor_data. environment ;
913+ let outer_priv_env = constructor_data. private_environment ;
914+ let source_code = constructor_data. source_code ;
915+ let decl_env = new_class_field_initializer_environment ( agent, f, o, outer_env) ;
916+ agent. execution_context_stack . push ( ExecutionContext {
917+ ecmascript_code : Some ( ECMAScriptCodeEvaluationState {
918+ lexical_environment : EnvironmentIndex :: Function ( decl_env) ,
919+ variable_environment : EnvironmentIndex :: Function ( decl_env) ,
920+ private_environment : outer_priv_env,
921+ is_strict_mode : true ,
922+ source_code,
923+ } ) ,
924+ function : Some ( f) ,
925+ realm : agent[ constructor] . realm ,
926+ script_or_module : None ,
927+ } ) ;
928+ let _ = Vm :: execute ( agent, bytecode, None ) . into_js_result ( ) ?;
929+ agent. execution_context_stack . pop ( ) ;
930+ }
931+ Ok ( ( ) )
932+ }
933+
873934/// ### [7.3.34 AddValueToKeyedGroup ( groups, key, value )](https://tc39.es/ecma262/#sec-add-value-to-keyed-group)
874935/// The abstract operation AddValueToKeyedGroup takes arguments groups (a List of Records with fields
875936/// [[Key]] (an ECMAScript language value) and [[Elements]] (a List of ECMAScript language values)),
0 commit comments