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-builtins.h"
18425bb815Sopenharmony_ci #include "ecma-conversion.h"
19425bb815Sopenharmony_ci #include "ecma-exceptions.h"
20425bb815Sopenharmony_ci #include "ecma-gc.h"
21425bb815Sopenharmony_ci #include "ecma-globals.h"
22425bb815Sopenharmony_ci #include "ecma-helpers.h"
23425bb815Sopenharmony_ci #include "ecma-objects.h"
24425bb815Sopenharmony_ci #include "ecma-symbol-object.h"
25425bb815Sopenharmony_ci #include "ecma-literal-storage.h"
26425bb815Sopenharmony_ci #include "ecma-try-catch-macro.h"
27425bb815Sopenharmony_ci #include "jcontext.h"
28425bb815Sopenharmony_ci #include "jrt.h"
29425bb815Sopenharmony_ci
30425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL
33425bb815Sopenharmony_ci#include "ecma-builtins-internal.h"
34425bb815Sopenharmony_ci
35425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h"
36425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID symbol
37425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h"
38425bb815Sopenharmony_ci
39425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
40425bb815Sopenharmony_ci * @{
41425bb815Sopenharmony_ci *
42425bb815Sopenharmony_ci * \addtogroup ecmabuiltins
43425bb815Sopenharmony_ci * @{
44425bb815Sopenharmony_ci *
45425bb815Sopenharmony_ci * \addtogroup symbol ECMA Symbol object built-in
46425bb815Sopenharmony_ci * @{
47425bb815Sopenharmony_ci */
48425bb815Sopenharmony_ci
49425bb815Sopenharmony_ci/**
50425bb815Sopenharmony_ci * Handle calling [[Call]] of built-in Symbol object.
51425bb815Sopenharmony_ci *
52425bb815Sopenharmony_ci * @return ecma value
53425bb815Sopenharmony_ci */
54425bb815Sopenharmony_ciecma_value_t
55425bb815Sopenharmony_ciecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
56425bb815Sopenharmony_ci                                   ecma_length_t arguments_list_len) /**< number of arguments */
57425bb815Sopenharmony_ci{
58425bb815Sopenharmony_ci  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
59425bb815Sopenharmony_ci
60425bb815Sopenharmony_ci  return ecma_op_create_symbol (arguments_list_p, arguments_list_len);
61425bb815Sopenharmony_ci} /* ecma_builtin_symbol_dispatch_call */
62425bb815Sopenharmony_ci
63425bb815Sopenharmony_ci/**
64425bb815Sopenharmony_ci * Handle calling [[Construct]] of built-in Symbol object.
65425bb815Sopenharmony_ci *
66425bb815Sopenharmony_ci * Symbol constructor is not intended to be used
67425bb815Sopenharmony_ci * with the new operator or to be subclassed.
68425bb815Sopenharmony_ci *
69425bb815Sopenharmony_ci * See also:
70425bb815Sopenharmony_ci *          ECMA-262 v6, 19.4.1
71425bb815Sopenharmony_ci * @return ecma value
72425bb815Sopenharmony_ci */
73425bb815Sopenharmony_ciecma_value_t
74425bb815Sopenharmony_ciecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
75425bb815Sopenharmony_ci                                        ecma_length_t arguments_list_len) /**< number of arguments */
76425bb815Sopenharmony_ci{
77425bb815Sopenharmony_ci  JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
78425bb815Sopenharmony_ci
79425bb815Sopenharmony_ci  return ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not a constructor."));
80425bb815Sopenharmony_ci} /* ecma_builtin_symbol_dispatch_construct */
81425bb815Sopenharmony_ci
82425bb815Sopenharmony_ci/**
83425bb815Sopenharmony_ci * Helper function for Symbol object's 'for' and `keyFor`
84425bb815Sopenharmony_ci * routines common parts
85425bb815Sopenharmony_ci *
86425bb815Sopenharmony_ci * @return ecma value
87425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
88425bb815Sopenharmony_ci */
89425bb815Sopenharmony_cistatic ecma_value_t
90425bb815Sopenharmony_ciecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */
91425bb815Sopenharmony_ci{
92425bb815Sopenharmony_ci  ecma_string_t *string_p;
93425bb815Sopenharmony_ci
94425bb815Sopenharmony_ci  bool is_for = ecma_is_value_string (value_to_find);
95425bb815Sopenharmony_ci
96425bb815Sopenharmony_ci  if (is_for)
97425bb815Sopenharmony_ci  {
98425bb815Sopenharmony_ci    string_p = ecma_get_string_from_value (value_to_find);
99425bb815Sopenharmony_ci  }
100425bb815Sopenharmony_ci  else
101425bb815Sopenharmony_ci  {
102425bb815Sopenharmony_ci    string_p = ecma_get_symbol_from_value (value_to_find);
103425bb815Sopenharmony_ci  }
104425bb815Sopenharmony_ci
105425bb815Sopenharmony_ci  jmem_cpointer_t symbol_list_cp = JERRY_CONTEXT (symbol_list_first_cp);
106425bb815Sopenharmony_ci  jmem_cpointer_t *empty_cpointer_p = NULL;
107425bb815Sopenharmony_ci
108425bb815Sopenharmony_ci  while (symbol_list_cp != JMEM_CP_NULL)
109425bb815Sopenharmony_ci  {
110425bb815Sopenharmony_ci    ecma_lit_storage_item_t *symbol_list_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_lit_storage_item_t,
111425bb815Sopenharmony_ci                                                                           symbol_list_cp);
112425bb815Sopenharmony_ci
113425bb815Sopenharmony_ci    for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
114425bb815Sopenharmony_ci    {
115425bb815Sopenharmony_ci      if (symbol_list_p->values[i] != JMEM_CP_NULL)
116425bb815Sopenharmony_ci      {
117425bb815Sopenharmony_ci        ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t,
118425bb815Sopenharmony_ci                                                               symbol_list_p->values[i]);
119425bb815Sopenharmony_ci
120425bb815Sopenharmony_ci        if (is_for)
121425bb815Sopenharmony_ci        {
122425bb815Sopenharmony_ci          ecma_string_t *symbol_desc_p = ecma_get_symbol_description (value_p);
123425bb815Sopenharmony_ci
124425bb815Sopenharmony_ci          if (ecma_compare_ecma_strings (symbol_desc_p, string_p))
125425bb815Sopenharmony_ci          {
126425bb815Sopenharmony_ci            /* The current symbol's descriptor matches with the value_to_find,
127425bb815Sopenharmony_ci               so the value is no longer needed. */
128425bb815Sopenharmony_ci            ecma_deref_ecma_string (string_p);
129425bb815Sopenharmony_ci            return ecma_copy_value (ecma_make_symbol_value (value_p));
130425bb815Sopenharmony_ci          }
131425bb815Sopenharmony_ci        }
132425bb815Sopenharmony_ci        else
133425bb815Sopenharmony_ci        {
134425bb815Sopenharmony_ci          if (string_p == value_p)
135425bb815Sopenharmony_ci          {
136425bb815Sopenharmony_ci            ecma_string_t *symbol_desc_p = ecma_get_symbol_description (string_p);
137425bb815Sopenharmony_ci            ecma_ref_ecma_string (symbol_desc_p);
138425bb815Sopenharmony_ci            return ecma_make_string_value (symbol_desc_p);
139425bb815Sopenharmony_ci          }
140425bb815Sopenharmony_ci        }
141425bb815Sopenharmony_ci      }
142425bb815Sopenharmony_ci      else
143425bb815Sopenharmony_ci      {
144425bb815Sopenharmony_ci        if (empty_cpointer_p == NULL)
145425bb815Sopenharmony_ci        {
146425bb815Sopenharmony_ci          empty_cpointer_p = symbol_list_p->values + i;
147425bb815Sopenharmony_ci        }
148425bb815Sopenharmony_ci      }
149425bb815Sopenharmony_ci    }
150425bb815Sopenharmony_ci
151425bb815Sopenharmony_ci    symbol_list_cp = symbol_list_p->next_cp;
152425bb815Sopenharmony_ci  }
153425bb815Sopenharmony_ci
154425bb815Sopenharmony_ci  if (!is_for)
155425bb815Sopenharmony_ci  {
156425bb815Sopenharmony_ci    return ECMA_VALUE_UNDEFINED;
157425bb815Sopenharmony_ci  }
158425bb815Sopenharmony_ci
159425bb815Sopenharmony_ci  /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires
160425bb815Sopenharmony_ci     an extra reference to the descriptor string, but this reference has already been added. */
161425bb815Sopenharmony_ci  ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find);
162425bb815Sopenharmony_ci
163425bb815Sopenharmony_ci  jmem_cpointer_t result;
164425bb815Sopenharmony_ci  JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p);
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci  if (empty_cpointer_p != NULL)
167425bb815Sopenharmony_ci  {
168425bb815Sopenharmony_ci    *empty_cpointer_p = result;
169425bb815Sopenharmony_ci    return ecma_copy_value (ecma_make_symbol_value (new_symbol_p));
170425bb815Sopenharmony_ci  }
171425bb815Sopenharmony_ci
172425bb815Sopenharmony_ci  ecma_lit_storage_item_t *new_item_p;
173425bb815Sopenharmony_ci  new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t));
174425bb815Sopenharmony_ci
175425bb815Sopenharmony_ci  new_item_p->values[0] = result;
176425bb815Sopenharmony_ci  for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++)
177425bb815Sopenharmony_ci  {
178425bb815Sopenharmony_ci    new_item_p->values[i] = JMEM_CP_NULL;
179425bb815Sopenharmony_ci  }
180425bb815Sopenharmony_ci
181425bb815Sopenharmony_ci  new_item_p->next_cp = JERRY_CONTEXT (symbol_list_first_cp);
182425bb815Sopenharmony_ci  JMEM_CP_SET_NON_NULL_POINTER (JERRY_CONTEXT (symbol_list_first_cp), new_item_p);
183425bb815Sopenharmony_ci
184425bb815Sopenharmony_ci  return ecma_copy_value (ecma_make_symbol_value (new_symbol_p));
185425bb815Sopenharmony_ci} /* ecma_builtin_symbol_for_helper */
186425bb815Sopenharmony_ci
187425bb815Sopenharmony_ci/**
188425bb815Sopenharmony_ci * The Symbol object's 'for' routine
189425bb815Sopenharmony_ci *
190425bb815Sopenharmony_ci * See also:
191425bb815Sopenharmony_ci *          ECMA-262 v6, 19.4.2.1
192425bb815Sopenharmony_ci *
193425bb815Sopenharmony_ci * @return ecma value
194425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
195425bb815Sopenharmony_ci */
196425bb815Sopenharmony_cistatic ecma_value_t
197425bb815Sopenharmony_ciecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */
198425bb815Sopenharmony_ci                         ecma_value_t key) /**< key string */
199425bb815Sopenharmony_ci{
200425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
201425bb815Sopenharmony_ci  ecma_string_t *string_desc_p = ecma_op_to_string (key);
202425bb815Sopenharmony_ci
203425bb815Sopenharmony_ci  /* 1. */
204425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (string_desc_p == NULL))
205425bb815Sopenharmony_ci  {
206425bb815Sopenharmony_ci    /* 2. */
207425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
208425bb815Sopenharmony_ci  }
209425bb815Sopenharmony_ci
210425bb815Sopenharmony_ci  return ecma_builtin_symbol_for_helper (ecma_make_string_value (string_desc_p));
211425bb815Sopenharmony_ci} /* ecma_builtin_symbol_for */
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci/**
214425bb815Sopenharmony_ci * The Symbol object's 'keyFor' routine
215425bb815Sopenharmony_ci *
216425bb815Sopenharmony_ci * See also:
217425bb815Sopenharmony_ci *          ECMA-262 v6, 19.4.2.
218425bb815Sopenharmony_ci *
219425bb815Sopenharmony_ci * @return ecma value
220425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
221425bb815Sopenharmony_ci */
222425bb815Sopenharmony_cistatic ecma_value_t
223425bb815Sopenharmony_ciecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */
224425bb815Sopenharmony_ci                             ecma_value_t symbol) /**< symbol */
225425bb815Sopenharmony_ci{
226425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
227425bb815Sopenharmony_ci
228425bb815Sopenharmony_ci  /* 1. */
229425bb815Sopenharmony_ci  if (!ecma_is_value_symbol (symbol))
230425bb815Sopenharmony_ci  {
231425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("The given argument is not a Symbol."));
232425bb815Sopenharmony_ci  }
233425bb815Sopenharmony_ci
234425bb815Sopenharmony_ci  /* 2-4. */
235425bb815Sopenharmony_ci  return ecma_builtin_symbol_for_helper (symbol);
236425bb815Sopenharmony_ci} /* ecma_builtin_symbol_key_for */
237425bb815Sopenharmony_ci
238425bb815Sopenharmony_ci/**
239425bb815Sopenharmony_ci * @}
240425bb815Sopenharmony_ci * @}
241425bb815Sopenharmony_ci * @}
242425bb815Sopenharmony_ci */
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
245