1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "ecma-alloc.h"
17425bb815Sopenharmony_ci#include "ecma-array-object.h"
18425bb815Sopenharmony_ci#include "ecma-builtins.h"
19425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h"
20425bb815Sopenharmony_ci#include "ecma-conversion.h"
21425bb815Sopenharmony_ci#include "ecma-exceptions.h"
22425bb815Sopenharmony_ci#include "ecma-function-object.h"
23425bb815Sopenharmony_ci#include "ecma-gc.h"
24425bb815Sopenharmony_ci#include "ecma-globals.h"
25425bb815Sopenharmony_ci#include "ecma-helpers.h"
26425bb815Sopenharmony_ci#include "ecma-iterator-object.h"
27425bb815Sopenharmony_ci#include "ecma-lex-env.h"
28425bb815Sopenharmony_ci#include "ecma-objects.h"
29425bb815Sopenharmony_ci#include "ecma-promise-object.h"
30425bb815Sopenharmony_ci#include "ecma-proxy-object.h"
31425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h"
32425bb815Sopenharmony_ci#include "jcontext.h"
33425bb815Sopenharmony_ci#include "opcodes.h"
34425bb815Sopenharmony_ci#include "vm-defines.h"
35425bb815Sopenharmony_ci#include "vm-stack.h"
36425bb815Sopenharmony_ci
37425bb815Sopenharmony_ci/** \addtogroup vm Virtual machine
38425bb815Sopenharmony_ci * @{
39425bb815Sopenharmony_ci *
40425bb815Sopenharmony_ci * \addtogroup vm_opcodes Opcodes
41425bb815Sopenharmony_ci * @{
42425bb815Sopenharmony_ci */
43425bb815Sopenharmony_ci
44425bb815Sopenharmony_ci/**
45425bb815Sopenharmony_ci * 'Variable declaration' opcode handler.
46425bb815Sopenharmony_ci *
47425bb815Sopenharmony_ci * See also: ECMA-262 v5, 10.5 - Declaration binding instantiation (block 8).
48425bb815Sopenharmony_ci *
49425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if no the operation fails
50425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY - otherwise
51425bb815Sopenharmony_ci */
52425bb815Sopenharmony_ciinline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
53425bb815Sopenharmony_civm_var_decl (ecma_object_t *lex_env_p, /**< target lexical environment */
54425bb815Sopenharmony_ci             ecma_string_t *var_name_str_p, /**< variable name */
55425bb815Sopenharmony_ci             bool is_configurable_bindings) /**< true if the binding can be deleted */
56425bb815Sopenharmony_ci{
57425bb815Sopenharmony_ci  ecma_value_t has_binding = ecma_op_has_binding (lex_env_p, var_name_str_p);
58425bb815Sopenharmony_ci
59425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
60425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (has_binding))
61425bb815Sopenharmony_ci  {
62425bb815Sopenharmony_ci    return has_binding;
63425bb815Sopenharmony_ci  }
64425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
65425bb815Sopenharmony_ci
66425bb815Sopenharmony_ci  if (ecma_is_value_false (has_binding))
67425bb815Sopenharmony_ci  {
68425bb815Sopenharmony_ci    ecma_value_t completion_value = ecma_op_create_mutable_binding (lex_env_p,
69425bb815Sopenharmony_ci                                                                    var_name_str_p,
70425bb815Sopenharmony_ci                                                                    is_configurable_bindings);
71425bb815Sopenharmony_ci
72425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_empty (completion_value));
73425bb815Sopenharmony_ci
74425bb815Sopenharmony_ci    /* Skipping SetMutableBinding as we have already checked that there were not
75425bb815Sopenharmony_ci     * any binding with specified name in current lexical environment
76425bb815Sopenharmony_ci     * and CreateMutableBinding sets the created binding's value to undefined */
77425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_undefined (ecma_op_get_binding_value (lex_env_p,
78425bb815Sopenharmony_ci                                                                      var_name_str_p,
79425bb815Sopenharmony_ci                                                                      vm_is_strict_mode ())));
80425bb815Sopenharmony_ci  }
81425bb815Sopenharmony_ci
82425bb815Sopenharmony_ci  return ECMA_VALUE_EMPTY;
83425bb815Sopenharmony_ci} /* vm_var_decl */
84425bb815Sopenharmony_ci
85425bb815Sopenharmony_ci/**
86425bb815Sopenharmony_ci * Set var binding to a function literal value.
87425bb815Sopenharmony_ci *
88425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if no the operation fails
89425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY - otherwise
90425bb815Sopenharmony_ci */
91425bb815Sopenharmony_ciinline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
92425bb815Sopenharmony_civm_set_var (ecma_object_t *lex_env_p, /**< target lexical environment */
93425bb815Sopenharmony_ci            ecma_string_t *var_name_str_p, /**< variable name */
94425bb815Sopenharmony_ci            bool is_strict, /**< true, if the engine is in strict mode */
95425bb815Sopenharmony_ci            ecma_value_t lit_value) /**< function value */
96425bb815Sopenharmony_ci{
97425bb815Sopenharmony_ci  ecma_value_t put_value_result;
98425bb815Sopenharmony_ci  put_value_result = ecma_op_put_value_lex_env_base (lex_env_p, var_name_str_p, is_strict, lit_value);
99425bb815Sopenharmony_ci
100425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_boolean (put_value_result)
101425bb815Sopenharmony_ci                || ecma_is_value_empty (put_value_result)
102425bb815Sopenharmony_ci                || ECMA_IS_VALUE_ERROR (put_value_result));
103425bb815Sopenharmony_ci
104425bb815Sopenharmony_ci  ecma_free_value (lit_value);
105425bb815Sopenharmony_ci
106425bb815Sopenharmony_ci  return put_value_result;
107425bb815Sopenharmony_ci} /* vm_set_var */
108425bb815Sopenharmony_ci
109425bb815Sopenharmony_ci/**
110425bb815Sopenharmony_ci * 'typeof' opcode handler.
111425bb815Sopenharmony_ci *
112425bb815Sopenharmony_ci * See also: ECMA-262 v5, 11.4.3
113425bb815Sopenharmony_ci *
114425bb815Sopenharmony_ci * @return ecma value
115425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value
116425bb815Sopenharmony_ci */
117425bb815Sopenharmony_ciecma_value_t
118425bb815Sopenharmony_ciopfunc_typeof (ecma_value_t left_value) /**< left value */
119425bb815Sopenharmony_ci{
120425bb815Sopenharmony_ci  return ecma_make_magic_string_value (ecma_get_typeof_lit_id (left_value));
121425bb815Sopenharmony_ci} /* opfunc_typeof */
122425bb815Sopenharmony_ci
123425bb815Sopenharmony_ci/**
124425bb815Sopenharmony_ci * Update getter or setter for object literals.
125425bb815Sopenharmony_ci */
126425bb815Sopenharmony_civoid
127425bb815Sopenharmony_ciopfunc_set_accessor (bool is_getter, /**< is getter accessor */
128425bb815Sopenharmony_ci                     ecma_value_t object, /**< object value */
129425bb815Sopenharmony_ci                     ecma_string_t *accessor_name_p, /**< accessor name */
130425bb815Sopenharmony_ci                     ecma_value_t accessor) /**< accessor value */
131425bb815Sopenharmony_ci{
132425bb815Sopenharmony_ci  ecma_object_t *object_p = ecma_get_object_from_value (object);
133425bb815Sopenharmony_ci
134425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
135425bb815Sopenharmony_ci
136425bb815Sopenharmony_ci  ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p);
137425bb815Sopenharmony_ci
138425bb815Sopenharmony_ci  if (property_p != NULL
139425bb815Sopenharmony_ci      && ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
140425bb815Sopenharmony_ci  {
141425bb815Sopenharmony_ci    ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
142425bb815Sopenharmony_ci    property_p = NULL;
143425bb815Sopenharmony_ci  }
144425bb815Sopenharmony_ci
145425bb815Sopenharmony_ci  if (property_p == NULL)
146425bb815Sopenharmony_ci  {
147425bb815Sopenharmony_ci    ecma_object_t *getter_func_p = NULL;
148425bb815Sopenharmony_ci    ecma_object_t *setter_func_p = NULL;
149425bb815Sopenharmony_ci
150425bb815Sopenharmony_ci    if (is_getter)
151425bb815Sopenharmony_ci    {
152425bb815Sopenharmony_ci      getter_func_p = ecma_get_object_from_value (accessor);
153425bb815Sopenharmony_ci    }
154425bb815Sopenharmony_ci    else
155425bb815Sopenharmony_ci    {
156425bb815Sopenharmony_ci      setter_func_p = ecma_get_object_from_value (accessor);
157425bb815Sopenharmony_ci    }
158425bb815Sopenharmony_ci
159425bb815Sopenharmony_ci    ecma_create_named_accessor_property (object_p,
160425bb815Sopenharmony_ci                                         accessor_name_p,
161425bb815Sopenharmony_ci                                         getter_func_p,
162425bb815Sopenharmony_ci                                         setter_func_p,
163425bb815Sopenharmony_ci                                         ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE,
164425bb815Sopenharmony_ci                                         NULL);
165425bb815Sopenharmony_ci  }
166425bb815Sopenharmony_ci  else if (is_getter)
167425bb815Sopenharmony_ci  {
168425bb815Sopenharmony_ci    ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor);
169425bb815Sopenharmony_ci
170425bb815Sopenharmony_ci    ecma_set_named_accessor_property_getter (object_p,
171425bb815Sopenharmony_ci                                             ECMA_PROPERTY_VALUE_PTR (property_p),
172425bb815Sopenharmony_ci                                             getter_func_p);
173425bb815Sopenharmony_ci  }
174425bb815Sopenharmony_ci  else
175425bb815Sopenharmony_ci  {
176425bb815Sopenharmony_ci    ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor);
177425bb815Sopenharmony_ci
178425bb815Sopenharmony_ci    ecma_set_named_accessor_property_setter (object_p,
179425bb815Sopenharmony_ci                                             ECMA_PROPERTY_VALUE_PTR (property_p),
180425bb815Sopenharmony_ci                                             setter_func_p);
181425bb815Sopenharmony_ci  }
182425bb815Sopenharmony_ci} /* opfunc_set_accessor */
183425bb815Sopenharmony_ci
184425bb815Sopenharmony_ci/**
185425bb815Sopenharmony_ci * Deletes an object property.
186425bb815Sopenharmony_ci *
187425bb815Sopenharmony_ci * @return ecma value
188425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value
189425bb815Sopenharmony_ci */
190425bb815Sopenharmony_ciecma_value_t
191425bb815Sopenharmony_civm_op_delete_prop (ecma_value_t object, /**< base object */
192425bb815Sopenharmony_ci                   ecma_value_t property, /**< property name */
193425bb815Sopenharmony_ci                   bool is_strict) /**< strict mode */
194425bb815Sopenharmony_ci{
195425bb815Sopenharmony_ci#if !ENABLED (JERRY_ES2015)
196425bb815Sopenharmony_ci  if (ecma_is_value_undefined (object))
197425bb815Sopenharmony_ci  {
198425bb815Sopenharmony_ci    return ECMA_VALUE_TRUE;
199425bb815Sopenharmony_ci  }
200425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
201425bb815Sopenharmony_ci
202425bb815Sopenharmony_ci  ecma_value_t check_coercible = ecma_op_check_object_coercible (object);
203425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (check_coercible))
204425bb815Sopenharmony_ci  {
205425bb815Sopenharmony_ci    return check_coercible;
206425bb815Sopenharmony_ci  }
207425bb815Sopenharmony_ci  JERRY_ASSERT (check_coercible == ECMA_VALUE_EMPTY);
208425bb815Sopenharmony_ci
209425bb815Sopenharmony_ci  ecma_string_t *name_string_p = ecma_op_to_prop_name (property);
210425bb815Sopenharmony_ci
211425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (name_string_p == NULL))
212425bb815Sopenharmony_ci  {
213425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
214425bb815Sopenharmony_ci  }
215425bb815Sopenharmony_ci
216425bb815Sopenharmony_ci  ecma_value_t obj_value = ecma_op_to_object (object);
217425bb815Sopenharmony_ci  /* The ecma_op_check_object_coercible call already checked the op_to_object error cases. */
218425bb815Sopenharmony_ci  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_value));
219425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_object (obj_value));
220425bb815Sopenharmony_ci  ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
221425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  ecma_value_t delete_op_ret = ecma_op_object_delete (obj_p, name_string_p, is_strict);
224425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_boolean (delete_op_ret) || ECMA_IS_VALUE_ERROR (delete_op_ret));
225425bb815Sopenharmony_ci  ecma_deref_object (obj_p);
226425bb815Sopenharmony_ci  ecma_deref_ecma_string (name_string_p);
227425bb815Sopenharmony_ci
228425bb815Sopenharmony_ci  return delete_op_ret;
229425bb815Sopenharmony_ci} /* vm_op_delete_prop */
230425bb815Sopenharmony_ci
231425bb815Sopenharmony_ci/**
232425bb815Sopenharmony_ci * Deletes a variable.
233425bb815Sopenharmony_ci *
234425bb815Sopenharmony_ci * @return ecma value
235425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value
236425bb815Sopenharmony_ci */
237425bb815Sopenharmony_ciecma_value_t
238425bb815Sopenharmony_civm_op_delete_var (ecma_value_t name_literal, /**< name literal */
239425bb815Sopenharmony_ci                  ecma_object_t *lex_env_p) /**< lexical environment */
240425bb815Sopenharmony_ci{
241425bb815Sopenharmony_ci  ecma_value_t completion_value = ECMA_VALUE_EMPTY;
242425bb815Sopenharmony_ci
243425bb815Sopenharmony_ci  ecma_string_t *var_name_str_p = ecma_get_string_from_value (name_literal);
244425bb815Sopenharmony_ci
245425bb815Sopenharmony_ci  ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);
246425bb815Sopenharmony_ci
247425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
248425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (ref_base_lex_env_p == ECMA_OBJECT_POINTER_ERROR))
249425bb815Sopenharmony_ci  {
250425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
251425bb815Sopenharmony_ci  }
252425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
253425bb815Sopenharmony_ci
254425bb815Sopenharmony_ci  if (ref_base_lex_env_p == NULL)
255425bb815Sopenharmony_ci  {
256425bb815Sopenharmony_ci    completion_value = ECMA_VALUE_TRUE;
257425bb815Sopenharmony_ci  }
258425bb815Sopenharmony_ci  else
259425bb815Sopenharmony_ci  {
260425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p));
261425bb815Sopenharmony_ci
262425bb815Sopenharmony_ci    completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p);
263425bb815Sopenharmony_ci  }
264425bb815Sopenharmony_ci
265425bb815Sopenharmony_ci  return completion_value;
266425bb815Sopenharmony_ci} /* vm_op_delete_var */
267425bb815Sopenharmony_ci
268425bb815Sopenharmony_ci/**
269425bb815Sopenharmony_ci * 'for-in' opcode handler
270425bb815Sopenharmony_ci *
271425bb815Sopenharmony_ci * See also:
272425bb815Sopenharmony_ci *          ECMA-262 v5, 12.6.4
273425bb815Sopenharmony_ci *
274425bb815Sopenharmony_ci * @return chain list of property names
275425bb815Sopenharmony_ci */
276425bb815Sopenharmony_ciecma_collection_t *
277425bb815Sopenharmony_ciopfunc_for_in (ecma_value_t left_value, /**< left value */
278425bb815Sopenharmony_ci               ecma_value_t *result_obj_p) /**< expression object */
279425bb815Sopenharmony_ci{
280425bb815Sopenharmony_ci  /* 3. */
281425bb815Sopenharmony_ci  if (ecma_is_value_undefined (left_value)
282425bb815Sopenharmony_ci      || ecma_is_value_null (left_value))
283425bb815Sopenharmony_ci  {
284425bb815Sopenharmony_ci    return NULL;
285425bb815Sopenharmony_ci  }
286425bb815Sopenharmony_ci
287425bb815Sopenharmony_ci  /* 4. */
288425bb815Sopenharmony_ci  ecma_value_t obj_expr_value = ecma_op_to_object (left_value);
289425bb815Sopenharmony_ci  /* ecma_op_to_object will only raise error on null/undefined values but those are handled above. */
290425bb815Sopenharmony_ci  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (obj_expr_value));
291425bb815Sopenharmony_ci  ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
292425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
293425bb815Sopenharmony_ci  JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p));
294425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
295425bb815Sopenharmony_ci  ecma_collection_t *prop_names_p = ecma_op_object_get_property_names (obj_p, ECMA_LIST_ENUMERABLE_PROTOTYPE);
296425bb815Sopenharmony_ci
297425bb815Sopenharmony_ci  if (prop_names_p->item_count != 0)
298425bb815Sopenharmony_ci  {
299425bb815Sopenharmony_ci    *result_obj_p = ecma_make_object_value (obj_p);
300425bb815Sopenharmony_ci    return prop_names_p;
301425bb815Sopenharmony_ci  }
302425bb815Sopenharmony_ci
303425bb815Sopenharmony_ci  ecma_deref_object (obj_p);
304425bb815Sopenharmony_ci  ecma_collection_destroy (prop_names_p);
305425bb815Sopenharmony_ci
306425bb815Sopenharmony_ci  return NULL;
307425bb815Sopenharmony_ci} /* opfunc_for_in */
308425bb815Sopenharmony_ci
309425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
310425bb815Sopenharmony_ci
311425bb815Sopenharmony_ci/**
312425bb815Sopenharmony_ci * 'VM_OC_APPEND_ARRAY' opcode handler specialized for spread objects
313425bb815Sopenharmony_ci *
314425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the operation failed
315425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY, otherwise
316425bb815Sopenharmony_ci */
317425bb815Sopenharmony_cistatic ecma_value_t JERRY_ATTR_NOINLINE
318425bb815Sopenharmony_ciopfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top */
319425bb815Sopenharmony_ci                               uint16_t values_length) /**< number of elements to set */
320425bb815Sopenharmony_ci{
321425bb815Sopenharmony_ci  JERRY_ASSERT (!(values_length & OPFUNC_HAS_SPREAD_ELEMENT));
322425bb815Sopenharmony_ci
323425bb815Sopenharmony_ci  ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
324425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
325425bb815Sopenharmony_ci
326425bb815Sopenharmony_ci  ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
327425bb815Sopenharmony_ci  uint32_t old_length = ext_array_obj_p->u.array.length;
328425bb815Sopenharmony_ci
329425bb815Sopenharmony_ci  for (uint32_t i = 0, idx = old_length; i < values_length; i++, idx++)
330425bb815Sopenharmony_ci  {
331425bb815Sopenharmony_ci    if (ecma_is_value_array_hole (stack_top_p[i]))
332425bb815Sopenharmony_ci    {
333425bb815Sopenharmony_ci      continue;
334425bb815Sopenharmony_ci    }
335425bb815Sopenharmony_ci
336425bb815Sopenharmony_ci    if (stack_top_p[i] == ECMA_VALUE_SPREAD_ELEMENT)
337425bb815Sopenharmony_ci    {
338425bb815Sopenharmony_ci      i++;
339425bb815Sopenharmony_ci      ecma_value_t ret_value = ECMA_VALUE_ERROR;
340425bb815Sopenharmony_ci      ecma_value_t spread_value = stack_top_p[i];
341425bb815Sopenharmony_ci
342425bb815Sopenharmony_ci      ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_EMPTY);
343425bb815Sopenharmony_ci
344425bb815Sopenharmony_ci      if (!ECMA_IS_VALUE_ERROR (iterator))
345425bb815Sopenharmony_ci      {
346425bb815Sopenharmony_ci        while (true)
347425bb815Sopenharmony_ci        {
348425bb815Sopenharmony_ci          ecma_value_t next_value = ecma_op_iterator_step (iterator);
349425bb815Sopenharmony_ci
350425bb815Sopenharmony_ci          if (ECMA_IS_VALUE_ERROR (next_value))
351425bb815Sopenharmony_ci          {
352425bb815Sopenharmony_ci            break;
353425bb815Sopenharmony_ci          }
354425bb815Sopenharmony_ci
355425bb815Sopenharmony_ci          if (ecma_is_value_false (next_value))
356425bb815Sopenharmony_ci          {
357425bb815Sopenharmony_ci            idx--;
358425bb815Sopenharmony_ci            ret_value = ECMA_VALUE_EMPTY;
359425bb815Sopenharmony_ci            break;
360425bb815Sopenharmony_ci          }
361425bb815Sopenharmony_ci
362425bb815Sopenharmony_ci          ecma_value_t value = ecma_op_iterator_value (next_value);
363425bb815Sopenharmony_ci
364425bb815Sopenharmony_ci          ecma_free_value (next_value);
365425bb815Sopenharmony_ci
366425bb815Sopenharmony_ci          if (ECMA_IS_VALUE_ERROR (value))
367425bb815Sopenharmony_ci          {
368425bb815Sopenharmony_ci            break;
369425bb815Sopenharmony_ci          }
370425bb815Sopenharmony_ci
371425bb815Sopenharmony_ci          ecma_value_t put_comp;
372425bb815Sopenharmony_ci          put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p,
373425bb815Sopenharmony_ci                                                            idx++,
374425bb815Sopenharmony_ci                                                            value,
375425bb815Sopenharmony_ci                                                            ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
376425bb815Sopenharmony_ci
377425bb815Sopenharmony_ci          JERRY_ASSERT (ecma_is_value_true (put_comp));
378425bb815Sopenharmony_ci          ecma_free_value (value);
379425bb815Sopenharmony_ci        }
380425bb815Sopenharmony_ci      }
381425bb815Sopenharmony_ci
382425bb815Sopenharmony_ci      ecma_free_value (iterator);
383425bb815Sopenharmony_ci      ecma_free_value (spread_value);
384425bb815Sopenharmony_ci
385425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (ret_value))
386425bb815Sopenharmony_ci      {
387425bb815Sopenharmony_ci        for (uint32_t k = i + 1; k < values_length; k++)
388425bb815Sopenharmony_ci        {
389425bb815Sopenharmony_ci          ecma_free_value (stack_top_p[k]);
390425bb815Sopenharmony_ci        }
391425bb815Sopenharmony_ci
392425bb815Sopenharmony_ci        return ret_value;
393425bb815Sopenharmony_ci      }
394425bb815Sopenharmony_ci    }
395425bb815Sopenharmony_ci    else
396425bb815Sopenharmony_ci    {
397425bb815Sopenharmony_ci      ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p,
398425bb815Sopenharmony_ci                                                                     idx,
399425bb815Sopenharmony_ci                                                                     stack_top_p[i],
400425bb815Sopenharmony_ci                                                                     ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
401425bb815Sopenharmony_ci      JERRY_ASSERT (ecma_is_value_true (put_comp));
402425bb815Sopenharmony_ci      ecma_free_value (stack_top_p[i]);
403425bb815Sopenharmony_ci    }
404425bb815Sopenharmony_ci  }
405425bb815Sopenharmony_ci
406425bb815Sopenharmony_ci  return ECMA_VALUE_EMPTY;
407425bb815Sopenharmony_ci} /* opfunc_append_to_spread_array */
408425bb815Sopenharmony_ci
409425bb815Sopenharmony_ci/**
410425bb815Sopenharmony_ci * Spread function call/construct arguments into an ecma-collection
411425bb815Sopenharmony_ci *
412425bb815Sopenharmony_ci * @return NULL - if the operation failed
413425bb815Sopenharmony_ci *         pointer to the ecma-collection with the spreaded arguments, otherwise
414425bb815Sopenharmony_ci */
415425bb815Sopenharmony_ciJERRY_ATTR_NOINLINE ecma_collection_t *
416425bb815Sopenharmony_ciopfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current stack top */
417425bb815Sopenharmony_ci                         uint8_t arguments_list_len) /**< number of arguments */
418425bb815Sopenharmony_ci{
419425bb815Sopenharmony_ci  ecma_collection_t *buff_p = ecma_new_collection ();
420425bb815Sopenharmony_ci
421425bb815Sopenharmony_ci  for (uint32_t i = 0; i < arguments_list_len; i++)
422425bb815Sopenharmony_ci  {
423425bb815Sopenharmony_ci    ecma_value_t arg = *stack_top_p++;
424425bb815Sopenharmony_ci
425425bb815Sopenharmony_ci    if (arg != ECMA_VALUE_SPREAD_ELEMENT)
426425bb815Sopenharmony_ci    {
427425bb815Sopenharmony_ci      ecma_collection_push_back (buff_p, arg);
428425bb815Sopenharmony_ci      continue;
429425bb815Sopenharmony_ci    }
430425bb815Sopenharmony_ci
431425bb815Sopenharmony_ci    ecma_value_t ret_value = ECMA_VALUE_ERROR;
432425bb815Sopenharmony_ci    ecma_value_t spread_value = *stack_top_p++;
433425bb815Sopenharmony_ci    i++;
434425bb815Sopenharmony_ci
435425bb815Sopenharmony_ci    ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_EMPTY);
436425bb815Sopenharmony_ci
437425bb815Sopenharmony_ci    if (!ECMA_IS_VALUE_ERROR (iterator))
438425bb815Sopenharmony_ci    {
439425bb815Sopenharmony_ci      while (true)
440425bb815Sopenharmony_ci      {
441425bb815Sopenharmony_ci        ecma_value_t next_value = ecma_op_iterator_step (iterator);
442425bb815Sopenharmony_ci
443425bb815Sopenharmony_ci        if (ECMA_IS_VALUE_ERROR (next_value))
444425bb815Sopenharmony_ci        {
445425bb815Sopenharmony_ci          break;
446425bb815Sopenharmony_ci        }
447425bb815Sopenharmony_ci
448425bb815Sopenharmony_ci        if (ecma_is_value_false (next_value))
449425bb815Sopenharmony_ci        {
450425bb815Sopenharmony_ci          ret_value = ECMA_VALUE_EMPTY;
451425bb815Sopenharmony_ci          break;
452425bb815Sopenharmony_ci        }
453425bb815Sopenharmony_ci
454425bb815Sopenharmony_ci        ecma_value_t value = ecma_op_iterator_value (next_value);
455425bb815Sopenharmony_ci
456425bb815Sopenharmony_ci        ecma_free_value (next_value);
457425bb815Sopenharmony_ci
458425bb815Sopenharmony_ci        if (ECMA_IS_VALUE_ERROR (value))
459425bb815Sopenharmony_ci        {
460425bb815Sopenharmony_ci          break;
461425bb815Sopenharmony_ci        }
462425bb815Sopenharmony_ci
463425bb815Sopenharmony_ci        ecma_collection_push_back (buff_p, value);
464425bb815Sopenharmony_ci      }
465425bb815Sopenharmony_ci    }
466425bb815Sopenharmony_ci
467425bb815Sopenharmony_ci    ecma_free_value (iterator);
468425bb815Sopenharmony_ci    ecma_free_value (spread_value);
469425bb815Sopenharmony_ci
470425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (ret_value))
471425bb815Sopenharmony_ci    {
472425bb815Sopenharmony_ci      for (uint32_t k = i + 1; k < arguments_list_len; k++)
473425bb815Sopenharmony_ci      {
474425bb815Sopenharmony_ci        ecma_free_value (*stack_top_p++);
475425bb815Sopenharmony_ci      }
476425bb815Sopenharmony_ci
477425bb815Sopenharmony_ci      ecma_collection_free (buff_p);
478425bb815Sopenharmony_ci      buff_p = NULL;
479425bb815Sopenharmony_ci      break;
480425bb815Sopenharmony_ci    }
481425bb815Sopenharmony_ci  }
482425bb815Sopenharmony_ci
483425bb815Sopenharmony_ci  return buff_p;
484425bb815Sopenharmony_ci} /* opfunc_spread_arguments */
485425bb815Sopenharmony_ci
486425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
487425bb815Sopenharmony_ci
488425bb815Sopenharmony_ci/**
489425bb815Sopenharmony_ci * 'VM_OC_APPEND_ARRAY' opcode handler, for setting array object properties
490425bb815Sopenharmony_ci *
491425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the operation failed
492425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY, otherwise
493425bb815Sopenharmony_ci */
494425bb815Sopenharmony_ciecma_value_t JERRY_ATTR_NOINLINE
495425bb815Sopenharmony_ciopfunc_append_array (ecma_value_t *stack_top_p, /**< current stack top */
496425bb815Sopenharmony_ci                     uint16_t values_length) /**< number of elements to set
497425bb815Sopenharmony_ci                                              *   with potential OPFUNC_HAS_SPREAD_ELEMENT flag */
498425bb815Sopenharmony_ci{
499425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
500425bb815Sopenharmony_ci  if (values_length >= OPFUNC_HAS_SPREAD_ELEMENT)
501425bb815Sopenharmony_ci  {
502425bb815Sopenharmony_ci    return opfunc_append_to_spread_array (stack_top_p, (uint16_t) (values_length & ~OPFUNC_HAS_SPREAD_ELEMENT));
503425bb815Sopenharmony_ci  }
504425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
505425bb815Sopenharmony_ci
506425bb815Sopenharmony_ci  ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-1]);
507425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
508425bb815Sopenharmony_ci
509425bb815Sopenharmony_ci  ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
510425bb815Sopenharmony_ci  uint32_t old_length = ext_array_obj_p->u.array.length;
511425bb815Sopenharmony_ci
512425bb815Sopenharmony_ci  if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_array_obj_p)))
513425bb815Sopenharmony_ci  {
514425bb815Sopenharmony_ci    uint32_t filled_holes = 0;
515425bb815Sopenharmony_ci    ecma_value_t *values_p = ecma_fast_array_extend (array_obj_p, old_length + values_length);
516425bb815Sopenharmony_ci
517425bb815Sopenharmony_ci    for (uint32_t i = 0; i < values_length; i++)
518425bb815Sopenharmony_ci    {
519425bb815Sopenharmony_ci      values_p[old_length + i] = stack_top_p[i];
520425bb815Sopenharmony_ci
521425bb815Sopenharmony_ci      if (!ecma_is_value_array_hole (stack_top_p[i]))
522425bb815Sopenharmony_ci      {
523425bb815Sopenharmony_ci        filled_holes++;
524425bb815Sopenharmony_ci
525425bb815Sopenharmony_ci        if (ecma_is_value_object (stack_top_p[i]))
526425bb815Sopenharmony_ci        {
527425bb815Sopenharmony_ci          ecma_deref_object (ecma_get_object_from_value (stack_top_p[i]));
528425bb815Sopenharmony_ci        }
529425bb815Sopenharmony_ci      }
530425bb815Sopenharmony_ci    }
531425bb815Sopenharmony_ci
532425bb815Sopenharmony_ci    ext_array_obj_p->u.array.u.hole_count -= filled_holes * ECMA_FAST_ARRAY_HOLE_ONE;
533425bb815Sopenharmony_ci
534425bb815Sopenharmony_ci    if (JERRY_UNLIKELY ((values_length - filled_holes) > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT))
535425bb815Sopenharmony_ci    {
536425bb815Sopenharmony_ci      ecma_fast_array_convert_to_normal (array_obj_p);
537425bb815Sopenharmony_ci    }
538425bb815Sopenharmony_ci  }
539425bb815Sopenharmony_ci  else
540425bb815Sopenharmony_ci  {
541425bb815Sopenharmony_ci    for (uint32_t i = 0; i < values_length; i++)
542425bb815Sopenharmony_ci    {
543425bb815Sopenharmony_ci      if (!ecma_is_value_array_hole (stack_top_p[i]))
544425bb815Sopenharmony_ci      {
545425bb815Sopenharmony_ci        ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (old_length + i);
546425bb815Sopenharmony_ci
547425bb815Sopenharmony_ci        ecma_property_value_t *prop_value_p;
548425bb815Sopenharmony_ci
549425bb815Sopenharmony_ci        prop_value_p = ecma_create_named_data_property (array_obj_p,
550425bb815Sopenharmony_ci                                                        index_str_p,
551425bb815Sopenharmony_ci                                                        ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
552425bb815Sopenharmony_ci                                                        NULL);
553425bb815Sopenharmony_ci
554425bb815Sopenharmony_ci        ecma_deref_ecma_string (index_str_p);
555425bb815Sopenharmony_ci        prop_value_p->value = stack_top_p[i];
556425bb815Sopenharmony_ci
557425bb815Sopenharmony_ci        if (ecma_is_value_object (stack_top_p[i]))
558425bb815Sopenharmony_ci        {
559425bb815Sopenharmony_ci          ecma_free_value (stack_top_p[i]);
560425bb815Sopenharmony_ci        }
561425bb815Sopenharmony_ci
562425bb815Sopenharmony_ci      }
563425bb815Sopenharmony_ci
564425bb815Sopenharmony_ci      ext_array_obj_p->u.array.length = old_length + values_length;
565425bb815Sopenharmony_ci    }
566425bb815Sopenharmony_ci  }
567425bb815Sopenharmony_ci
568425bb815Sopenharmony_ci  return ECMA_VALUE_EMPTY;
569425bb815Sopenharmony_ci} /* opfunc_append_array */
570425bb815Sopenharmony_ci
571425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
572425bb815Sopenharmony_ci
573425bb815Sopenharmony_ci/**
574425bb815Sopenharmony_ci * Create an executable object using the current frame context
575425bb815Sopenharmony_ci *
576425bb815Sopenharmony_ci * @return executable object
577425bb815Sopenharmony_ci */
578425bb815Sopenharmony_ciecma_value_t
579425bb815Sopenharmony_ciopfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
580425bb815Sopenharmony_ci{
581425bb815Sopenharmony_ci  const ecma_compiled_code_t *bytecode_header_p = frame_ctx_p->bytecode_header_p;
582425bb815Sopenharmony_ci  size_t size;
583425bb815Sopenharmony_ci
584425bb815Sopenharmony_ci  ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_header_p);
585425bb815Sopenharmony_ci
586425bb815Sopenharmony_ci  if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
587425bb815Sopenharmony_ci  {
588425bb815Sopenharmony_ci    cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
589425bb815Sopenharmony_ci    size = ((size_t) args_p->register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
590425bb815Sopenharmony_ci  }
591425bb815Sopenharmony_ci  else
592425bb815Sopenharmony_ci  {
593425bb815Sopenharmony_ci    cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
594425bb815Sopenharmony_ci    size = ((size_t) args_p->register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
595425bb815Sopenharmony_ci  }
596425bb815Sopenharmony_ci
597425bb815Sopenharmony_ci  size_t total_size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t));
598425bb815Sopenharmony_ci
599425bb815Sopenharmony_ci  ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_function_obj_p),
600425bb815Sopenharmony_ci                                                                   ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE);
601425bb815Sopenharmony_ci
602425bb815Sopenharmony_ci  ecma_object_t *object_p = ecma_create_object (proto_p,
603425bb815Sopenharmony_ci                                                total_size,
604425bb815Sopenharmony_ci                                                ECMA_OBJECT_TYPE_CLASS);
605425bb815Sopenharmony_ci
606425bb815Sopenharmony_ci  ecma_deref_object (proto_p);
607425bb815Sopenharmony_ci
608425bb815Sopenharmony_ci  vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
609425bb815Sopenharmony_ci
610425bb815Sopenharmony_ci  executable_object_p->extended_object.u.class_prop.class_id = LIT_MAGIC_STRING_GENERATOR_UL;
611425bb815Sopenharmony_ci  executable_object_p->extended_object.u.class_prop.extra_info = 0;
612425bb815Sopenharmony_ci
613425bb815Sopenharmony_ci  JERRY_ASSERT (!frame_ctx_p->is_eval_code);
614425bb815Sopenharmony_ci  JERRY_ASSERT (frame_ctx_p->context_depth == 0);
615425bb815Sopenharmony_ci
616425bb815Sopenharmony_ci  vm_frame_ctx_t *new_frame_ctx_p = &(executable_object_p->frame_ctx);
617425bb815Sopenharmony_ci  *new_frame_ctx_p = *frame_ctx_p;
618425bb815Sopenharmony_ci
619425bb815Sopenharmony_ci  /* The old register values are discarded. */
620425bb815Sopenharmony_ci  ecma_value_t *new_registers_p = VM_GET_REGISTERS (new_frame_ctx_p);
621425bb815Sopenharmony_ci  memcpy (new_registers_p, VM_GET_REGISTERS (frame_ctx_p), size);
622425bb815Sopenharmony_ci
623425bb815Sopenharmony_ci  size_t stack_top = (size_t) (frame_ctx_p->stack_top_p - VM_GET_REGISTERS (frame_ctx_p));
624425bb815Sopenharmony_ci  ecma_value_t *new_stack_top_p = new_registers_p + stack_top;
625425bb815Sopenharmony_ci
626425bb815Sopenharmony_ci  new_frame_ctx_p->stack_top_p = new_stack_top_p;
627425bb815Sopenharmony_ci
628425bb815Sopenharmony_ci  /* Initial state is "not running", so all object references are released. */
629425bb815Sopenharmony_ci
630425bb815Sopenharmony_ci  while (new_registers_p < new_stack_top_p)
631425bb815Sopenharmony_ci  {
632425bb815Sopenharmony_ci    ecma_deref_if_object (*new_registers_p++);
633425bb815Sopenharmony_ci  }
634425bb815Sopenharmony_ci
635425bb815Sopenharmony_ci  new_frame_ctx_p->this_binding = ecma_copy_value_if_not_object (new_frame_ctx_p->this_binding);
636425bb815Sopenharmony_ci
637425bb815Sopenharmony_ci  JERRY_CONTEXT (vm_top_context_p) = new_frame_ctx_p->prev_context_p;
638425bb815Sopenharmony_ci
639425bb815Sopenharmony_ci  return ecma_make_object_value (object_p);
640425bb815Sopenharmony_ci} /* opfunc_create_executable_object */
641425bb815Sopenharmony_ci
642425bb815Sopenharmony_ci/**
643425bb815Sopenharmony_ci * Resume the execution of an inactive executable object
644425bb815Sopenharmony_ci *
645425bb815Sopenharmony_ci * @return value provided by the execution
646425bb815Sopenharmony_ci */
647425bb815Sopenharmony_ciecma_value_t
648425bb815Sopenharmony_ciopfunc_resume_executable_object (vm_executable_object_t *executable_object_p, /**< executable object */
649425bb815Sopenharmony_ci                                 ecma_value_t value) /**< value pushed onto the stack (takes the reference) */
650425bb815Sopenharmony_ci{
651425bb815Sopenharmony_ci  const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p;
652425bb815Sopenharmony_ci  ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
653425bb815Sopenharmony_ci  ecma_value_t *register_end_p;
654425bb815Sopenharmony_ci
655425bb815Sopenharmony_ci  if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
656425bb815Sopenharmony_ci  {
657425bb815Sopenharmony_ci    cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
658425bb815Sopenharmony_ci    register_end_p = register_p + args_p->register_end;
659425bb815Sopenharmony_ci  }
660425bb815Sopenharmony_ci  else
661425bb815Sopenharmony_ci  {
662425bb815Sopenharmony_ci    cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
663425bb815Sopenharmony_ci    register_end_p = register_p + args_p->register_end;
664425bb815Sopenharmony_ci  }
665425bb815Sopenharmony_ci
666425bb815Sopenharmony_ci  while (register_p < register_end_p)
667425bb815Sopenharmony_ci  {
668425bb815Sopenharmony_ci    ecma_ref_if_object (*register_p++);
669425bb815Sopenharmony_ci  }
670425bb815Sopenharmony_ci
671425bb815Sopenharmony_ci  if (executable_object_p->frame_ctx.context_depth > 0)
672425bb815Sopenharmony_ci  {
673425bb815Sopenharmony_ci    vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p,
674425bb815Sopenharmony_ci                          executable_object_p->frame_ctx.context_depth,
675425bb815Sopenharmony_ci                          register_p,
676425bb815Sopenharmony_ci                          true);
677425bb815Sopenharmony_ci
678425bb815Sopenharmony_ci    register_p += executable_object_p->frame_ctx.context_depth;
679425bb815Sopenharmony_ci  }
680425bb815Sopenharmony_ci
681425bb815Sopenharmony_ci  ecma_value_t *stack_top_p = executable_object_p->frame_ctx.stack_top_p;
682425bb815Sopenharmony_ci
683425bb815Sopenharmony_ci  while (register_p < stack_top_p)
684425bb815Sopenharmony_ci  {
685425bb815Sopenharmony_ci    ecma_ref_if_object (*register_p++);
686425bb815Sopenharmony_ci  }
687425bb815Sopenharmony_ci
688425bb815Sopenharmony_ci  *register_p++ = value;
689425bb815Sopenharmony_ci  executable_object_p->frame_ctx.stack_top_p = register_p;
690425bb815Sopenharmony_ci
691425bb815Sopenharmony_ci  JERRY_ASSERT (ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p->extended_object.u.class_prop.extra_info));
692425bb815Sopenharmony_ci
693425bb815Sopenharmony_ci  executable_object_p->extended_object.u.class_prop.extra_info |= ECMA_EXECUTABLE_OBJECT_RUNNING;
694425bb815Sopenharmony_ci
695425bb815Sopenharmony_ci  executable_object_p->frame_ctx.prev_context_p = JERRY_CONTEXT (vm_top_context_p);
696425bb815Sopenharmony_ci  JERRY_CONTEXT (vm_top_context_p) = &executable_object_p->frame_ctx;
697425bb815Sopenharmony_ci
698425bb815Sopenharmony_ci  /* inside the generators the "new.target" is always "undefined" as it can't be invoked with "new" */
699425bb815Sopenharmony_ci  ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
700425bb815Sopenharmony_ci  JERRY_CONTEXT (current_new_target) = NULL;
701425bb815Sopenharmony_ci
702425bb815Sopenharmony_ci  ecma_value_t result = vm_execute (&executable_object_p->frame_ctx);
703425bb815Sopenharmony_ci
704425bb815Sopenharmony_ci  JERRY_CONTEXT (current_new_target) = old_new_target;
705425bb815Sopenharmony_ci  executable_object_p->extended_object.u.class_prop.extra_info &= (uint16_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING;
706425bb815Sopenharmony_ci
707425bb815Sopenharmony_ci  if (executable_object_p->frame_ctx.call_operation != VM_EXEC_RETURN)
708425bb815Sopenharmony_ci  {
709425bb815Sopenharmony_ci    JERRY_ASSERT (executable_object_p->frame_ctx.call_operation == VM_NO_EXEC_OP);
710425bb815Sopenharmony_ci
711425bb815Sopenharmony_ci    /* All resources are released. */
712425bb815Sopenharmony_ci    executable_object_p->extended_object.u.class_prop.extra_info |= ECMA_EXECUTABLE_OBJECT_COMPLETED;
713425bb815Sopenharmony_ci    return result;
714425bb815Sopenharmony_ci  }
715425bb815Sopenharmony_ci
716425bb815Sopenharmony_ci  JERRY_CONTEXT (vm_top_context_p) = executable_object_p->frame_ctx.prev_context_p;
717425bb815Sopenharmony_ci
718425bb815Sopenharmony_ci  register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
719425bb815Sopenharmony_ci
720425bb815Sopenharmony_ci  while (register_p < register_end_p)
721425bb815Sopenharmony_ci  {
722425bb815Sopenharmony_ci    ecma_deref_if_object (*register_p++);
723425bb815Sopenharmony_ci  }
724425bb815Sopenharmony_ci
725425bb815Sopenharmony_ci  if (executable_object_p->frame_ctx.context_depth > 0)
726425bb815Sopenharmony_ci  {
727425bb815Sopenharmony_ci    vm_ref_lex_env_chain (executable_object_p->frame_ctx.lex_env_p,
728425bb815Sopenharmony_ci                          executable_object_p->frame_ctx.context_depth,
729425bb815Sopenharmony_ci                          register_p,
730425bb815Sopenharmony_ci                          false);
731425bb815Sopenharmony_ci
732425bb815Sopenharmony_ci    register_p += executable_object_p->frame_ctx.context_depth;
733425bb815Sopenharmony_ci  }
734425bb815Sopenharmony_ci
735425bb815Sopenharmony_ci  stack_top_p = executable_object_p->frame_ctx.stack_top_p;
736425bb815Sopenharmony_ci
737425bb815Sopenharmony_ci  while (register_p < stack_top_p)
738425bb815Sopenharmony_ci  {
739425bb815Sopenharmony_ci    ecma_deref_if_object (*register_p++);
740425bb815Sopenharmony_ci  }
741425bb815Sopenharmony_ci
742425bb815Sopenharmony_ci  return result;
743425bb815Sopenharmony_ci} /* opfunc_resume_executable_object */
744425bb815Sopenharmony_ci
745425bb815Sopenharmony_ci/**
746425bb815Sopenharmony_ci * Create a Promise object if needed and resolve it with a value
747425bb815Sopenharmony_ci *
748425bb815Sopenharmony_ci * @return Promise object
749425bb815Sopenharmony_ci */
750425bb815Sopenharmony_ciecma_value_t
751425bb815Sopenharmony_ciopfunc_return_promise (ecma_value_t value) /**< value */
752425bb815Sopenharmony_ci{
753425bb815Sopenharmony_ci  ecma_value_t promise = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_PROMISE));
754425bb815Sopenharmony_ci  ecma_value_t result = ecma_promise_reject_or_resolve (promise, value, true);
755425bb815Sopenharmony_ci
756425bb815Sopenharmony_ci  ecma_free_value (value);
757425bb815Sopenharmony_ci  return result;
758425bb815Sopenharmony_ci} /* opfunc_return_promise */
759425bb815Sopenharmony_ci
760425bb815Sopenharmony_ci/**
761425bb815Sopenharmony_ci * Implicit class constructor handler when the classHeritage is not present.
762425bb815Sopenharmony_ci *
763425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14.10.b.i
764425bb815Sopenharmony_ci *
765425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the function was invoked without 'new'
766425bb815Sopenharmony_ci *         ECMA_VALUE_UNDEFINED - otherwise
767425bb815Sopenharmony_ci */
768425bb815Sopenharmony_cistatic ecma_value_t
769425bb815Sopenharmony_ciecma_op_implicit_constructor_handler_cb (const ecma_value_t function_obj, /**< the function itself */
770425bb815Sopenharmony_ci                                         const ecma_value_t this_val, /**< this_arg of the function */
771425bb815Sopenharmony_ci                                         const ecma_value_t args_p[], /**< argument list */
772425bb815Sopenharmony_ci                                         const ecma_length_t args_count) /**< argument number */
773425bb815Sopenharmony_ci{
774425bb815Sopenharmony_ci  JERRY_UNUSED_4 (function_obj, this_val, args_p, args_count);
775425bb815Sopenharmony_ci
776425bb815Sopenharmony_ci  if (JERRY_CONTEXT (current_new_target) == NULL)
777425bb815Sopenharmony_ci  {
778425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
779425bb815Sopenharmony_ci  }
780425bb815Sopenharmony_ci
781425bb815Sopenharmony_ci  return ECMA_VALUE_UNDEFINED;
782425bb815Sopenharmony_ci} /* ecma_op_implicit_constructor_handler_cb */
783425bb815Sopenharmony_ci
784425bb815Sopenharmony_ci/**
785425bb815Sopenharmony_ci * Implicit class constructor handler when the classHeritage is present.
786425bb815Sopenharmony_ci *
787425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14.10.a.i
788425bb815Sopenharmony_ci *
789425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the operation fails
790425bb815Sopenharmony_ci *         result of the super call - otherwise
791425bb815Sopenharmony_ci */
792425bb815Sopenharmony_cistatic ecma_value_t
793425bb815Sopenharmony_ciecma_op_implicit_constructor_handler_heritage_cb (const ecma_value_t function_obj, /**< the function itself */
794425bb815Sopenharmony_ci                                                  const ecma_value_t this_val, /**< this_arg of the function */
795425bb815Sopenharmony_ci                                                  const ecma_value_t args_p[], /**< argument list */
796425bb815Sopenharmony_ci                                                  const ecma_length_t args_count) /**< argument number */
797425bb815Sopenharmony_ci{
798425bb815Sopenharmony_ci  JERRY_UNUSED_4 (function_obj, this_val, args_p, args_count);
799425bb815Sopenharmony_ci
800425bb815Sopenharmony_ci  if (JERRY_CONTEXT (current_new_target) == NULL)
801425bb815Sopenharmony_ci  {
802425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
803425bb815Sopenharmony_ci  }
804425bb815Sopenharmony_ci
805425bb815Sopenharmony_ci  ecma_object_t *func_obj_p = ecma_get_object_from_value (function_obj);
806425bb815Sopenharmony_ci  ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p);
807425bb815Sopenharmony_ci
808425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (super_ctor))
809425bb815Sopenharmony_ci  {
810425bb815Sopenharmony_ci    return super_ctor;
811425bb815Sopenharmony_ci  }
812425bb815Sopenharmony_ci
813425bb815Sopenharmony_ci  ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor);
814425bb815Sopenharmony_ci
815425bb815Sopenharmony_ci  ecma_value_t result = ecma_op_function_construct (super_ctor_p,
816425bb815Sopenharmony_ci                                                    JERRY_CONTEXT (current_new_target),
817425bb815Sopenharmony_ci                                                    args_p,
818425bb815Sopenharmony_ci                                                    args_count);
819425bb815Sopenharmony_ci
820425bb815Sopenharmony_ci  if (ecma_is_value_object (result))
821425bb815Sopenharmony_ci  {
822425bb815Sopenharmony_ci    ecma_value_t proto_value = ecma_op_object_get_by_magic_id (JERRY_CONTEXT (current_new_target),
823425bb815Sopenharmony_ci                                                               LIT_MAGIC_STRING_PROTOTYPE);
824425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (proto_value))
825425bb815Sopenharmony_ci    {
826425bb815Sopenharmony_ci      ecma_free_value (result);
827425bb815Sopenharmony_ci      result = ECMA_VALUE_ERROR;
828425bb815Sopenharmony_ci    }
829425bb815Sopenharmony_ci    else if (ecma_is_value_object (proto_value))
830425bb815Sopenharmony_ci    {
831425bb815Sopenharmony_ci      ECMA_SET_POINTER (ecma_get_object_from_value (result)->u2.prototype_cp,
832425bb815Sopenharmony_ci                        ecma_get_object_from_value (proto_value));
833425bb815Sopenharmony_ci    }
834425bb815Sopenharmony_ci    ecma_free_value (proto_value);
835425bb815Sopenharmony_ci  }
836425bb815Sopenharmony_ci
837425bb815Sopenharmony_ci  ecma_deref_object (super_ctor_p);
838425bb815Sopenharmony_ci
839425bb815Sopenharmony_ci  return result;
840425bb815Sopenharmony_ci} /* ecma_op_implicit_constructor_handler_heritage_cb */
841425bb815Sopenharmony_ci
842425bb815Sopenharmony_ci/**
843425bb815Sopenharmony_ci * Create implicit class constructor
844425bb815Sopenharmony_ci *
845425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14
846425bb815Sopenharmony_ci *
847425bb815Sopenharmony_ci * @return - new external function ecma-object
848425bb815Sopenharmony_ci */
849425bb815Sopenharmony_ciecma_value_t
850425bb815Sopenharmony_ciopfunc_create_implicit_class_constructor (uint8_t opcode) /**< current cbc opcode */
851425bb815Sopenharmony_ci{
852425bb815Sopenharmony_ci  /* 8. */
853425bb815Sopenharmony_ci  ecma_object_t *func_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE),
854425bb815Sopenharmony_ci                                                  sizeof (ecma_extended_object_t),
855425bb815Sopenharmony_ci                                                  ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
856425bb815Sopenharmony_ci
857425bb815Sopenharmony_ci  ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
858425bb815Sopenharmony_ci
859425bb815Sopenharmony_ci  /* 10.a.i */
860425bb815Sopenharmony_ci  if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE)
861425bb815Sopenharmony_ci  {
862425bb815Sopenharmony_ci    ext_func_obj_p->u.external_handler_cb = ecma_op_implicit_constructor_handler_heritage_cb;
863425bb815Sopenharmony_ci  }
864425bb815Sopenharmony_ci  /* 10.b.i */
865425bb815Sopenharmony_ci  else
866425bb815Sopenharmony_ci  {
867425bb815Sopenharmony_ci    ext_func_obj_p->u.external_handler_cb = ecma_op_implicit_constructor_handler_cb;
868425bb815Sopenharmony_ci  }
869425bb815Sopenharmony_ci
870425bb815Sopenharmony_ci  ecma_property_value_t *prop_value_p;
871425bb815Sopenharmony_ci  prop_value_p = ecma_create_named_data_property (func_obj_p,
872425bb815Sopenharmony_ci                                                  ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH),
873425bb815Sopenharmony_ci                                                  ECMA_PROPERTY_FLAG_CONFIGURABLE,
874425bb815Sopenharmony_ci                                                  NULL);
875425bb815Sopenharmony_ci
876425bb815Sopenharmony_ci  prop_value_p->value = ecma_make_uint32_value (0);
877425bb815Sopenharmony_ci
878425bb815Sopenharmony_ci  return ecma_make_object_value (func_obj_p);
879425bb815Sopenharmony_ci} /* opfunc_create_implicit_class_constructor */
880425bb815Sopenharmony_ci
881425bb815Sopenharmony_ci/**
882425bb815Sopenharmony_ci * Set the [[HomeObject]] attribute of the given functon object
883425bb815Sopenharmony_ci */
884425bb815Sopenharmony_cistatic inline void JERRY_ATTR_ALWAYS_INLINE
885425bb815Sopenharmony_ciopfunc_set_home_object (ecma_object_t *func_p, /**< function object */
886425bb815Sopenharmony_ci                        ecma_object_t *parent_env_p) /**< parent environment */
887425bb815Sopenharmony_ci{
888425bb815Sopenharmony_ci  if (ecma_get_object_type (func_p) == ECMA_OBJECT_TYPE_FUNCTION)
889425bb815Sopenharmony_ci  {
890425bb815Sopenharmony_ci    JERRY_ASSERT (!ecma_get_object_is_builtin (func_p));
891425bb815Sopenharmony_ci
892425bb815Sopenharmony_ci    ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) func_p)->u.function.scope_cp, parent_env_p, 0);
893425bb815Sopenharmony_ci  }
894425bb815Sopenharmony_ci} /* opfunc_set_home_object */
895425bb815Sopenharmony_ci
896425bb815Sopenharmony_ci/**
897425bb815Sopenharmony_ci * ClassDefinitionEvaluation environment initialization part
898425bb815Sopenharmony_ci *
899425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14
900425bb815Sopenharmony_ci *
901425bb815Sopenharmony_ci * @return - ECMA_VALUE_ERROR - if the operation fails
902425bb815Sopenharmony_ci *           ECMA_VALUE_EMPTY - otherwise
903425bb815Sopenharmony_ci */
904425bb815Sopenharmony_civoid
905425bb815Sopenharmony_ciopfunc_push_class_environment (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
906425bb815Sopenharmony_ci                               ecma_value_t **vm_stack_top, /**< VM stack top */
907425bb815Sopenharmony_ci                               ecma_value_t class_name) /**< class name */
908425bb815Sopenharmony_ci{
909425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_undefined (class_name) || ecma_is_value_string (class_name));
910425bb815Sopenharmony_ci  ecma_object_t *class_env_p = ecma_create_decl_lex_env (frame_ctx_p->lex_env_p);
911425bb815Sopenharmony_ci
912425bb815Sopenharmony_ci  /* 4.a */
913425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (class_name))
914425bb815Sopenharmony_ci  {
915425bb815Sopenharmony_ci    ecma_op_create_immutable_binding (class_env_p,
916425bb815Sopenharmony_ci                                      ecma_get_string_from_value (class_name),
917425bb815Sopenharmony_ci                                      ECMA_VALUE_UNINITIALIZED);
918425bb815Sopenharmony_ci  }
919425bb815Sopenharmony_ci  frame_ctx_p->lex_env_p = class_env_p;
920425bb815Sopenharmony_ci
921425bb815Sopenharmony_ci  *(*vm_stack_top)++ = ECMA_VALUE_RELEASE_LEX_ENV;
922425bb815Sopenharmony_ci} /* opfunc_push_class_environment */
923425bb815Sopenharmony_ci
924425bb815Sopenharmony_ci/**
925425bb815Sopenharmony_ci * ClassDefinitionEvaluation object initialization part
926425bb815Sopenharmony_ci *
927425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14
928425bb815Sopenharmony_ci *
929425bb815Sopenharmony_ci * @return - ECMA_VALUE_ERROR - if the operation fails
930425bb815Sopenharmony_ci *           ECMA_VALUE_EMPTY - otherwise
931425bb815Sopenharmony_ci */
932425bb815Sopenharmony_ciecma_value_t
933425bb815Sopenharmony_ciopfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
934425bb815Sopenharmony_ci                   ecma_value_t *stack_top_p) /**< stack top */
935425bb815Sopenharmony_ci{
936425bb815Sopenharmony_ci  /* 5.b, 6.e.ii */
937425bb815Sopenharmony_ci  ecma_object_t *ctor_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
938425bb815Sopenharmony_ci  ecma_object_t *proto_parent_p = NULL;
939425bb815Sopenharmony_ci  bool free_proto_parent = false;
940425bb815Sopenharmony_ci
941425bb815Sopenharmony_ci  ecma_value_t super_class = stack_top_p[-2];
942425bb815Sopenharmony_ci  ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-1]);
943425bb815Sopenharmony_ci
944425bb815Sopenharmony_ci  bool heritage_present = !ecma_is_value_array_hole (super_class);
945425bb815Sopenharmony_ci
946425bb815Sopenharmony_ci  /* 5. ClassHeritage opt is not present */
947425bb815Sopenharmony_ci  if (!heritage_present)
948425bb815Sopenharmony_ci  {
949425bb815Sopenharmony_ci    /* 5.a */
950425bb815Sopenharmony_ci    proto_parent_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
951425bb815Sopenharmony_ci  }
952425bb815Sopenharmony_ci  else if (!ecma_is_value_null (super_class))
953425bb815Sopenharmony_ci  {
954425bb815Sopenharmony_ci    /* 6.f, 6.g.i */
955425bb815Sopenharmony_ci    if (!ecma_is_constructor (super_class)
956425bb815Sopenharmony_ci        || ecma_op_function_is_generator (ecma_get_object_from_value (super_class)))
957425bb815Sopenharmony_ci    {
958425bb815Sopenharmony_ci      return ecma_raise_type_error ("Class extends value is not a constructor or null");
959425bb815Sopenharmony_ci    }
960425bb815Sopenharmony_ci
961425bb815Sopenharmony_ci    ecma_object_t *parent_p = ecma_get_object_from_value (super_class);
962425bb815Sopenharmony_ci
963425bb815Sopenharmony_ci    /* 6.g.ii */
964425bb815Sopenharmony_ci    ecma_value_t proto_parent = ecma_op_object_get_by_magic_id (parent_p, LIT_MAGIC_STRING_PROTOTYPE);
965425bb815Sopenharmony_ci
966425bb815Sopenharmony_ci    /* 6.g.iii */
967425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (proto_parent))
968425bb815Sopenharmony_ci    {
969425bb815Sopenharmony_ci      return proto_parent;
970425bb815Sopenharmony_ci    }
971425bb815Sopenharmony_ci
972425bb815Sopenharmony_ci    /* 6.g.iv */
973425bb815Sopenharmony_ci    if (ecma_is_value_object (proto_parent))
974425bb815Sopenharmony_ci    {
975425bb815Sopenharmony_ci      proto_parent_p = ecma_get_object_from_value (proto_parent);
976425bb815Sopenharmony_ci      free_proto_parent = true;
977425bb815Sopenharmony_ci    }
978425bb815Sopenharmony_ci    else if (ecma_is_value_null (proto_parent))
979425bb815Sopenharmony_ci    {
980425bb815Sopenharmony_ci      proto_parent_p = NULL;
981425bb815Sopenharmony_ci    }
982425bb815Sopenharmony_ci    else
983425bb815Sopenharmony_ci    {
984425bb815Sopenharmony_ci      ecma_free_value (proto_parent);
985425bb815Sopenharmony_ci      return ecma_raise_type_error ("Property 'prototype' is not an object or null");
986425bb815Sopenharmony_ci    }
987425bb815Sopenharmony_ci
988425bb815Sopenharmony_ci    /* 6.g.v */
989425bb815Sopenharmony_ci    ctor_parent_p = parent_p;
990425bb815Sopenharmony_ci  }
991425bb815Sopenharmony_ci
992425bb815Sopenharmony_ci  /* 7. */
993425bb815Sopenharmony_ci  ecma_object_t *proto_p = ecma_create_object (proto_parent_p, 0, ECMA_OBJECT_TYPE_GENERAL);
994425bb815Sopenharmony_ci  ecma_value_t proto = ecma_make_object_value (proto_p);
995425bb815Sopenharmony_ci
996425bb815Sopenharmony_ci  ECMA_SET_POINTER (ctor_p->u2.prototype_cp, ctor_parent_p);
997425bb815Sopenharmony_ci
998425bb815Sopenharmony_ci  if (free_proto_parent)
999425bb815Sopenharmony_ci  {
1000425bb815Sopenharmony_ci    ecma_deref_object (proto_parent_p);
1001425bb815Sopenharmony_ci  }
1002425bb815Sopenharmony_ci  ecma_free_value (super_class);
1003425bb815Sopenharmony_ci
1004425bb815Sopenharmony_ci  /* 16. */
1005425bb815Sopenharmony_ci  ecma_property_value_t *property_value_p;
1006425bb815Sopenharmony_ci  property_value_p = ecma_create_named_data_property (ctor_p,
1007425bb815Sopenharmony_ci                                                      ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE),
1008425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_FIXED,
1009425bb815Sopenharmony_ci                                                      NULL);
1010425bb815Sopenharmony_ci  property_value_p->value = proto;
1011425bb815Sopenharmony_ci
1012425bb815Sopenharmony_ci  /* 18. */
1013425bb815Sopenharmony_ci  property_value_p = ecma_create_named_data_property (proto_p,
1014425bb815Sopenharmony_ci                                                      ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
1015425bb815Sopenharmony_ci                                                      ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
1016425bb815Sopenharmony_ci                                                      NULL);
1017425bb815Sopenharmony_ci  property_value_p->value = ecma_make_object_value (ctor_p);
1018425bb815Sopenharmony_ci
1019425bb815Sopenharmony_ci  if (ecma_get_object_type (ctor_p) == ECMA_OBJECT_TYPE_FUNCTION)
1020425bb815Sopenharmony_ci  {
1021425bb815Sopenharmony_ci    ecma_object_t *proto_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p,
1022425bb815Sopenharmony_ci                                                             proto_p,
1023425bb815Sopenharmony_ci                                                             ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
1024425bb815Sopenharmony_ci
1025425bb815Sopenharmony_ci    ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp, proto_env_p, 0);
1026425bb815Sopenharmony_ci
1027425bb815Sopenharmony_ci    /* 15. set F’s [[ConstructorKind]] internal slot to "derived". */
1028425bb815Sopenharmony_ci    if (heritage_present)
1029425bb815Sopenharmony_ci    {
1030425bb815Sopenharmony_ci      ECMA_SET_THIRD_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp);
1031425bb815Sopenharmony_ci    }
1032425bb815Sopenharmony_ci
1033425bb815Sopenharmony_ci    ecma_deref_object (proto_env_p);
1034425bb815Sopenharmony_ci  }
1035425bb815Sopenharmony_ci
1036425bb815Sopenharmony_ci  stack_top_p[-2] = stack_top_p[-1];
1037425bb815Sopenharmony_ci  stack_top_p[-1] = proto;
1038425bb815Sopenharmony_ci
1039425bb815Sopenharmony_ci  return ECMA_VALUE_EMPTY;
1040425bb815Sopenharmony_ci} /* opfunc_init_class */
1041425bb815Sopenharmony_ci
1042425bb815Sopenharmony_ci/**
1043425bb815Sopenharmony_ci * Set [[Enumerable]] and [[HomeObject]] attributes for all class method
1044425bb815Sopenharmony_ci */
1045425bb815Sopenharmony_cistatic void
1046425bb815Sopenharmony_ciopfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */
1047425bb815Sopenharmony_ci                             ecma_object_t *parent_env_p) /**< parent environment */
1048425bb815Sopenharmony_ci{
1049425bb815Sopenharmony_ci  jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp;
1050425bb815Sopenharmony_ci
1051425bb815Sopenharmony_ci#if ENABLED (JERRY_PROPRETY_HASHMAP)
1052425bb815Sopenharmony_ci  if (prop_iter_cp != JMEM_CP_NULL)
1053425bb815Sopenharmony_ci  {
1054425bb815Sopenharmony_ci    ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
1055425bb815Sopenharmony_ci    if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
1056425bb815Sopenharmony_ci    {
1057425bb815Sopenharmony_ci      prop_iter_cp = prop_iter_p->next_property_cp;
1058425bb815Sopenharmony_ci    }
1059425bb815Sopenharmony_ci  }
1060425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
1061425bb815Sopenharmony_ci
1062425bb815Sopenharmony_ci  while (prop_iter_cp != JMEM_CP_NULL)
1063425bb815Sopenharmony_ci  {
1064425bb815Sopenharmony_ci    ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
1065425bb815Sopenharmony_ci    JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
1066425bb815Sopenharmony_ci
1067425bb815Sopenharmony_ci    ecma_property_pair_t *property_pair_p = (ecma_property_pair_t *) prop_iter_p;
1068425bb815Sopenharmony_ci
1069425bb815Sopenharmony_ci    for (uint32_t index = 0; index < ECMA_PROPERTY_PAIR_ITEM_COUNT; index++)
1070425bb815Sopenharmony_ci    {
1071425bb815Sopenharmony_ci      uint8_t property = property_pair_p->header.types[index];
1072425bb815Sopenharmony_ci
1073425bb815Sopenharmony_ci      if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA)
1074425bb815Sopenharmony_ci      {
1075425bb815Sopenharmony_ci        if (ecma_is_value_object (property_pair_p->values[index].value)
1076425bb815Sopenharmony_ci            && ecma_is_property_enumerable (property))
1077425bb815Sopenharmony_ci        {
1078425bb815Sopenharmony_ci          property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE);
1079425bb815Sopenharmony_ci          opfunc_set_home_object (ecma_get_object_from_value (property_pair_p->values[index].value), parent_env_p);
1080425bb815Sopenharmony_ci        }
1081425bb815Sopenharmony_ci      }
1082425bb815Sopenharmony_ci      else if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
1083425bb815Sopenharmony_ci      {
1084425bb815Sopenharmony_ci        ecma_property_value_t *accessor_objs_p = property_pair_p->values + index;
1085425bb815Sopenharmony_ci
1086425bb815Sopenharmony_ci        ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (accessor_objs_p);
1087425bb815Sopenharmony_ci
1088425bb815Sopenharmony_ci        if (get_set_pair_p->getter_cp != JMEM_CP_NULL)
1089425bb815Sopenharmony_ci        {
1090425bb815Sopenharmony_ci          opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp), parent_env_p);
1091425bb815Sopenharmony_ci        }
1092425bb815Sopenharmony_ci
1093425bb815Sopenharmony_ci        if (get_set_pair_p->setter_cp != JMEM_CP_NULL)
1094425bb815Sopenharmony_ci        {
1095425bb815Sopenharmony_ci          opfunc_set_home_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp), parent_env_p);
1096425bb815Sopenharmony_ci        }
1097425bb815Sopenharmony_ci      }
1098425bb815Sopenharmony_ci      else
1099425bb815Sopenharmony_ci      {
1100425bb815Sopenharmony_ci        JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_SPECIAL);
1101425bb815Sopenharmony_ci
1102425bb815Sopenharmony_ci        JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_HASHMAP
1103425bb815Sopenharmony_ci                      || property == ECMA_PROPERTY_TYPE_DELETED);
1104425bb815Sopenharmony_ci      }
1105425bb815Sopenharmony_ci    }
1106425bb815Sopenharmony_ci
1107425bb815Sopenharmony_ci    prop_iter_cp = prop_iter_p->next_property_cp;
1108425bb815Sopenharmony_ci  }
1109425bb815Sopenharmony_ci} /* opfunc_set_class_attributes */
1110425bb815Sopenharmony_ci
1111425bb815Sopenharmony_ci/**
1112425bb815Sopenharmony_ci * Pop the current lexical environment referenced by the frame context
1113425bb815Sopenharmony_ci */
1114425bb815Sopenharmony_civoid
1115425bb815Sopenharmony_ciopfunc_pop_lexical_environment (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
1116425bb815Sopenharmony_ci{
1117425bb815Sopenharmony_ci  ecma_object_t *outer_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, frame_ctx_p->lex_env_p->u2.outer_reference_cp);
1118425bb815Sopenharmony_ci  ecma_deref_object (frame_ctx_p->lex_env_p);
1119425bb815Sopenharmony_ci  frame_ctx_p->lex_env_p = outer_env_p;
1120425bb815Sopenharmony_ci} /* opfunc_pop_lexical_environment */
1121425bb815Sopenharmony_ci
1122425bb815Sopenharmony_ci/**
1123425bb815Sopenharmony_ci * ClassDefinitionEvaluation finalization part
1124425bb815Sopenharmony_ci *
1125425bb815Sopenharmony_ci * See also: ECMAScript v6, 14.5.14
1126425bb815Sopenharmony_ci */
1127425bb815Sopenharmony_civoid
1128425bb815Sopenharmony_ciopfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
1129425bb815Sopenharmony_ci                       ecma_value_t **vm_stack_top_p, /**< current vm stack top */
1130425bb815Sopenharmony_ci                       ecma_value_t class_name) /**< class name */
1131425bb815Sopenharmony_ci{
1132425bb815Sopenharmony_ci  JERRY_ASSERT (ecma_is_value_undefined (class_name) || ecma_is_value_string (class_name));
1133425bb815Sopenharmony_ci  ecma_value_t *stack_top_p = *vm_stack_top_p;
1134425bb815Sopenharmony_ci
1135425bb815Sopenharmony_ci  ecma_object_t *ctor_p = ecma_get_object_from_value (stack_top_p[-2]);
1136425bb815Sopenharmony_ci  ecma_object_t *proto_p = ecma_get_object_from_value (stack_top_p[-1]);
1137425bb815Sopenharmony_ci
1138425bb815Sopenharmony_ci  ecma_object_t *class_env_p = frame_ctx_p->lex_env_p;
1139425bb815Sopenharmony_ci
1140425bb815Sopenharmony_ci  /* 23.a */
1141425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (class_name))
1142425bb815Sopenharmony_ci  {
1143425bb815Sopenharmony_ci    ecma_op_initialize_binding (class_env_p, ecma_get_string_from_value (class_name), stack_top_p[-2]);
1144425bb815Sopenharmony_ci  }
1145425bb815Sopenharmony_ci
1146425bb815Sopenharmony_ci  ecma_object_t *ctor_env_p = ecma_create_object_lex_env (class_env_p,
1147425bb815Sopenharmony_ci                                                          ctor_p,
1148425bb815Sopenharmony_ci                                                          ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
1149425bb815Sopenharmony_ci  ecma_object_t *proto_env_p = ecma_create_object_lex_env (class_env_p,
1150425bb815Sopenharmony_ci                                                           proto_p,
1151425bb815Sopenharmony_ci                                                           ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
1152425bb815Sopenharmony_ci
1153425bb815Sopenharmony_ci  opfunc_set_class_attributes (ctor_p, ctor_env_p);
1154425bb815Sopenharmony_ci  opfunc_set_class_attributes (proto_p, proto_env_p);
1155425bb815Sopenharmony_ci
1156425bb815Sopenharmony_ci  ecma_deref_object (proto_env_p);
1157425bb815Sopenharmony_ci  ecma_deref_object (ctor_env_p);
1158425bb815Sopenharmony_ci
1159425bb815Sopenharmony_ci  opfunc_pop_lexical_environment (frame_ctx_p);
1160425bb815Sopenharmony_ci
1161425bb815Sopenharmony_ci  ecma_deref_object (proto_p);
1162425bb815Sopenharmony_ci
1163425bb815Sopenharmony_ci  /* only the current class remains on the stack */
1164425bb815Sopenharmony_ci  JERRY_ASSERT (stack_top_p[-3] == ECMA_VALUE_RELEASE_LEX_ENV);
1165425bb815Sopenharmony_ci  stack_top_p[-3] = stack_top_p[-2];
1166425bb815Sopenharmony_ci  *vm_stack_top_p -= 2;
1167425bb815Sopenharmony_ci} /* opfunc_finalize_class */
1168425bb815Sopenharmony_ci
1169425bb815Sopenharmony_ci/**
1170425bb815Sopenharmony_ci * MakeSuperPropertyReference operation
1171425bb815Sopenharmony_ci *
1172425bb815Sopenharmony_ci * See also: ECMAScript v6, 12.3.5.3
1173425bb815Sopenharmony_ci *
1174425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the operation fails
1175425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY - otherwise
1176425bb815Sopenharmony_ci */
1177425bb815Sopenharmony_ciecma_value_t
1178425bb815Sopenharmony_ciopfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stack top */
1179425bb815Sopenharmony_ci                             vm_frame_ctx_t *frame_ctx_p, /**< frame context */
1180425bb815Sopenharmony_ci                             ecma_value_t prop_name, /**< property name to resolve */
1181425bb815Sopenharmony_ci                             uint8_t opcode) /**< current cbc opcode */
1182425bb815Sopenharmony_ci{
1183425bb815Sopenharmony_ci  ecma_value_t parent = ecma_op_resolve_super_base (frame_ctx_p->lex_env_p);
1184425bb815Sopenharmony_ci
1185425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (parent))
1186425bb815Sopenharmony_ci  {
1187425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot invoke nullable super method."));
1188425bb815Sopenharmony_ci  }
1189425bb815Sopenharmony_ci
1190425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (ecma_op_check_object_coercible (parent)))
1191425bb815Sopenharmony_ci  {
1192425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
1193425bb815Sopenharmony_ci  }
1194425bb815Sopenharmony_ci
1195425bb815Sopenharmony_ci  ecma_value_t *stack_top_p = *vm_stack_top_p;
1196425bb815Sopenharmony_ci
1197425bb815Sopenharmony_ci  if (opcode >= CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE)
1198425bb815Sopenharmony_ci  {
1199425bb815Sopenharmony_ci    JERRY_ASSERT (opcode == CBC_EXT_SUPER_PROP_ASSIGNMENT_REFERENCE
1200425bb815Sopenharmony_ci                  || opcode == CBC_EXT_SUPER_PROP_LITERAL_ASSIGNMENT_REFERENCE);
1201425bb815Sopenharmony_ci    *stack_top_p++ = parent;
1202425bb815Sopenharmony_ci    *stack_top_p++ = ecma_copy_value (prop_name);
1203425bb815Sopenharmony_ci    *vm_stack_top_p = stack_top_p;
1204425bb815Sopenharmony_ci
1205425bb815Sopenharmony_ci    return ECMA_VALUE_EMPTY;
1206425bb815Sopenharmony_ci  }
1207425bb815Sopenharmony_ci
1208425bb815Sopenharmony_ci  ecma_object_t *parent_p = ecma_get_object_from_value (parent);
1209425bb815Sopenharmony_ci  ecma_string_t *prop_name_p = ecma_op_to_prop_name (prop_name);
1210425bb815Sopenharmony_ci
1211425bb815Sopenharmony_ci  if (prop_name_p == NULL)
1212425bb815Sopenharmony_ci  {
1213425bb815Sopenharmony_ci    ecma_deref_object (parent_p);
1214425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
1215425bb815Sopenharmony_ci  }
1216425bb815Sopenharmony_ci
1217425bb815Sopenharmony_ci  ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding);
1218425bb815Sopenharmony_ci  ecma_deref_ecma_string (prop_name_p);
1219425bb815Sopenharmony_ci  ecma_deref_object (parent_p);
1220425bb815Sopenharmony_ci
1221425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (result))
1222425bb815Sopenharmony_ci  {
1223425bb815Sopenharmony_ci    return result;
1224425bb815Sopenharmony_ci  }
1225425bb815Sopenharmony_ci
1226425bb815Sopenharmony_ci  if (opcode == CBC_EXT_SUPER_PROP_LITERAL_REFERENCE || opcode == CBC_EXT_SUPER_PROP_REFERENCE)
1227425bb815Sopenharmony_ci  {
1228425bb815Sopenharmony_ci    *stack_top_p++ = ecma_copy_value (frame_ctx_p->this_binding);
1229425bb815Sopenharmony_ci    *stack_top_p++ = ECMA_VALUE_UNDEFINED;
1230425bb815Sopenharmony_ci  }
1231425bb815Sopenharmony_ci
1232425bb815Sopenharmony_ci  *stack_top_p++ = result;
1233425bb815Sopenharmony_ci  *vm_stack_top_p = stack_top_p;
1234425bb815Sopenharmony_ci
1235425bb815Sopenharmony_ci  return ECMA_VALUE_EMPTY;
1236425bb815Sopenharmony_ci} /* opfunc_form_super_reference */
1237425bb815Sopenharmony_ci
1238425bb815Sopenharmony_ci/**
1239425bb815Sopenharmony_ci * Assignment operation for SuperRefence base
1240425bb815Sopenharmony_ci *
1241425bb815Sopenharmony_ci * @return ECMA_VALUE_ERROR - if the operation fails
1242425bb815Sopenharmony_ci *         ECMA_VALUE_EMPTY - otherwise
1243425bb815Sopenharmony_ci */
1244425bb815Sopenharmony_ciecma_value_t
1245425bb815Sopenharmony_ciopfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top */
1246425bb815Sopenharmony_ci                               vm_frame_ctx_t *frame_ctx_p, /**< frame context */
1247425bb815Sopenharmony_ci                               uint32_t opcode_data) /**< opcode data to store the result */
1248425bb815Sopenharmony_ci{
1249425bb815Sopenharmony_ci  ecma_value_t *stack_top_p = *vm_stack_top_p;
1250425bb815Sopenharmony_ci
1251425bb815Sopenharmony_ci  ecma_value_t base_obj = ecma_op_to_object (stack_top_p[-3]);
1252425bb815Sopenharmony_ci
1253425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (base_obj))
1254425bb815Sopenharmony_ci  {
1255425bb815Sopenharmony_ci    return base_obj;
1256425bb815Sopenharmony_ci  }
1257425bb815Sopenharmony_ci
1258425bb815Sopenharmony_ci  ecma_object_t *base_obj_p = ecma_get_object_from_value (base_obj);
1259425bb815Sopenharmony_ci  ecma_string_t *prop_name_p = ecma_op_to_prop_name (stack_top_p[-2]);
1260425bb815Sopenharmony_ci
1261425bb815Sopenharmony_ci  if (prop_name_p == NULL)
1262425bb815Sopenharmony_ci  {
1263425bb815Sopenharmony_ci    ecma_deref_object (base_obj_p);
1264425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
1265425bb815Sopenharmony_ci  }
1266425bb815Sopenharmony_ci
1267425bb815Sopenharmony_ci  bool is_strict = (frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0;
1268425bb815Sopenharmony_ci
1269425bb815Sopenharmony_ci  ecma_value_t result = ecma_op_object_put_with_receiver (base_obj_p,
1270425bb815Sopenharmony_ci                                                          prop_name_p,
1271425bb815Sopenharmony_ci                                                          stack_top_p[-1],
1272425bb815Sopenharmony_ci                                                          frame_ctx_p->this_binding,
1273425bb815Sopenharmony_ci                                                          is_strict);
1274425bb815Sopenharmony_ci
1275425bb815Sopenharmony_ci  ecma_deref_ecma_string (prop_name_p);
1276425bb815Sopenharmony_ci  ecma_deref_object (base_obj_p);
1277425bb815Sopenharmony_ci
1278425bb815Sopenharmony_ci  if (ECMA_IS_VALUE_ERROR (result))
1279425bb815Sopenharmony_ci  {
1280425bb815Sopenharmony_ci    return result;
1281425bb815Sopenharmony_ci  }
1282425bb815Sopenharmony_ci
1283425bb815Sopenharmony_ci  for (int32_t i = 1; i <= 3; i++)
1284425bb815Sopenharmony_ci  {
1285425bb815Sopenharmony_ci    ecma_free_value (stack_top_p[-i]);
1286425bb815Sopenharmony_ci  }
1287425bb815Sopenharmony_ci
1288425bb815Sopenharmony_ci  stack_top_p -= 3;
1289425bb815Sopenharmony_ci
1290425bb815Sopenharmony_ci  if (opcode_data & VM_OC_PUT_STACK)
1291425bb815Sopenharmony_ci  {
1292425bb815Sopenharmony_ci    *stack_top_p++ = result;
1293425bb815Sopenharmony_ci  }
1294425bb815Sopenharmony_ci  else if (opcode_data & VM_OC_PUT_BLOCK)
1295425bb815Sopenharmony_ci  {
1296425bb815Sopenharmony_ci    ecma_fast_free_value (frame_ctx_p->block_result);
1297425bb815Sopenharmony_ci    frame_ctx_p->block_result = result;
1298425bb815Sopenharmony_ci  }
1299425bb815Sopenharmony_ci
1300425bb815Sopenharmony_ci  *vm_stack_top_p = stack_top_p;
1301425bb815Sopenharmony_ci
1302425bb815Sopenharmony_ci  return result;
1303425bb815Sopenharmony_ci} /* opfunc_assign_super_reference */
1304425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1305425bb815Sopenharmony_ci
1306425bb815Sopenharmony_ci/**
1307425bb815Sopenharmony_ci * @}
1308425bb815Sopenharmony_ci * @}
1309425bb815Sopenharmony_ci */
1310