Skip to content

Commit 5ed104a

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 5ed104a

File tree

4 files changed

+113
-120
lines changed

4 files changed

+113
-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: 109 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,18 @@ 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' argument's value or ECMA_VALUE_UNDEFINED */
793714
const ecma_value_t *arguments_list_p, /**< arguments list */
794715
ecma_length_t arguments_list_len) /**< length of arguments list */
795716
{
796717
JERRY_ASSERT (func_obj_p != NULL
797718
&& !ecma_is_lexical_environment (func_obj_p));
798719

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);
720+
JERRY_ASSERT (ecma_is_value_object (this_arg_value)
721+
|| this_arg_value == ECMA_VALUE_UNDEFINED);
837722

723+
while (JERRY_UNLIKELY (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION))
724+
{
838725
/* 1-3. */
839726
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
840727

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

875762
/* 5. */
876763
ret_value = ecma_op_function_construct (target_func_obj_p,
764+
this_arg_value,
877765
merged_args_list_p,
878766
merged_args_list_len);
879767

880768
JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
881769

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

886877
/**

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)