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 "js-parser-internal.h"
17425bb815Sopenharmony_ci
18425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
19425bb815Sopenharmony_ci#include "jcontext.h"
20425bb815Sopenharmony_ci#include "jerryscript-port.h"
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci#include "ecma-function-object.h"
23425bb815Sopenharmony_ci#include "ecma-gc.h"
24425bb815Sopenharmony_ci#include "ecma-globals.h"
25425bb815Sopenharmony_ci#include "ecma-helpers.h"
26425bb815Sopenharmony_ci#include "ecma-lex-env.h"
27425bb815Sopenharmony_ci#include "ecma-module.h"
28425bb815Sopenharmony_ci
29425bb815Sopenharmony_ci/**
30425bb815Sopenharmony_ci * Description of "*default*" literal string.
31425bb815Sopenharmony_ci */
32425bb815Sopenharmony_ciconst lexer_lit_location_t lexer_default_literal =
33425bb815Sopenharmony_ci{
34425bb815Sopenharmony_ci  (const uint8_t *) "*default*", 9, LEXER_IDENT_LITERAL, false
35425bb815Sopenharmony_ci};
36425bb815Sopenharmony_ci
37425bb815Sopenharmony_ci/**
38425bb815Sopenharmony_ci * Check for duplicated imported binding names.
39425bb815Sopenharmony_ci *
40425bb815Sopenharmony_ci * @return true - if the given name is a duplicate
41425bb815Sopenharmony_ci *         false - otherwise
42425bb815Sopenharmony_ci */
43425bb815Sopenharmony_cibool
44425bb815Sopenharmony_ciparser_module_check_duplicate_import (parser_context_t *context_p, /**< parser context */
45425bb815Sopenharmony_ci                                      ecma_string_t *local_name_p) /**< newly imported name */
46425bb815Sopenharmony_ci{
47425bb815Sopenharmony_ci  ecma_module_names_t *module_names_p = context_p->module_current_node_p->module_names_p;
48425bb815Sopenharmony_ci  while (module_names_p != NULL)
49425bb815Sopenharmony_ci  {
50425bb815Sopenharmony_ci    if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p))
51425bb815Sopenharmony_ci    {
52425bb815Sopenharmony_ci      return true;
53425bb815Sopenharmony_ci    }
54425bb815Sopenharmony_ci
55425bb815Sopenharmony_ci    module_names_p = module_names_p->next_p;
56425bb815Sopenharmony_ci  }
57425bb815Sopenharmony_ci
58425bb815Sopenharmony_ci  ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
59425bb815Sopenharmony_ci  while (module_node_p != NULL)
60425bb815Sopenharmony_ci  {
61425bb815Sopenharmony_ci    module_names_p = module_node_p->module_names_p;
62425bb815Sopenharmony_ci
63425bb815Sopenharmony_ci    while (module_names_p != NULL)
64425bb815Sopenharmony_ci    {
65425bb815Sopenharmony_ci      if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p))
66425bb815Sopenharmony_ci      {
67425bb815Sopenharmony_ci        return true;
68425bb815Sopenharmony_ci      }
69425bb815Sopenharmony_ci
70425bb815Sopenharmony_ci      module_names_p = module_names_p->next_p;
71425bb815Sopenharmony_ci    }
72425bb815Sopenharmony_ci
73425bb815Sopenharmony_ci    module_node_p = module_node_p->next_p;
74425bb815Sopenharmony_ci  }
75425bb815Sopenharmony_ci
76425bb815Sopenharmony_ci  return false;
77425bb815Sopenharmony_ci} /* parser_module_check_duplicate_import */
78425bb815Sopenharmony_ci
79425bb815Sopenharmony_ci/**
80425bb815Sopenharmony_ci * Append an identifier to the exported bindings.
81425bb815Sopenharmony_ci */
82425bb815Sopenharmony_civoid
83425bb815Sopenharmony_ciparser_module_append_export_name (parser_context_t *context_p) /**< parser context */
84425bb815Sopenharmony_ci{
85425bb815Sopenharmony_ci  if (!(context_p->status_flags & PARSER_MODULE_STORE_IDENT))
86425bb815Sopenharmony_ci  {
87425bb815Sopenharmony_ci    return;
88425bb815Sopenharmony_ci  }
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_ci  context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
91425bb815Sopenharmony_ci
92425bb815Sopenharmony_ci  ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
93425bb815Sopenharmony_ci                                                          context_p->lit_object.literal_p->prop.length);
94425bb815Sopenharmony_ci
95425bb815Sopenharmony_ci  if (parser_module_check_duplicate_export (context_p, name_p))
96425bb815Sopenharmony_ci  {
97425bb815Sopenharmony_ci    ecma_deref_ecma_string (name_p);
98425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
99425bb815Sopenharmony_ci  }
100425bb815Sopenharmony_ci
101425bb815Sopenharmony_ci  parser_module_add_names_to_node (context_p,
102425bb815Sopenharmony_ci                                   name_p,
103425bb815Sopenharmony_ci                                   name_p);
104425bb815Sopenharmony_ci  ecma_deref_ecma_string (name_p);
105425bb815Sopenharmony_ci} /* parser_module_append_export_name */
106425bb815Sopenharmony_ci
107425bb815Sopenharmony_ci/**
108425bb815Sopenharmony_ci * Check for duplicated exported bindings.
109425bb815Sopenharmony_ci * @return - true - if the exported name is a duplicate
110425bb815Sopenharmony_ci *           false - otherwise
111425bb815Sopenharmony_ci */
112425bb815Sopenharmony_cibool
113425bb815Sopenharmony_ciparser_module_check_duplicate_export (parser_context_t *context_p, /**< parser context */
114425bb815Sopenharmony_ci                                      ecma_string_t *export_name_p) /**< exported identifier */
115425bb815Sopenharmony_ci{
116425bb815Sopenharmony_ci  /* We have to check in the currently constructed node, as well as all of the already added nodes. */
117425bb815Sopenharmony_ci  ecma_module_names_t *current_names_p = context_p->module_current_node_p->module_names_p;
118425bb815Sopenharmony_ci  while (current_names_p != NULL)
119425bb815Sopenharmony_ci  {
120425bb815Sopenharmony_ci    if (ecma_compare_ecma_strings (current_names_p->imex_name_p, export_name_p))
121425bb815Sopenharmony_ci    {
122425bb815Sopenharmony_ci      return true;
123425bb815Sopenharmony_ci    }
124425bb815Sopenharmony_ci    current_names_p = current_names_p->next_p;
125425bb815Sopenharmony_ci  }
126425bb815Sopenharmony_ci
127425bb815Sopenharmony_ci  ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_top_context_p)->local_exports_p;
128425bb815Sopenharmony_ci  if (export_node_p != NULL)
129425bb815Sopenharmony_ci  {
130425bb815Sopenharmony_ci    JERRY_ASSERT (export_node_p->next_p == NULL);
131425bb815Sopenharmony_ci    ecma_module_names_t *name_p = export_node_p->module_names_p;
132425bb815Sopenharmony_ci
133425bb815Sopenharmony_ci    while (name_p != NULL)
134425bb815Sopenharmony_ci    {
135425bb815Sopenharmony_ci      if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
136425bb815Sopenharmony_ci      {
137425bb815Sopenharmony_ci        return true;
138425bb815Sopenharmony_ci      }
139425bb815Sopenharmony_ci
140425bb815Sopenharmony_ci      name_p = name_p->next_p;
141425bb815Sopenharmony_ci    }
142425bb815Sopenharmony_ci  }
143425bb815Sopenharmony_ci
144425bb815Sopenharmony_ci  export_node_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
145425bb815Sopenharmony_ci  while (export_node_p != NULL)
146425bb815Sopenharmony_ci  {
147425bb815Sopenharmony_ci    ecma_module_names_t *name_p = export_node_p->module_names_p;
148425bb815Sopenharmony_ci
149425bb815Sopenharmony_ci    while (name_p != NULL)
150425bb815Sopenharmony_ci    {
151425bb815Sopenharmony_ci      if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
152425bb815Sopenharmony_ci      {
153425bb815Sopenharmony_ci        return true;
154425bb815Sopenharmony_ci      }
155425bb815Sopenharmony_ci
156425bb815Sopenharmony_ci      name_p = name_p->next_p;
157425bb815Sopenharmony_ci    }
158425bb815Sopenharmony_ci
159425bb815Sopenharmony_ci    export_node_p = export_node_p->next_p;
160425bb815Sopenharmony_ci  }
161425bb815Sopenharmony_ci
162425bb815Sopenharmony_ci  /* Star exports don't have any names associated with them, so no need to check those. */
163425bb815Sopenharmony_ci  return false;
164425bb815Sopenharmony_ci} /* parser_module_check_duplicate_export */
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci/**
167425bb815Sopenharmony_ci * Add export node to parser context.
168425bb815Sopenharmony_ci */
169425bb815Sopenharmony_civoid
170425bb815Sopenharmony_ciparser_module_add_export_node_to_context (parser_context_t *context_p) /**< parser context */
171425bb815Sopenharmony_ci{
172425bb815Sopenharmony_ci  ecma_module_node_t *module_node_p = context_p->module_current_node_p;
173425bb815Sopenharmony_ci  context_p->module_current_node_p = NULL;
174425bb815Sopenharmony_ci  ecma_module_node_t **export_list_p;
175425bb815Sopenharmony_ci
176425bb815Sopenharmony_ci  /* Check which list we should add it to. */
177425bb815Sopenharmony_ci  if (module_node_p->module_request_p)
178425bb815Sopenharmony_ci  {
179425bb815Sopenharmony_ci    /* If the export node has a module request, that means it's either an indirect export, or a star export. */
180425bb815Sopenharmony_ci    if (!module_node_p->module_names_p)
181425bb815Sopenharmony_ci    {
182425bb815Sopenharmony_ci      /* If there are no names in the node, then it's a star export. */
183425bb815Sopenharmony_ci      export_list_p = &(JERRY_CONTEXT (module_top_context_p)->star_exports_p);
184425bb815Sopenharmony_ci    }
185425bb815Sopenharmony_ci    else
186425bb815Sopenharmony_ci    {
187425bb815Sopenharmony_ci      export_list_p = &(JERRY_CONTEXT (module_top_context_p)->indirect_exports_p);
188425bb815Sopenharmony_ci    }
189425bb815Sopenharmony_ci  }
190425bb815Sopenharmony_ci  else
191425bb815Sopenharmony_ci  {
192425bb815Sopenharmony_ci    /* If there is no module request, then it's a local export. */
193425bb815Sopenharmony_ci    export_list_p = &(JERRY_CONTEXT (module_top_context_p)->local_exports_p);
194425bb815Sopenharmony_ci  }
195425bb815Sopenharmony_ci
196425bb815Sopenharmony_ci  /* Check if we have a node with the same module request, append to it if we do. */
197425bb815Sopenharmony_ci  ecma_module_node_t *stored_exports_p = *export_list_p;
198425bb815Sopenharmony_ci  while (stored_exports_p != NULL)
199425bb815Sopenharmony_ci  {
200425bb815Sopenharmony_ci    if (stored_exports_p->module_request_p == module_node_p->module_request_p)
201425bb815Sopenharmony_ci    {
202425bb815Sopenharmony_ci      ecma_module_names_t *module_names_p = module_node_p->module_names_p;
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci      if (module_names_p != NULL)
205425bb815Sopenharmony_ci      {
206425bb815Sopenharmony_ci        while (module_names_p->next_p != NULL)
207425bb815Sopenharmony_ci        {
208425bb815Sopenharmony_ci          module_names_p = module_names_p->next_p;
209425bb815Sopenharmony_ci        }
210425bb815Sopenharmony_ci
211425bb815Sopenharmony_ci        module_names_p->next_p = stored_exports_p->module_names_p;
212425bb815Sopenharmony_ci        stored_exports_p->module_names_p = module_node_p->module_names_p;
213425bb815Sopenharmony_ci        module_node_p->module_names_p = NULL;
214425bb815Sopenharmony_ci      }
215425bb815Sopenharmony_ci
216425bb815Sopenharmony_ci      ecma_module_release_module_nodes (module_node_p);
217425bb815Sopenharmony_ci      return;
218425bb815Sopenharmony_ci    }
219425bb815Sopenharmony_ci
220425bb815Sopenharmony_ci    stored_exports_p = stored_exports_p->next_p;
221425bb815Sopenharmony_ci  }
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  module_node_p->next_p = *export_list_p;
224425bb815Sopenharmony_ci  *export_list_p = module_node_p;
225425bb815Sopenharmony_ci} /* parser_module_add_export_node_to_context */
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci/**
228425bb815Sopenharmony_ci * Add import node to parser context.
229425bb815Sopenharmony_ci */
230425bb815Sopenharmony_civoid
231425bb815Sopenharmony_ciparser_module_add_import_node_to_context (parser_context_t *context_p) /**< parser context */
232425bb815Sopenharmony_ci{
233425bb815Sopenharmony_ci  ecma_module_node_t *module_node_p = context_p->module_current_node_p;
234425bb815Sopenharmony_ci  context_p->module_current_node_p = NULL;
235425bb815Sopenharmony_ci  ecma_module_node_t *stored_imports = JERRY_CONTEXT (module_top_context_p)->imports_p;
236425bb815Sopenharmony_ci
237425bb815Sopenharmony_ci  /* Check if we have a node with the same module request, append to it if we do. */
238425bb815Sopenharmony_ci  while (stored_imports != NULL)
239425bb815Sopenharmony_ci  {
240425bb815Sopenharmony_ci    if (stored_imports->module_request_p == module_node_p->module_request_p)
241425bb815Sopenharmony_ci    {
242425bb815Sopenharmony_ci      ecma_module_names_t *module_names_p = module_node_p->module_names_p;
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci      if (module_names_p != NULL)
245425bb815Sopenharmony_ci      {
246425bb815Sopenharmony_ci        while (module_names_p->next_p != NULL)
247425bb815Sopenharmony_ci        {
248425bb815Sopenharmony_ci          module_names_p = module_names_p->next_p;
249425bb815Sopenharmony_ci        }
250425bb815Sopenharmony_ci
251425bb815Sopenharmony_ci        module_names_p->next_p = stored_imports->module_names_p;
252425bb815Sopenharmony_ci        stored_imports->module_names_p = module_node_p->module_names_p;
253425bb815Sopenharmony_ci        module_node_p->module_names_p = NULL;
254425bb815Sopenharmony_ci      }
255425bb815Sopenharmony_ci
256425bb815Sopenharmony_ci      ecma_module_release_module_nodes (module_node_p);
257425bb815Sopenharmony_ci      return;
258425bb815Sopenharmony_ci    }
259425bb815Sopenharmony_ci
260425bb815Sopenharmony_ci    stored_imports = stored_imports->next_p;
261425bb815Sopenharmony_ci  }
262425bb815Sopenharmony_ci
263425bb815Sopenharmony_ci  module_node_p->next_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
264425bb815Sopenharmony_ci  JERRY_CONTEXT (module_top_context_p)->imports_p = module_node_p;
265425bb815Sopenharmony_ci} /* parser_module_add_import_node_to_context */
266425bb815Sopenharmony_ci
267425bb815Sopenharmony_ci/**
268425bb815Sopenharmony_ci * Add module names to current module node.
269425bb815Sopenharmony_ci */
270425bb815Sopenharmony_civoid
271425bb815Sopenharmony_ciparser_module_add_names_to_node (parser_context_t *context_p, /**< parser context */
272425bb815Sopenharmony_ci                                 ecma_string_t *imex_name_p, /**< import/export name */
273425bb815Sopenharmony_ci                                 ecma_string_t *local_name_p) /**< local name */
274425bb815Sopenharmony_ci{
275425bb815Sopenharmony_ci  ecma_module_names_t *new_names_p = (ecma_module_names_t *) parser_malloc (context_p,
276425bb815Sopenharmony_ci                                                                            sizeof (ecma_module_names_t));
277425bb815Sopenharmony_ci  memset (new_names_p, 0, sizeof (ecma_module_names_t));
278425bb815Sopenharmony_ci
279425bb815Sopenharmony_ci  ecma_module_node_t *module_node_p = context_p->module_current_node_p;
280425bb815Sopenharmony_ci  new_names_p->next_p = module_node_p->module_names_p;
281425bb815Sopenharmony_ci  module_node_p->module_names_p = new_names_p;
282425bb815Sopenharmony_ci
283425bb815Sopenharmony_ci  JERRY_ASSERT (imex_name_p != NULL);
284425bb815Sopenharmony_ci  ecma_ref_ecma_string (imex_name_p);
285425bb815Sopenharmony_ci  new_names_p->imex_name_p = imex_name_p;
286425bb815Sopenharmony_ci
287425bb815Sopenharmony_ci  JERRY_ASSERT (local_name_p != NULL);
288425bb815Sopenharmony_ci  ecma_ref_ecma_string (local_name_p);
289425bb815Sopenharmony_ci  new_names_p->local_name_p = local_name_p;
290425bb815Sopenharmony_ci} /* parser_module_add_names_to_node */
291425bb815Sopenharmony_ci
292425bb815Sopenharmony_ci/**
293425bb815Sopenharmony_ci * Create module context if needed.
294425bb815Sopenharmony_ci */
295425bb815Sopenharmony_civoid
296425bb815Sopenharmony_ciparser_module_context_init (void)
297425bb815Sopenharmony_ci{
298425bb815Sopenharmony_ci  if (JERRY_CONTEXT (module_top_context_p) == NULL)
299425bb815Sopenharmony_ci  {
300425bb815Sopenharmony_ci    ecma_module_context_t *module_context_p;
301425bb815Sopenharmony_ci    module_context_p = (ecma_module_context_t *) jmem_heap_alloc_block (sizeof (ecma_module_context_t));
302425bb815Sopenharmony_ci    memset (module_context_p, 0, sizeof (ecma_module_context_t));
303425bb815Sopenharmony_ci    JERRY_CONTEXT (module_top_context_p) = module_context_p;
304425bb815Sopenharmony_ci
305425bb815Sopenharmony_ci    ecma_string_t *path_str_p = ecma_get_string_from_value (JERRY_CONTEXT (resource_name));
306425bb815Sopenharmony_ci
307425bb815Sopenharmony_ci    lit_utf8_size_t path_str_size;
308425bb815Sopenharmony_ci    uint8_t flags = ECMA_STRING_FLAG_EMPTY;
309425bb815Sopenharmony_ci
310425bb815Sopenharmony_ci    const lit_utf8_byte_t *path_str_chars_p = ecma_string_get_chars (path_str_p,
311425bb815Sopenharmony_ci                                                                     &path_str_size,
312425bb815Sopenharmony_ci                                                                     NULL,
313425bb815Sopenharmony_ci                                                                     NULL,
314425bb815Sopenharmony_ci                                                                     &flags);
315425bb815Sopenharmony_ci
316425bb815Sopenharmony_ci    ecma_string_t *path_p = ecma_module_create_normalized_path (path_str_chars_p,
317425bb815Sopenharmony_ci                                                                (prop_length_t) path_str_size);
318425bb815Sopenharmony_ci
319425bb815Sopenharmony_ci    if (path_p == NULL)
320425bb815Sopenharmony_ci    {
321425bb815Sopenharmony_ci      ecma_ref_ecma_string (path_str_p);
322425bb815Sopenharmony_ci      path_p = path_str_p;
323425bb815Sopenharmony_ci    }
324425bb815Sopenharmony_ci
325425bb815Sopenharmony_ci    ecma_module_t *module_p = ecma_module_find_or_create_module (path_p);
326425bb815Sopenharmony_ci
327425bb815Sopenharmony_ci    module_p->state = ECMA_MODULE_STATE_EVALUATED;
328425bb815Sopenharmony_ci    /* The lexical scope of the root module does not exist yet. */
329425bb815Sopenharmony_ci    module_p->scope_p = NULL;
330425bb815Sopenharmony_ci
331425bb815Sopenharmony_ci    module_p->context_p = module_context_p;
332425bb815Sopenharmony_ci    module_context_p->module_p = module_p;
333425bb815Sopenharmony_ci  }
334425bb815Sopenharmony_ci} /* parser_module_context_init */
335425bb815Sopenharmony_ci
336425bb815Sopenharmony_ci/**
337425bb815Sopenharmony_ci * Create a permanent import/export node from a template node.
338425bb815Sopenharmony_ci * @return - the copy of the template if the second parameter is not NULL.
339425bb815Sopenharmony_ci *         - otherwise: an empty node.
340425bb815Sopenharmony_ci */
341425bb815Sopenharmony_ciecma_module_node_t *
342425bb815Sopenharmony_ciparser_module_create_module_node (parser_context_t *context_p) /**< parser context */
343425bb815Sopenharmony_ci{
344425bb815Sopenharmony_ci  ecma_module_node_t *node_p = (ecma_module_node_t *) parser_malloc (context_p, sizeof (ecma_module_node_t));
345425bb815Sopenharmony_ci  memset (node_p, 0, sizeof (ecma_module_node_t));
346425bb815Sopenharmony_ci
347425bb815Sopenharmony_ci  return node_p;
348425bb815Sopenharmony_ci} /* parser_module_create_module_node */
349425bb815Sopenharmony_ci
350425bb815Sopenharmony_ci/**
351425bb815Sopenharmony_ci * Parse an ExportClause.
352425bb815Sopenharmony_ci */
353425bb815Sopenharmony_civoid
354425bb815Sopenharmony_ciparser_module_parse_export_clause (parser_context_t *context_p) /**< parser context */
355425bb815Sopenharmony_ci{
356425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
357425bb815Sopenharmony_ci  lexer_next_token (context_p);
358425bb815Sopenharmony_ci
359425bb815Sopenharmony_ci  while (true)
360425bb815Sopenharmony_ci  {
361425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_RIGHT_BRACE)
362425bb815Sopenharmony_ci    {
363425bb815Sopenharmony_ci      lexer_next_token (context_p);
364425bb815Sopenharmony_ci      break;
365425bb815Sopenharmony_ci    }
366425bb815Sopenharmony_ci
367425bb815Sopenharmony_ci    /* 15.2.3.1 The referenced binding cannot be a reserved word. */
368425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_LITERAL
369425bb815Sopenharmony_ci        || context_p->token.lit_location.type != LEXER_IDENT_LITERAL
370425bb815Sopenharmony_ci        || context_p->token.keyword_type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD)
371425bb815Sopenharmony_ci    {
372425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
373425bb815Sopenharmony_ci    }
374425bb815Sopenharmony_ci
375425bb815Sopenharmony_ci    ecma_string_t *export_name_p = NULL;
376425bb815Sopenharmony_ci    ecma_string_t *local_name_p = NULL;
377425bb815Sopenharmony_ci
378425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
379425bb815Sopenharmony_ci
380425bb815Sopenharmony_ci    uint16_t local_name_index = context_p->lit_object.index;
381425bb815Sopenharmony_ci    uint16_t export_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
382425bb815Sopenharmony_ci
383425bb815Sopenharmony_ci    lexer_next_token (context_p);
384425bb815Sopenharmony_ci    if (lexer_token_is_identifier (context_p, "as", 2))
385425bb815Sopenharmony_ci    {
386425bb815Sopenharmony_ci      lexer_next_token (context_p);
387425bb815Sopenharmony_ci
388425bb815Sopenharmony_ci      if (context_p->token.type != LEXER_LITERAL
389425bb815Sopenharmony_ci          || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
390425bb815Sopenharmony_ci      {
391425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
392425bb815Sopenharmony_ci      }
393425bb815Sopenharmony_ci
394425bb815Sopenharmony_ci      lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
395425bb815Sopenharmony_ci
396425bb815Sopenharmony_ci      export_name_index = context_p->lit_object.index;
397425bb815Sopenharmony_ci
398425bb815Sopenharmony_ci      lexer_next_token (context_p);
399425bb815Sopenharmony_ci    }
400425bb815Sopenharmony_ci
401425bb815Sopenharmony_ci    lexer_literal_t *literal_p = PARSER_GET_LITERAL (local_name_index);
402425bb815Sopenharmony_ci    local_name_p = ecma_new_ecma_string_from_utf8 (literal_p->u.char_p, literal_p->prop.length);
403425bb815Sopenharmony_ci
404425bb815Sopenharmony_ci    if (export_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS)
405425bb815Sopenharmony_ci    {
406425bb815Sopenharmony_ci      lexer_literal_t *as_literal_p = PARSER_GET_LITERAL (export_name_index);
407425bb815Sopenharmony_ci      export_name_p = ecma_new_ecma_string_from_utf8 (as_literal_p->u.char_p, as_literal_p->prop.length);
408425bb815Sopenharmony_ci    }
409425bb815Sopenharmony_ci    else
410425bb815Sopenharmony_ci    {
411425bb815Sopenharmony_ci      export_name_p = local_name_p;
412425bb815Sopenharmony_ci      ecma_ref_ecma_string (local_name_p);
413425bb815Sopenharmony_ci    }
414425bb815Sopenharmony_ci
415425bb815Sopenharmony_ci    if (parser_module_check_duplicate_export (context_p, export_name_p))
416425bb815Sopenharmony_ci    {
417425bb815Sopenharmony_ci      ecma_deref_ecma_string (local_name_p);
418425bb815Sopenharmony_ci      ecma_deref_ecma_string (export_name_p);
419425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
420425bb815Sopenharmony_ci    }
421425bb815Sopenharmony_ci
422425bb815Sopenharmony_ci    parser_module_add_names_to_node (context_p, export_name_p, local_name_p);
423425bb815Sopenharmony_ci    ecma_deref_ecma_string (local_name_p);
424425bb815Sopenharmony_ci    ecma_deref_ecma_string (export_name_p);
425425bb815Sopenharmony_ci
426425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_COMMA
427425bb815Sopenharmony_ci        && context_p->token.type != LEXER_RIGHT_BRACE)
428425bb815Sopenharmony_ci    {
429425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED);
430425bb815Sopenharmony_ci    }
431425bb815Sopenharmony_ci    else if (context_p->token.type == LEXER_COMMA)
432425bb815Sopenharmony_ci    {
433425bb815Sopenharmony_ci      lexer_next_token (context_p);
434425bb815Sopenharmony_ci    }
435425bb815Sopenharmony_ci
436425bb815Sopenharmony_ci    if (lexer_token_is_identifier (context_p, "from", 4))
437425bb815Sopenharmony_ci    {
438425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
439425bb815Sopenharmony_ci    }
440425bb815Sopenharmony_ci  }
441425bb815Sopenharmony_ci} /* parser_module_parse_export_clause */
442425bb815Sopenharmony_ci
443425bb815Sopenharmony_ci/**
444425bb815Sopenharmony_ci * Parse an ImportClause
445425bb815Sopenharmony_ci */
446425bb815Sopenharmony_civoid
447425bb815Sopenharmony_ciparser_module_parse_import_clause (parser_context_t *context_p) /**< parser context */
448425bb815Sopenharmony_ci{
449425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
450425bb815Sopenharmony_ci  lexer_next_token (context_p);
451425bb815Sopenharmony_ci
452425bb815Sopenharmony_ci  while (true)
453425bb815Sopenharmony_ci  {
454425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_RIGHT_BRACE)
455425bb815Sopenharmony_ci    {
456425bb815Sopenharmony_ci      lexer_next_token (context_p);
457425bb815Sopenharmony_ci      break;
458425bb815Sopenharmony_ci    }
459425bb815Sopenharmony_ci
460425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_LITERAL
461425bb815Sopenharmony_ci        || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
462425bb815Sopenharmony_ci    {
463425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
464425bb815Sopenharmony_ci    }
465425bb815Sopenharmony_ci
466425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
467425bb815Sopenharmony_ci    if (context_p->next_scanner_info_p->source_p == context_p->source_p)
468425bb815Sopenharmony_ci    {
469425bb815Sopenharmony_ci      JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
470425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
471425bb815Sopenharmony_ci    }
472425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
473425bb815Sopenharmony_ci
474425bb815Sopenharmony_ci    ecma_string_t *import_name_p = NULL;
475425bb815Sopenharmony_ci    ecma_string_t *local_name_p = NULL;
476425bb815Sopenharmony_ci
477425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
478425bb815Sopenharmony_ci
479425bb815Sopenharmony_ci    uint16_t import_name_index = context_p->lit_object.index;
480425bb815Sopenharmony_ci    uint16_t local_name_index = PARSER_MAXIMUM_NUMBER_OF_LITERALS;
481425bb815Sopenharmony_ci
482425bb815Sopenharmony_ci    lexer_next_token (context_p);
483425bb815Sopenharmony_ci    if (lexer_token_is_identifier (context_p, "as", 2))
484425bb815Sopenharmony_ci    {
485425bb815Sopenharmony_ci      lexer_next_token (context_p);
486425bb815Sopenharmony_ci
487425bb815Sopenharmony_ci      if (context_p->token.type != LEXER_LITERAL
488425bb815Sopenharmony_ci          || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
489425bb815Sopenharmony_ci      {
490425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
491425bb815Sopenharmony_ci      }
492425bb815Sopenharmony_ci
493425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
494425bb815Sopenharmony_ci      if (context_p->next_scanner_info_p->source_p == context_p->source_p)
495425bb815Sopenharmony_ci      {
496425bb815Sopenharmony_ci        JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED);
497425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_VARIABLE_REDECLARED);
498425bb815Sopenharmony_ci      }
499425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
500425bb815Sopenharmony_ci
501425bb815Sopenharmony_ci      lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_NEW_IDENT_LITERAL);
502425bb815Sopenharmony_ci
503425bb815Sopenharmony_ci      local_name_index = context_p->lit_object.index;
504425bb815Sopenharmony_ci
505425bb815Sopenharmony_ci      lexer_next_token (context_p);
506425bb815Sopenharmony_ci    }
507425bb815Sopenharmony_ci
508425bb815Sopenharmony_ci    lexer_literal_t *literal_p = PARSER_GET_LITERAL (import_name_index);
509425bb815Sopenharmony_ci    import_name_p = ecma_new_ecma_string_from_utf8 (literal_p->u.char_p, literal_p->prop.length);
510425bb815Sopenharmony_ci
511425bb815Sopenharmony_ci    if (local_name_index != PARSER_MAXIMUM_NUMBER_OF_LITERALS)
512425bb815Sopenharmony_ci    {
513425bb815Sopenharmony_ci      lexer_literal_t *as_literal_p = PARSER_GET_LITERAL (local_name_index);
514425bb815Sopenharmony_ci      local_name_p = ecma_new_ecma_string_from_utf8 (as_literal_p->u.char_p, as_literal_p->prop.length);
515425bb815Sopenharmony_ci    }
516425bb815Sopenharmony_ci    else
517425bb815Sopenharmony_ci    {
518425bb815Sopenharmony_ci      local_name_p = import_name_p;
519425bb815Sopenharmony_ci      ecma_ref_ecma_string (local_name_p);
520425bb815Sopenharmony_ci    }
521425bb815Sopenharmony_ci
522425bb815Sopenharmony_ci    if (parser_module_check_duplicate_import (context_p, local_name_p))
523425bb815Sopenharmony_ci    {
524425bb815Sopenharmony_ci      ecma_deref_ecma_string (local_name_p);
525425bb815Sopenharmony_ci      ecma_deref_ecma_string (import_name_p);
526425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING);
527425bb815Sopenharmony_ci    }
528425bb815Sopenharmony_ci
529425bb815Sopenharmony_ci    parser_module_add_names_to_node (context_p, import_name_p, local_name_p);
530425bb815Sopenharmony_ci    ecma_deref_ecma_string (local_name_p);
531425bb815Sopenharmony_ci    ecma_deref_ecma_string (import_name_p);
532425bb815Sopenharmony_ci
533425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_COMMA
534425bb815Sopenharmony_ci        && (context_p->token.type != LEXER_RIGHT_BRACE))
535425bb815Sopenharmony_ci    {
536425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED);
537425bb815Sopenharmony_ci    }
538425bb815Sopenharmony_ci    else if (context_p->token.type == LEXER_COMMA)
539425bb815Sopenharmony_ci    {
540425bb815Sopenharmony_ci      lexer_next_token (context_p);
541425bb815Sopenharmony_ci    }
542425bb815Sopenharmony_ci
543425bb815Sopenharmony_ci    if (lexer_token_is_identifier (context_p, "from", 4))
544425bb815Sopenharmony_ci    {
545425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
546425bb815Sopenharmony_ci    }
547425bb815Sopenharmony_ci  }
548425bb815Sopenharmony_ci} /* parser_module_parse_import_clause */
549425bb815Sopenharmony_ci
550425bb815Sopenharmony_ci/**
551425bb815Sopenharmony_ci * Raises parser error if the import or export statement is not in the global scope.
552425bb815Sopenharmony_ci */
553425bb815Sopenharmony_civoid
554425bb815Sopenharmony_ciparser_module_check_request_place (parser_context_t *context_p) /**< parser context */
555425bb815Sopenharmony_ci{
556425bb815Sopenharmony_ci  if (context_p->last_context_p != NULL
557425bb815Sopenharmony_ci      || context_p->stack_top_uint8 != 0
558425bb815Sopenharmony_ci      || (context_p->status_flags & PARSER_IS_FUNCTION)
559425bb815Sopenharmony_ci      || (context_p->global_status_flags & ECMA_PARSE_EVAL))
560425bb815Sopenharmony_ci  {
561425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED);
562425bb815Sopenharmony_ci  }
563425bb815Sopenharmony_ci} /* parser_module_check_request_place */
564425bb815Sopenharmony_ci
565425bb815Sopenharmony_ci/**
566425bb815Sopenharmony_ci * Handle module specifier at the end of the import / export statement.
567425bb815Sopenharmony_ci */
568425bb815Sopenharmony_civoid
569425bb815Sopenharmony_ciparser_module_handle_module_specifier (parser_context_t *context_p) /**< parser context */
570425bb815Sopenharmony_ci{
571425bb815Sopenharmony_ci  ecma_module_node_t *module_node_p = context_p->module_current_node_p;
572425bb815Sopenharmony_ci  if (context_p->token.type != LEXER_LITERAL
573425bb815Sopenharmony_ci      || context_p->token.lit_location.type != LEXER_STRING_LITERAL
574425bb815Sopenharmony_ci      || context_p->token.lit_location.length == 0)
575425bb815Sopenharmony_ci  {
576425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_STRING_EXPECTED);
577425bb815Sopenharmony_ci  }
578425bb815Sopenharmony_ci
579425bb815Sopenharmony_ci  lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
580425bb815Sopenharmony_ci
581425bb815Sopenharmony_ci  ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
582425bb815Sopenharmony_ci                                                          context_p->lit_object.literal_p->prop.length);
583425bb815Sopenharmony_ci
584425bb815Sopenharmony_ci  ecma_module_t *module_p = ecma_module_find_module (name_p);
585425bb815Sopenharmony_ci  if (module_p)
586425bb815Sopenharmony_ci  {
587425bb815Sopenharmony_ci    ecma_deref_ecma_string (name_p);
588425bb815Sopenharmony_ci    goto module_found;
589425bb815Sopenharmony_ci  }
590425bb815Sopenharmony_ci
591425bb815Sopenharmony_ci  ecma_value_t native = jerry_port_get_native_module (ecma_make_string_value (name_p));
592425bb815Sopenharmony_ci
593425bb815Sopenharmony_ci  if (!ecma_is_value_undefined (native))
594425bb815Sopenharmony_ci  {
595425bb815Sopenharmony_ci    JERRY_ASSERT (ecma_is_value_object (native));
596425bb815Sopenharmony_ci    ecma_object_t *module_object_p = ecma_get_object_from_value (native);
597425bb815Sopenharmony_ci
598425bb815Sopenharmony_ci    module_p = ecma_module_create_native_module (name_p, module_object_p);
599425bb815Sopenharmony_ci    goto module_found;
600425bb815Sopenharmony_ci  }
601425bb815Sopenharmony_ci
602425bb815Sopenharmony_ci  ecma_deref_ecma_string (name_p);
603425bb815Sopenharmony_ci  ecma_string_t *path_p = ecma_module_create_normalized_path (context_p->lit_object.literal_p->u.char_p,
604425bb815Sopenharmony_ci                                                              context_p->lit_object.literal_p->prop.length);
605425bb815Sopenharmony_ci
606425bb815Sopenharmony_ci  if (path_p == NULL)
607425bb815Sopenharmony_ci  {
608425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_FILE_NOT_FOUND);
609425bb815Sopenharmony_ci  }
610425bb815Sopenharmony_ci
611425bb815Sopenharmony_ci  module_p = ecma_module_find_or_create_module (path_p);
612425bb815Sopenharmony_ci
613425bb815Sopenharmony_cimodule_found:
614425bb815Sopenharmony_ci  module_node_p->module_request_p = module_p;
615425bb815Sopenharmony_ci  lexer_next_token (context_p);
616425bb815Sopenharmony_ci} /* parser_module_handle_module_specifier */
617425bb815Sopenharmony_ci
618425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
619