Skip to content

Commit ef12207

Browse files
committed
Rework op_construct.
The new form should be more suitable for classes. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 7717d2e commit ef12207

File tree

4 files changed

+114
-120
lines changed

4 files changed

+114
-120
lines changed

jerry-core/api/jerry.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,6 +2213,7 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio
22132213
JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
22142214

22152215
return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
2216+
ECMA_VALUE_UNDEFINED,
22162217
args_p,
22172218
args_count));
22182219
}

jerry-core/ecma/operations/ecma-function-object.c

Lines changed: 110 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -699,86 +699,6 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
699699
}
700700
} /* ecma_op_function_call */
701701

702-
/**
703-
* [[Construct]] implementation for Function objects (13.2.2),
704-
* created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) and
705-
* externally defined (host) functions (ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION).
706-
*
707-
* @return ecma value
708-
* Returned value must be freed with ecma_free_value
709-
*/
710-
static ecma_value_t
711-
ecma_op_function_construct_ecma_or_external (ecma_object_t *func_obj_p, /**< Function object */
712-
const ecma_value_t *arguments_list_p, /**< arguments list */
713-
ecma_length_t arguments_list_len) /**< length of arguments list */
714-
{
715-
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION
716-
|| ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
717-
718-
/* 5. */
719-
ecma_value_t prototype_prop_value = ecma_op_object_get_by_magic_id (func_obj_p,
720-
LIT_MAGIC_STRING_PROTOTYPE);
721-
722-
if (ECMA_IS_VALUE_ERROR (prototype_prop_value))
723-
{
724-
return prototype_prop_value;
725-
}
726-
727-
/* 1., 2., 4. */
728-
ecma_object_t *obj_p;
729-
if (ecma_is_value_object (prototype_prop_value))
730-
{
731-
/* 6. */
732-
obj_p = ecma_create_object (ecma_get_object_from_value (prototype_prop_value),
733-
0,
734-
ECMA_OBJECT_TYPE_GENERAL);
735-
}
736-
else
737-
{
738-
/* 7. */
739-
ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
740-
741-
obj_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
742-
743-
ecma_deref_object (prototype_p);
744-
}
745-
746-
ecma_free_value (prototype_prop_value);
747-
748-
/* 3. */
749-
/*
750-
* [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects
751-
* without ECMA_INTERNAL_PROPERTY_CLASS internal property
752-
* is "Object".
753-
*
754-
* See also: ecma_object_get_class_name.
755-
*/
756-
757-
/* 8. */
758-
ecma_value_t this_obj = ecma_make_object_value (obj_p);
759-
ecma_value_t ret_value;
760-
761-
if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
762-
{
763-
arguments_list_p = ecma_op_function_set_construct_flag (arguments_list_p);
764-
}
765-
766-
ret_value = ecma_op_function_call (func_obj_p,
767-
this_obj,
768-
arguments_list_p,
769-
arguments_list_len);
770-
771-
/* 9. */
772-
if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
773-
{
774-
ecma_deref_object (obj_p);
775-
return ret_value;
776-
}
777-
778-
ecma_fast_free_value (ret_value);
779-
return this_obj;
780-
} /* ecma_op_function_construct_ecma_or_external */
781-
782702
/**
783703
* [[Construct]] implementation:
784704
* 13.2.2 - for Function objects, created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION),
@@ -790,51 +710,19 @@ ecma_op_function_construct_ecma_or_external (ecma_object_t *func_obj_p, /**< Fun
790710
*/
791711
ecma_value_t
792712
ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
713+
ecma_value_t this_arg_value, /**< optional 'this' object value
714+
* or ECMA_VALUE_UNDEFINED */
793715
const ecma_value_t *arguments_list_p, /**< arguments list */
794716
ecma_length_t arguments_list_len) /**< length of arguments list */
795717
{
796718
JERRY_ASSERT (func_obj_p != NULL
797719
&& !ecma_is_lexical_environment (func_obj_p));
798720

799-
while (true)
800-
{
801-
switch (ecma_get_object_type (func_obj_p))
802-
{
803-
case ECMA_OBJECT_TYPE_FUNCTION:
804-
{
805-
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
806-
{
807-
if (ecma_builtin_function_is_routine (func_obj_p))
808-
{
809-
return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor."));
810-
}
811-
812-
return ecma_builtin_dispatch_construct (func_obj_p,
813-
arguments_list_p,
814-
arguments_list_len);
815-
}
816-
/* FALLTHRU */
817-
}
818-
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
819-
{
820-
return ecma_op_function_construct_ecma_or_external (func_obj_p,
821-
arguments_list_p,
822-
arguments_list_len);
823-
}
824-
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
825-
case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
826-
{
827-
return ecma_raise_type_error (ECMA_ERR_MSG ("Arrow functions have no constructor."));
828-
}
829-
#endif /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
830-
default:
831-
{
832-
break;
833-
}
834-
}
835-
836-
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
721+
JERRY_ASSERT (ecma_is_value_object (this_arg_value)
722+
|| this_arg_value == ECMA_VALUE_UNDEFINED);
837723

724+
while (JERRY_UNLIKELY (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION))
725+
{
838726
/* 1-3. */
839727
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
840728

@@ -874,13 +762,117 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
874762

875763
/* 5. */
876764
ret_value = ecma_op_function_construct (target_func_obj_p,
765+
this_arg_value,
877766
merged_args_list_p,
878767
merged_args_list_len);
879768

880769
JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
881770

882771
return ret_value;
883772
}
773+
774+
ecma_object_type_t type = ecma_get_object_type (func_obj_p);
775+
776+
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
777+
if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_ARROW_FUNCTION))
778+
{
779+
return ecma_raise_type_error (ECMA_ERR_MSG ("Arrow functions have no constructor."));
780+
}
781+
#endif /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
782+
783+
if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_FUNCTION && ecma_get_object_is_builtin (func_obj_p)))
784+
{
785+
if (ecma_builtin_function_is_routine (func_obj_p))
786+
{
787+
return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor."));
788+
}
789+
790+
return ecma_builtin_dispatch_construct (func_obj_p,
791+
arguments_list_p,
792+
arguments_list_len);
793+
}
794+
795+
ecma_object_t *new_this_obj_p = NULL;
796+
797+
if (JERRY_LIKELY (this_arg_value == ECMA_VALUE_UNDEFINED))
798+
{
799+
/* 5. */
800+
ecma_value_t prototype_prop_value = ecma_op_object_get_by_magic_id (func_obj_p,
801+
LIT_MAGIC_STRING_PROTOTYPE);
802+
803+
if (ECMA_IS_VALUE_ERROR (prototype_prop_value))
804+
{
805+
return prototype_prop_value;
806+
}
807+
808+
/* 1., 2., 4. */
809+
if (ecma_is_value_object (prototype_prop_value))
810+
{
811+
/* 6. */
812+
new_this_obj_p = ecma_create_object (ecma_get_object_from_value (prototype_prop_value),
813+
0,
814+
ECMA_OBJECT_TYPE_GENERAL);
815+
}
816+
else
817+
{
818+
/* 7. */
819+
ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
820+
821+
new_this_obj_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
822+
823+
ecma_deref_object (prototype_p);
824+
}
825+
826+
ecma_free_value (prototype_prop_value);
827+
828+
this_arg_value = ecma_make_object_value (new_this_obj_p);
829+
}
830+
831+
/* 8. */
832+
ecma_value_t ret_value;
833+
834+
switch (type)
835+
{
836+
case ECMA_OBJECT_TYPE_FUNCTION:
837+
{
838+
arguments_list_p = ecma_op_function_set_construct_flag (arguments_list_p);
839+
840+
ret_value = ecma_op_function_call (func_obj_p,
841+
this_arg_value,
842+
arguments_list_p,
843+
arguments_list_len);
844+
break;
845+
}
846+
default:
847+
{
848+
JERRY_ASSERT (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
849+
850+
ret_value = ecma_op_function_call (func_obj_p,
851+
this_arg_value,
852+
arguments_list_p,
853+
arguments_list_len);
854+
break;
855+
}
856+
}
857+
858+
/* 9. */
859+
if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
860+
{
861+
if (new_this_obj_p != NULL)
862+
{
863+
ecma_deref_object (new_this_obj_p);
864+
}
865+
return ret_value;
866+
}
867+
868+
ecma_fast_free_value (ret_value);
869+
870+
if (JERRY_UNLIKELY (new_this_obj_p == NULL))
871+
{
872+
ecma_ref_object (ecma_get_object_from_value (this_arg_value));
873+
}
874+
875+
return this_arg_value;
884876
} /* ecma_op_function_construct */
885877

886878
/**

jerry-core/ecma/operations/ecma-function-object.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ ecma_op_function_call (ecma_object_t *func_obj_p, ecma_value_t this_arg_value,
5959
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
6060

6161
ecma_value_t
62-
ecma_op_function_construct (ecma_object_t *func_obj_p, const ecma_value_t *arguments_list_p,
63-
ecma_length_t arguments_list_len);
62+
ecma_op_function_construct (ecma_object_t *func_obj_p, ecma_value_t this_arg_value,
63+
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
6464

6565
ecma_property_t *
6666
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);

jerry-core/vm/vm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
494494
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value);
495495

496496
completion_value = ecma_op_function_construct (constructor_obj_p,
497+
ECMA_VALUE_UNDEFINED,
497498
stack_top_p,
498499
arguments_list_len);
499500
}

0 commit comments

Comments
 (0)