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-helpers.h"
17425bb815Sopenharmony_ci#include "jcontext.h"
18425bb815Sopenharmony_ci#include "js-parser-internal.h"
19425bb815Sopenharmony_ci#include "js-scanner-internal.h"
20425bb815Sopenharmony_ci#include "lit-char-helpers.h"
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER)
23425bb815Sopenharmony_ci
24425bb815Sopenharmony_ci/** \addtogroup parser Parser
25425bb815Sopenharmony_ci * @{
26425bb815Sopenharmony_ci *
27425bb815Sopenharmony_ci * \addtogroup jsparser JavaScript
28425bb815Sopenharmony_ci * @{
29425bb815Sopenharmony_ci *
30425bb815Sopenharmony_ci * \addtogroup jsparser_scanner Scanner
31425bb815Sopenharmony_ci * @{
32425bb815Sopenharmony_ci */
33425bb815Sopenharmony_ci
34425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START,
35425bb815Sopenharmony_ci                     maximum_number_of_literals_plus_registers_must_be_less_than_register_start);
36425bb815Sopenharmony_ci
37425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
38425bb815Sopenharmony_ci
39425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0,
40425bb815Sopenharmony_ci                     is_arrow_arg_binding_flag_must_not_use_local_flags);
41425bb815Sopenharmony_ci
42425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0,
43425bb815Sopenharmony_ci                     is_let_flag_must_use_local_flags);
44425bb815Sopenharmony_ci
45425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0,
46425bb815Sopenharmony_ci                     is_const_flag_must_use_local_flags);
47425bb815Sopenharmony_ci
48425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0,
49425bb815Sopenharmony_ci                     is_func_declaration_flag_must_use_local_flags);
50425bb815Sopenharmony_ci
51425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0,
52425bb815Sopenharmony_ci                     is_arg_binding_flag_must_use_local_flags);
53425bb815Sopenharmony_ci
54425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (SCANNER_LITERAL_IS_FUNC_DECLARATION != SCANNER_LITERAL_IS_DESTRUCTURED_ARG,
55425bb815Sopenharmony_ci                     is_func_declaration_must_be_different_from_is_arg_binding);
56425bb815Sopenharmony_ci
57425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_SCOPE_STACK_IS_CONST_REG == PARSER_SCOPE_STACK_IS_LOCAL_CREATED,
58425bb815Sopenharmony_ci                     scope_stack_is_const_reg_and_scope_stack_is_local_created_must_be_the_same);
59425bb815Sopenharmony_ci
60425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
61425bb815Sopenharmony_ci
62425bb815Sopenharmony_ci/**
63425bb815Sopenharmony_ci * Raise a scanner error.
64425bb815Sopenharmony_ci */
65425bb815Sopenharmony_civoid
66425bb815Sopenharmony_ciscanner_raise_error (parser_context_t *context_p) /**< context */
67425bb815Sopenharmony_ci{
68425bb815Sopenharmony_ci  PARSER_THROW (context_p->try_buffer);
69425bb815Sopenharmony_ci  /* Should never been reached. */
70425bb815Sopenharmony_ci  JERRY_ASSERT (0);
71425bb815Sopenharmony_ci} /* scanner_raise_error */
72425bb815Sopenharmony_ci
73425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
74425bb815Sopenharmony_ci
75425bb815Sopenharmony_ci/**
76425bb815Sopenharmony_ci * Raise a variable redeclaration error.
77425bb815Sopenharmony_ci */
78425bb815Sopenharmony_civoid
79425bb815Sopenharmony_ciscanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */
80425bb815Sopenharmony_ci{
81425bb815Sopenharmony_ci  scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
82425bb815Sopenharmony_ci  info_p->type = SCANNER_TYPE_ERR_REDECLARED;
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci  scanner_raise_error (context_p);
85425bb815Sopenharmony_ci} /* scanner_raise_redeclaration_error */
86425bb815Sopenharmony_ci
87425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
88425bb815Sopenharmony_ci
89425bb815Sopenharmony_ci/**
90425bb815Sopenharmony_ci * Allocate memory for scanner.
91425bb815Sopenharmony_ci *
92425bb815Sopenharmony_ci * @return allocated memory
93425bb815Sopenharmony_ci */
94425bb815Sopenharmony_civoid *
95425bb815Sopenharmony_ciscanner_malloc (parser_context_t *context_p, /**< context */
96425bb815Sopenharmony_ci                size_t size) /**< size of the memory block */
97425bb815Sopenharmony_ci{
98425bb815Sopenharmony_ci  void *result;
99425bb815Sopenharmony_ci
100425bb815Sopenharmony_ci  JERRY_ASSERT (size > 0);
101425bb815Sopenharmony_ci  result = jmem_heap_alloc_block_null_on_error (size);
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci  if (result == NULL)
104425bb815Sopenharmony_ci  {
105425bb815Sopenharmony_ci    scanner_cleanup (context_p);
106425bb815Sopenharmony_ci
107425bb815Sopenharmony_ci    /* This is the only error which specify its reason. */
108425bb815Sopenharmony_ci    context_p->error = PARSER_ERR_OUT_OF_MEMORY;
109425bb815Sopenharmony_ci    PARSER_THROW (context_p->try_buffer);
110425bb815Sopenharmony_ci  }
111425bb815Sopenharmony_ci  return result;
112425bb815Sopenharmony_ci} /* scanner_malloc */
113425bb815Sopenharmony_ci
114425bb815Sopenharmony_ci/**
115425bb815Sopenharmony_ci * Free memory allocated by scanner_malloc.
116425bb815Sopenharmony_ci */
117425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
118425bb815Sopenharmony_ciscanner_free (void *ptr, /**< pointer to free */
119425bb815Sopenharmony_ci              size_t size) /**< size of the memory block */
120425bb815Sopenharmony_ci{
121425bb815Sopenharmony_ci  jmem_heap_free_block (ptr, size);
122425bb815Sopenharmony_ci} /* scanner_free */
123425bb815Sopenharmony_ci
124425bb815Sopenharmony_ci/**
125425bb815Sopenharmony_ci * Count the size of a stream after an info block.
126425bb815Sopenharmony_ci *
127425bb815Sopenharmony_ci * @return the size in bytes
128425bb815Sopenharmony_ci */
129425bb815Sopenharmony_cisize_t
130425bb815Sopenharmony_ciscanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
131425bb815Sopenharmony_ci                         size_t size) /**< size excluding the stream */
132425bb815Sopenharmony_ci{
133425bb815Sopenharmony_ci  const uint8_t *data_p = ((const uint8_t *) info_p) + size;
134425bb815Sopenharmony_ci  const uint8_t *data_p_start = data_p;
135425bb815Sopenharmony_ci
136425bb815Sopenharmony_ci  while (data_p[0] != SCANNER_STREAM_TYPE_END)
137425bb815Sopenharmony_ci  {
138425bb815Sopenharmony_ci    switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
139425bb815Sopenharmony_ci    {
140425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_VAR:
141425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
142425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_LET:
143425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_CONST:
144425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_LOCAL:
145425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
146425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
147425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_IMPORT:
148425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
149425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_ARG:
150425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
151425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_ARG_VAR:
152425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
153425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
154425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
155425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_ARG_FUNC:
156425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
157425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
158425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
159425bb815Sopenharmony_ci      case SCANNER_STREAM_TYPE_FUNC:
160425bb815Sopenharmony_ci      {
161425bb815Sopenharmony_ci        break;
162425bb815Sopenharmony_ci      }
163425bb815Sopenharmony_ci      default:
164425bb815Sopenharmony_ci      {
165425bb815Sopenharmony_ci        JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
166425bb815Sopenharmony_ci        data_p++;
167425bb815Sopenharmony_ci        continue;
168425bb815Sopenharmony_ci      }
169425bb815Sopenharmony_ci    }
170425bb815Sopenharmony_ci
171425bb815Sopenharmony_ci    data_p += 3;
172425bb815Sopenharmony_ci
173425bb815Sopenharmony_ci    if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF)
174425bb815Sopenharmony_ci    {
175425bb815Sopenharmony_ci      data_p++;
176425bb815Sopenharmony_ci    }
177425bb815Sopenharmony_ci    else if (data_p[-1] == 0)
178425bb815Sopenharmony_ci    {
179425bb815Sopenharmony_ci      data_p += sizeof (const uint8_t *);
180425bb815Sopenharmony_ci    }
181425bb815Sopenharmony_ci  }
182425bb815Sopenharmony_ci
183425bb815Sopenharmony_ci  return size + 1 + (size_t) (data_p - data_p_start);
184425bb815Sopenharmony_ci} /* scanner_get_stream_size */
185425bb815Sopenharmony_ci
186425bb815Sopenharmony_ci/**
187425bb815Sopenharmony_ci * Insert a scanner info block into the scanner info chain.
188425bb815Sopenharmony_ci *
189425bb815Sopenharmony_ci * @return newly allocated scanner info
190425bb815Sopenharmony_ci */
191425bb815Sopenharmony_ciscanner_info_t *
192425bb815Sopenharmony_ciscanner_insert_info (parser_context_t *context_p, /**< context */
193425bb815Sopenharmony_ci                     const uint8_t *source_p, /**< triggering position */
194425bb815Sopenharmony_ci                     size_t size) /**< size of the memory block */
195425bb815Sopenharmony_ci{
196425bb815Sopenharmony_ci  scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
197425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
198425bb815Sopenharmony_ci  scanner_info_t *prev_scanner_info_p = NULL;
199425bb815Sopenharmony_ci
200425bb815Sopenharmony_ci  JERRY_ASSERT (scanner_info_p != NULL);
201425bb815Sopenharmony_ci  JERRY_ASSERT (source_p != NULL);
202425bb815Sopenharmony_ci
203425bb815Sopenharmony_ci  new_scanner_info_p->source_p = source_p;
204425bb815Sopenharmony_ci
205425bb815Sopenharmony_ci  while (source_p < scanner_info_p->source_p)
206425bb815Sopenharmony_ci  {
207425bb815Sopenharmony_ci    prev_scanner_info_p = scanner_info_p;
208425bb815Sopenharmony_ci    scanner_info_p = scanner_info_p->next_p;
209425bb815Sopenharmony_ci
210425bb815Sopenharmony_ci    JERRY_ASSERT (scanner_info_p != NULL);
211425bb815Sopenharmony_ci  }
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci  /* Multiple scanner info blocks cannot be assigned to the same position. */
214425bb815Sopenharmony_ci  JERRY_ASSERT (source_p != scanner_info_p->source_p);
215425bb815Sopenharmony_ci
216425bb815Sopenharmony_ci  new_scanner_info_p->next_p = scanner_info_p;
217425bb815Sopenharmony_ci
218425bb815Sopenharmony_ci  if (JERRY_LIKELY (prev_scanner_info_p == NULL))
219425bb815Sopenharmony_ci  {
220425bb815Sopenharmony_ci    context_p->next_scanner_info_p = new_scanner_info_p;
221425bb815Sopenharmony_ci  }
222425bb815Sopenharmony_ci  else
223425bb815Sopenharmony_ci  {
224425bb815Sopenharmony_ci    prev_scanner_info_p->next_p = new_scanner_info_p;
225425bb815Sopenharmony_ci  }
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci  return new_scanner_info_p;
228425bb815Sopenharmony_ci} /* scanner_insert_info */
229425bb815Sopenharmony_ci
230425bb815Sopenharmony_ci/**
231425bb815Sopenharmony_ci * Insert a scanner info block into the scanner info chain before a given info block.
232425bb815Sopenharmony_ci *
233425bb815Sopenharmony_ci * @return newly allocated scanner info
234425bb815Sopenharmony_ci */
235425bb815Sopenharmony_ciscanner_info_t *
236425bb815Sopenharmony_ciscanner_insert_info_before (parser_context_t *context_p, /**< context */
237425bb815Sopenharmony_ci                            const uint8_t *source_p, /**< triggering position */
238425bb815Sopenharmony_ci                            scanner_info_t *start_info_p, /**< first info position */
239425bb815Sopenharmony_ci                            size_t size) /**< size of the memory block */
240425bb815Sopenharmony_ci{
241425bb815Sopenharmony_ci  JERRY_ASSERT (start_info_p != NULL);
242425bb815Sopenharmony_ci
243425bb815Sopenharmony_ci  scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
244425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = start_info_p->next_p;
245425bb815Sopenharmony_ci  scanner_info_t *prev_scanner_info_p = start_info_p;
246425bb815Sopenharmony_ci
247425bb815Sopenharmony_ci  new_scanner_info_p->source_p = source_p;
248425bb815Sopenharmony_ci
249425bb815Sopenharmony_ci  while (source_p < scanner_info_p->source_p)
250425bb815Sopenharmony_ci  {
251425bb815Sopenharmony_ci    prev_scanner_info_p = scanner_info_p;
252425bb815Sopenharmony_ci    scanner_info_p = scanner_info_p->next_p;
253425bb815Sopenharmony_ci
254425bb815Sopenharmony_ci    JERRY_ASSERT (scanner_info_p != NULL);
255425bb815Sopenharmony_ci  }
256425bb815Sopenharmony_ci
257425bb815Sopenharmony_ci  /* Multiple scanner info blocks cannot be assigned to the same position. */
258425bb815Sopenharmony_ci  JERRY_ASSERT (source_p != scanner_info_p->source_p);
259425bb815Sopenharmony_ci
260425bb815Sopenharmony_ci  new_scanner_info_p->next_p = scanner_info_p;
261425bb815Sopenharmony_ci
262425bb815Sopenharmony_ci  prev_scanner_info_p->next_p = new_scanner_info_p;
263425bb815Sopenharmony_ci  return new_scanner_info_p;
264425bb815Sopenharmony_ci} /* scanner_insert_info_before */
265425bb815Sopenharmony_ci
266425bb815Sopenharmony_ci/**
267425bb815Sopenharmony_ci * Release the next scanner info.
268425bb815Sopenharmony_ci */
269425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
270425bb815Sopenharmony_ciscanner_release_next (parser_context_t *context_p, /**< context */
271425bb815Sopenharmony_ci                      size_t size) /**< size of the memory block */
272425bb815Sopenharmony_ci{
273425bb815Sopenharmony_ci  scanner_info_t *next_p = context_p->next_scanner_info_p->next_p;
274425bb815Sopenharmony_ci
275425bb815Sopenharmony_ci  jmem_heap_free_block (context_p->next_scanner_info_p, size);
276425bb815Sopenharmony_ci  context_p->next_scanner_info_p = next_p;
277425bb815Sopenharmony_ci} /* scanner_release_next */
278425bb815Sopenharmony_ci
279425bb815Sopenharmony_ci/**
280425bb815Sopenharmony_ci * Set the active scanner info to the next scanner info.
281425bb815Sopenharmony_ci */
282425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
283425bb815Sopenharmony_ciscanner_set_active (parser_context_t *context_p) /**< context */
284425bb815Sopenharmony_ci{
285425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
286425bb815Sopenharmony_ci
287425bb815Sopenharmony_ci  context_p->next_scanner_info_p = scanner_info_p->next_p;
288425bb815Sopenharmony_ci  scanner_info_p->next_p = context_p->active_scanner_info_p;
289425bb815Sopenharmony_ci  context_p->active_scanner_info_p = scanner_info_p;
290425bb815Sopenharmony_ci} /* scanner_set_active */
291425bb815Sopenharmony_ci
292425bb815Sopenharmony_ci/**
293425bb815Sopenharmony_ci * Set the next scanner info to the active scanner info.
294425bb815Sopenharmony_ci */
295425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
296425bb815Sopenharmony_ciscanner_revert_active (parser_context_t *context_p) /**< context */
297425bb815Sopenharmony_ci{
298425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = context_p->active_scanner_info_p;
299425bb815Sopenharmony_ci
300425bb815Sopenharmony_ci  context_p->active_scanner_info_p = scanner_info_p->next_p;
301425bb815Sopenharmony_ci  scanner_info_p->next_p = context_p->next_scanner_info_p;
302425bb815Sopenharmony_ci  context_p->next_scanner_info_p = scanner_info_p;
303425bb815Sopenharmony_ci} /* scanner_revert_active */
304425bb815Sopenharmony_ci
305425bb815Sopenharmony_ci/**
306425bb815Sopenharmony_ci * Release the active scanner info.
307425bb815Sopenharmony_ci */
308425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
309425bb815Sopenharmony_ciscanner_release_active (parser_context_t *context_p, /**< context */
310425bb815Sopenharmony_ci                        size_t size) /**< size of the memory block */
311425bb815Sopenharmony_ci{
312425bb815Sopenharmony_ci  scanner_info_t *next_p = context_p->active_scanner_info_p->next_p;
313425bb815Sopenharmony_ci
314425bb815Sopenharmony_ci  jmem_heap_free_block (context_p->active_scanner_info_p, size);
315425bb815Sopenharmony_ci  context_p->active_scanner_info_p = next_p;
316425bb815Sopenharmony_ci} /* scanner_release_active */
317425bb815Sopenharmony_ci
318425bb815Sopenharmony_ci/**
319425bb815Sopenharmony_ci * Release switch cases.
320425bb815Sopenharmony_ci */
321425bb815Sopenharmony_civoid
322425bb815Sopenharmony_ciscanner_release_switch_cases (scanner_case_info_t *case_p) /**< case list */
323425bb815Sopenharmony_ci{
324425bb815Sopenharmony_ci  while (case_p != NULL)
325425bb815Sopenharmony_ci  {
326425bb815Sopenharmony_ci    scanner_case_info_t *next_p = case_p->next_p;
327425bb815Sopenharmony_ci
328425bb815Sopenharmony_ci    jmem_heap_free_block (case_p, sizeof (scanner_case_info_t));
329425bb815Sopenharmony_ci    case_p = next_p;
330425bb815Sopenharmony_ci  }
331425bb815Sopenharmony_ci} /* scanner_release_switch_cases */
332425bb815Sopenharmony_ci
333425bb815Sopenharmony_ci/**
334425bb815Sopenharmony_ci * Seek to correct position in the scanner info list.
335425bb815Sopenharmony_ci */
336425bb815Sopenharmony_civoid
337425bb815Sopenharmony_ciscanner_seek (parser_context_t *context_p) /**< context */
338425bb815Sopenharmony_ci{
339425bb815Sopenharmony_ci  const uint8_t *source_p = context_p->source_p;
340425bb815Sopenharmony_ci  scanner_info_t *prev_p;
341425bb815Sopenharmony_ci
342425bb815Sopenharmony_ci  if (context_p->skipped_scanner_info_p != NULL)
343425bb815Sopenharmony_ci  {
344425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->skipped_scanner_info_p->source_p != NULL);
345425bb815Sopenharmony_ci
346425bb815Sopenharmony_ci    context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
347425bb815Sopenharmony_ci
348425bb815Sopenharmony_ci    if (context_p->skipped_scanner_info_end_p->source_p <= source_p)
349425bb815Sopenharmony_ci    {
350425bb815Sopenharmony_ci      prev_p = context_p->skipped_scanner_info_end_p;
351425bb815Sopenharmony_ci    }
352425bb815Sopenharmony_ci    else
353425bb815Sopenharmony_ci    {
354425bb815Sopenharmony_ci      prev_p = context_p->skipped_scanner_info_p;
355425bb815Sopenharmony_ci
356425bb815Sopenharmony_ci      if (prev_p->source_p > source_p)
357425bb815Sopenharmony_ci      {
358425bb815Sopenharmony_ci        context_p->next_scanner_info_p = prev_p;
359425bb815Sopenharmony_ci        context_p->skipped_scanner_info_p = NULL;
360425bb815Sopenharmony_ci        return;
361425bb815Sopenharmony_ci      }
362425bb815Sopenharmony_ci
363425bb815Sopenharmony_ci      context_p->skipped_scanner_info_p = prev_p;
364425bb815Sopenharmony_ci    }
365425bb815Sopenharmony_ci  }
366425bb815Sopenharmony_ci  else
367425bb815Sopenharmony_ci  {
368425bb815Sopenharmony_ci    prev_p = context_p->next_scanner_info_p;
369425bb815Sopenharmony_ci
370425bb815Sopenharmony_ci    if (prev_p->source_p == NULL || prev_p->source_p > source_p)
371425bb815Sopenharmony_ci    {
372425bb815Sopenharmony_ci      return;
373425bb815Sopenharmony_ci    }
374425bb815Sopenharmony_ci
375425bb815Sopenharmony_ci    context_p->skipped_scanner_info_p = prev_p;
376425bb815Sopenharmony_ci  }
377425bb815Sopenharmony_ci
378425bb815Sopenharmony_ci  while (prev_p->next_p->source_p != NULL && prev_p->next_p->source_p <= source_p)
379425bb815Sopenharmony_ci  {
380425bb815Sopenharmony_ci    prev_p = prev_p->next_p;
381425bb815Sopenharmony_ci  }
382425bb815Sopenharmony_ci
383425bb815Sopenharmony_ci  context_p->skipped_scanner_info_end_p = prev_p;
384425bb815Sopenharmony_ci  context_p->next_scanner_info_p = prev_p->next_p;
385425bb815Sopenharmony_ci} /* scanner_seek */
386425bb815Sopenharmony_ci
387425bb815Sopenharmony_ci/**
388425bb815Sopenharmony_ci * Push a new literal pool.
389425bb815Sopenharmony_ci *
390425bb815Sopenharmony_ci * @return the newly created literal pool
391425bb815Sopenharmony_ci */
392425bb815Sopenharmony_ciscanner_literal_pool_t *
393425bb815Sopenharmony_ciscanner_push_literal_pool (parser_context_t *context_p, /**< context */
394425bb815Sopenharmony_ci                           scanner_context_t *scanner_context_p, /**< scanner context */
395425bb815Sopenharmony_ci                           uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */
396425bb815Sopenharmony_ci{
397425bb815Sopenharmony_ci  scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p;
398425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p;
399425bb815Sopenharmony_ci
400425bb815Sopenharmony_ci  literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
401425bb815Sopenharmony_ci
402425bb815Sopenharmony_ci  if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION))
403425bb815Sopenharmony_ci  {
404425bb815Sopenharmony_ci    JERRY_ASSERT (prev_literal_pool_p != NULL);
405425bb815Sopenharmony_ci    status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
406425bb815Sopenharmony_ci
407425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
408425bb815Sopenharmony_ci    const uint16_t copied_flags = (SCANNER_LITERAL_POOL_IN_WITH
409425bb815Sopenharmony_ci                                   | SCANNER_LITERAL_POOL_GENERATOR
410425bb815Sopenharmony_ci                                   | SCANNER_LITERAL_POOL_ASYNC);
411425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
412425bb815Sopenharmony_ci    const uint16_t copied_flags = SCANNER_LITERAL_POOL_IN_WITH;
413425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
414425bb815Sopenharmony_ci
415425bb815Sopenharmony_ci    status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
416425bb815Sopenharmony_ci  }
417425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
418425bb815Sopenharmony_ci  else
419425bb815Sopenharmony_ci  {
420425bb815Sopenharmony_ci    context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
421425bb815Sopenharmony_ci
422425bb815Sopenharmony_ci    if (status_flags & SCANNER_LITERAL_POOL_GENERATOR)
423425bb815Sopenharmony_ci    {
424425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
425425bb815Sopenharmony_ci    }
426425bb815Sopenharmony_ci
427425bb815Sopenharmony_ci    if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
428425bb815Sopenharmony_ci    {
429425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
430425bb815Sopenharmony_ci    }
431425bb815Sopenharmony_ci  }
432425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
433425bb815Sopenharmony_ci
434425bb815Sopenharmony_ci  if (prev_literal_pool_p != NULL)
435425bb815Sopenharmony_ci  {
436425bb815Sopenharmony_ci    const uint16_t copied_flags = SCANNER_LITERAL_POOL_IS_STRICT;
437425bb815Sopenharmony_ci    status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
438425bb815Sopenharmony_ci
439425bb815Sopenharmony_ci    /* The logical value of these flags must be the same. */
440425bb815Sopenharmony_ci    JERRY_ASSERT (!(status_flags & SCANNER_LITERAL_POOL_IS_STRICT) == !(context_p->status_flags & PARSER_IS_STRICT));
441425bb815Sopenharmony_ci  }
442425bb815Sopenharmony_ci
443425bb815Sopenharmony_ci  parser_list_init (&literal_pool_p->literal_pool,
444425bb815Sopenharmony_ci                    sizeof (lexer_lit_location_t),
445425bb815Sopenharmony_ci                    (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
446425bb815Sopenharmony_ci  literal_pool_p->source_p = NULL;
447425bb815Sopenharmony_ci  literal_pool_p->status_flags = status_flags;
448425bb815Sopenharmony_ci  literal_pool_p->no_declarations = 0;
449425bb815Sopenharmony_ci
450425bb815Sopenharmony_ci  literal_pool_p->prev_p = prev_literal_pool_p;
451425bb815Sopenharmony_ci  scanner_context_p->active_literal_pool_p = literal_pool_p;
452425bb815Sopenharmony_ci
453425bb815Sopenharmony_ci  return literal_pool_p;
454425bb815Sopenharmony_ci} /* scanner_push_literal_pool */
455425bb815Sopenharmony_ci
456425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX,
457425bb815Sopenharmony_ci                     maximum_ident_length_must_fit_in_a_byte);
458425bb815Sopenharmony_ci
459425bb815Sopenharmony_ci/**
460425bb815Sopenharmony_ci * Checks whether a literal is equal to "arguments".
461425bb815Sopenharmony_ci */
462425bb815Sopenharmony_cistatic inline bool JERRY_ATTR_ALWAYS_INLINE
463425bb815Sopenharmony_ciscanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */
464425bb815Sopenharmony_ci{
465425bb815Sopenharmony_ci  return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9);
466425bb815Sopenharmony_ci} /* scanner_literal_is_arguments */
467425bb815Sopenharmony_ci
468425bb815Sopenharmony_ci/**
469425bb815Sopenharmony_ci * Pop the last literal pool from the end.
470425bb815Sopenharmony_ci */
471425bb815Sopenharmony_civoid
472425bb815Sopenharmony_ciscanner_pop_literal_pool (parser_context_t *context_p, /**< context */
473425bb815Sopenharmony_ci                          scanner_context_t *scanner_context_p) /**< scanner context */
474425bb815Sopenharmony_ci{
475425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
476425bb815Sopenharmony_ci  scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
477425bb815Sopenharmony_ci
478425bb815Sopenharmony_ci  if (literal_pool_p->source_p == NULL)
479425bb815Sopenharmony_ci  {
480425bb815Sopenharmony_ci    JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION);
481425bb815Sopenharmony_ci    JERRY_ASSERT (literal_pool_p->literal_pool.data.first_p == NULL
482425bb815Sopenharmony_ci                  && literal_pool_p->literal_pool.data.last_p == NULL);
483425bb815Sopenharmony_ci
484425bb815Sopenharmony_ci    scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
485425bb815Sopenharmony_ci    scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
486425bb815Sopenharmony_ci    return;
487425bb815Sopenharmony_ci  }
488425bb815Sopenharmony_ci
489425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
490425bb815Sopenharmony_ci  lexer_lit_location_t *literal_p;
491425bb815Sopenharmony_ci  uint16_t status_flags = literal_pool_p->status_flags;
492425bb815Sopenharmony_ci  bool arguments_required = ((status_flags & (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_NO_ARGUMENTS))
493425bb815Sopenharmony_ci                             == SCANNER_LITERAL_POOL_CAN_EVAL);
494425bb815Sopenharmony_ci
495425bb815Sopenharmony_ci  uint8_t can_eval_types = 0;
496425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
497425bb815Sopenharmony_ci  if (prev_literal_pool_p == NULL && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
498425bb815Sopenharmony_ci  {
499425bb815Sopenharmony_ci    can_eval_types |= SCANNER_LITERAL_IS_FUNC;
500425bb815Sopenharmony_ci  }
501425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
502425bb815Sopenharmony_ci
503425bb815Sopenharmony_ci  if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && prev_literal_pool_p != NULL)
504425bb815Sopenharmony_ci  {
505425bb815Sopenharmony_ci    prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
506425bb815Sopenharmony_ci  }
507425bb815Sopenharmony_ci
508425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
509425bb815Sopenharmony_ci  if (scanner_context_p->status_flags & SCANNER_CONTEXT_DEBUGGER_ENABLED)
510425bb815Sopenharmony_ci  {
511425bb815Sopenharmony_ci    /* When debugger is enabled, identifiers are not stored in registers. However,
512425bb815Sopenharmony_ci     * this does not affect 'eval' detection, so 'arguments' object is not created. */
513425bb815Sopenharmony_ci    status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
514425bb815Sopenharmony_ci  }
515425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
516425bb815Sopenharmony_ci
517425bb815Sopenharmony_ci  parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
518425bb815Sopenharmony_ci
519425bb815Sopenharmony_ci  const uint8_t *prev_source_p = literal_pool_p->source_p - 1;
520425bb815Sopenharmony_ci  size_t compressed_size = 1;
521425bb815Sopenharmony_ci  uint32_t no_declarations = literal_pool_p->no_declarations;
522425bb815Sopenharmony_ci
523425bb815Sopenharmony_ci  while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
524425bb815Sopenharmony_ci  {
525425bb815Sopenharmony_ci    uint8_t type = literal_p->type;
526425bb815Sopenharmony_ci
527425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK))
528425bb815Sopenharmony_ci    {
529425bb815Sopenharmony_ci      continue;
530425bb815Sopenharmony_ci    }
531425bb815Sopenharmony_ci
532425bb815Sopenharmony_ci    if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p))
533425bb815Sopenharmony_ci    {
534425bb815Sopenharmony_ci      status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
535425bb815Sopenharmony_ci
536425bb815Sopenharmony_ci      if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL))
537425bb815Sopenharmony_ci      {
538425bb815Sopenharmony_ci        arguments_required = false;
539425bb815Sopenharmony_ci      }
540425bb815Sopenharmony_ci      else
541425bb815Sopenharmony_ci      {
542425bb815Sopenharmony_ci        literal_p->type = 0;
543425bb815Sopenharmony_ci        arguments_required = true;
544425bb815Sopenharmony_ci        continue;
545425bb815Sopenharmony_ci      }
546425bb815Sopenharmony_ci    }
547425bb815Sopenharmony_ci
548425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
549425bb815Sopenharmony_ci    if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
550425bb815Sopenharmony_ci        && (type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION)) == SCANNER_LITERAL_IS_FUNC)
551425bb815Sopenharmony_ci    {
552425bb815Sopenharmony_ci      if (prev_literal_pool_p == NULL
553425bb815Sopenharmony_ci          && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
554425bb815Sopenharmony_ci          && scanner_scope_find_let_declaration (context_p, literal_p))
555425bb815Sopenharmony_ci      {
556425bb815Sopenharmony_ci        literal_p->type = 0;
557425bb815Sopenharmony_ci        continue;
558425bb815Sopenharmony_ci      }
559425bb815Sopenharmony_ci
560425bb815Sopenharmony_ci      if (!(type & SCANNER_LITERAL_IS_ARG))
561425bb815Sopenharmony_ci      {
562425bb815Sopenharmony_ci        type |= SCANNER_LITERAL_IS_VAR;
563425bb815Sopenharmony_ci      }
564425bb815Sopenharmony_ci
565425bb815Sopenharmony_ci      type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
566425bb815Sopenharmony_ci      literal_p->type = type;
567425bb815Sopenharmony_ci    }
568425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
569425bb815Sopenharmony_ci
570425bb815Sopenharmony_ci    if ((type & SCANNER_LITERAL_IS_LOCAL)
571425bb815Sopenharmony_ci        || ((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
572425bb815Sopenharmony_ci            && (status_flags & SCANNER_LITERAL_POOL_FUNCTION)))
573425bb815Sopenharmony_ci    {
574425bb815Sopenharmony_ci      JERRY_ASSERT ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
575425bb815Sopenharmony_ci                    || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
576425bb815Sopenharmony_ci
577425bb815Sopenharmony_ci      if (literal_p->length == 0)
578425bb815Sopenharmony_ci      {
579425bb815Sopenharmony_ci        compressed_size += 1;
580425bb815Sopenharmony_ci        continue;
581425bb815Sopenharmony_ci      }
582425bb815Sopenharmony_ci
583425bb815Sopenharmony_ci      no_declarations++;
584425bb815Sopenharmony_ci
585425bb815Sopenharmony_ci      if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) || (type & can_eval_types))
586425bb815Sopenharmony_ci      {
587425bb815Sopenharmony_ci        type |= SCANNER_LITERAL_NO_REG;
588425bb815Sopenharmony_ci        literal_p->type = type;
589425bb815Sopenharmony_ci      }
590425bb815Sopenharmony_ci
591425bb815Sopenharmony_ci      if (type & SCANNER_LITERAL_IS_FUNC)
592425bb815Sopenharmony_ci      {
593425bb815Sopenharmony_ci        no_declarations++;
594425bb815Sopenharmony_ci
595425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
596425bb815Sopenharmony_ci        if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST)
597425bb815Sopenharmony_ci        {
598425bb815Sopenharmony_ci          JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET);
599425bb815Sopenharmony_ci
600425bb815Sopenharmony_ci          /* Catch parameters cannot be functions. */
601425bb815Sopenharmony_ci          literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
602425bb815Sopenharmony_ci          no_declarations--;
603425bb815Sopenharmony_ci        }
604425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
605425bb815Sopenharmony_ci        if (type & SCANNER_LITERAL_IS_LOCAL)
606425bb815Sopenharmony_ci        {
607425bb815Sopenharmony_ci          /* Catch parameters cannot be functions. */
608425bb815Sopenharmony_ci          literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
609425bb815Sopenharmony_ci          no_declarations--;
610425bb815Sopenharmony_ci        }
611425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
612425bb815Sopenharmony_ci      }
613425bb815Sopenharmony_ci
614425bb815Sopenharmony_ci      intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
615425bb815Sopenharmony_ci
616425bb815Sopenharmony_ci      if (diff >= 1 && diff <= UINT8_MAX)
617425bb815Sopenharmony_ci      {
618425bb815Sopenharmony_ci        compressed_size += 2 + 1;
619425bb815Sopenharmony_ci      }
620425bb815Sopenharmony_ci      else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
621425bb815Sopenharmony_ci      {
622425bb815Sopenharmony_ci        compressed_size += 2 + 2;
623425bb815Sopenharmony_ci      }
624425bb815Sopenharmony_ci      else
625425bb815Sopenharmony_ci      {
626425bb815Sopenharmony_ci        compressed_size += 2 + 1 + sizeof (const uint8_t *);
627425bb815Sopenharmony_ci      }
628425bb815Sopenharmony_ci
629425bb815Sopenharmony_ci      prev_source_p = literal_p->char_p + literal_p->length;
630425bb815Sopenharmony_ci
631425bb815Sopenharmony_ci      if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
632425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
633425bb815Sopenharmony_ci          || ((type & SCANNER_LITERAL_IS_FUNC) && (status_flags & SCANNER_LITERAL_POOL_IS_STRICT))
634425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
635425bb815Sopenharmony_ci          || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)))
636425bb815Sopenharmony_ci      {
637425bb815Sopenharmony_ci        continue;
638425bb815Sopenharmony_ci      }
639425bb815Sopenharmony_ci    }
640425bb815Sopenharmony_ci
641425bb815Sopenharmony_ci    if (prev_literal_pool_p != NULL && literal_p->length > 0)
642425bb815Sopenharmony_ci    {
643425bb815Sopenharmony_ci      /* Propagate literal to upper level. */
644425bb815Sopenharmony_ci      lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
645425bb815Sopenharmony_ci                                                                             prev_literal_pool_p,
646425bb815Sopenharmony_ci                                                                             literal_p);
647425bb815Sopenharmony_ci      uint8_t extended_type = literal_location_p->type;
648425bb815Sopenharmony_ci
649425bb815Sopenharmony_ci      if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (type & SCANNER_LITERAL_NO_REG))
650425bb815Sopenharmony_ci      {
651425bb815Sopenharmony_ci        extended_type |= SCANNER_LITERAL_NO_REG;
652425bb815Sopenharmony_ci      }
653425bb815Sopenharmony_ci
654425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
655425bb815Sopenharmony_ci      extended_type |= SCANNER_LITERAL_IS_USED;
656425bb815Sopenharmony_ci
657425bb815Sopenharmony_ci      if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
658425bb815Sopenharmony_ci      {
659425bb815Sopenharmony_ci        extended_type |= SCANNER_LITERAL_EARLY_CREATE;
660425bb815Sopenharmony_ci      }
661425bb815Sopenharmony_ci
662425bb815Sopenharmony_ci      const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL);
663425bb815Sopenharmony_ci
664425bb815Sopenharmony_ci      if ((type & SCANNER_LITERAL_IS_ARG)
665425bb815Sopenharmony_ci          || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET
666425bb815Sopenharmony_ci          || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST)
667425bb815Sopenharmony_ci      {
668425bb815Sopenharmony_ci        /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags
669425bb815Sopenharmony_ci         * for speculative arrow parameters and local (non-var) functions. */
670425bb815Sopenharmony_ci        type = 0;
671425bb815Sopenharmony_ci      }
672425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
673425bb815Sopenharmony_ci
674425bb815Sopenharmony_ci      type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
675425bb815Sopenharmony_ci      JERRY_ASSERT (type == 0 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION));
676425bb815Sopenharmony_ci
677425bb815Sopenharmony_ci      literal_location_p->type = (uint8_t) (extended_type | type);
678425bb815Sopenharmony_ci    }
679425bb815Sopenharmony_ci  }
680425bb815Sopenharmony_ci
681425bb815Sopenharmony_ci  if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (compressed_size > 1))
682425bb815Sopenharmony_ci  {
683425bb815Sopenharmony_ci    compressed_size += sizeof (scanner_info_t);
684425bb815Sopenharmony_ci
685425bb815Sopenharmony_ci    scanner_info_t *info_p;
686425bb815Sopenharmony_ci
687425bb815Sopenharmony_ci    if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL)
688425bb815Sopenharmony_ci    {
689425bb815Sopenharmony_ci      info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size);
690425bb815Sopenharmony_ci    }
691425bb815Sopenharmony_ci    else
692425bb815Sopenharmony_ci    {
693425bb815Sopenharmony_ci      scanner_info_t *start_info_p = scanner_context_p->end_arguments_p;
694425bb815Sopenharmony_ci      info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size);
695425bb815Sopenharmony_ci    }
696425bb815Sopenharmony_ci
697425bb815Sopenharmony_ci    if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
698425bb815Sopenharmony_ci    {
699425bb815Sopenharmony_ci      no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
700425bb815Sopenharmony_ci    }
701425bb815Sopenharmony_ci
702425bb815Sopenharmony_ci    uint8_t *data_p = (uint8_t *) (info_p + 1);
703425bb815Sopenharmony_ci
704425bb815Sopenharmony_ci    if (status_flags & SCANNER_LITERAL_POOL_FUNCTION)
705425bb815Sopenharmony_ci    {
706425bb815Sopenharmony_ci      info_p->type = SCANNER_TYPE_FUNCTION;
707425bb815Sopenharmony_ci
708425bb815Sopenharmony_ci      uint8_t u8_arg = 0;
709425bb815Sopenharmony_ci
710425bb815Sopenharmony_ci      if (arguments_required)
711425bb815Sopenharmony_ci      {
712425bb815Sopenharmony_ci        u8_arg |= SCANNER_FUNCTION_ARGUMENTS_NEEDED;
713425bb815Sopenharmony_ci
714425bb815Sopenharmony_ci        if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
715425bb815Sopenharmony_ci        {
716425bb815Sopenharmony_ci          no_declarations++;
717425bb815Sopenharmony_ci        }
718425bb815Sopenharmony_ci
719425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
720425bb815Sopenharmony_ci        const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT | SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
721425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
722425bb815Sopenharmony_ci        const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT;
723425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
724425bb815Sopenharmony_ci
725425bb815Sopenharmony_ci        if (status_flags & is_unmapped)
726425bb815Sopenharmony_ci        {
727425bb815Sopenharmony_ci          arguments_required = false;
728425bb815Sopenharmony_ci        }
729425bb815Sopenharmony_ci        else
730425bb815Sopenharmony_ci        {
731425bb815Sopenharmony_ci          u8_arg |= SCANNER_FUNCTION_MAPPED_ARGUMENTS;
732425bb815Sopenharmony_ci        }
733425bb815Sopenharmony_ci      }
734425bb815Sopenharmony_ci
735425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
736425bb815Sopenharmony_ci      if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
737425bb815Sopenharmony_ci      {
738425bb815Sopenharmony_ci        u8_arg |= SCANNER_FUNCTION_ASYNC;
739425bb815Sopenharmony_ci
740425bb815Sopenharmony_ci        if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
741425bb815Sopenharmony_ci        {
742425bb815Sopenharmony_ci          u8_arg |= SCANNER_FUNCTION_STATEMENT;
743425bb815Sopenharmony_ci        }
744425bb815Sopenharmony_ci      }
745425bb815Sopenharmony_ci
746425bb815Sopenharmony_ci      if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL)
747425bb815Sopenharmony_ci      {
748425bb815Sopenharmony_ci        u8_arg |= SCANNER_FUNCTION_LEXICAL_ENV_NEEDED;
749425bb815Sopenharmony_ci      }
750425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
751425bb815Sopenharmony_ci
752425bb815Sopenharmony_ci      info_p->u8_arg = u8_arg;
753425bb815Sopenharmony_ci      info_p->u16_arg = (uint16_t) no_declarations;
754425bb815Sopenharmony_ci    }
755425bb815Sopenharmony_ci    else
756425bb815Sopenharmony_ci    {
757425bb815Sopenharmony_ci      info_p->type = SCANNER_TYPE_BLOCK;
758425bb815Sopenharmony_ci
759425bb815Sopenharmony_ci      JERRY_ASSERT (prev_literal_pool_p != NULL);
760425bb815Sopenharmony_ci    }
761425bb815Sopenharmony_ci
762425bb815Sopenharmony_ci    parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
763425bb815Sopenharmony_ci    prev_source_p = literal_pool_p->source_p - 1;
764425bb815Sopenharmony_ci    no_declarations = literal_pool_p->no_declarations;
765425bb815Sopenharmony_ci
766425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
767425bb815Sopenharmony_ci    {
768425bb815Sopenharmony_ci      if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
769425bb815Sopenharmony_ci          || (!(literal_p->type & SCANNER_LITERAL_IS_LOCAL)
770425bb815Sopenharmony_ci              && (!(literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
771425bb815Sopenharmony_ci                  || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION))))
772425bb815Sopenharmony_ci      {
773425bb815Sopenharmony_ci        continue;
774425bb815Sopenharmony_ci      }
775425bb815Sopenharmony_ci
776425bb815Sopenharmony_ci      if (literal_p->length == 0)
777425bb815Sopenharmony_ci      {
778425bb815Sopenharmony_ci        *data_p++ = SCANNER_STREAM_TYPE_HOLE;
779425bb815Sopenharmony_ci        continue;
780425bb815Sopenharmony_ci      }
781425bb815Sopenharmony_ci
782425bb815Sopenharmony_ci      no_declarations++;
783425bb815Sopenharmony_ci
784425bb815Sopenharmony_ci      uint8_t type = SCANNER_STREAM_TYPE_VAR;
785425bb815Sopenharmony_ci
786425bb815Sopenharmony_ci      if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
787425bb815Sopenharmony_ci      {
788425bb815Sopenharmony_ci        no_declarations++;
789425bb815Sopenharmony_ci        type = SCANNER_STREAM_TYPE_FUNC;
790425bb815Sopenharmony_ci
791425bb815Sopenharmony_ci        if (literal_p->type & SCANNER_LITERAL_IS_ARG)
792425bb815Sopenharmony_ci        {
793425bb815Sopenharmony_ci          type = SCANNER_STREAM_TYPE_ARG_FUNC;
794425bb815Sopenharmony_ci
795425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
796425bb815Sopenharmony_ci          if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
797425bb815Sopenharmony_ci          {
798425bb815Sopenharmony_ci            type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC;
799425bb815Sopenharmony_ci          }
800425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
801425bb815Sopenharmony_ci        }
802425bb815Sopenharmony_ci      }
803425bb815Sopenharmony_ci      else if (literal_p->type & SCANNER_LITERAL_IS_ARG)
804425bb815Sopenharmony_ci      {
805425bb815Sopenharmony_ci        type = SCANNER_STREAM_TYPE_ARG;
806425bb815Sopenharmony_ci
807425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
808425bb815Sopenharmony_ci        if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
809425bb815Sopenharmony_ci        {
810425bb815Sopenharmony_ci          type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG;
811425bb815Sopenharmony_ci        }
812425bb815Sopenharmony_ci
813425bb815Sopenharmony_ci        if (literal_p->type & SCANNER_LITERAL_IS_VAR)
814425bb815Sopenharmony_ci        {
815425bb815Sopenharmony_ci          type = (uint8_t) (type + 1);
816425bb815Sopenharmony_ci
817425bb815Sopenharmony_ci          JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR
818425bb815Sopenharmony_ci                        || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR);
819425bb815Sopenharmony_ci        }
820425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
821425bb815Sopenharmony_ci      }
822425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
823425bb815Sopenharmony_ci      else if (literal_p->type & SCANNER_LITERAL_IS_LET)
824425bb815Sopenharmony_ci      {
825425bb815Sopenharmony_ci        if (!(literal_p->type & SCANNER_LITERAL_IS_CONST))
826425bb815Sopenharmony_ci        {
827425bb815Sopenharmony_ci          type = SCANNER_STREAM_TYPE_LET;
828425bb815Sopenharmony_ci
829425bb815Sopenharmony_ci          if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
830425bb815Sopenharmony_ci          {
831425bb815Sopenharmony_ci            literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
832425bb815Sopenharmony_ci          }
833425bb815Sopenharmony_ci        }
834425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
835425bb815Sopenharmony_ci        else if (prev_literal_pool_p == NULL)
836425bb815Sopenharmony_ci        {
837425bb815Sopenharmony_ci          type = SCANNER_STREAM_TYPE_IMPORT;
838425bb815Sopenharmony_ci        }
839425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
840425bb815Sopenharmony_ci        else
841425bb815Sopenharmony_ci        {
842425bb815Sopenharmony_ci          type = SCANNER_STREAM_TYPE_LOCAL;
843425bb815Sopenharmony_ci        }
844425bb815Sopenharmony_ci      }
845425bb815Sopenharmony_ci      else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
846425bb815Sopenharmony_ci      {
847425bb815Sopenharmony_ci        type = SCANNER_STREAM_TYPE_CONST;
848425bb815Sopenharmony_ci
849425bb815Sopenharmony_ci        if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
850425bb815Sopenharmony_ci        {
851425bb815Sopenharmony_ci          literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
852425bb815Sopenharmony_ci        }
853425bb815Sopenharmony_ci      }
854425bb815Sopenharmony_ci
855425bb815Sopenharmony_ci      if (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)
856425bb815Sopenharmony_ci      {
857425bb815Sopenharmony_ci        type |= SCANNER_STREAM_NO_REG | SCANNER_STREAM_EARLY_CREATE;
858425bb815Sopenharmony_ci      }
859425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
860425bb815Sopenharmony_ci
861425bb815Sopenharmony_ci      if (literal_p->has_escape)
862425bb815Sopenharmony_ci      {
863425bb815Sopenharmony_ci        type |= SCANNER_STREAM_HAS_ESCAPE;
864425bb815Sopenharmony_ci      }
865425bb815Sopenharmony_ci
866425bb815Sopenharmony_ci      if ((literal_p->type & SCANNER_LITERAL_NO_REG)
867425bb815Sopenharmony_ci          || (arguments_required && (literal_p->type & SCANNER_LITERAL_IS_ARG)))
868425bb815Sopenharmony_ci      {
869425bb815Sopenharmony_ci        type |= SCANNER_STREAM_NO_REG;
870425bb815Sopenharmony_ci      }
871425bb815Sopenharmony_ci
872425bb815Sopenharmony_ci      data_p[0] = type;
873425bb815Sopenharmony_ci      data_p[1] = (uint8_t) literal_p->length;
874425bb815Sopenharmony_ci      data_p += 3;
875425bb815Sopenharmony_ci
876425bb815Sopenharmony_ci      intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
877425bb815Sopenharmony_ci
878425bb815Sopenharmony_ci      if (diff >= 1 && diff <= UINT8_MAX)
879425bb815Sopenharmony_ci      {
880425bb815Sopenharmony_ci        data_p[-1] = (uint8_t) diff;
881425bb815Sopenharmony_ci      }
882425bb815Sopenharmony_ci      else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
883425bb815Sopenharmony_ci      {
884425bb815Sopenharmony_ci        if (diff < 0)
885425bb815Sopenharmony_ci        {
886425bb815Sopenharmony_ci          diff = -diff;
887425bb815Sopenharmony_ci        }
888425bb815Sopenharmony_ci
889425bb815Sopenharmony_ci        data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
890425bb815Sopenharmony_ci        data_p[-1] = (uint8_t) diff;
891425bb815Sopenharmony_ci        data_p[0] = (uint8_t) (diff >> 8);
892425bb815Sopenharmony_ci        data_p += 1;
893425bb815Sopenharmony_ci      }
894425bb815Sopenharmony_ci      else
895425bb815Sopenharmony_ci      {
896425bb815Sopenharmony_ci        data_p[-1] = 0;
897425bb815Sopenharmony_ci        memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
898425bb815Sopenharmony_ci        data_p += sizeof (const uint8_t *);
899425bb815Sopenharmony_ci      }
900425bb815Sopenharmony_ci
901425bb815Sopenharmony_ci      prev_source_p = literal_p->char_p + literal_p->length;
902425bb815Sopenharmony_ci    }
903425bb815Sopenharmony_ci
904425bb815Sopenharmony_ci    data_p[0] = SCANNER_STREAM_TYPE_END;
905425bb815Sopenharmony_ci
906425bb815Sopenharmony_ci    JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
907425bb815Sopenharmony_ci  }
908425bb815Sopenharmony_ci
909425bb815Sopenharmony_ci  if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION)
910425bb815Sopenharmony_ci      && prev_literal_pool_p->no_declarations < no_declarations)
911425bb815Sopenharmony_ci  {
912425bb815Sopenharmony_ci    prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
913425bb815Sopenharmony_ci  }
914425bb815Sopenharmony_ci
915425bb815Sopenharmony_ci  if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) && prev_literal_pool_p != NULL)
916425bb815Sopenharmony_ci  {
917425bb815Sopenharmony_ci    if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IS_STRICT)
918425bb815Sopenharmony_ci    {
919425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_STRICT;
920425bb815Sopenharmony_ci    }
921425bb815Sopenharmony_ci    else
922425bb815Sopenharmony_ci    {
923425bb815Sopenharmony_ci      context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
924425bb815Sopenharmony_ci    }
925425bb815Sopenharmony_ci
926425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
927425bb815Sopenharmony_ci    if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_GENERATOR)
928425bb815Sopenharmony_ci    {
929425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
930425bb815Sopenharmony_ci    }
931425bb815Sopenharmony_ci    else
932425bb815Sopenharmony_ci    {
933425bb815Sopenharmony_ci      context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
934425bb815Sopenharmony_ci    }
935425bb815Sopenharmony_ci
936425bb815Sopenharmony_ci    if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC)
937425bb815Sopenharmony_ci    {
938425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
939425bb815Sopenharmony_ci    }
940425bb815Sopenharmony_ci    else
941425bb815Sopenharmony_ci    {
942425bb815Sopenharmony_ci      context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
943425bb815Sopenharmony_ci    }
944425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
945425bb815Sopenharmony_ci  }
946425bb815Sopenharmony_ci
947425bb815Sopenharmony_ci  scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
948425bb815Sopenharmony_ci
949425bb815Sopenharmony_ci  parser_list_free (&literal_pool_p->literal_pool);
950425bb815Sopenharmony_ci  scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
951425bb815Sopenharmony_ci} /* scanner_pop_literal_pool */
952425bb815Sopenharmony_ci
953425bb815Sopenharmony_ci/**
954425bb815Sopenharmony_ci * Filter out the arguments from a literal pool.
955425bb815Sopenharmony_ci */
956425bb815Sopenharmony_civoid
957425bb815Sopenharmony_ciscanner_filter_arguments (parser_context_t *context_p, /**< context */
958425bb815Sopenharmony_ci                          scanner_context_t *scanner_context_p) /**< scanner context */
959425bb815Sopenharmony_ci{
960425bb815Sopenharmony_ci  /* Fast case: check whether all literals are arguments. */
961425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
962425bb815Sopenharmony_ci  scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
963425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
964425bb815Sopenharmony_ci  lexer_lit_location_t *literal_p;
965425bb815Sopenharmony_ci  bool can_eval = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) != 0;
966425bb815Sopenharmony_ci  bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
967425bb815Sopenharmony_ci
968425bb815Sopenharmony_ci  if (can_eval && prev_literal_pool_p != NULL)
969425bb815Sopenharmony_ci  {
970425bb815Sopenharmony_ci    prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
971425bb815Sopenharmony_ci  }
972425bb815Sopenharmony_ci
973425bb815Sopenharmony_ci  literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_CAN_EVAL;
974425bb815Sopenharmony_ci
975425bb815Sopenharmony_ci  parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
976425bb815Sopenharmony_ci
977425bb815Sopenharmony_ci  while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
978425bb815Sopenharmony_ci  {
979425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
980425bb815Sopenharmony_ci    if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
981425bb815Sopenharmony_ci    {
982425bb815Sopenharmony_ci      literal_p->type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
983425bb815Sopenharmony_ci    }
984425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
985425bb815Sopenharmony_ci    if (can_eval)
986425bb815Sopenharmony_ci    {
987425bb815Sopenharmony_ci      literal_p->type |= SCANNER_LITERAL_NO_REG;
988425bb815Sopenharmony_ci    }
989425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
990425bb815Sopenharmony_ci
991425bb815Sopenharmony_ci    uint8_t type = literal_p->type;
992425bb815Sopenharmony_ci
993425bb815Sopenharmony_ci    if (!(type & SCANNER_LITERAL_IS_ARG) && !(has_arguments && scanner_literal_is_arguments (literal_p)))
994425bb815Sopenharmony_ci    {
995425bb815Sopenharmony_ci      break;
996425bb815Sopenharmony_ci    }
997425bb815Sopenharmony_ci
998425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
999425bb815Sopenharmony_ci    if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1000425bb815Sopenharmony_ci    {
1001425bb815Sopenharmony_ci      break;
1002425bb815Sopenharmony_ci    }
1003425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1004425bb815Sopenharmony_ci  }
1005425bb815Sopenharmony_ci
1006425bb815Sopenharmony_ci  if (literal_p == NULL)
1007425bb815Sopenharmony_ci  {
1008425bb815Sopenharmony_ci    return;
1009425bb815Sopenharmony_ci  }
1010425bb815Sopenharmony_ci
1011425bb815Sopenharmony_ci  scanner_literal_pool_t *new_literal_pool_p;
1012425bb815Sopenharmony_ci
1013425bb815Sopenharmony_ci  new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
1014425bb815Sopenharmony_ci
1015425bb815Sopenharmony_ci  new_literal_pool_p->prev_p = literal_pool_p;
1016425bb815Sopenharmony_ci  scanner_context_p->active_literal_pool_p = new_literal_pool_p;
1017425bb815Sopenharmony_ci
1018425bb815Sopenharmony_ci  *new_literal_pool_p = *literal_pool_p;
1019425bb815Sopenharmony_ci  parser_list_init (&new_literal_pool_p->literal_pool,
1020425bb815Sopenharmony_ci                    sizeof (lexer_lit_location_t),
1021425bb815Sopenharmony_ci                    (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
1022425bb815Sopenharmony_ci
1023425bb815Sopenharmony_ci  parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1024425bb815Sopenharmony_ci
1025425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1026425bb815Sopenharmony_ci  /* Destructured args are placed after the other arguments because of register assignments. */
1027425bb815Sopenharmony_ci  bool has_destructured_arg = false;
1028425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1029425bb815Sopenharmony_ci
1030425bb815Sopenharmony_ci  while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1031425bb815Sopenharmony_ci  {
1032425bb815Sopenharmony_ci    uint8_t type = literal_p->type;
1033425bb815Sopenharmony_ci
1034425bb815Sopenharmony_ci    if ((type & SCANNER_LITERAL_IS_ARG) || (has_arguments && scanner_literal_is_arguments (literal_p)))
1035425bb815Sopenharmony_ci    {
1036425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1037425bb815Sopenharmony_ci      if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
1038425bb815Sopenharmony_ci      {
1039425bb815Sopenharmony_ci        type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
1040425bb815Sopenharmony_ci        literal_p->type = type;
1041425bb815Sopenharmony_ci      }
1042425bb815Sopenharmony_ci
1043425bb815Sopenharmony_ci      if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1044425bb815Sopenharmony_ci      {
1045425bb815Sopenharmony_ci        has_destructured_arg = true;
1046425bb815Sopenharmony_ci
1047425bb815Sopenharmony_ci        if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
1048425bb815Sopenharmony_ci        {
1049425bb815Sopenharmony_ci          continue;
1050425bb815Sopenharmony_ci        }
1051425bb815Sopenharmony_ci
1052425bb815Sopenharmony_ci        type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
1053425bb815Sopenharmony_ci        type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1054425bb815Sopenharmony_ci
1055425bb815Sopenharmony_ci        literal_p->type = type;
1056425bb815Sopenharmony_ci        continue;
1057425bb815Sopenharmony_ci      }
1058425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
1059425bb815Sopenharmony_ci      if (can_eval)
1060425bb815Sopenharmony_ci      {
1061425bb815Sopenharmony_ci        literal_p->type |= SCANNER_LITERAL_NO_REG;
1062425bb815Sopenharmony_ci      }
1063425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1064425bb815Sopenharmony_ci
1065425bb815Sopenharmony_ci      lexer_lit_location_t *new_literal_p;
1066425bb815Sopenharmony_ci      new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1067425bb815Sopenharmony_ci      *new_literal_p = *literal_p;
1068425bb815Sopenharmony_ci    }
1069425bb815Sopenharmony_ci    else if (prev_literal_pool_p != NULL)
1070425bb815Sopenharmony_ci    {
1071425bb815Sopenharmony_ci      /* Propagate literal to upper level. */
1072425bb815Sopenharmony_ci      lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
1073425bb815Sopenharmony_ci                                                                             prev_literal_pool_p,
1074425bb815Sopenharmony_ci                                                                             literal_p);
1075425bb815Sopenharmony_ci      type |= SCANNER_LITERAL_NO_REG;
1076425bb815Sopenharmony_ci
1077425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1078425bb815Sopenharmony_ci      type |= SCANNER_LITERAL_IS_USED;
1079425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1080425bb815Sopenharmony_ci
1081425bb815Sopenharmony_ci      literal_location_p->type |= type;
1082425bb815Sopenharmony_ci    }
1083425bb815Sopenharmony_ci  }
1084425bb815Sopenharmony_ci
1085425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1086425bb815Sopenharmony_ci  if (has_destructured_arg)
1087425bb815Sopenharmony_ci  {
1088425bb815Sopenharmony_ci    parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1089425bb815Sopenharmony_ci
1090425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1091425bb815Sopenharmony_ci    {
1092425bb815Sopenharmony_ci      const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1093425bb815Sopenharmony_ci
1094425bb815Sopenharmony_ci      if ((literal_p->type & expected_flags) == expected_flags)
1095425bb815Sopenharmony_ci      {
1096425bb815Sopenharmony_ci        lexer_lit_location_t *new_literal_p;
1097425bb815Sopenharmony_ci        new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1098425bb815Sopenharmony_ci        *new_literal_p = *literal_p;
1099425bb815Sopenharmony_ci      }
1100425bb815Sopenharmony_ci    }
1101425bb815Sopenharmony_ci  }
1102425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1103425bb815Sopenharmony_ci
1104425bb815Sopenharmony_ci  new_literal_pool_p->prev_p = prev_literal_pool_p;
1105425bb815Sopenharmony_ci
1106425bb815Sopenharmony_ci  parser_list_free (&literal_pool_p->literal_pool);
1107425bb815Sopenharmony_ci  scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
1108425bb815Sopenharmony_ci} /* scanner_filter_arguments */
1109425bb815Sopenharmony_ci
1110425bb815Sopenharmony_ci/**
1111425bb815Sopenharmony_ci * Add any literal to the specified literal pool.
1112425bb815Sopenharmony_ci *
1113425bb815Sopenharmony_ci * @return pointer to the literal
1114425bb815Sopenharmony_ci */
1115425bb815Sopenharmony_cilexer_lit_location_t *
1116425bb815Sopenharmony_ciscanner_add_custom_literal (parser_context_t *context_p, /**< context */
1117425bb815Sopenharmony_ci                            scanner_literal_pool_t *literal_pool_p, /**< literal pool */
1118425bb815Sopenharmony_ci                            const lexer_lit_location_t *literal_location_p) /**< literal */
1119425bb815Sopenharmony_ci{
1120425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
1121425bb815Sopenharmony_ci  parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1122425bb815Sopenharmony_ci  lexer_lit_location_t *literal_p;
1123425bb815Sopenharmony_ci
1124425bb815Sopenharmony_ci  const uint8_t *char_p = literal_location_p->char_p;
1125425bb815Sopenharmony_ci  prop_length_t length = literal_location_p->length;
1126425bb815Sopenharmony_ci
1127425bb815Sopenharmony_ci  if (JERRY_LIKELY (!literal_location_p->has_escape))
1128425bb815Sopenharmony_ci  {
1129425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1130425bb815Sopenharmony_ci    {
1131425bb815Sopenharmony_ci      if (literal_p->length == length)
1132425bb815Sopenharmony_ci      {
1133425bb815Sopenharmony_ci        if (JERRY_LIKELY (!literal_p->has_escape))
1134425bb815Sopenharmony_ci        {
1135425bb815Sopenharmony_ci          if (memcmp (literal_p->char_p, char_p, length) == 0)
1136425bb815Sopenharmony_ci          {
1137425bb815Sopenharmony_ci            return literal_p;
1138425bb815Sopenharmony_ci          }
1139425bb815Sopenharmony_ci        }
1140425bb815Sopenharmony_ci        else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1141425bb815Sopenharmony_ci        {
1142425bb815Sopenharmony_ci          /* The non-escaped version is preferred. */
1143425bb815Sopenharmony_ci          literal_p->char_p = char_p;
1144425bb815Sopenharmony_ci          literal_p->has_escape = 0;
1145425bb815Sopenharmony_ci          return literal_p;
1146425bb815Sopenharmony_ci        }
1147425bb815Sopenharmony_ci      }
1148425bb815Sopenharmony_ci    }
1149425bb815Sopenharmony_ci  }
1150425bb815Sopenharmony_ci  else
1151425bb815Sopenharmony_ci  {
1152425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1153425bb815Sopenharmony_ci    {
1154425bb815Sopenharmony_ci      if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1155425bb815Sopenharmony_ci      {
1156425bb815Sopenharmony_ci        return literal_p;
1157425bb815Sopenharmony_ci      }
1158425bb815Sopenharmony_ci    }
1159425bb815Sopenharmony_ci  }
1160425bb815Sopenharmony_ci
1161425bb815Sopenharmony_ci  literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1162425bb815Sopenharmony_ci  *literal_p = *literal_location_p;
1163425bb815Sopenharmony_ci
1164425bb815Sopenharmony_ci  literal_p->type = 0;
1165425bb815Sopenharmony_ci
1166425bb815Sopenharmony_ci  return literal_p;
1167425bb815Sopenharmony_ci} /* scanner_add_custom_literal */
1168425bb815Sopenharmony_ci
1169425bb815Sopenharmony_ci/**
1170425bb815Sopenharmony_ci * Add the current literal token to the current literal pool.
1171425bb815Sopenharmony_ci *
1172425bb815Sopenharmony_ci * @return pointer to the literal
1173425bb815Sopenharmony_ci */
1174425bb815Sopenharmony_ciinline lexer_lit_location_t * JERRY_ATTR_ALWAYS_INLINE
1175425bb815Sopenharmony_ciscanner_add_literal (parser_context_t *context_p, /**< context */
1176425bb815Sopenharmony_ci                     scanner_context_t *scanner_context_p) /**< scanner context */
1177425bb815Sopenharmony_ci{
1178425bb815Sopenharmony_ci  return scanner_add_custom_literal (context_p,
1179425bb815Sopenharmony_ci                                     scanner_context_p->active_literal_pool_p,
1180425bb815Sopenharmony_ci                                     &context_p->token.lit_location);
1181425bb815Sopenharmony_ci} /* scanner_add_literal */
1182425bb815Sopenharmony_ci
1183425bb815Sopenharmony_ci/**
1184425bb815Sopenharmony_ci * Add the current literal token to the current literal pool and
1185425bb815Sopenharmony_ci * set SCANNER_LITERAL_NO_REG if it is inside a with statement.
1186425bb815Sopenharmony_ci *
1187425bb815Sopenharmony_ci * @return pointer to the literal
1188425bb815Sopenharmony_ci */
1189425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
1190425bb815Sopenharmony_ciscanner_add_reference (parser_context_t *context_p, /**< context */
1191425bb815Sopenharmony_ci                       scanner_context_t *scanner_context_p) /**< scanner context */
1192425bb815Sopenharmony_ci{
1193425bb815Sopenharmony_ci  lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
1194425bb815Sopenharmony_ci                                                                     scanner_context_p->active_literal_pool_p,
1195425bb815Sopenharmony_ci                                                                     &context_p->token.lit_location);
1196425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1197425bb815Sopenharmony_ci  lit_location_p->type |= SCANNER_LITERAL_IS_USED;
1198425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1199425bb815Sopenharmony_ci
1200425bb815Sopenharmony_ci  if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
1201425bb815Sopenharmony_ci  {
1202425bb815Sopenharmony_ci    lit_location_p->type |= SCANNER_LITERAL_NO_REG;
1203425bb815Sopenharmony_ci  }
1204425bb815Sopenharmony_ci
1205425bb815Sopenharmony_ci  scanner_detect_eval_call (context_p, scanner_context_p);
1206425bb815Sopenharmony_ci} /* scanner_add_reference */
1207425bb815Sopenharmony_ci
1208425bb815Sopenharmony_ci/**
1209425bb815Sopenharmony_ci * Append an argument to the literal pool. If the argument is already present, make it a "hole".
1210425bb815Sopenharmony_ci *
1211425bb815Sopenharmony_ci * @return newly created literal
1212425bb815Sopenharmony_ci */
1213425bb815Sopenharmony_cilexer_lit_location_t *
1214425bb815Sopenharmony_ciscanner_append_argument (parser_context_t *context_p, /**< context */
1215425bb815Sopenharmony_ci                         scanner_context_t *scanner_context_p) /**< scanner context */
1216425bb815Sopenharmony_ci{
1217425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1218425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
1219425bb815Sopenharmony_ci  parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1220425bb815Sopenharmony_ci  lexer_lit_location_t *literal_location_p = &context_p->token.lit_location;
1221425bb815Sopenharmony_ci  lexer_lit_location_t *literal_p;
1222425bb815Sopenharmony_ci
1223425bb815Sopenharmony_ci  const uint8_t *char_p = literal_location_p->char_p;
1224425bb815Sopenharmony_ci  prop_length_t length = literal_location_p->length;
1225425bb815Sopenharmony_ci
1226425bb815Sopenharmony_ci  if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1227425bb815Sopenharmony_ci  {
1228425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1229425bb815Sopenharmony_ci    {
1230425bb815Sopenharmony_ci      if (literal_p->length == length)
1231425bb815Sopenharmony_ci      {
1232425bb815Sopenharmony_ci        if (JERRY_LIKELY (!literal_p->has_escape))
1233425bb815Sopenharmony_ci        {
1234425bb815Sopenharmony_ci          if (memcmp (literal_p->char_p, char_p, length) == 0)
1235425bb815Sopenharmony_ci          {
1236425bb815Sopenharmony_ci            break;
1237425bb815Sopenharmony_ci          }
1238425bb815Sopenharmony_ci        }
1239425bb815Sopenharmony_ci        else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1240425bb815Sopenharmony_ci        {
1241425bb815Sopenharmony_ci          break;
1242425bb815Sopenharmony_ci        }
1243425bb815Sopenharmony_ci      }
1244425bb815Sopenharmony_ci    }
1245425bb815Sopenharmony_ci  }
1246425bb815Sopenharmony_ci  else
1247425bb815Sopenharmony_ci  {
1248425bb815Sopenharmony_ci    while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1249425bb815Sopenharmony_ci    {
1250425bb815Sopenharmony_ci      if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1251425bb815Sopenharmony_ci      {
1252425bb815Sopenharmony_ci        break;
1253425bb815Sopenharmony_ci      }
1254425bb815Sopenharmony_ci    }
1255425bb815Sopenharmony_ci  }
1256425bb815Sopenharmony_ci
1257425bb815Sopenharmony_ci  uint8_t literal_type = SCANNER_LITERAL_IS_ARG;
1258425bb815Sopenharmony_ci
1259425bb815Sopenharmony_ci  if (literal_p != NULL)
1260425bb815Sopenharmony_ci  {
1261425bb815Sopenharmony_ci    literal_p->length = 0;
1262425bb815Sopenharmony_ci
1263425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1264425bb815Sopenharmony_ci    if (literal_p->type & SCANNER_LITERAL_IS_USED)
1265425bb815Sopenharmony_ci    {
1266425bb815Sopenharmony_ci      literal_type = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_EARLY_CREATE;
1267425bb815Sopenharmony_ci    }
1268425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1269425bb815Sopenharmony_ci  }
1270425bb815Sopenharmony_ci
1271425bb815Sopenharmony_ci  literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1272425bb815Sopenharmony_ci
1273425bb815Sopenharmony_ci  *literal_p = context_p->token.lit_location;
1274425bb815Sopenharmony_ci  literal_p->type = literal_type;
1275425bb815Sopenharmony_ci
1276425bb815Sopenharmony_ci  return literal_p;
1277425bb815Sopenharmony_ci} /* scanner_append_argument */
1278425bb815Sopenharmony_ci
1279425bb815Sopenharmony_ci/**
1280425bb815Sopenharmony_ci * Check whether an eval call is performed and update the status flags accordingly.
1281425bb815Sopenharmony_ci */
1282425bb815Sopenharmony_civoid
1283425bb815Sopenharmony_ciscanner_detect_eval_call (parser_context_t *context_p, /**< context */
1284425bb815Sopenharmony_ci                          scanner_context_t *scanner_context_p) /**< scanner context */
1285425bb815Sopenharmony_ci{
1286425bb815Sopenharmony_ci  if (context_p->token.keyword_type == LEXER_KEYW_EVAL
1287425bb815Sopenharmony_ci      && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
1288425bb815Sopenharmony_ci  {
1289425bb815Sopenharmony_ci    scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
1290425bb815Sopenharmony_ci  }
1291425bb815Sopenharmony_ci} /* scanner_detect_eval_call */
1292425bb815Sopenharmony_ci
1293425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1294425bb815Sopenharmony_ci
1295425bb815Sopenharmony_ci/**
1296425bb815Sopenharmony_ci * Find a let/const declaration of a given literal.
1297425bb815Sopenharmony_ci *
1298425bb815Sopenharmony_ci * @return true - if the literal is found, false - otherwise
1299425bb815Sopenharmony_ci */
1300425bb815Sopenharmony_cibool
1301425bb815Sopenharmony_ciscanner_scope_find_let_declaration (parser_context_t *context_p, /**< context */
1302425bb815Sopenharmony_ci                                    lexer_lit_location_t *literal_p) /**< literal */
1303425bb815Sopenharmony_ci{
1304425bb815Sopenharmony_ci  ecma_string_t *name_p;
1305425bb815Sopenharmony_ci
1306425bb815Sopenharmony_ci  if (JERRY_LIKELY (!literal_p->has_escape))
1307425bb815Sopenharmony_ci  {
1308425bb815Sopenharmony_ci    name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length);
1309425bb815Sopenharmony_ci  }
1310425bb815Sopenharmony_ci  else
1311425bb815Sopenharmony_ci  {
1312425bb815Sopenharmony_ci    uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);
1313425bb815Sopenharmony_ci
1314425bb815Sopenharmony_ci    lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
1315425bb815Sopenharmony_ci
1316425bb815Sopenharmony_ci    name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);
1317425bb815Sopenharmony_ci    scanner_free (destination_p, literal_p->length);
1318425bb815Sopenharmony_ci  }
1319425bb815Sopenharmony_ci
1320425bb815Sopenharmony_ci  ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
1321425bb815Sopenharmony_ci
1322425bb815Sopenharmony_ci  while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
1323425bb815Sopenharmony_ci  {
1324425bb815Sopenharmony_ci    if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1325425bb815Sopenharmony_ci    {
1326425bb815Sopenharmony_ci      ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1327425bb815Sopenharmony_ci
1328425bb815Sopenharmony_ci      if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1329425bb815Sopenharmony_ci      {
1330425bb815Sopenharmony_ci        ecma_deref_ecma_string (name_p);
1331425bb815Sopenharmony_ci        return true;
1332425bb815Sopenharmony_ci      }
1333425bb815Sopenharmony_ci    }
1334425bb815Sopenharmony_ci
1335425bb815Sopenharmony_ci    JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
1336425bb815Sopenharmony_ci    lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
1337425bb815Sopenharmony_ci  }
1338425bb815Sopenharmony_ci
1339425bb815Sopenharmony_ci  if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1340425bb815Sopenharmony_ci  {
1341425bb815Sopenharmony_ci    ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1342425bb815Sopenharmony_ci
1343425bb815Sopenharmony_ci    if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1344425bb815Sopenharmony_ci    {
1345425bb815Sopenharmony_ci      ecma_deref_ecma_string (name_p);
1346425bb815Sopenharmony_ci      return true;
1347425bb815Sopenharmony_ci    }
1348425bb815Sopenharmony_ci  }
1349425bb815Sopenharmony_ci
1350425bb815Sopenharmony_ci  ecma_deref_ecma_string (name_p);
1351425bb815Sopenharmony_ci  return false;
1352425bb815Sopenharmony_ci} /* scanner_scope_find_let_declaration */
1353425bb815Sopenharmony_ci
1354425bb815Sopenharmony_ci/**
1355425bb815Sopenharmony_ci * Throws an error for invalid var statements.
1356425bb815Sopenharmony_ci */
1357425bb815Sopenharmony_civoid
1358425bb815Sopenharmony_ciscanner_detect_invalid_var (parser_context_t *context_p, /**< context */
1359425bb815Sopenharmony_ci                            scanner_context_t *scanner_context_p, /**< scanner context */
1360425bb815Sopenharmony_ci                            lexer_lit_location_t *var_literal_p) /**< var literal */
1361425bb815Sopenharmony_ci{
1362425bb815Sopenharmony_ci  if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL
1363425bb815Sopenharmony_ci      && !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG))
1364425bb815Sopenharmony_ci      && (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL)
1365425bb815Sopenharmony_ci  {
1366425bb815Sopenharmony_ci    scanner_raise_redeclaration_error (context_p);
1367425bb815Sopenharmony_ci  }
1368425bb815Sopenharmony_ci
1369425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1370425bb815Sopenharmony_ci  const uint8_t *char_p = var_literal_p->char_p;
1371425bb815Sopenharmony_ci  prop_length_t length = var_literal_p->length;
1372425bb815Sopenharmony_ci
1373425bb815Sopenharmony_ci  while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION))
1374425bb815Sopenharmony_ci  {
1375425bb815Sopenharmony_ci    literal_pool_p = literal_pool_p->prev_p;
1376425bb815Sopenharmony_ci
1377425bb815Sopenharmony_ci    parser_list_iterator_t literal_iterator;
1378425bb815Sopenharmony_ci    parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1379425bb815Sopenharmony_ci    lexer_lit_location_t *literal_p;
1380425bb815Sopenharmony_ci
1381425bb815Sopenharmony_ci    if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1382425bb815Sopenharmony_ci    {
1383425bb815Sopenharmony_ci      while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1384425bb815Sopenharmony_ci      {
1385425bb815Sopenharmony_ci        if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1386425bb815Sopenharmony_ci            && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1387425bb815Sopenharmony_ci            && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1388425bb815Sopenharmony_ci            && literal_p->length == length)
1389425bb815Sopenharmony_ci        {
1390425bb815Sopenharmony_ci          if (JERRY_LIKELY (!literal_p->has_escape))
1391425bb815Sopenharmony_ci          {
1392425bb815Sopenharmony_ci            if (memcmp (literal_p->char_p, char_p, length) == 0)
1393425bb815Sopenharmony_ci            {
1394425bb815Sopenharmony_ci              scanner_raise_redeclaration_error (context_p);
1395425bb815Sopenharmony_ci              return;
1396425bb815Sopenharmony_ci            }
1397425bb815Sopenharmony_ci          }
1398425bb815Sopenharmony_ci          else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1399425bb815Sopenharmony_ci          {
1400425bb815Sopenharmony_ci            scanner_raise_redeclaration_error (context_p);
1401425bb815Sopenharmony_ci            return;
1402425bb815Sopenharmony_ci          }
1403425bb815Sopenharmony_ci        }
1404425bb815Sopenharmony_ci      }
1405425bb815Sopenharmony_ci    }
1406425bb815Sopenharmony_ci    else
1407425bb815Sopenharmony_ci    {
1408425bb815Sopenharmony_ci      while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1409425bb815Sopenharmony_ci      {
1410425bb815Sopenharmony_ci        if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1411425bb815Sopenharmony_ci            && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1412425bb815Sopenharmony_ci            && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1413425bb815Sopenharmony_ci            && lexer_compare_identifiers (context_p, literal_p, var_literal_p))
1414425bb815Sopenharmony_ci        {
1415425bb815Sopenharmony_ci          scanner_raise_redeclaration_error (context_p);
1416425bb815Sopenharmony_ci          return;
1417425bb815Sopenharmony_ci        }
1418425bb815Sopenharmony_ci      }
1419425bb815Sopenharmony_ci    }
1420425bb815Sopenharmony_ci  }
1421425bb815Sopenharmony_ci
1422425bb815Sopenharmony_ci  if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
1423425bb815Sopenharmony_ci      && scanner_scope_find_let_declaration (context_p, var_literal_p))
1424425bb815Sopenharmony_ci  {
1425425bb815Sopenharmony_ci    scanner_raise_redeclaration_error (context_p);
1426425bb815Sopenharmony_ci  }
1427425bb815Sopenharmony_ci} /* scanner_detect_invalid_var */
1428425bb815Sopenharmony_ci
1429425bb815Sopenharmony_ci/**
1430425bb815Sopenharmony_ci * Throws an error for invalid let statements.
1431425bb815Sopenharmony_ci */
1432425bb815Sopenharmony_civoid
1433425bb815Sopenharmony_ciscanner_detect_invalid_let (parser_context_t *context_p, /**< context */
1434425bb815Sopenharmony_ci                            lexer_lit_location_t *let_literal_p) /**< let literal */
1435425bb815Sopenharmony_ci{
1436425bb815Sopenharmony_ci  if (let_literal_p->type & (SCANNER_LITERAL_IS_ARG
1437425bb815Sopenharmony_ci                             | SCANNER_LITERAL_IS_VAR
1438425bb815Sopenharmony_ci                             | SCANNER_LITERAL_IS_LOCAL))
1439425bb815Sopenharmony_ci  {
1440425bb815Sopenharmony_ci    scanner_raise_redeclaration_error (context_p);
1441425bb815Sopenharmony_ci  }
1442425bb815Sopenharmony_ci
1443425bb815Sopenharmony_ci  if (let_literal_p->type & SCANNER_LITERAL_IS_FUNC)
1444425bb815Sopenharmony_ci  {
1445425bb815Sopenharmony_ci    let_literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
1446425bb815Sopenharmony_ci  }
1447425bb815Sopenharmony_ci} /* scanner_detect_invalid_let */
1448425bb815Sopenharmony_ci
1449425bb815Sopenharmony_ci/**
1450425bb815Sopenharmony_ci * Push the values required for class declaration parsing.
1451425bb815Sopenharmony_ci */
1452425bb815Sopenharmony_civoid
1453425bb815Sopenharmony_ciscanner_push_class_declaration (parser_context_t *context_p, /**< context */
1454425bb815Sopenharmony_ci                                scanner_context_t *scanner_context_p, /* scanner context */
1455425bb815Sopenharmony_ci                                uint8_t stack_mode) /**< stack mode */
1456425bb815Sopenharmony_ci{
1457425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);
1458425bb815Sopenharmony_ci
1459425bb815Sopenharmony_ci  parser_stack_push_uint8 (context_p, stack_mode);
1460425bb815Sopenharmony_ci  scanner_source_start_t source_start;
1461425bb815Sopenharmony_ci  source_start.source_p = context_p->source_p;
1462425bb815Sopenharmony_ci
1463425bb815Sopenharmony_ci  parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1464425bb815Sopenharmony_ci  parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR);
1465425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
1466425bb815Sopenharmony_ci
1467425bb815Sopenharmony_ci  lexer_next_token (context_p);
1468425bb815Sopenharmony_ci} /* scanner_push_class_declaration */
1469425bb815Sopenharmony_ci
1470425bb815Sopenharmony_ci/**
1471425bb815Sopenharmony_ci * Push the values required for destructuring assignment or binding parsing.
1472425bb815Sopenharmony_ci */
1473425bb815Sopenharmony_civoid
1474425bb815Sopenharmony_ciscanner_push_destructuring_pattern (parser_context_t *context_p, /**< context */
1475425bb815Sopenharmony_ci                                    scanner_context_t *scanner_context_p, /**< scanner context */
1476425bb815Sopenharmony_ci                                    uint8_t binding_type, /**< type of destructuring binding pattern */
1477425bb815Sopenharmony_ci                                    bool is_nested) /**< nested declaration */
1478425bb815Sopenharmony_ci{
1479425bb815Sopenharmony_ci  JERRY_ASSERT (binding_type != SCANNER_BINDING_NONE || !is_nested);
1480425bb815Sopenharmony_ci
1481425bb815Sopenharmony_ci  scanner_source_start_t source_start;
1482425bb815Sopenharmony_ci  source_start.source_p = context_p->source_p;
1483425bb815Sopenharmony_ci
1484425bb815Sopenharmony_ci  parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1485425bb815Sopenharmony_ci  parser_stack_push_uint8 (context_p, scanner_context_p->binding_type);
1486425bb815Sopenharmony_ci  scanner_context_p->binding_type = binding_type;
1487425bb815Sopenharmony_ci
1488425bb815Sopenharmony_ci  if (SCANNER_NEEDS_BINDING_LIST (binding_type))
1489425bb815Sopenharmony_ci  {
1490425bb815Sopenharmony_ci    scanner_binding_list_t *binding_list_p;
1491425bb815Sopenharmony_ci    binding_list_p = (scanner_binding_list_t *) scanner_malloc (context_p, sizeof (scanner_binding_list_t));
1492425bb815Sopenharmony_ci
1493425bb815Sopenharmony_ci    binding_list_p->prev_p = scanner_context_p->active_binding_list_p;
1494425bb815Sopenharmony_ci    binding_list_p->items_p = NULL;
1495425bb815Sopenharmony_ci    binding_list_p->is_nested = is_nested;
1496425bb815Sopenharmony_ci
1497425bb815Sopenharmony_ci    scanner_context_p->active_binding_list_p = binding_list_p;
1498425bb815Sopenharmony_ci  }
1499425bb815Sopenharmony_ci} /* scanner_push_destructuring_pattern */
1500425bb815Sopenharmony_ci
1501425bb815Sopenharmony_ci/**
1502425bb815Sopenharmony_ci * Pop binding list.
1503425bb815Sopenharmony_ci */
1504425bb815Sopenharmony_civoid
1505425bb815Sopenharmony_ciscanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner context */
1506425bb815Sopenharmony_ci{
1507425bb815Sopenharmony_ci  scanner_binding_list_t *binding_list_p = scanner_context_p->active_binding_list_p;
1508425bb815Sopenharmony_ci  scanner_binding_item_t *item_p = binding_list_p->items_p;
1509425bb815Sopenharmony_ci  scanner_binding_list_t *prev_binding_list_p = binding_list_p->prev_p;
1510425bb815Sopenharmony_ci  bool is_nested = binding_list_p->is_nested;
1511425bb815Sopenharmony_ci
1512425bb815Sopenharmony_ci  scanner_free (binding_list_p, sizeof (scanner_binding_list_t));
1513425bb815Sopenharmony_ci  scanner_context_p->active_binding_list_p = prev_binding_list_p;
1514425bb815Sopenharmony_ci
1515425bb815Sopenharmony_ci  JERRY_ASSERT (binding_list_p != NULL);
1516425bb815Sopenharmony_ci
1517425bb815Sopenharmony_ci  if (!is_nested)
1518425bb815Sopenharmony_ci  {
1519425bb815Sopenharmony_ci    while (item_p != NULL)
1520425bb815Sopenharmony_ci    {
1521425bb815Sopenharmony_ci      scanner_binding_item_t *next_p = item_p->next_p;
1522425bb815Sopenharmony_ci
1523425bb815Sopenharmony_ci      JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG));
1524425bb815Sopenharmony_ci
1525425bb815Sopenharmony_ci      scanner_free (item_p, sizeof (scanner_binding_item_t));
1526425bb815Sopenharmony_ci      item_p = next_p;
1527425bb815Sopenharmony_ci    }
1528425bb815Sopenharmony_ci    return;
1529425bb815Sopenharmony_ci  }
1530425bb815Sopenharmony_ci
1531425bb815Sopenharmony_ci  JERRY_ASSERT (prev_binding_list_p != NULL);
1532425bb815Sopenharmony_ci
1533425bb815Sopenharmony_ci  while (item_p != NULL)
1534425bb815Sopenharmony_ci  {
1535425bb815Sopenharmony_ci    scanner_binding_item_t *next_p = item_p->next_p;
1536425bb815Sopenharmony_ci
1537425bb815Sopenharmony_ci    item_p->next_p = prev_binding_list_p->items_p;
1538425bb815Sopenharmony_ci    prev_binding_list_p->items_p = item_p;
1539425bb815Sopenharmony_ci
1540425bb815Sopenharmony_ci    item_p = next_p;
1541425bb815Sopenharmony_ci  }
1542425bb815Sopenharmony_ci} /* scanner_pop_binding_list */
1543425bb815Sopenharmony_ci
1544425bb815Sopenharmony_ci/**
1545425bb815Sopenharmony_ci * Append a hole into the literal pool.
1546425bb815Sopenharmony_ci */
1547425bb815Sopenharmony_civoid
1548425bb815Sopenharmony_ciscanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p)
1549425bb815Sopenharmony_ci{
1550425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1551425bb815Sopenharmony_ci
1552425bb815Sopenharmony_ci  lexer_lit_location_t *literal_p;
1553425bb815Sopenharmony_ci  literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1554425bb815Sopenharmony_ci
1555425bb815Sopenharmony_ci  literal_p->char_p = NULL;
1556425bb815Sopenharmony_ci  literal_p->length = 0;
1557425bb815Sopenharmony_ci  literal_p->type = SCANNER_LITERAL_IS_ARG;
1558425bb815Sopenharmony_ci  literal_p->has_escape = 0;
1559425bb815Sopenharmony_ci} /* scanner_append_hole */
1560425bb815Sopenharmony_ci
1561425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1562425bb815Sopenharmony_ci
1563425bb815Sopenharmony_ci/**
1564425bb815Sopenharmony_ci * Reverse the scanner info chain after the scanning is completed.
1565425bb815Sopenharmony_ci */
1566425bb815Sopenharmony_civoid
1567425bb815Sopenharmony_ciscanner_reverse_info_list (parser_context_t *context_p) /**< context */
1568425bb815Sopenharmony_ci{
1569425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1570425bb815Sopenharmony_ci  scanner_info_t *last_scanner_info_p = NULL;
1571425bb815Sopenharmony_ci
1572425bb815Sopenharmony_ci  if (scanner_info_p->type == SCANNER_TYPE_END)
1573425bb815Sopenharmony_ci  {
1574425bb815Sopenharmony_ci    return;
1575425bb815Sopenharmony_ci  }
1576425bb815Sopenharmony_ci
1577425bb815Sopenharmony_ci  do
1578425bb815Sopenharmony_ci  {
1579425bb815Sopenharmony_ci    scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1580425bb815Sopenharmony_ci    scanner_info_p->next_p = last_scanner_info_p;
1581425bb815Sopenharmony_ci
1582425bb815Sopenharmony_ci    last_scanner_info_p = scanner_info_p;
1583425bb815Sopenharmony_ci    scanner_info_p = next_scanner_info_p;
1584425bb815Sopenharmony_ci  }
1585425bb815Sopenharmony_ci  while (scanner_info_p->type != SCANNER_TYPE_END);
1586425bb815Sopenharmony_ci
1587425bb815Sopenharmony_ci  context_p->next_scanner_info_p->next_p = scanner_info_p;
1588425bb815Sopenharmony_ci  context_p->next_scanner_info_p = last_scanner_info_p;
1589425bb815Sopenharmony_ci} /* scanner_reverse_info_list */
1590425bb815Sopenharmony_ci
1591425bb815Sopenharmony_ci/**
1592425bb815Sopenharmony_ci * Release unused scanner info blocks.
1593425bb815Sopenharmony_ci * This should happen only if an error is occured.
1594425bb815Sopenharmony_ci */
1595425bb815Sopenharmony_civoid
1596425bb815Sopenharmony_ciscanner_cleanup (parser_context_t *context_p) /**< context */
1597425bb815Sopenharmony_ci{
1598425bb815Sopenharmony_ci  if (context_p->skipped_scanner_info_p != NULL)
1599425bb815Sopenharmony_ci  {
1600425bb815Sopenharmony_ci    context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
1601425bb815Sopenharmony_ci    context_p->next_scanner_info_p = context_p->skipped_scanner_info_p;
1602425bb815Sopenharmony_ci    context_p->skipped_scanner_info_p = NULL;
1603425bb815Sopenharmony_ci  }
1604425bb815Sopenharmony_ci
1605425bb815Sopenharmony_ci  scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1606425bb815Sopenharmony_ci
1607425bb815Sopenharmony_ci  while (scanner_info_p != NULL)
1608425bb815Sopenharmony_ci  {
1609425bb815Sopenharmony_ci    scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1610425bb815Sopenharmony_ci
1611425bb815Sopenharmony_ci    size_t size = sizeof (scanner_info_t);
1612425bb815Sopenharmony_ci
1613425bb815Sopenharmony_ci    switch (scanner_info_p->type)
1614425bb815Sopenharmony_ci    {
1615425bb815Sopenharmony_ci      case SCANNER_TYPE_END:
1616425bb815Sopenharmony_ci      {
1617425bb815Sopenharmony_ci        scanner_info_p = context_p->active_scanner_info_p;
1618425bb815Sopenharmony_ci        continue;
1619425bb815Sopenharmony_ci      }
1620425bb815Sopenharmony_ci      case SCANNER_TYPE_FUNCTION:
1621425bb815Sopenharmony_ci      case SCANNER_TYPE_BLOCK:
1622425bb815Sopenharmony_ci      {
1623425bb815Sopenharmony_ci        size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
1624425bb815Sopenharmony_ci        break;
1625425bb815Sopenharmony_ci      }
1626425bb815Sopenharmony_ci      case SCANNER_TYPE_WHILE:
1627425bb815Sopenharmony_ci      case SCANNER_TYPE_FOR_IN:
1628425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1629425bb815Sopenharmony_ci      case SCANNER_TYPE_FOR_OF:
1630425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1631425bb815Sopenharmony_ci      case SCANNER_TYPE_CASE:
1632425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1633425bb815Sopenharmony_ci      case SCANNER_TYPE_INITIALIZER:
1634425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1635425bb815Sopenharmony_ci      {
1636425bb815Sopenharmony_ci        size = sizeof (scanner_location_info_t);
1637425bb815Sopenharmony_ci        break;
1638425bb815Sopenharmony_ci      }
1639425bb815Sopenharmony_ci      case SCANNER_TYPE_FOR:
1640425bb815Sopenharmony_ci      {
1641425bb815Sopenharmony_ci        size = sizeof (scanner_for_info_t);
1642425bb815Sopenharmony_ci        break;
1643425bb815Sopenharmony_ci      }
1644425bb815Sopenharmony_ci      case SCANNER_TYPE_SWITCH:
1645425bb815Sopenharmony_ci      {
1646425bb815Sopenharmony_ci        scanner_release_switch_cases (((scanner_switch_info_t *) scanner_info_p)->case_p);
1647425bb815Sopenharmony_ci        size = sizeof (scanner_switch_info_t);
1648425bb815Sopenharmony_ci        break;
1649425bb815Sopenharmony_ci      }
1650425bb815Sopenharmony_ci      default:
1651425bb815Sopenharmony_ci      {
1652425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1653425bb815Sopenharmony_ci        JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
1654425bb815Sopenharmony_ci                      || scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
1655425bb815Sopenharmony_ci                      || scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
1656425bb815Sopenharmony_ci                      || scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
1657425bb815Sopenharmony_ci                      || scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION);
1658425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
1659425bb815Sopenharmony_ci        JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
1660425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1661425bb815Sopenharmony_ci        break;
1662425bb815Sopenharmony_ci      }
1663425bb815Sopenharmony_ci    }
1664425bb815Sopenharmony_ci
1665425bb815Sopenharmony_ci    scanner_free (scanner_info_p, size);
1666425bb815Sopenharmony_ci    scanner_info_p = next_scanner_info_p;
1667425bb815Sopenharmony_ci  }
1668425bb815Sopenharmony_ci
1669425bb815Sopenharmony_ci  context_p->next_scanner_info_p = NULL;
1670425bb815Sopenharmony_ci  context_p->active_scanner_info_p = NULL;
1671425bb815Sopenharmony_ci} /* scanner_cleanup */
1672425bb815Sopenharmony_ci
1673425bb815Sopenharmony_ci/**
1674425bb815Sopenharmony_ci * Checks whether a context needs to be created for a block.
1675425bb815Sopenharmony_ci *
1676425bb815Sopenharmony_ci * @return true - if context is needed,
1677425bb815Sopenharmony_ci *         false - otherwise
1678425bb815Sopenharmony_ci */
1679425bb815Sopenharmony_cibool
1680425bb815Sopenharmony_ciscanner_is_context_needed (parser_context_t *context_p, /**< context */
1681425bb815Sopenharmony_ci                           parser_check_context_type_t check_type) /**< context type */
1682425bb815Sopenharmony_ci{
1683425bb815Sopenharmony_ci  scanner_info_t *info_p = context_p->next_scanner_info_p;
1684425bb815Sopenharmony_ci  const uint8_t *data_p = (const uint8_t *) (info_p + 1);
1685425bb815Sopenharmony_ci
1686425bb815Sopenharmony_ci  JERRY_UNUSED (check_type);
1687425bb815Sopenharmony_ci
1688425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1689425bb815Sopenharmony_ci  JERRY_ASSERT ((check_type == PARSER_CHECK_BLOCK_CONTEXT ? info_p->type == SCANNER_TYPE_BLOCK
1690425bb815Sopenharmony_ci                                                          : info_p->type == SCANNER_TYPE_FUNCTION));
1691425bb815Sopenharmony_ci
1692425bb815Sopenharmony_ci  uint32_t scope_stack_reg_top = (check_type != PARSER_CHECK_GLOBAL_CONTEXT ? context_p->scope_stack_reg_top
1693425bb815Sopenharmony_ci                                                                            : 0);
1694425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
1695425bb815Sopenharmony_ci  JERRY_ASSERT (check_type == PARSER_CHECK_BLOCK_CONTEXT);
1696425bb815Sopenharmony_ci  JERRY_ASSERT (info_p->type == SCANNER_TYPE_BLOCK);
1697425bb815Sopenharmony_ci
1698425bb815Sopenharmony_ci  uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
1699425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
1700425bb815Sopenharmony_ci
1701425bb815Sopenharmony_ci  while (data_p[0] != SCANNER_STREAM_TYPE_END)
1702425bb815Sopenharmony_ci  {
1703425bb815Sopenharmony_ci    uint8_t data = data_p[0];
1704425bb815Sopenharmony_ci
1705425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1706425bb815Sopenharmony_ci    uint32_t type = data & SCANNER_STREAM_TYPE_MASK;
1707425bb815Sopenharmony_ci
1708425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE))
1709425bb815Sopenharmony_ci    {
1710425bb815Sopenharmony_ci      JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1711425bb815Sopenharmony_ci      data_p++;
1712425bb815Sopenharmony_ci      continue;
1713425bb815Sopenharmony_ci    }
1714425bb815Sopenharmony_ci
1715425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
1716425bb815Sopenharmony_ci    if (check_type == PARSER_CHECK_BLOCK_CONTEXT)
1717425bb815Sopenharmony_ci    {
1718425bb815Sopenharmony_ci      JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1719425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LET
1720425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_CONST
1721425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LOCAL
1722425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_FUNC);
1723425bb815Sopenharmony_ci    }
1724425bb815Sopenharmony_ci    else if (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1725425bb815Sopenharmony_ci    {
1726425bb815Sopenharmony_ci      /* FIXME: a private declarative lexical environment should always be present
1727425bb815Sopenharmony_ci       * for modules. Remove SCANNER_STREAM_TYPE_IMPORT after it is implemented. */
1728425bb815Sopenharmony_ci      JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1729425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LET
1730425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_CONST
1731425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_FUNC
1732425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_IMPORT);
1733425bb815Sopenharmony_ci
1734425bb815Sopenharmony_ci      /* Only let/const can be stored in registers */
1735425bb815Sopenharmony_ci      JERRY_ASSERT ((data & SCANNER_STREAM_NO_REG)
1736425bb815Sopenharmony_ci                    || (type == SCANNER_STREAM_TYPE_FUNC && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1737425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LET
1738425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_CONST);
1739425bb815Sopenharmony_ci    }
1740425bb815Sopenharmony_ci    else
1741425bb815Sopenharmony_ci    {
1742425bb815Sopenharmony_ci      JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1743425bb815Sopenharmony_ci
1744425bb815Sopenharmony_ci      JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1745425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LET
1746425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_CONST
1747425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_LOCAL
1748425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_ARG
1749425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_ARG_VAR
1750425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
1751425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
1752425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_ARG_FUNC
1753425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC
1754425bb815Sopenharmony_ci                    || type == SCANNER_STREAM_TYPE_FUNC);
1755425bb815Sopenharmony_ci    }
1756425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
1757425bb815Sopenharmony_ci
1758425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
1759425bb815Sopenharmony_ci    JERRY_ASSERT ((data & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_VAR);
1760425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1761425bb815Sopenharmony_ci
1762425bb815Sopenharmony_ci    if (!(data & SCANNER_STREAM_UINT16_DIFF))
1763425bb815Sopenharmony_ci    {
1764425bb815Sopenharmony_ci      if (data_p[2] != 0)
1765425bb815Sopenharmony_ci      {
1766425bb815Sopenharmony_ci        data_p += 2 + 1;
1767425bb815Sopenharmony_ci      }
1768425bb815Sopenharmony_ci      else
1769425bb815Sopenharmony_ci      {
1770425bb815Sopenharmony_ci        data_p += 2 + 1 + sizeof (const uint8_t *);
1771425bb815Sopenharmony_ci      }
1772425bb815Sopenharmony_ci    }
1773425bb815Sopenharmony_ci    else
1774425bb815Sopenharmony_ci    {
1775425bb815Sopenharmony_ci      data_p += 2 + 2;
1776425bb815Sopenharmony_ci    }
1777425bb815Sopenharmony_ci
1778425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1779425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1780425bb815Sopenharmony_ci        && (type == SCANNER_STREAM_TYPE_VAR
1781425bb815Sopenharmony_ci            || (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1782425bb815Sopenharmony_ci            || type == SCANNER_STREAM_TYPE_IMPORT))
1783425bb815Sopenharmony_ci    {
1784425bb815Sopenharmony_ci      continue;
1785425bb815Sopenharmony_ci    }
1786425bb815Sopenharmony_ci
1787425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT))
1788425bb815Sopenharmony_ci    {
1789425bb815Sopenharmony_ci      if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)
1790425bb815Sopenharmony_ci          || type == SCANNER_STREAM_TYPE_ARG_VAR
1791425bb815Sopenharmony_ci          || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)
1792425bb815Sopenharmony_ci      {
1793425bb815Sopenharmony_ci        /* The return value is true, if the variable is stored in the lexical environment
1794425bb815Sopenharmony_ci         * or all registers have already been used for function arguments. This can be
1795425bb815Sopenharmony_ci         * inprecise in the latter case, but this is a very rare corner case. A more
1796425bb815Sopenharmony_ci         * sophisticated check would require to decode the literal. */
1797425bb815Sopenharmony_ci        if ((data & SCANNER_STREAM_NO_REG)
1798425bb815Sopenharmony_ci            || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1799425bb815Sopenharmony_ci        {
1800425bb815Sopenharmony_ci          return true;
1801425bb815Sopenharmony_ci        }
1802425bb815Sopenharmony_ci        continue;
1803425bb815Sopenharmony_ci      }
1804425bb815Sopenharmony_ci
1805425bb815Sopenharmony_ci      if (SCANNER_STREAM_TYPE_IS_ARG (type))
1806425bb815Sopenharmony_ci      {
1807425bb815Sopenharmony_ci        continue;
1808425bb815Sopenharmony_ci      }
1809425bb815Sopenharmony_ci    }
1810425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1811425bb815Sopenharmony_ci
1812425bb815Sopenharmony_ci    if ((data & SCANNER_STREAM_NO_REG)
1813425bb815Sopenharmony_ci        || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1814425bb815Sopenharmony_ci    {
1815425bb815Sopenharmony_ci      return true;
1816425bb815Sopenharmony_ci    }
1817425bb815Sopenharmony_ci
1818425bb815Sopenharmony_ci    scope_stack_reg_top++;
1819425bb815Sopenharmony_ci  }
1820425bb815Sopenharmony_ci
1821425bb815Sopenharmony_ci  return false;
1822425bb815Sopenharmony_ci} /* scanner_is_context_needed */
1823425bb815Sopenharmony_ci
1824425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1825425bb815Sopenharmony_ci
1826425bb815Sopenharmony_ci/**
1827425bb815Sopenharmony_ci * Try to scan/parse the ".target" part in the "new.target" expression.
1828425bb815Sopenharmony_ci *
1829425bb815Sopenharmony_ci * Upon exiting with "true" the current token will point to the "target"
1830425bb815Sopenharmony_ci * literal.
1831425bb815Sopenharmony_ci *
1832425bb815Sopenharmony_ci * If the "target" literal is not after the "new." then a scanner/parser
1833425bb815Sopenharmony_ci * error will be raised.
1834425bb815Sopenharmony_ci *
1835425bb815Sopenharmony_ci * @returns true if the ".target" part was found
1836425bb815Sopenharmony_ci *          false if there is no "." after the new.
1837425bb815Sopenharmony_ci */
1838425bb815Sopenharmony_cibool
1839425bb815Sopenharmony_ciscanner_try_scan_new_target (parser_context_t *context_p) /**< parser/scanner context */
1840425bb815Sopenharmony_ci{
1841425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_KEYW_NEW);
1842425bb815Sopenharmony_ci
1843425bb815Sopenharmony_ci  if (lexer_check_next_character (context_p, LIT_CHAR_DOT))
1844425bb815Sopenharmony_ci  {
1845425bb815Sopenharmony_ci    lexer_next_token (context_p);
1846425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_DOT)
1847425bb815Sopenharmony_ci    {
1848425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
1849425bb815Sopenharmony_ci    }
1850425bb815Sopenharmony_ci
1851425bb815Sopenharmony_ci    lexer_next_token (context_p);
1852425bb815Sopenharmony_ci    if (!lexer_token_is_identifier (context_p, "target", 6))
1853425bb815Sopenharmony_ci    {
1854425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_EXPECTED);
1855425bb815Sopenharmony_ci    }
1856425bb815Sopenharmony_ci
1857425bb815Sopenharmony_ci    return true;
1858425bb815Sopenharmony_ci  }
1859425bb815Sopenharmony_ci  return false;
1860425bb815Sopenharmony_ci} /* scanner_try_scan_new_target */
1861425bb815Sopenharmony_ci
1862425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1863425bb815Sopenharmony_ci
1864425bb815Sopenharmony_ci/**
1865425bb815Sopenharmony_ci * Description of "arguments" literal string.
1866425bb815Sopenharmony_ci */
1867425bb815Sopenharmony_ciconst lexer_lit_location_t lexer_arguments_literal =
1868425bb815Sopenharmony_ci{
1869425bb815Sopenharmony_ci  (const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
1870425bb815Sopenharmony_ci};
1871425bb815Sopenharmony_ci
1872425bb815Sopenharmony_ci/**
1873425bb815Sopenharmony_ci * Create an unused literal.
1874425bb815Sopenharmony_ci */
1875425bb815Sopenharmony_cistatic void
1876425bb815Sopenharmony_ciscanner_create_unused_literal (parser_context_t *context_p, /**< context */
1877425bb815Sopenharmony_ci                               uint8_t status_flags) /**< initial status flags */
1878425bb815Sopenharmony_ci{
1879425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
1880425bb815Sopenharmony_ci  {
1881425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
1882425bb815Sopenharmony_ci  }
1883425bb815Sopenharmony_ci
1884425bb815Sopenharmony_ci  lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
1885425bb815Sopenharmony_ci
1886425bb815Sopenharmony_ci  literal_p->type = LEXER_UNUSED_LITERAL;
1887425bb815Sopenharmony_ci  literal_p->status_flags = status_flags;
1888425bb815Sopenharmony_ci
1889425bb815Sopenharmony_ci  context_p->literal_count++;
1890425bb815Sopenharmony_ci} /* scanner_create_unused_literal */
1891425bb815Sopenharmony_ci
1892425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1893425bb815Sopenharmony_ci/**
1894425bb815Sopenharmony_ci * Emit checks for redeclared bindings in the global lexical scope.
1895425bb815Sopenharmony_ci */
1896425bb815Sopenharmony_civoid
1897425bb815Sopenharmony_ciscanner_check_variables (parser_context_t *context_p) /**< context */
1898425bb815Sopenharmony_ci{
1899425bb815Sopenharmony_ci  scanner_info_t *info_p = context_p->next_scanner_info_p;
1900425bb815Sopenharmony_ci  const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1901425bb815Sopenharmony_ci  lexer_lit_location_t literal;
1902425bb815Sopenharmony_ci
1903425bb815Sopenharmony_ci  JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
1904425bb815Sopenharmony_ci
1905425bb815Sopenharmony_ci  literal.char_p = info_p->source_p - 1;
1906425bb815Sopenharmony_ci
1907425bb815Sopenharmony_ci  while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
1908425bb815Sopenharmony_ci  {
1909425bb815Sopenharmony_ci    uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
1910425bb815Sopenharmony_ci    const uint8_t *data_p = next_data_p;
1911425bb815Sopenharmony_ci
1912425bb815Sopenharmony_ci    JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE
1913425bb815Sopenharmony_ci                  && !SCANNER_STREAM_TYPE_IS_ARG (type)
1914425bb815Sopenharmony_ci                  && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type));
1915425bb815Sopenharmony_ci    JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
1916425bb815Sopenharmony_ci
1917425bb815Sopenharmony_ci    if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
1918425bb815Sopenharmony_ci    {
1919425bb815Sopenharmony_ci      if (data_p[2] != 0)
1920425bb815Sopenharmony_ci      {
1921425bb815Sopenharmony_ci        literal.char_p += data_p[2];
1922425bb815Sopenharmony_ci        next_data_p += 2 + 1;
1923425bb815Sopenharmony_ci      }
1924425bb815Sopenharmony_ci      else
1925425bb815Sopenharmony_ci      {
1926425bb815Sopenharmony_ci        memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
1927425bb815Sopenharmony_ci        next_data_p += 2 + 1 + sizeof (const uint8_t *);
1928425bb815Sopenharmony_ci      }
1929425bb815Sopenharmony_ci    }
1930425bb815Sopenharmony_ci    else
1931425bb815Sopenharmony_ci    {
1932425bb815Sopenharmony_ci      int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
1933425bb815Sopenharmony_ci
1934425bb815Sopenharmony_ci      if (diff <= UINT8_MAX)
1935425bb815Sopenharmony_ci      {
1936425bb815Sopenharmony_ci        diff = -diff;
1937425bb815Sopenharmony_ci      }
1938425bb815Sopenharmony_ci
1939425bb815Sopenharmony_ci      literal.char_p += diff;
1940425bb815Sopenharmony_ci      next_data_p += 2 + 2;
1941425bb815Sopenharmony_ci    }
1942425bb815Sopenharmony_ci
1943425bb815Sopenharmony_ci    literal.length = data_p[1];
1944425bb815Sopenharmony_ci    literal.type = LEXER_IDENT_LITERAL;
1945425bb815Sopenharmony_ci    literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
1946425bb815Sopenharmony_ci
1947425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
1948425bb815Sopenharmony_ci    literal.char_p += data_p[1];
1949425bb815Sopenharmony_ci
1950425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1951425bb815Sopenharmony_ci    if (type == SCANNER_STREAM_TYPE_IMPORT)
1952425bb815Sopenharmony_ci    {
1953425bb815Sopenharmony_ci      continue;
1954425bb815Sopenharmony_ci    }
1955425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1956425bb815Sopenharmony_ci
1957425bb815Sopenharmony_ci    context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
1958425bb815Sopenharmony_ci
1959425bb815Sopenharmony_ci    uint16_t opcode;
1960425bb815Sopenharmony_ci    if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC)
1961425bb815Sopenharmony_ci    {
1962425bb815Sopenharmony_ci      opcode = CBC_CHECK_VAR;
1963425bb815Sopenharmony_ci    }
1964425bb815Sopenharmony_ci    else
1965425bb815Sopenharmony_ci    {
1966425bb815Sopenharmony_ci      opcode = CBC_CHECK_LET;
1967425bb815Sopenharmony_ci    }
1968425bb815Sopenharmony_ci
1969425bb815Sopenharmony_ci    parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index);
1970425bb815Sopenharmony_ci  }
1971425bb815Sopenharmony_ci
1972425bb815Sopenharmony_ci  parser_flush_cbc (context_p);
1973425bb815Sopenharmony_ci} /* scanner_check_variables */
1974425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1975425bb815Sopenharmony_ci
1976425bb815Sopenharmony_ci/**
1977425bb815Sopenharmony_ci * Create and/or initialize var/let/const/function/etc. variables.
1978425bb815Sopenharmony_ci */
1979425bb815Sopenharmony_civoid
1980425bb815Sopenharmony_ciscanner_create_variables (parser_context_t *context_p, /**< context */
1981425bb815Sopenharmony_ci                          uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */
1982425bb815Sopenharmony_ci{
1983425bb815Sopenharmony_ci  scanner_info_t *info_p = context_p->next_scanner_info_p;
1984425bb815Sopenharmony_ci  const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1985425bb815Sopenharmony_ci  uint8_t info_type = info_p->type;
1986425bb815Sopenharmony_ci  uint8_t info_u8_arg = info_p->u8_arg;
1987425bb815Sopenharmony_ci  lexer_lit_location_t literal;
1988425bb815Sopenharmony_ci  parser_scope_stack_t *scope_stack_p;
1989425bb815Sopenharmony_ci  parser_scope_stack_t *scope_stack_end_p;
1990425bb815Sopenharmony_ci
1991425bb815Sopenharmony_ci  JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
1992425bb815Sopenharmony_ci  JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
1993425bb815Sopenharmony_ci                || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY));
1994425bb815Sopenharmony_ci  JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION
1995425bb815Sopenharmony_ci                || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY)));
1996425bb815Sopenharmony_ci
1997425bb815Sopenharmony_ci  if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
1998425bb815Sopenharmony_ci  {
1999425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->scope_stack_p == NULL);
2000425bb815Sopenharmony_ci
2001425bb815Sopenharmony_ci    size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack_t);
2002425bb815Sopenharmony_ci    context_p->scope_stack_size = info_p->u16_arg;
2003425bb815Sopenharmony_ci
2004425bb815Sopenharmony_ci    scope_stack_p = NULL;
2005425bb815Sopenharmony_ci
2006425bb815Sopenharmony_ci    if (stack_size > 0)
2007425bb815Sopenharmony_ci    {
2008425bb815Sopenharmony_ci      scope_stack_p = (parser_scope_stack_t *) parser_malloc (context_p, stack_size);
2009425bb815Sopenharmony_ci    }
2010425bb815Sopenharmony_ci
2011425bb815Sopenharmony_ci    context_p->scope_stack_p = scope_stack_p;
2012425bb815Sopenharmony_ci    scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2013425bb815Sopenharmony_ci  }
2014425bb815Sopenharmony_ci  else
2015425bb815Sopenharmony_ci  {
2016425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->scope_stack_p != NULL || context_p->scope_stack_size == 0);
2017425bb815Sopenharmony_ci
2018425bb815Sopenharmony_ci    scope_stack_p = context_p->scope_stack_p;
2019425bb815Sopenharmony_ci    scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2020425bb815Sopenharmony_ci    scope_stack_p += context_p->scope_stack_top;
2021425bb815Sopenharmony_ci  }
2022425bb815Sopenharmony_ci
2023425bb815Sopenharmony_ci  uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
2024425bb815Sopenharmony_ci
2025425bb815Sopenharmony_ci  literal.char_p = info_p->source_p - 1;
2026425bb815Sopenharmony_ci
2027425bb815Sopenharmony_ci  while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
2028425bb815Sopenharmony_ci  {
2029425bb815Sopenharmony_ci    uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
2030425bb815Sopenharmony_ci    const uint8_t *data_p = next_data_p;
2031425bb815Sopenharmony_ci
2032425bb815Sopenharmony_ci    JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2033425bb815Sopenharmony_ci                  || (type != SCANNER_STREAM_TYPE_HOLE
2034425bb815Sopenharmony_ci                      && !SCANNER_STREAM_TYPE_IS_ARG (type)
2035425bb815Sopenharmony_ci                      && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)));
2036425bb815Sopenharmony_ci
2037425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2038425bb815Sopenharmony_ci    JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
2039425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2040425bb815Sopenharmony_ci
2041425bb815Sopenharmony_ci    if (type == SCANNER_STREAM_TYPE_HOLE)
2042425bb815Sopenharmony_ci    {
2043425bb815Sopenharmony_ci      next_data_p++;
2044425bb815Sopenharmony_ci
2045425bb815Sopenharmony_ci      if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2046425bb815Sopenharmony_ci      {
2047425bb815Sopenharmony_ci        continue;
2048425bb815Sopenharmony_ci      }
2049425bb815Sopenharmony_ci
2050425bb815Sopenharmony_ci      if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2051425bb815Sopenharmony_ci      {
2052425bb815Sopenharmony_ci        scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT);
2053425bb815Sopenharmony_ci      }
2054425bb815Sopenharmony_ci
2055425bb815Sopenharmony_ci      if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2056425bb815Sopenharmony_ci      {
2057425bb815Sopenharmony_ci        scope_stack_reg_top++;
2058425bb815Sopenharmony_ci      }
2059425bb815Sopenharmony_ci      continue;
2060425bb815Sopenharmony_ci    }
2061425bb815Sopenharmony_ci
2062425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->scope_stack_size != 0);
2063425bb815Sopenharmony_ci
2064425bb815Sopenharmony_ci    if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
2065425bb815Sopenharmony_ci    {
2066425bb815Sopenharmony_ci      if (data_p[2] != 0)
2067425bb815Sopenharmony_ci      {
2068425bb815Sopenharmony_ci        literal.char_p += data_p[2];
2069425bb815Sopenharmony_ci        next_data_p += 2 + 1;
2070425bb815Sopenharmony_ci      }
2071425bb815Sopenharmony_ci      else
2072425bb815Sopenharmony_ci      {
2073425bb815Sopenharmony_ci        memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
2074425bb815Sopenharmony_ci        next_data_p += 2 + 1 + sizeof (const uint8_t *);
2075425bb815Sopenharmony_ci      }
2076425bb815Sopenharmony_ci    }
2077425bb815Sopenharmony_ci    else
2078425bb815Sopenharmony_ci    {
2079425bb815Sopenharmony_ci      int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
2080425bb815Sopenharmony_ci
2081425bb815Sopenharmony_ci      if (diff <= UINT8_MAX)
2082425bb815Sopenharmony_ci      {
2083425bb815Sopenharmony_ci        diff = -diff;
2084425bb815Sopenharmony_ci      }
2085425bb815Sopenharmony_ci
2086425bb815Sopenharmony_ci      literal.char_p += diff;
2087425bb815Sopenharmony_ci      next_data_p += 2 + 2;
2088425bb815Sopenharmony_ci    }
2089425bb815Sopenharmony_ci
2090425bb815Sopenharmony_ci    if (SCANNER_STREAM_TYPE_IS_ARG (type))
2091425bb815Sopenharmony_ci    {
2092425bb815Sopenharmony_ci      if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2093425bb815Sopenharmony_ci      {
2094425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2095425bb815Sopenharmony_ci        if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2096425bb815Sopenharmony_ci            && (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR))
2097425bb815Sopenharmony_ci        {
2098425bb815Sopenharmony_ci          literal.length = data_p[1];
2099425bb815Sopenharmony_ci          literal.type = LEXER_IDENT_LITERAL;
2100425bb815Sopenharmony_ci          literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2101425bb815Sopenharmony_ci
2102425bb815Sopenharmony_ci          /* Literal must be exists. */
2103425bb815Sopenharmony_ci          lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL);
2104425bb815Sopenharmony_ci
2105425bb815Sopenharmony_ci          if (context_p->lit_object.index < PARSER_REGISTER_START)
2106425bb815Sopenharmony_ci          {
2107425bb815Sopenharmony_ci            parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG);
2108425bb815Sopenharmony_ci          }
2109425bb815Sopenharmony_ci        }
2110425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2111425bb815Sopenharmony_ci
2112425bb815Sopenharmony_ci        literal.char_p += data_p[1];
2113425bb815Sopenharmony_ci        continue;
2114425bb815Sopenharmony_ci      }
2115425bb815Sopenharmony_ci    }
2116425bb815Sopenharmony_ci    else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
2117425bb815Sopenharmony_ci             && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2118425bb815Sopenharmony_ci    {
2119425bb815Sopenharmony_ci      /* Function arguments must come first. */
2120425bb815Sopenharmony_ci      break;
2121425bb815Sopenharmony_ci    }
2122425bb815Sopenharmony_ci
2123425bb815Sopenharmony_ci    literal.length = data_p[1];
2124425bb815Sopenharmony_ci    literal.type = LEXER_IDENT_LITERAL;
2125425bb815Sopenharmony_ci    literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2126425bb815Sopenharmony_ci
2127425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
2128425bb815Sopenharmony_ci    literal.char_p += data_p[1];
2129425bb815Sopenharmony_ci
2130425bb815Sopenharmony_ci    if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
2131425bb815Sopenharmony_ci    {
2132425bb815Sopenharmony_ci      JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
2133425bb815Sopenharmony_ci      JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION);
2134425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2135425bb815Sopenharmony_ci      JERRY_ASSERT (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS));
2136425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2137425bb815Sopenharmony_ci
2138425bb815Sopenharmony_ci      parser_scope_stack_t *function_map_p = scope_stack_p - 2;
2139425bb815Sopenharmony_ci      uint16_t literal_index = context_p->lit_object.index;
2140425bb815Sopenharmony_ci
2141425bb815Sopenharmony_ci      while (literal_index != function_map_p->map_from)
2142425bb815Sopenharmony_ci      {
2143425bb815Sopenharmony_ci        function_map_p--;
2144425bb815Sopenharmony_ci
2145425bb815Sopenharmony_ci        JERRY_ASSERT (function_map_p >= context_p->scope_stack_p);
2146425bb815Sopenharmony_ci      }
2147425bb815Sopenharmony_ci
2148425bb815Sopenharmony_ci      JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
2149425bb815Sopenharmony_ci
2150425bb815Sopenharmony_ci      cbc_opcode_t opcode = CBC_SET_VAR_FUNC;
2151425bb815Sopenharmony_ci
2152425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2153425bb815Sopenharmony_ci      if (JERRY_UNLIKELY (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2154425bb815Sopenharmony_ci          && (function_map_p[0].map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0)
2155425bb815Sopenharmony_ci      {
2156425bb815Sopenharmony_ci        opcode = CBC_INIT_ARG_OR_FUNC;
2157425bb815Sopenharmony_ci      }
2158425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2159425bb815Sopenharmony_ci
2160425bb815Sopenharmony_ci      parser_emit_cbc_literal_value (context_p,
2161425bb815Sopenharmony_ci                                     (uint16_t) opcode,
2162425bb815Sopenharmony_ci                                     function_map_p[1].map_to,
2163425bb815Sopenharmony_ci                                     scanner_decode_map_to (function_map_p));
2164425bb815Sopenharmony_ci      continue;
2165425bb815Sopenharmony_ci    }
2166425bb815Sopenharmony_ci
2167425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2168425bb815Sopenharmony_ci    {
2169425bb815Sopenharmony_ci      JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2170425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2171425bb815Sopenharmony_ci    }
2172425bb815Sopenharmony_ci
2173425bb815Sopenharmony_ci    scope_stack_p->map_from = context_p->lit_object.index;
2174425bb815Sopenharmony_ci
2175425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2176425bb815Sopenharmony_ci    if (info_type == SCANNER_TYPE_FUNCTION)
2177425bb815Sopenharmony_ci    {
2178425bb815Sopenharmony_ci      if (type != SCANNER_STREAM_TYPE_LET
2179425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2180425bb815Sopenharmony_ci          && type != SCANNER_STREAM_TYPE_IMPORT
2181425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2182425bb815Sopenharmony_ci          && type != SCANNER_STREAM_TYPE_CONST)
2183425bb815Sopenharmony_ci      {
2184425bb815Sopenharmony_ci        context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
2185425bb815Sopenharmony_ci      }
2186425bb815Sopenharmony_ci    }
2187425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2188425bb815Sopenharmony_ci
2189425bb815Sopenharmony_ci    uint16_t map_to;
2190425bb815Sopenharmony_ci    uint16_t func_init_opcode = CBC_INIT_ARG_OR_FUNC;
2191425bb815Sopenharmony_ci
2192425bb815Sopenharmony_ci    if (!(data_p[0] & SCANNER_STREAM_NO_REG)
2193425bb815Sopenharmony_ci        && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2194425bb815Sopenharmony_ci    {
2195425bb815Sopenharmony_ci      map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
2196425bb815Sopenharmony_ci
2197425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2198425bb815Sopenharmony_ci      scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1);
2199425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2200425bb815Sopenharmony_ci      scope_stack_p->map_to = map_to;
2201425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2202425bb815Sopenharmony_ci
2203425bb815Sopenharmony_ci      scope_stack_reg_top++;
2204425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2205425bb815Sopenharmony_ci      switch (type)
2206425bb815Sopenharmony_ci      {
2207425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_CONST:
2208425bb815Sopenharmony_ci        {
2209425bb815Sopenharmony_ci          scope_stack_p->map_to |= PARSER_SCOPE_STACK_IS_CONST_REG;
2210425bb815Sopenharmony_ci          /* FALLTHRU */
2211425bb815Sopenharmony_ci        }
2212425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_LET:
2213425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG:
2214425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG_VAR:
2215425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2216425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2217425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG_FUNC:
2218425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2219425bb815Sopenharmony_ci        {
2220425bb815Sopenharmony_ci          scope_stack_p->map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2221425bb815Sopenharmony_ci          break;
2222425bb815Sopenharmony_ci        }
2223425bb815Sopenharmony_ci      }
2224425bb815Sopenharmony_ci
2225425bb815Sopenharmony_ci      func_init_opcode = CBC_SET_VAR_FUNC;
2226425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2227425bb815Sopenharmony_ci    }
2228425bb815Sopenharmony_ci    else
2229425bb815Sopenharmony_ci    {
2230425bb815Sopenharmony_ci      context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
2231425bb815Sopenharmony_ci      map_to = context_p->lit_object.index;
2232425bb815Sopenharmony_ci
2233425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2234425bb815Sopenharmony_ci      uint16_t scope_stack_map_to = 0;
2235425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2236425bb815Sopenharmony_ci      scope_stack_p->map_to = map_to;
2237425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2238425bb815Sopenharmony_ci
2239425bb815Sopenharmony_ci      if (info_type == SCANNER_TYPE_FUNCTION)
2240425bb815Sopenharmony_ci      {
2241425bb815Sopenharmony_ci        context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
2242425bb815Sopenharmony_ci      }
2243425bb815Sopenharmony_ci
2244425bb815Sopenharmony_ci      switch (type)
2245425bb815Sopenharmony_ci      {
2246425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2247425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_LET:
2248425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_CONST:
2249425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2250425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2251425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2252425bb815Sopenharmony_ci        {
2253425bb815Sopenharmony_ci          scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2254425bb815Sopenharmony_ci
2255425bb815Sopenharmony_ci          if (!(data_p[0] & SCANNER_STREAM_EARLY_CREATE))
2256425bb815Sopenharmony_ci          {
2257425bb815Sopenharmony_ci            break;
2258425bb815Sopenharmony_ci          }
2259425bb815Sopenharmony_ci          scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2260425bb815Sopenharmony_ci          /* FALLTHRU */
2261425bb815Sopenharmony_ci        }
2262425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_LOCAL:
2263425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2264425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_VAR:
2265425bb815Sopenharmony_ci        {
2266425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2267425bb815Sopenharmony_ci          context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2268425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2269425bb815Sopenharmony_ci
2270425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2271425bb815Sopenharmony_ci          uint16_t opcode;
2272425bb815Sopenharmony_ci
2273425bb815Sopenharmony_ci          switch (type)
2274425bb815Sopenharmony_ci          {
2275425bb815Sopenharmony_ci            case SCANNER_STREAM_TYPE_LET:
2276425bb815Sopenharmony_ci            {
2277425bb815Sopenharmony_ci              opcode = CBC_CREATE_LET;
2278425bb815Sopenharmony_ci              break;
2279425bb815Sopenharmony_ci            }
2280425bb815Sopenharmony_ci            case SCANNER_STREAM_TYPE_CONST:
2281425bb815Sopenharmony_ci            {
2282425bb815Sopenharmony_ci              opcode = CBC_CREATE_CONST;
2283425bb815Sopenharmony_ci              break;
2284425bb815Sopenharmony_ci            }
2285425bb815Sopenharmony_ci            case SCANNER_STREAM_TYPE_VAR:
2286425bb815Sopenharmony_ci            {
2287425bb815Sopenharmony_ci              opcode = CBC_CREATE_VAR;
2288425bb815Sopenharmony_ci
2289425bb815Sopenharmony_ci              if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT)
2290425bb815Sopenharmony_ci              {
2291425bb815Sopenharmony_ci                opcode = CBC_CREATE_VAR_EVAL;
2292425bb815Sopenharmony_ci
2293425bb815Sopenharmony_ci                if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2294425bb815Sopenharmony_ci                {
2295425bb815Sopenharmony_ci                  opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL);
2296425bb815Sopenharmony_ci                }
2297425bb815Sopenharmony_ci              }
2298425bb815Sopenharmony_ci              break;
2299425bb815Sopenharmony_ci            }
2300425bb815Sopenharmony_ci            default:
2301425bb815Sopenharmony_ci            {
2302425bb815Sopenharmony_ci              JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL
2303425bb815Sopenharmony_ci                            || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
2304425bb815Sopenharmony_ci                            || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
2305425bb815Sopenharmony_ci                            || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC);
2306425bb815Sopenharmony_ci
2307425bb815Sopenharmony_ci              opcode = CBC_CREATE_LOCAL;
2308425bb815Sopenharmony_ci              break;
2309425bb815Sopenharmony_ci            }
2310425bb815Sopenharmony_ci          }
2311425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2312425bb815Sopenharmony_ci          uint16_t opcode = ((option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) ? CBC_CREATE_VAR_EVAL
2313425bb815Sopenharmony_ci                                                                            : CBC_CREATE_VAR);
2314425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2315425bb815Sopenharmony_ci
2316425bb815Sopenharmony_ci          parser_emit_cbc_literal (context_p, opcode, map_to);
2317425bb815Sopenharmony_ci          break;
2318425bb815Sopenharmony_ci        }
2319425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG:
2320425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2321425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG_VAR:
2322425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2323425bb815Sopenharmony_ci        case SCANNER_STREAM_TYPE_ARG_FUNC:
2324425bb815Sopenharmony_ci        {
2325425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2326425bb815Sopenharmony_ci          context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2327425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2328425bb815Sopenharmony_ci
2329425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2330425bb815Sopenharmony_ci          scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2331425bb815Sopenharmony_ci
2332425bb815Sopenharmony_ci          /* Argument initializers of functions with mapped arguments (e.g. function f(a,b,a) {}) are
2333425bb815Sopenharmony_ci           * generated here. The other initializers are handled by parser_parse_function_arguments(). */
2334425bb815Sopenharmony_ci          if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2335425bb815Sopenharmony_ci          {
2336425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2337425bb815Sopenharmony_ci            parser_emit_cbc_literal_value (context_p,
2338425bb815Sopenharmony_ci                                           CBC_INIT_ARG_OR_FUNC,
2339425bb815Sopenharmony_ci                                           (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
2340425bb815Sopenharmony_ci                                           map_to);
2341425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2342425bb815Sopenharmony_ci          }
2343425bb815Sopenharmony_ci          else if (data_p[0] & SCANNER_STREAM_EARLY_CREATE)
2344425bb815Sopenharmony_ci          {
2345425bb815Sopenharmony_ci            parser_emit_cbc_literal (context_p, CBC_CREATE_LOCAL, map_to);
2346425bb815Sopenharmony_ci            scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2347425bb815Sopenharmony_ci          }
2348425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2349425bb815Sopenharmony_ci
2350425bb815Sopenharmony_ci          if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2351425bb815Sopenharmony_ci          {
2352425bb815Sopenharmony_ci            scope_stack_reg_top++;
2353425bb815Sopenharmony_ci          }
2354425bb815Sopenharmony_ci          break;
2355425bb815Sopenharmony_ci        }
2356425bb815Sopenharmony_ci      }
2357425bb815Sopenharmony_ci
2358425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2359425bb815Sopenharmony_ci      scope_stack_p->map_to = scope_stack_map_to;
2360425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2361425bb815Sopenharmony_ci    }
2362425bb815Sopenharmony_ci
2363425bb815Sopenharmony_ci    scope_stack_p++;
2364425bb815Sopenharmony_ci
2365425bb815Sopenharmony_ci    if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
2366425bb815Sopenharmony_ci    {
2367425bb815Sopenharmony_ci      continue;
2368425bb815Sopenharmony_ci    }
2369425bb815Sopenharmony_ci
2370425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2371425bb815Sopenharmony_ci    {
2372425bb815Sopenharmony_ci      JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2373425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2374425bb815Sopenharmony_ci    }
2375425bb815Sopenharmony_ci
2376425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2377425bb815Sopenharmony_ci    context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2378425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2379425bb815Sopenharmony_ci
2380425bb815Sopenharmony_ci    if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2381425bb815Sopenharmony_ci    {
2382425bb815Sopenharmony_ci      if (func_init_opcode == CBC_INIT_ARG_OR_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT))
2383425bb815Sopenharmony_ci      {
2384425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2385425bb815Sopenharmony_ci        literal.char_p -= data_p[1];
2386425bb815Sopenharmony_ci        if (!(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
2387425bb815Sopenharmony_ci            || !scanner_scope_find_let_declaration (context_p, &literal))
2388425bb815Sopenharmony_ci        {
2389425bb815Sopenharmony_ci          func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2390425bb815Sopenharmony_ci
2391425bb815Sopenharmony_ci          if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2392425bb815Sopenharmony_ci          {
2393425bb815Sopenharmony_ci            func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL);
2394425bb815Sopenharmony_ci          }
2395425bb815Sopenharmony_ci        }
2396425bb815Sopenharmony_ci        literal.char_p += data_p[1];
2397425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2398425bb815Sopenharmony_ci        func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2399425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2400425bb815Sopenharmony_ci      }
2401425bb815Sopenharmony_ci
2402425bb815Sopenharmony_ci      parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
2403425bb815Sopenharmony_ci    }
2404425bb815Sopenharmony_ci
2405425bb815Sopenharmony_ci    scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
2406425bb815Sopenharmony_ci    scope_stack_p->map_to = context_p->literal_count;
2407425bb815Sopenharmony_ci    scope_stack_p++;
2408425bb815Sopenharmony_ci
2409425bb815Sopenharmony_ci    scanner_create_unused_literal (context_p, 0);
2410425bb815Sopenharmony_ci  }
2411425bb815Sopenharmony_ci
2412425bb815Sopenharmony_ci  if (info_type == SCANNER_TYPE_FUNCTION
2413425bb815Sopenharmony_ci      && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2414425bb815Sopenharmony_ci      && (info_u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
2415425bb815Sopenharmony_ci  {
2416425bb815Sopenharmony_ci    JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
2417425bb815Sopenharmony_ci
2418425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2419425bb815Sopenharmony_ci    {
2420425bb815Sopenharmony_ci      JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2421425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2422425bb815Sopenharmony_ci    }
2423425bb815Sopenharmony_ci
2424425bb815Sopenharmony_ci    context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED;
2425425bb815Sopenharmony_ci
2426425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p, &lexer_arguments_literal, lexer_arguments_literal.type);
2427425bb815Sopenharmony_ci
2428425bb815Sopenharmony_ci    scope_stack_p->map_from = context_p->lit_object.index;
2429425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2430425bb815Sopenharmony_ci    scope_stack_p->map_to = 0;
2431425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2432425bb815Sopenharmony_ci    scope_stack_p->map_to = context_p->lit_object.index;
2433425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2434425bb815Sopenharmony_ci    scope_stack_p++;
2435425bb815Sopenharmony_ci  }
2436425bb815Sopenharmony_ci
2437425bb815Sopenharmony_ci  context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2438425bb815Sopenharmony_ci  context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
2439425bb815Sopenharmony_ci
2440425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2441425bb815Sopenharmony_ci  if (info_type == SCANNER_TYPE_FUNCTION)
2442425bb815Sopenharmony_ci  {
2443425bb815Sopenharmony_ci    context_p->scope_stack_global_end = context_p->scope_stack_top;
2444425bb815Sopenharmony_ci  }
2445425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2446425bb815Sopenharmony_ci
2447425bb815Sopenharmony_ci  if (context_p->register_count < scope_stack_reg_top)
2448425bb815Sopenharmony_ci  {
2449425bb815Sopenharmony_ci    context_p->register_count = (uint16_t) scope_stack_reg_top;
2450425bb815Sopenharmony_ci  }
2451425bb815Sopenharmony_ci
2452425bb815Sopenharmony_ci  if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2453425bb815Sopenharmony_ci  {
2454425bb815Sopenharmony_ci    scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p)));
2455425bb815Sopenharmony_ci  }
2456425bb815Sopenharmony_ci  parser_flush_cbc (context_p);
2457425bb815Sopenharmony_ci} /* scanner_create_variables */
2458425bb815Sopenharmony_ci
2459425bb815Sopenharmony_ci/**
2460425bb815Sopenharmony_ci * Get location from context.
2461425bb815Sopenharmony_ci */
2462425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
2463425bb815Sopenharmony_ciscanner_get_location (scanner_location_t *location_p, /**< location */
2464425bb815Sopenharmony_ci                      parser_context_t *context_p) /**< context */
2465425bb815Sopenharmony_ci{
2466425bb815Sopenharmony_ci  location_p->source_p = context_p->source_p;
2467425bb815Sopenharmony_ci  location_p->line = context_p->line;
2468425bb815Sopenharmony_ci  location_p->column = context_p->column;
2469425bb815Sopenharmony_ci} /* scanner_get_location */
2470425bb815Sopenharmony_ci
2471425bb815Sopenharmony_ci/**
2472425bb815Sopenharmony_ci * Set context location.
2473425bb815Sopenharmony_ci */
2474425bb815Sopenharmony_ciinline void JERRY_ATTR_ALWAYS_INLINE
2475425bb815Sopenharmony_ciscanner_set_location (parser_context_t *context_p, /**< context */
2476425bb815Sopenharmony_ci                      scanner_location_t *location_p) /**< location */
2477425bb815Sopenharmony_ci{
2478425bb815Sopenharmony_ci  context_p->source_p = location_p->source_p;
2479425bb815Sopenharmony_ci  context_p->line = location_p->line;
2480425bb815Sopenharmony_ci  context_p->column = location_p->column;
2481425bb815Sopenharmony_ci} /* scanner_set_location */
2482425bb815Sopenharmony_ci
2483425bb815Sopenharmony_ci/**
2484425bb815Sopenharmony_ci * Get the real map_to value.
2485425bb815Sopenharmony_ci */
2486425bb815Sopenharmony_ciinline uint16_t JERRY_ATTR_ALWAYS_INLINE
2487425bb815Sopenharmony_ciscanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item */
2488425bb815Sopenharmony_ci{
2489425bb815Sopenharmony_ci  JERRY_ASSERT (stack_item_p->map_from != PARSER_SCOPE_STACK_FUNC);
2490425bb815Sopenharmony_ci
2491425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2492425bb815Sopenharmony_ci  uint16_t value = (stack_item_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK);
2493425bb815Sopenharmony_ci  return (value == 0) ? stack_item_p->map_from : (uint16_t) (value + (PARSER_REGISTER_START - 1));
2494425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2495425bb815Sopenharmony_ci  return stack_item_p->map_to;
2496425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2497425bb815Sopenharmony_ci} /* scanner_decode_map_to */
2498425bb815Sopenharmony_ci
2499425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2500425bb815Sopenharmony_ci
2501425bb815Sopenharmony_ci/**
2502425bb815Sopenharmony_ci * Checks whether the literal is a const in the current scope.
2503425bb815Sopenharmony_ci *
2504425bb815Sopenharmony_ci * @return true if the literal is a const, false otherwise
2505425bb815Sopenharmony_ci */
2506425bb815Sopenharmony_cibool
2507425bb815Sopenharmony_ciscanner_literal_is_const_reg (parser_context_t *context_p, /**< context */
2508425bb815Sopenharmony_ci                              uint16_t literal_index) /**< literal index */
2509425bb815Sopenharmony_ci{
2510425bb815Sopenharmony_ci  if (literal_index < PARSER_REGISTER_START)
2511425bb815Sopenharmony_ci  {
2512425bb815Sopenharmony_ci    /* Re-assignment of non-register const bindings are detected elsewhere. */
2513425bb815Sopenharmony_ci    return false;
2514425bb815Sopenharmony_ci  }
2515425bb815Sopenharmony_ci
2516425bb815Sopenharmony_ci  parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2517425bb815Sopenharmony_ci
2518425bb815Sopenharmony_ci  literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1));
2519425bb815Sopenharmony_ci
2520425bb815Sopenharmony_ci  do
2521425bb815Sopenharmony_ci  {
2522425bb815Sopenharmony_ci    /* Registers must be found in the scope stack. */
2523425bb815Sopenharmony_ci    JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2524425bb815Sopenharmony_ci    scope_stack_p--;
2525425bb815Sopenharmony_ci  }
2526425bb815Sopenharmony_ci  while (literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK));
2527425bb815Sopenharmony_ci
2528425bb815Sopenharmony_ci  return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_CONST_REG) != 0;
2529425bb815Sopenharmony_ci} /* scanner_literal_is_const_reg */
2530425bb815Sopenharmony_ci
2531425bb815Sopenharmony_ci/**
2532425bb815Sopenharmony_ci * Checks whether the literal is created before.
2533425bb815Sopenharmony_ci *
2534425bb815Sopenharmony_ci * @return true if the literal is created before, false otherwise
2535425bb815Sopenharmony_ci */
2536425bb815Sopenharmony_cibool
2537425bb815Sopenharmony_ciscanner_literal_is_created (parser_context_t *context_p, /**< context */
2538425bb815Sopenharmony_ci                            uint16_t literal_index) /**< literal index */
2539425bb815Sopenharmony_ci{
2540425bb815Sopenharmony_ci  JERRY_ASSERT (literal_index < PARSER_REGISTER_START);
2541425bb815Sopenharmony_ci
2542425bb815Sopenharmony_ci  parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2543425bb815Sopenharmony_ci
2544425bb815Sopenharmony_ci  do
2545425bb815Sopenharmony_ci  {
2546425bb815Sopenharmony_ci    /* These literals must be found in the scope stack. */
2547425bb815Sopenharmony_ci    JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2548425bb815Sopenharmony_ci    scope_stack_p--;
2549425bb815Sopenharmony_ci  }
2550425bb815Sopenharmony_ci  while (literal_index != scope_stack_p->map_from);
2551425bb815Sopenharmony_ci
2552425bb815Sopenharmony_ci  JERRY_ASSERT ((scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0);
2553425bb815Sopenharmony_ci
2554425bb815Sopenharmony_ci  return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_LOCAL_CREATED) != 0;
2555425bb815Sopenharmony_ci} /* scanner_literal_is_created */
2556425bb815Sopenharmony_ci
2557425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2558425bb815Sopenharmony_ci
2559425bb815Sopenharmony_ci/**
2560425bb815Sopenharmony_ci * @}
2561425bb815Sopenharmony_ci * @}
2562425bb815Sopenharmony_ci * @}
2563425bb815Sopenharmony_ci */
2564425bb815Sopenharmony_ci
2565425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */
2566