Rework ES2015 module system and add missing features. (#2792)
Co-authored-by: Dániel Bátyai <dbatyai@inf.u-szeged.hu> JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu JerryScript-DCO-1.0-Signed-off-by: Daniel Vince vinced@inf.u-szeged.hu
This commit is contained in:
committed by
Robert Fancsik
parent
938e9c7530
commit
37b7645e6a
+17
-1
@@ -85,7 +85,8 @@ void jerry_port_print_char (char c);
|
||||
|
||||
### ES2015 Module system helper functions
|
||||
|
||||
The import statement requires two specific functions for opening and closing files (the modules) port specific.
|
||||
The module system requires two specific functions for opening and closing files.
|
||||
It also requires a platform specific way of normalizing file paths.
|
||||
|
||||
```c
|
||||
/**
|
||||
@@ -108,6 +109,21 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
{
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size) /**< size of output buffer */
|
||||
{
|
||||
// normalize in_path_p by expanding relative paths etc.
|
||||
// write to out_buf_p the normalized path
|
||||
// return length of written path
|
||||
} /* jerry_port_normalize_path */
|
||||
```
|
||||
|
||||
## Date
|
||||
|
||||
+65
-39
@@ -1,34 +1,48 @@
|
||||
# ES6 module support for JerryScript
|
||||
|
||||
The module system allows users to write import and export statements in scripts. Therefore the logic of the application could be separated in custom modules.
|
||||
The module system allows users to write import and export statements in scripts, which can be used to separate the logic of the application into custom modules.
|
||||
The standard's relevant part can be found [here](https://www.ecma-international.org/ecma-262/6.0/#sec-modules).
|
||||
|
||||
## General
|
||||
|
||||
If the main script contains import statements, then Jerry opens and runs the appropriate scripts before the main script (as the standard says). The script's and the module's extension is `.js`, custom extensions are unnecessary.
|
||||
If a script contains import statements, then JerryScript will open and evaluate the the referenced modules before the main script runs, resolving and creating bindings for the referenced identifiers in the process.
|
||||
It is not necessary to use any specific filename extensions for modules, JerryScript will try to open the given file paths as they are, but will try to normalize them before doing so. The exact normalization process is dependant on the port implementation provided. It is the user's responsibility to verify that the given files are valid EcmaScript modules.
|
||||
|
||||
main.js
|
||||
|
||||
```js
|
||||
import { secret_number } from "./module.js"
|
||||
import { exported_value } from "./module.js"
|
||||
|
||||
print (secret_number);
|
||||
print (exported_value);
|
||||
```
|
||||
|
||||
module.js
|
||||
|
||||
```js
|
||||
var secret_number = 42;
|
||||
var exported_value = 42;
|
||||
|
||||
export secret_number;
|
||||
export exported_value;
|
||||
```
|
||||
|
||||
## Supported features
|
||||
|
||||
* import variable or function
|
||||
* add alias name to the imported variable (function)
|
||||
* export variable or function
|
||||
* add alias name to the exported variable (function)
|
||||
* exporting identifiers from the module's lexical environment
|
||||
* specifying export names for the exported values
|
||||
* importing exported identifiers from a module
|
||||
* specifying local binding names for the imported values
|
||||
* module namespace imports
|
||||
* `import * as module from 'module.js`
|
||||
* indirect export statements
|
||||
* `export {variable} from 'module.js'`
|
||||
* star export statements
|
||||
* `export * from 'module.js'`
|
||||
* importing a module for side-effects
|
||||
* `import 'module.js'`
|
||||
* default import and export statements
|
||||
* `export default local_identifier`
|
||||
* `import def from 'module.js'`
|
||||
* anonymous default exports
|
||||
* `export default function () {}`
|
||||
|
||||
### Example
|
||||
|
||||
@@ -69,22 +83,20 @@ export function getFeatureDetails() {
|
||||
}
|
||||
```
|
||||
|
||||
## Unsupported features
|
||||
### Module namespace import statements
|
||||
|
||||
* **snapshot**
|
||||
* errors from the imported scripts
|
||||
* redirection ( `export { a, b } from 'module.js'` )
|
||||
* default import and export
|
||||
* `import b from 'module.js'`
|
||||
* `export default b`,
|
||||
* whole module import statements
|
||||
* `import * from 'module.js`
|
||||
* `import { * as module } from 'module.js`
|
||||
* object freezing ( `Object.freeze (this)` )
|
||||
A module namespace object can be imported. In this case the local binding will contain an object holding the exported values of the module, including local exports and all indirect exports. Ambiguous exported names are exluded from the namespace object.
|
||||
|
||||
### Redirection
|
||||
```js
|
||||
import * as module from './module.js';
|
||||
|
||||
An export statement can import variables from a custom module and export it directly from the current script. This statement is called redirection. In this case the `export { b } from 'module2.js'` works as the `b` was imported before then exported as a local variable.
|
||||
print(">> Engine: " + module.engine);
|
||||
print(">> Version: " + module.version);
|
||||
```
|
||||
|
||||
### Indirect export statements
|
||||
|
||||
An export statement can transitively export variables from another module, either via named indirect exports or a star export statement. In this case the resolving process will follow the chain until it reaches a module containing a local binding for that export name. If there are multiple modules which satisfy the export, that means the export is ambiguous, and will result in a SyntaxError.
|
||||
|
||||
```js
|
||||
import { a, b } from 'module.js'
|
||||
@@ -105,28 +117,42 @@ export var b = 40;
|
||||
|
||||
### Default imports and exports
|
||||
|
||||
TODO: This part is going to be written in the next part of the patch.
|
||||
|
||||
### Import the whole module
|
||||
|
||||
The whole module can be imported. In this case the `m` object would contain the exported parts of the module. If the import is not aliased, the `global object` would contain the exports.
|
||||
Each module can optionally provide a single default export by using the `export default` statement. Default exports can either reference identifiers in the module's lexical environment, or be an anonymous default export, in which case they will only be accessible by an importing script.
|
||||
|
||||
```js
|
||||
import { * as m } from "./module.js"
|
||||
import defaultExport, { b as c } from 'module.js'
|
||||
|
||||
print (m.secret_number);
|
||||
print (m.getPrettifiedNumber());
|
||||
print (m.api.version);
|
||||
print (defaultExport); // 2
|
||||
print (c ()); // 42
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
var secret_number = 42;
|
||||
export secret_number;
|
||||
|
||||
export function getPrettifiedNumber() {
|
||||
return "*** " + secret_number + " ***";
|
||||
export default 2;
|
||||
export function b () {
|
||||
return 42;
|
||||
}
|
||||
|
||||
export { ble as api } from "./ble.js";
|
||||
```
|
||||
|
||||
### Importing modules for side-effects
|
||||
|
||||
Evaluate a module without importing anything. Any errors encountered in the module will be propagated.
|
||||
|
||||
```js
|
||||
import 'module.js' // > module.js
|
||||
// "> module.js" is printed
|
||||
b (); // (ReferenceError) b is not defined
|
||||
```
|
||||
|
||||
```js
|
||||
// module.js
|
||||
export function b () {
|
||||
print ("> module.js");
|
||||
return 42;
|
||||
}
|
||||
b ();
|
||||
```
|
||||
|
||||
## Unsupported features
|
||||
|
||||
* **snapshot**
|
||||
|
||||
@@ -60,11 +60,6 @@ void
|
||||
ecma_finalize (void)
|
||||
{
|
||||
jmem_unregister_free_unused_memory_callback (ecma_free_unused_memory);
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
ecma_module_finalize_lex_envs ();
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
ecma_finalize_global_lex_env ();
|
||||
ecma_finalize_builtins ();
|
||||
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
|
||||
|
||||
+830
-200
File diff suppressed because it is too large
Load Diff
@@ -16,12 +16,125 @@
|
||||
#ifndef ECMA_MODULE_H
|
||||
#define ECMA_MODULE_H
|
||||
|
||||
#include "js-parser-internal.h"
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
|
||||
void ecma_module_load_modules (parser_context_t *context_p);
|
||||
#include "common.h"
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#define ECMA_MODULE_MAX_PATH 255u
|
||||
|
||||
/**
|
||||
* Imported or exported names, such as "a as b"
|
||||
* Note: See https://www.ecma-international.org/ecma-262/6.0/#table-39
|
||||
* and https://www.ecma-international.org/ecma-262/6.0/#table-41
|
||||
*/
|
||||
typedef struct ecma_module_names
|
||||
{
|
||||
struct ecma_module_names *next_p; /**< next linked list node */
|
||||
ecma_string_t *imex_name_p; /**< Import/export name of the item */
|
||||
ecma_string_t *local_name_p; /**< Local name of the item */
|
||||
} ecma_module_names_t;
|
||||
|
||||
typedef struct ecma_module ecma_module_t;
|
||||
|
||||
/**
|
||||
* Module node to store imports / exports.
|
||||
*/
|
||||
typedef struct ecma_module_node
|
||||
{
|
||||
struct ecma_module_node *next_p; /**< next linked list node */
|
||||
ecma_module_names_t *module_names_p; /**< names of the requested import/export node */
|
||||
ecma_module_t *module_request_p; /**< module structure of the requested module */
|
||||
} ecma_module_node_t;
|
||||
|
||||
/**
|
||||
* Module context containing all import and export nodes.
|
||||
*/
|
||||
typedef struct ecma_module_context
|
||||
{
|
||||
struct ecma_module_context *parent_p; /**< parent context */
|
||||
ecma_module_node_t *imports_p; /**< import item of the current context */
|
||||
ecma_module_node_t *local_exports_p; /**< export item of the current context */
|
||||
ecma_module_node_t *indirect_exports_p; /**< export item of the current context */
|
||||
ecma_module_node_t *star_exports_p; /**< export item of the current context */
|
||||
ecma_module_t *module_p; /**< module request */
|
||||
} ecma_module_context_t;
|
||||
|
||||
/**
|
||||
* An enum identifing the current state of the module
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_MODULE_STATE_INIT = 0, /**< module is initialized */
|
||||
ECMA_MODULE_STATE_PARSING = 1, /**< module is currently being parsed */
|
||||
ECMA_MODULE_STATE_PARSED = 2, /**< module has been parsed */
|
||||
ECMA_MODULE_STATE_EVALUATING = 3, /**< module is currently being evaluated */
|
||||
ECMA_MODULE_STATE_EVALUATED = 4, /**< module has been evaluated */
|
||||
} ecma_module_state_t;
|
||||
|
||||
/**
|
||||
* Module structure storing an instance of a module
|
||||
*/
|
||||
struct ecma_module
|
||||
{
|
||||
struct ecma_module *next_p; /**< next linked list node */
|
||||
ecma_module_state_t state; /**< state of the mode */
|
||||
ecma_string_t *path_p; /**< path of the module */
|
||||
ecma_module_context_t *context_p; /**< module context of the module */
|
||||
ecma_object_t *compiled_code_p; /**< compiled code of the module */
|
||||
ecma_object_t *scope_p; /**< lexica lenvironment of the module */
|
||||
ecma_object_t *namespace_object_p; /**< namespace import object of the module */
|
||||
};
|
||||
|
||||
/**
|
||||
* A record that can be used to store {module, identifier} pairs
|
||||
*/
|
||||
typedef struct ecma_module_record
|
||||
{
|
||||
ecma_module_t *module_p; /**< module */
|
||||
ecma_string_t *name_p; /**< identifier name */
|
||||
} ecma_module_record_t;
|
||||
|
||||
/**
|
||||
* A list of module records that can be used to identify circular imports during resolution
|
||||
*/
|
||||
typedef struct ecma_module_resolve_set
|
||||
{
|
||||
struct ecma_module_resolve_set *next_p; /**< next in linked list */
|
||||
ecma_module_record_t record; /**< module record */
|
||||
} ecma_module_resolve_set_t;
|
||||
|
||||
/**
|
||||
* A list that is used like a stack to drive the resolution process, instead of recursion.
|
||||
*/
|
||||
typedef struct ecma_module_resolve_stack
|
||||
{
|
||||
struct ecma_module_resolve_stack *next_p; /**< next in linked list */
|
||||
ecma_module_t *module_p; /**< module request */
|
||||
ecma_string_t *export_name_p; /**< export identifier name */
|
||||
bool resolving; /**< flag storing wether the current frame started resolving */
|
||||
} ecma_module_resolve_stack_t;
|
||||
|
||||
bool ecma_module_resolve_set_insert (ecma_module_resolve_set_t **set_p,
|
||||
ecma_module_t *module_p,
|
||||
ecma_string_t *export_name_p);
|
||||
void ecma_module_resolve_set_cleanup (ecma_module_resolve_set_t *set_p);
|
||||
|
||||
void ecma_module_resolve_stack_push (ecma_module_resolve_stack_t **stack_p,
|
||||
ecma_module_t *module_p,
|
||||
ecma_string_t *export_name_p);
|
||||
void ecma_module_resolve_stack_pop (ecma_module_resolve_stack_t **stack_p);
|
||||
|
||||
ecma_string_t *ecma_module_create_normalized_path (const uint8_t *char_p,
|
||||
prop_length_t size);
|
||||
ecma_module_t *ecma_module_find_or_create_module (ecma_string_t *path_p);
|
||||
|
||||
ecma_value_t ecma_module_connect_imports (void);
|
||||
ecma_value_t ecma_module_parse_modules (void);
|
||||
ecma_value_t ecma_module_check_indirect_exports (void);
|
||||
|
||||
void ecma_module_release_module_names (ecma_module_names_t *module_name_p);
|
||||
void ecma_module_cleanup (void);
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
#endif /* !ECMA_MODULE_H */
|
||||
|
||||
@@ -68,46 +68,6 @@ ecma_get_global_environment (void)
|
||||
return JERRY_CONTEXT (ecma_global_lex_env_p);
|
||||
} /* ecma_get_global_environment */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
/**
|
||||
* Add the lexenv of the newly imported module to the JERRY_CONTEXT.
|
||||
*/
|
||||
void
|
||||
ecma_module_add_lex_env (ecma_object_t *lex_env_p) /**< module lexenv */
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL);
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_module_lex_envs_t *new_module_lex_env_p;
|
||||
new_module_lex_env_p = jmem_heap_alloc_block (sizeof (ecma_module_lex_envs_t));
|
||||
new_module_lex_env_p->lex_env_p = lex_env_p;
|
||||
|
||||
new_module_lex_env_p->next_p = JERRY_CONTEXT (ecma_module_lex_envs_p);
|
||||
JERRY_CONTEXT (ecma_module_lex_envs_p) = new_module_lex_env_p;
|
||||
} /* ecma_module_add_lex_env */
|
||||
|
||||
/**
|
||||
* Finalize the lexenvs of the imported modules and its ECMA components.
|
||||
*/
|
||||
void
|
||||
ecma_module_finalize_lex_envs (void)
|
||||
{
|
||||
ecma_module_lex_envs_t *module_lex_envs = JERRY_CONTEXT (ecma_module_lex_envs_p);
|
||||
|
||||
while (module_lex_envs != NULL)
|
||||
{
|
||||
ecma_module_lex_envs_t *next_p = module_lex_envs->next_p;
|
||||
|
||||
ecma_deref_object (module_lex_envs->lex_env_p);
|
||||
jmem_heap_free_block (module_lex_envs, sizeof (ecma_module_lex_envs_t));
|
||||
|
||||
module_lex_envs = next_p;
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (ecma_module_lex_envs_p) = NULL;
|
||||
} /* ecma_module_finalize_lex_envs */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -215,6 +215,22 @@ uint8_t *jerry_port_read_source (const char *file_name_p, size_t *out_size_p);
|
||||
*/
|
||||
void jerry_port_release_source (uint8_t *buffer_p);
|
||||
|
||||
/**
|
||||
* Normalize a file path string.
|
||||
*
|
||||
* Note:
|
||||
* This port function is called by jerry-core when ES2015_MODULE_SYSTEM
|
||||
* is enabled. The normalized path is used to uniquely identify modules.
|
||||
*
|
||||
* @param in_path_p Input path as a zero terminated string.
|
||||
* @param out_buf_p Pointer to the output buffer where the normalized path should be written.
|
||||
* @param out_buf_size Size of the output buffer.
|
||||
*
|
||||
* @return length of the string written to the output buffer
|
||||
* zero, if the buffer was not sufficient or an error occured
|
||||
*/
|
||||
size_t jerry_port_normalize_path (const char *in_path_p, char *out_buf_p, size_t out_buf_size);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -67,17 +67,6 @@ typedef struct jerry_context_data_header
|
||||
*/
|
||||
#define JERRY_CONTEXT_FIRST_MEMBER ecma_builtin_objects
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
/**
|
||||
* Contains the lexical environments of the loaded modules.
|
||||
*/
|
||||
typedef struct ecma_module_lex_envs
|
||||
{
|
||||
ecma_object_t *lex_env_p; /**< pointer to loaded module's lexical environment */
|
||||
struct ecma_module_lex_envs *next_p; /**< pointer to the next item in the linked list */
|
||||
} ecma_module_lex_envs_t;
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
/**
|
||||
* JerryScript context
|
||||
*
|
||||
@@ -116,8 +105,8 @@ struct jerry_context_t
|
||||
ecma_object_t *ecma_global_lex_env_p; /**< global lexical environment */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
ecma_module_lex_envs_t *ecma_module_lex_envs_p; /**< list of module's lexical environments */
|
||||
parser_module_context_t *module_top_context_p; /**< top (current) module parser context */
|
||||
ecma_module_t *ecma_modules_p; /**< list of referenced modules */
|
||||
ecma_module_context_t *module_top_context_p; /**< top (current) module parser context */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */
|
||||
|
||||
@@ -22,6 +22,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ")
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_PAREN, ")")
|
||||
#endif
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASTERIX_CHAR, "*")
|
||||
#endif
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",")
|
||||
#if ENABLED (JERRY_BUILTIN_REGEXP)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/")
|
||||
@@ -325,6 +328,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean")
|
||||
#if ENABLED (JERRY_BUILTIN_ANNEXB) && ENABLED (JERRY_BUILTIN_REGEXP)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile")
|
||||
#endif
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFAULT, "default")
|
||||
#endif
|
||||
#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries")
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
[LIT_MAGIC_STRINGS]
|
||||
|
||||
LIT_MAGIC_STRING__EMPTY = ""
|
||||
LIT_MAGIC_STRING_ASTERIX_CHAR = "*"
|
||||
LIT_MAGIC_STRING_SPACE_CHAR = " "
|
||||
LIT_MAGIC_STRING_RIGHT_PAREN = ")"
|
||||
LIT_MAGIC_STRING_COMMA_CHAR = ","
|
||||
@@ -152,6 +153,7 @@ LIT_MAGIC_STRING_SYMBOL_LEFT_PAREN_UL = "Symbol("
|
||||
LIT_MAGIC_STRING_SYMBOL_DOT_UL = "Symbol."
|
||||
LIT_MAGIC_STRING_BOOLEAN = "boolean"
|
||||
LIT_MAGIC_STRING_COMPILE = "compile"
|
||||
LIT_MAGIC_STRING_DEFAULT = "default"
|
||||
LIT_MAGIC_STRING_FOR_EACH_UL = "forEach"
|
||||
LIT_MAGIC_STRING_GET_DATE_UL = "getDate"
|
||||
LIT_MAGIC_STRING_GET_INT8_UL = "getInt8"
|
||||
|
||||
@@ -2277,6 +2277,21 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
else if (context_p->status_flags & PARSER_MODULE_DEFAULT_CLASS_OR_FUNC)
|
||||
{
|
||||
/* When parsing default exports for modules, it is not required by functions or classes to have identifiers.
|
||||
* In this case we use a synthetic name for them. */
|
||||
context_p->token.type = LEXER_LITERAL;
|
||||
context_p->token.literal_is_reserved = false;
|
||||
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
|
||||
context_p->token.lit_location.has_escape = false;
|
||||
lexer_construct_literal_object (context_p,
|
||||
(lexer_lit_location_t *) &lexer_default_literal,
|
||||
lexer_default_literal.type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
} /* lexer_expect_identifier */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#ifndef JERRY_DISABLE_JS_PARSER
|
||||
#include "jcontext.h"
|
||||
|
||||
#include "ecma-helpers.h"
|
||||
#include "lit-char-helpers.h"
|
||||
|
||||
/** \addtogroup parser Parser
|
||||
@@ -568,6 +570,14 @@ parser_parse_class (parser_context_t *context_p, /**< context */
|
||||
|
||||
class_ident_index = context_p->lit_object.index;
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL && context_p->module_current_node_p != NULL)
|
||||
{
|
||||
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
else
|
||||
@@ -1266,6 +1276,15 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
|
||||
lexer_construct_literal_object (context_p,
|
||||
&context_p->token.lit_location,
|
||||
context_p->token.lit_location.type);
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context_p->status_flags & PARSER_MODULE_DEFAULT_EXPR
|
||||
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
||||
{
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
|
||||
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_EXPR);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
}
|
||||
else if (context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "js-parser-limits.h"
|
||||
#include "js-lexer.h"
|
||||
|
||||
#include "ecma-module.h"
|
||||
|
||||
/** \addtogroup parser Parser
|
||||
* @{
|
||||
*
|
||||
@@ -78,6 +80,10 @@ typedef enum
|
||||
PARSER_CLASS_STATIC_FUNCTION = (1u << 23), /**< this function is a static class method */
|
||||
PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 24), /**< super property call or assignment */
|
||||
#endif /* ENABLED (JERRY_ES2015_CLASS) */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 25), /**< parsing a function or class default export */
|
||||
PARSER_MODULE_DEFAULT_EXPR = (1u << 26), /**< parsing a default export expression */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
} parser_general_flags_t;
|
||||
|
||||
/**
|
||||
@@ -296,59 +302,6 @@ typedef struct
|
||||
|
||||
#endif /* JERRY_DEBUGGER */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
/**
|
||||
* String struct for storing the module path.
|
||||
*/
|
||||
typedef struct parser_module_utf8_string
|
||||
{
|
||||
uint8_t *value_p; /**< string value stored as uint8_t */
|
||||
prop_length_t length; /**< length of the string */
|
||||
} parser_module_utf8_string_t;
|
||||
|
||||
/**
|
||||
* Imported or exported names, for example:
|
||||
* import { v as x } from "module";
|
||||
* exported name: v
|
||||
* imported name: x
|
||||
* export x as v;
|
||||
* exported variable: x
|
||||
* exported as: v
|
||||
* Reference: https://www.ecma-international.org/ecma-262/6.0/#table-41
|
||||
*/
|
||||
typedef struct parser_module_names
|
||||
{
|
||||
ecma_string_t *import_name_p; /**< local name of the import - export item */
|
||||
ecma_string_t *local_name_p; /**< import name of the import - export item */
|
||||
|
||||
struct parser_module_names *next_p; /**< next linked list node */
|
||||
} parser_module_names_t;
|
||||
|
||||
/**
|
||||
* Module node to store imports / exports.
|
||||
*/
|
||||
typedef struct parser_module_node
|
||||
{
|
||||
parser_module_names_t *module_names_p; /**< names of the requested imports - exports */
|
||||
uint16_t module_request_count; /**< count of the requested imports - exports */
|
||||
|
||||
parser_module_utf8_string_t script_path; /**< path of the requested module*/
|
||||
|
||||
struct parser_module_node *next_p; /**< next linked list node */
|
||||
} parser_module_node_t;
|
||||
|
||||
/**
|
||||
* Module context in the parser context. It is not in the context if modules
|
||||
* are not enabled during the build. It's value is NULL if there is no import /
|
||||
* export in the script, otherwise it contains all the imports and exports.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
parser_module_node_t *imports_p; /**< import item of the current context */
|
||||
parser_module_node_t *exports_p; /**< export item of the current context */
|
||||
} parser_module_context_t;
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
/**
|
||||
* Those members of a context which needs
|
||||
* to be saved when a sub-function is parsed.
|
||||
@@ -396,8 +349,8 @@ typedef struct
|
||||
parser_stack_iterator_t last_statement; /**< last statement position */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
parser_module_context_t *module_context_p; /**< shared module context inside the parser */
|
||||
parser_module_node_t *module_current_node_p; /**< import / export node that is being processed */
|
||||
ecma_module_node_t *module_current_node_p; /**< import / export node that is being processed */
|
||||
lexer_literal_t *module_identifier_lit_p; /**< the literal for the identifier of the current element */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
/* Lexer members. */
|
||||
@@ -614,27 +567,23 @@ void parser_free_jumps (parser_stack_iterator_t iterator);
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern const lexer_lit_location_t lexer_default_literal;
|
||||
void parser_module_add_export_node_to_context (parser_context_t *context_p);
|
||||
void parser_module_add_import_node_to_context (parser_context_t *context_p);
|
||||
void parser_module_check_request_place (parser_context_t *context_p);
|
||||
void parser_module_context_cleanup (parser_context_t *context_p);
|
||||
void parser_module_context_init (parser_context_t *context_p);
|
||||
void parser_module_free_saved_names (parser_module_node_t *module_node_p);
|
||||
void parser_module_handle_from_clause (parser_context_t *context_p);
|
||||
void parser_module_handle_module_specifier (parser_context_t *context_p);
|
||||
void parser_module_handle_requests (parser_context_t *context_p);
|
||||
void parser_module_partial_cleanup_on_error (parser_module_node_t *module_node_p);
|
||||
void parser_module_parse_export_item_list (parser_context_t *context_p);
|
||||
void parser_module_parse_import_item_list (parser_context_t *context_p);
|
||||
|
||||
parser_module_node_t *parser_module_create_module_node (parser_context_t *context_p,
|
||||
parser_module_node_t *template_node_p);
|
||||
parser_module_node_t *parser_module_get_export_node (parser_context_t *context_p);
|
||||
|
||||
void parser_module_add_item_to_node (parser_context_t *context_p,
|
||||
parser_module_node_t *module_node_p,
|
||||
lexer_literal_t *import_name_p,
|
||||
lexer_literal_t *local_name_p,
|
||||
bool is_import_item);
|
||||
void parser_module_parse_export_clause (parser_context_t *context_p);
|
||||
void parser_module_parse_import_clause (parser_context_t *context_p);
|
||||
void parser_module_set_default (parser_context_t *context_p);
|
||||
ecma_module_node_t *parser_module_create_module_node (parser_context_t *context_p,
|
||||
ecma_module_node_t *template_node_p);
|
||||
bool parser_module_check_duplicate_import (parser_context_t *context_p, ecma_string_t *local_name_p);
|
||||
bool parser_module_check_duplicate_export (parser_context_t *context_p, ecma_string_t *export_name_p);
|
||||
void parser_module_add_names_to_node (parser_context_t *context_p,
|
||||
ecma_string_t *imex_name_p,
|
||||
ecma_string_t *local_name_p);
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
|
||||
@@ -19,114 +19,121 @@
|
||||
#include "jcontext.h"
|
||||
#include "jerryscript-port.h"
|
||||
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "ecma-lex-env.h"
|
||||
#include "ecma-module.h"
|
||||
|
||||
/**
|
||||
* Maximum import count limit.
|
||||
* Description of "*default*" literal string.
|
||||
*/
|
||||
#define MAX_IMPORT_COUNT UINT16_MAX
|
||||
const lexer_lit_location_t lexer_default_literal =
|
||||
{
|
||||
(const uint8_t *) "*default*", 9, LEXER_IDENT_LITERAL, false
|
||||
};
|
||||
|
||||
/**
|
||||
* Check duplicates in module node.
|
||||
* @return true - if the given item is duplicated entry in the current node
|
||||
* Check for duplicated imported binding names.
|
||||
*
|
||||
* @return true - if the given name is a duplicate
|
||||
* false - otherwise
|
||||
*/
|
||||
static bool
|
||||
parser_module_check_for_duplicates_in_node (parser_module_node_t *module_node_p, /**< module node */
|
||||
lexer_literal_t *import_name_p) /**< newly imported name */
|
||||
bool
|
||||
parser_module_check_duplicate_import (parser_context_t *context_p, /**< parser context */
|
||||
ecma_string_t *local_name_p) /**< newly imported name */
|
||||
{
|
||||
JERRY_ASSERT (import_name_p != NULL);
|
||||
|
||||
parser_module_names_t *import_names_p = module_node_p->module_names_p;
|
||||
|
||||
while (import_names_p != NULL)
|
||||
ecma_module_names_t *module_names_p = context_p->module_current_node_p->module_names_p;
|
||||
while (module_names_p != NULL)
|
||||
{
|
||||
uint8_t flags = ECMA_STRING_FLAG_IS_ASCII;
|
||||
lit_utf8_size_t current_length = 0;
|
||||
const uint8_t *current_p = ecma_string_get_chars (import_names_p->import_name_p, ¤t_length, &flags);
|
||||
|
||||
if (current_p != NULL && current_length == import_name_p->prop.length
|
||||
&& memcmp (current_p, import_name_p->u.char_p, current_length) == 0)
|
||||
if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
import_names_p = import_names_p->next_p;
|
||||
module_names_p = module_names_p->next_p;
|
||||
}
|
||||
|
||||
ecma_module_node_t *module_node_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
|
||||
while (module_node_p != NULL)
|
||||
{
|
||||
module_names_p = module_node_p->module_names_p;
|
||||
|
||||
while (module_names_p != NULL)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
module_names_p = module_names_p->next_p;
|
||||
}
|
||||
|
||||
module_node_p = module_node_p->next_p;
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* parser_module_check_for_duplicates_in_node */
|
||||
} /* parser_module_check_duplicate_import */
|
||||
|
||||
/**
|
||||
* Check duplicates in the whole module context.
|
||||
* @return true - if the given item is duplicated entry
|
||||
* Check for duplicated exported bindings.
|
||||
* @return - true - if the exported name is a duplicate
|
||||
* false - otherwise
|
||||
*/
|
||||
static bool
|
||||
parser_module_check_for_duplicates (parser_context_t *context_p, /**< parser context */
|
||||
parser_module_node_t *module_node_p, /**< module noda */
|
||||
lexer_literal_t *import_name_p) /**< newly imported name */
|
||||
bool
|
||||
parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser context */
|
||||
ecma_string_t *export_name_p) /**< exported identifier */
|
||||
{
|
||||
if (import_name_p == NULL)
|
||||
/* We have to check in the currently constructed node, as well as all of the already added nodes. */
|
||||
ecma_module_names_t *current_names_p = context_p->module_current_node_p->module_names_p;
|
||||
while (current_names_p != NULL)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (current_names_p->imex_name_p, export_name_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
current_names_p = current_names_p->next_p;
|
||||
}
|
||||
|
||||
ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_top_context_p)->local_exports_p;
|
||||
if (export_node_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (export_node_p->next_p == NULL);
|
||||
ecma_module_names_t *name_p = export_node_p->module_names_p;
|
||||
|
||||
while (name_p != NULL)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
name_p = name_p->next_p;
|
||||
}
|
||||
}
|
||||
|
||||
export_node_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
|
||||
while (export_node_p != NULL)
|
||||
{
|
||||
ecma_module_names_t *name_p = export_node_p->module_names_p;
|
||||
|
||||
while (name_p != NULL)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
name_p = name_p->next_p;
|
||||
}
|
||||
|
||||
export_node_p = export_node_p->next_p;
|
||||
}
|
||||
|
||||
/* Star exports don't have any names associated with them, so no need to check those. */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasDuplicate = parser_module_check_for_duplicates_in_node (module_node_p,
|
||||
import_name_p);
|
||||
|
||||
if (!hasDuplicate)
|
||||
{
|
||||
parser_module_node_t *node_p = context_p->module_context_p->imports_p;
|
||||
while (node_p != NULL && !hasDuplicate)
|
||||
{
|
||||
hasDuplicate = parser_module_check_for_duplicates_in_node (node_p,
|
||||
import_name_p);
|
||||
node_p = node_p->next_p;
|
||||
}
|
||||
}
|
||||
|
||||
return hasDuplicate;
|
||||
} /* parser_module_check_for_duplicates */
|
||||
|
||||
/**
|
||||
* Delete the saved names from the given module node.
|
||||
*/
|
||||
void
|
||||
parser_module_free_saved_names (parser_module_node_t *module_node_p) /**< module node */
|
||||
{
|
||||
if (module_node_p == NULL || module_node_p->module_names_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
parser_module_names_t *current_p = module_node_p->module_names_p;
|
||||
|
||||
for (uint16_t i = 0; i < module_node_p->module_request_count; i++)
|
||||
{
|
||||
parser_module_names_t *next_p = current_p->next_p;
|
||||
|
||||
if (current_p->import_name_p != NULL)
|
||||
{
|
||||
ecma_deref_ecma_string (current_p->import_name_p);
|
||||
current_p->import_name_p = NULL;
|
||||
}
|
||||
|
||||
if (current_p->local_name_p != NULL)
|
||||
{
|
||||
ecma_deref_ecma_string (current_p->local_name_p);
|
||||
current_p->local_name_p = NULL;
|
||||
}
|
||||
|
||||
parser_free (current_p, sizeof (parser_module_names_t));
|
||||
current_p = next_p;
|
||||
}
|
||||
} /* parser_module_free_saved_names */
|
||||
} /* parser_module_check_duplicate_export */
|
||||
|
||||
/**
|
||||
* Add export node to parser context.
|
||||
@@ -134,37 +141,56 @@ parser_module_free_saved_names (parser_module_node_t *module_node_p) /**< module
|
||||
void
|
||||
parser_module_add_export_node_to_context (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
parser_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
parser_module_node_t *exports_p = context_p->module_context_p->exports_p;
|
||||
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
ecma_module_node_t **export_list_p;
|
||||
|
||||
if (exports_p != NULL)
|
||||
/* Check which list we should add it to. */
|
||||
if (module_node_p->module_request_p)
|
||||
{
|
||||
parser_module_names_t *module_names_p = module_node_p->module_names_p;
|
||||
/* If the export node has a module request, that means it's either an indirect export, or a star export. */
|
||||
if (!module_node_p->module_names_p)
|
||||
{
|
||||
/* If there are no names in the node, then it's a star export. */
|
||||
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->star_exports_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->indirect_exports_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there is no module request, then it's a local export. */
|
||||
export_list_p = &(JERRY_CONTEXT (module_top_context_p)->local_exports_p);
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < module_node_p->module_request_count - 1 ; i++)
|
||||
/* Check if we have a node with the same module request, append to it if we do. */
|
||||
ecma_module_node_t *stored_exports_p = *export_list_p;
|
||||
while (stored_exports_p != NULL)
|
||||
{
|
||||
if (stored_exports_p->module_request_p == module_node_p->module_request_p)
|
||||
{
|
||||
ecma_module_names_t *module_names_p = module_node_p->module_names_p;
|
||||
|
||||
if (module_names_p != NULL)
|
||||
{
|
||||
while (module_names_p->next_p != NULL)
|
||||
{
|
||||
module_names_p = module_names_p->next_p;
|
||||
}
|
||||
|
||||
module_names_p->next_p = exports_p->module_names_p;
|
||||
exports_p->module_names_p = module_node_p->module_names_p;
|
||||
module_names_p->next_p = stored_exports_p->module_names_p;
|
||||
stored_exports_p->module_names_p = module_node_p->module_names_p;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int request_count = exports_p->module_request_count + module_node_p->module_request_count;
|
||||
stored_exports_p = stored_exports_p->next_p;
|
||||
}
|
||||
|
||||
if ((uint16_t) request_count < MAX_IMPORT_COUNT)
|
||||
{
|
||||
exports_p->module_request_count = (uint16_t) request_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_module_node_t *export_node_p = parser_module_create_module_node (context_p, module_node_p);
|
||||
context_p->module_context_p->exports_p = export_node_p;
|
||||
}
|
||||
ecma_module_node_t *export_node_p = parser_module_create_module_node (context_p, module_node_p);
|
||||
export_node_p->next_p = *export_list_p;
|
||||
*export_list_p = export_node_p;
|
||||
} /* parser_module_add_export_node_to_context */
|
||||
|
||||
/**
|
||||
@@ -173,393 +199,275 @@ parser_module_add_export_node_to_context (parser_context_t *context_p) /**< pars
|
||||
void
|
||||
parser_module_add_import_node_to_context (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
parser_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
parser_module_node_t *stored_imports = context_p->module_context_p->imports_p;
|
||||
bool is_stored_module = false;
|
||||
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
ecma_module_node_t *stored_imports = JERRY_CONTEXT (module_top_context_p)->imports_p;
|
||||
|
||||
/* Check if we have a node with the same module request, append to it if we do. */
|
||||
while (stored_imports != NULL)
|
||||
{
|
||||
if (stored_imports->script_path.length == module_node_p->script_path.length
|
||||
&& memcmp (stored_imports->script_path.value_p,
|
||||
module_node_p->script_path.value_p,
|
||||
stored_imports->script_path.length) == 0)
|
||||
if (stored_imports->module_request_p == module_node_p->module_request_p)
|
||||
{
|
||||
parser_free (module_node_p->script_path.value_p, module_node_p->script_path.length * sizeof (uint8_t));
|
||||
ecma_module_names_t *module_names_p = module_node_p->module_names_p;
|
||||
|
||||
parser_module_names_t *module_names_p = module_node_p->module_names_p;
|
||||
is_stored_module = true;
|
||||
|
||||
for (uint16_t i = 0; i < module_node_p->module_request_count - 1; i++)
|
||||
if (module_names_p != NULL)
|
||||
{
|
||||
while (module_names_p->next_p != NULL)
|
||||
{
|
||||
module_names_p = module_names_p->next_p;
|
||||
}
|
||||
|
||||
module_names_p->next_p = stored_imports->module_names_p;
|
||||
stored_imports->module_names_p = module_node_p->module_names_p;
|
||||
|
||||
int request_count = stored_imports->module_request_count + module_node_p->module_request_count;
|
||||
if ((uint16_t) request_count < MAX_IMPORT_COUNT)
|
||||
{
|
||||
stored_imports->module_request_count = (uint16_t) request_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
stored_imports = stored_imports->next_p;
|
||||
}
|
||||
|
||||
if (!is_stored_module)
|
||||
{
|
||||
parser_module_node_t *permanent_node_p = parser_module_create_module_node (context_p, module_node_p);
|
||||
permanent_node_p->next_p = context_p->module_context_p->imports_p;
|
||||
context_p->module_context_p->imports_p = permanent_node_p;
|
||||
}
|
||||
|
||||
} /* parser_module_add_import_node_to_context */
|
||||
|
||||
/**
|
||||
* Add import or export item to module node.
|
||||
*/
|
||||
void
|
||||
parser_module_add_item_to_node (parser_context_t *context_p, /**< parser context */
|
||||
parser_module_node_t *module_node_p, /**< current module node */
|
||||
lexer_literal_t *import_name_p, /**< import name */
|
||||
lexer_literal_t *local_name_p, /**< local name */
|
||||
bool is_import_item) /**< given item is import item */
|
||||
{
|
||||
if (is_import_item
|
||||
&& parser_module_check_for_duplicates (context_p, module_node_p, import_name_p))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_LABEL);
|
||||
}
|
||||
|
||||
parser_module_names_t *new_names_p = (parser_module_names_t *) parser_malloc (context_p,
|
||||
sizeof (parser_module_names_t));
|
||||
|
||||
new_names_p->next_p = module_node_p->module_names_p;
|
||||
module_node_p->module_names_p = new_names_p;
|
||||
|
||||
module_node_p->module_names_p->import_name_p = ecma_new_ecma_string_from_utf8 (import_name_p->u.char_p,
|
||||
import_name_p->prop.length);
|
||||
|
||||
module_node_p->module_names_p->local_name_p = ecma_new_ecma_string_from_utf8 (local_name_p->u.char_p,
|
||||
local_name_p->prop.length);
|
||||
|
||||
module_node_p->module_request_count++;
|
||||
} /* parser_module_add_item_to_node */
|
||||
|
||||
/**
|
||||
* Cleanup the whole module context from parser context.
|
||||
*/
|
||||
void
|
||||
parser_module_context_cleanup (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
parser_module_context_t *module_context_p = context_p->module_context_p;
|
||||
|
||||
if (module_context_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
parser_module_node_t *current_node_p = module_context_p->imports_p;
|
||||
|
||||
while (current_node_p != NULL)
|
||||
{
|
||||
parser_free (current_node_p->script_path.value_p, current_node_p->script_path.length * sizeof (uint8_t));
|
||||
parser_module_free_saved_names (current_node_p);
|
||||
|
||||
parser_module_node_t *next_node_p = current_node_p->next_p;
|
||||
|
||||
parser_free (current_node_p, sizeof (parser_module_node_t));
|
||||
current_node_p = next_node_p;
|
||||
stored_imports = stored_imports->next_p;
|
||||
}
|
||||
|
||||
parser_module_context_t *parent_context_p = JERRY_CONTEXT (module_top_context_p);
|
||||
if ((parent_context_p == NULL || parent_context_p->exports_p == NULL || parent_context_p->imports_p == NULL)
|
||||
&& module_context_p->exports_p != NULL)
|
||||
{
|
||||
parser_module_free_saved_names (module_context_p->exports_p);
|
||||
parser_free (module_context_p->exports_p, sizeof (parser_module_node_t));
|
||||
}
|
||||
|
||||
parser_free (module_context_p, sizeof (parser_module_context_t));
|
||||
context_p->module_context_p = NULL;
|
||||
} /* parser_module_context_cleanup */
|
||||
ecma_module_node_t *permanent_node_p = parser_module_create_module_node (context_p, module_node_p);
|
||||
permanent_node_p->next_p = JERRY_CONTEXT (module_top_context_p)->imports_p;
|
||||
JERRY_CONTEXT (module_top_context_p)->imports_p = permanent_node_p;
|
||||
} /* parser_module_add_import_node_to_context */
|
||||
|
||||
/**
|
||||
* Create module context and bind to the parser context.
|
||||
* Add module names to current module node.
|
||||
*/
|
||||
void
|
||||
parser_module_add_names_to_node (parser_context_t *context_p, /**< parser context */
|
||||
ecma_string_t *imex_name_p, /**< import/export name */
|
||||
ecma_string_t *local_name_p) /**< local name */
|
||||
{
|
||||
ecma_module_names_t *new_names_p = (ecma_module_names_t *) parser_malloc (context_p,
|
||||
sizeof (ecma_module_names_t));
|
||||
memset (new_names_p, 0, sizeof (ecma_module_names_t));
|
||||
|
||||
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
new_names_p->next_p = module_node_p->module_names_p;
|
||||
module_node_p->module_names_p = new_names_p;
|
||||
|
||||
JERRY_ASSERT (imex_name_p != NULL);
|
||||
ecma_ref_ecma_string (imex_name_p);
|
||||
new_names_p->imex_name_p = imex_name_p;
|
||||
|
||||
JERRY_ASSERT (local_name_p != NULL);
|
||||
ecma_ref_ecma_string (local_name_p);
|
||||
new_names_p->local_name_p = local_name_p;
|
||||
} /* parser_module_add_names_to_node */
|
||||
|
||||
/**
|
||||
* Create module context if needed.
|
||||
*/
|
||||
void
|
||||
parser_module_context_init (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
if (context_p->module_context_p == NULL)
|
||||
if (JERRY_CONTEXT (module_top_context_p) == NULL)
|
||||
{
|
||||
context_p->module_context_p = (parser_module_context_t *) parser_malloc (context_p,
|
||||
sizeof (parser_module_context_t));
|
||||
ecma_module_context_t *module_context_p;
|
||||
module_context_p = (ecma_module_context_t *) parser_malloc (context_p,
|
||||
sizeof (ecma_module_context_t));
|
||||
|
||||
memset (context_p->module_context_p, 0, sizeof (parser_module_context_t));
|
||||
memset (module_context_p, 0, sizeof (ecma_module_context_t));
|
||||
JERRY_CONTEXT (module_top_context_p) = module_context_p;
|
||||
}
|
||||
} /* parser_module_context_init */
|
||||
|
||||
/**
|
||||
* Create import node.
|
||||
* Create a permanent import/export node from a template node.
|
||||
* @return - the copy of the template if the second parameter is not NULL.
|
||||
* - otherwise: an empty import node.
|
||||
* - otherwise: an empty node.
|
||||
*/
|
||||
parser_module_node_t *
|
||||
ecma_module_node_t *
|
||||
parser_module_create_module_node (parser_context_t *context_p, /**< parser context */
|
||||
parser_module_node_t *template_node_p) /**< template node for the new node */
|
||||
ecma_module_node_t *template_node_p) /**< template node for the new node */
|
||||
{
|
||||
parser_module_node_t *node = (parser_module_node_t *) parser_malloc (context_p, sizeof (parser_module_node_t));
|
||||
ecma_module_node_t *node_p = (ecma_module_node_t *) parser_malloc (context_p, sizeof (ecma_module_node_t));
|
||||
|
||||
if (template_node_p != NULL)
|
||||
{
|
||||
node->module_names_p = template_node_p->module_names_p;
|
||||
node->module_request_count = template_node_p->module_request_count;
|
||||
|
||||
node->script_path.value_p = template_node_p->script_path.value_p;
|
||||
node->script_path.length = template_node_p->script_path.length;
|
||||
node->next_p = NULL;
|
||||
node_p->module_names_p = template_node_p->module_names_p;
|
||||
node_p->module_request_p = template_node_p->module_request_p;
|
||||
node_p->next_p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (node, 0, sizeof (parser_module_node_t));
|
||||
memset (node_p, 0, sizeof (ecma_module_node_t));
|
||||
}
|
||||
|
||||
return node;
|
||||
return node_p;
|
||||
} /* parser_module_create_module_node */
|
||||
|
||||
/**
|
||||
* Create export node or get the previously created one.
|
||||
* @return the export node
|
||||
*/
|
||||
parser_module_node_t *
|
||||
parser_module_get_export_node (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
if (context_p->module_context_p->exports_p != NULL)
|
||||
{
|
||||
return context_p->module_context_p->exports_p;
|
||||
}
|
||||
|
||||
return parser_module_create_module_node (context_p, NULL);
|
||||
} /* parser_module_get_export_node */
|
||||
|
||||
/**
|
||||
* Parse export item list.
|
||||
* Parse an ExportClause.
|
||||
*/
|
||||
void
|
||||
parser_module_parse_export_item_list (parser_context_t *context_p) /**< parser context */
|
||||
parser_module_parse_export_clause (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_KEYW_DEFAULT || context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
/* TODO: This part is going to be implemented in the next part of the patch. */
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
bool has_export_name = false;
|
||||
lexer_literal_t *export_name_p = NULL;
|
||||
lexer_literal_t *local_name_p = NULL;
|
||||
parser_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
|
||||
lexer_next_token (context_p);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (has_export_name
|
||||
&& context_p->token.type != LEXER_KEYW_DEFAULT
|
||||
&& (context_p->token.type != LEXER_LITERAL
|
||||
|| lexer_compare_raw_identifier_to_current (context_p, "from", 4)
|
||||
|| lexer_compare_raw_identifier_to_current (context_p, "as", 2)))
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
|
||||
}
|
||||
|
||||
if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL
|
||||
&& context_p->token.lit_location.type != LEXER_STRING_LITERAL)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
|
||||
|
||||
if (has_export_name)
|
||||
{
|
||||
export_name_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_name_p = context_p->lit_object.literal_p;
|
||||
export_name_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_COMMA)
|
||||
{
|
||||
has_export_name = false;
|
||||
parser_module_add_item_to_node (context_p, module_node_p, export_name_p, local_name_p, false);
|
||||
}
|
||||
else if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
{
|
||||
if (has_export_name)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
|
||||
}
|
||||
|
||||
has_export_name = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser_module_add_item_to_node (context_p, module_node_p, export_name_p, local_name_p, false);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 15.2.3.1 The referenced binding cannot be a reserved word. */
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL
|
||||
|| context_p->token.literal_is_reserved)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
ecma_string_t *export_name_p = NULL;
|
||||
ecma_string_t *local_name_p = NULL;
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
local_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
|
||||
ecma_ref_ecma_string (local_name_p);
|
||||
export_name_p = local_name_p;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
} /* parser_module_parse_export_item_list */
|
||||
|
||||
/**
|
||||
* Parse import item list.
|
||||
*/
|
||||
void
|
||||
parser_module_parse_import_item_list (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
/* Import list is empty, the whole module will be loaded. */
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
{
|
||||
/* TODO: This part is going to be implemented in the next part of the patch. */
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
bool has_import_name = false;
|
||||
lexer_literal_t *import_name_p = NULL;
|
||||
lexer_literal_t *local_name_p = NULL;
|
||||
parser_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool whole_module_needed = context_p->token.type == LEXER_MULTIPLY;
|
||||
|
||||
if (whole_module_needed)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
}
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| lexer_compare_raw_identifier_to_current (context_p, "from", 4)
|
||||
|| lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (export_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
if (has_import_name)
|
||||
{
|
||||
import_name_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
local_name_p = context_p->lit_object.literal_p;
|
||||
import_name_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
export_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE
|
||||
|| (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4)))
|
||||
{
|
||||
parser_module_add_item_to_node (context_p, module_node_p, import_name_p, local_name_p, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_COMMA)
|
||||
if (parser_module_check_duplicate_export (context_p, export_name_p))
|
||||
{
|
||||
parser_module_add_item_to_node (context_p, module_node_p, import_name_p, local_name_p, true);
|
||||
has_import_name = false;
|
||||
}
|
||||
else if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
{
|
||||
if (has_import_name)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (export_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
|
||||
}
|
||||
|
||||
has_import_name = true;
|
||||
}
|
||||
else
|
||||
parser_module_add_names_to_node (context_p, export_name_p, local_name_p);
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (export_name_p);
|
||||
|
||||
if (context_p->token.type != LEXER_COMMA
|
||||
&& context_p->token.type != LEXER_RIGHT_BRACE)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_COMMA_FROM_EXPECTED);
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED);
|
||||
}
|
||||
else if (context_p->token.type == LEXER_COMMA)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
} /* parser_module_parse_import_item_list */
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
|
||||
}
|
||||
}
|
||||
} /* parser_module_parse_export_clause */
|
||||
|
||||
/**
|
||||
* Handle import requests.
|
||||
* Check if imported variables are exported in the appropriate module.
|
||||
* Raise parser error if imported item is not exported.
|
||||
* Parse an ImportClause
|
||||
*/
|
||||
void
|
||||
parser_module_handle_requests (parser_context_t *context_p) /**< parser context */
|
||||
parser_module_parse_import_clause (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
parser_module_context_t *module_context_p = JERRY_CONTEXT (module_top_context_p);
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->module_context_p->exports_p == NULL || module_context_p == NULL)
|
||||
while (true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool throw_error = false;
|
||||
|
||||
parser_module_names_t *import_name_p = module_context_p->imports_p->module_names_p;
|
||||
parser_module_names_t *current_exports_p = context_p->module_context_p->exports_p->module_names_p;
|
||||
|
||||
for (uint16_t i = 0; i < module_context_p->imports_p->module_request_count; ++i)
|
||||
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
||||
{
|
||||
bool request_is_found_in_module = false;
|
||||
parser_module_names_t *export_iterator_p = current_exports_p;
|
||||
|
||||
for (uint16_t j = 0; j < context_p->module_context_p->exports_p->module_request_count;
|
||||
++j, export_iterator_p = export_iterator_p->next_p)
|
||||
{
|
||||
if (ecma_compare_ecma_strings (import_name_p->local_name_p, export_iterator_p->import_name_p))
|
||||
{
|
||||
request_is_found_in_module = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!request_is_found_in_module)
|
||||
{
|
||||
parser_module_free_saved_names (context_p->module_context_p->exports_p);
|
||||
throw_error = true;
|
||||
lexer_next_token (context_p);
|
||||
break;
|
||||
}
|
||||
|
||||
import_name_p = import_name_p->next_p;
|
||||
}
|
||||
|
||||
*module_context_p->exports_p = *context_p->module_context_p->exports_p;
|
||||
parser_free (context_p->module_context_p->exports_p, sizeof (parser_module_node_t));
|
||||
|
||||
if (throw_error)
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_NOT_FOUND);
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
} /* parser_module_handle_requests */
|
||||
|
||||
ecma_string_t *import_name_p = NULL;
|
||||
ecma_string_t *local_name_p = NULL;
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
local_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
ecma_ref_ecma_string (local_name_p);
|
||||
import_name_p = local_name_p;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
||||
{
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (import_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
local_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if (parser_module_check_duplicate_import (context_p, local_name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (import_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING);
|
||||
}
|
||||
|
||||
parser_module_add_names_to_node (context_p, import_name_p, local_name_p);
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (import_name_p);
|
||||
|
||||
if (context_p->token.type != LEXER_COMMA
|
||||
&& (context_p->token.type != LEXER_RIGHT_BRACE))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED);
|
||||
}
|
||||
else if (context_p->token.type == LEXER_COMMA)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_BRACE_EXPECTED);
|
||||
}
|
||||
}
|
||||
} /* parser_module_parse_import_clause */
|
||||
|
||||
/**
|
||||
* Raises parser error if the import or export statement is not in the global scope.
|
||||
@@ -569,35 +477,37 @@ parser_module_check_request_place (parser_context_t *context_p) /**< parser cont
|
||||
{
|
||||
if (context_p->last_context_p != NULL
|
||||
|| context_p->stack_top_uint8 != 0
|
||||
|| (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0)
|
||||
|| (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL) != 0
|
||||
|| (context_p->status_flags & PARSER_IS_FUNCTION) != 0)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED);
|
||||
}
|
||||
} /* parser_module_check_request_place */
|
||||
|
||||
/**
|
||||
* Handle from clause at the end of the import / export statement.
|
||||
* Handle module specifier at the end of the import / export statement.
|
||||
*/
|
||||
void
|
||||
parser_module_handle_from_clause (parser_context_t *context_p) /**< parser context */
|
||||
parser_module_handle_module_specifier (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
parser_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_NO_OPTS);
|
||||
|
||||
if (context_p->lit_object.literal_p->prop.length == 0)
|
||||
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| context_p->token.lit_location.type != LEXER_STRING_LITERAL
|
||||
|| context_p->token.lit_location.length == 0)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_PROPERTY_IDENTIFIER_EXPECTED);
|
||||
parser_raise_error (context_p, PARSER_ERR_STRING_EXPECTED);
|
||||
}
|
||||
|
||||
module_node_p->script_path.length = (prop_length_t) (context_p->lit_object.literal_p->prop.length + 1);
|
||||
module_node_p->script_path.value_p = (uint8_t *) parser_malloc (context_p,
|
||||
module_node_p->script_path.length * sizeof (uint8_t));
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
|
||||
|
||||
memcpy (module_node_p->script_path.value_p,
|
||||
context_p->lit_object.literal_p->u.char_p,
|
||||
module_node_p->script_path.length);
|
||||
module_node_p->script_path.value_p[module_node_p->script_path.length - 1] = '\0';
|
||||
ecma_string_t *path_p = ecma_module_create_normalized_path (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
|
||||
ecma_module_t *module_p = ecma_module_find_or_create_module (path_p);
|
||||
ecma_deref_ecma_string (path_p);
|
||||
|
||||
module_node_p->module_request_p = module_p;
|
||||
lexer_next_token (context_p);
|
||||
} /* parser_module_handle_from_clause */
|
||||
} /* parser_module_handle_module_specifier */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#ifndef JERRY_DISABLE_JS_PARSER
|
||||
#include "jcontext.h"
|
||||
|
||||
#include "ecma-helpers.h"
|
||||
#include "lit-char-helpers.h"
|
||||
|
||||
/** \addtogroup parser Parser
|
||||
@@ -325,13 +327,9 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context_p->module_context_p != NULL && context_p->module_current_node_p != NULL)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL && context_p->module_current_node_p != NULL)
|
||||
{
|
||||
parser_module_add_item_to_node (context_p,
|
||||
context_p->module_current_node_p,
|
||||
context_p->lit_object.literal_p,
|
||||
context_p->lit_object.literal_p,
|
||||
false);
|
||||
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
@@ -401,13 +399,9 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
|
||||
name_p = context_p->lit_object.literal_p;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context_p->module_context_p != NULL && context_p->module_current_node_p != NULL)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL && context_p->module_current_node_p != NULL)
|
||||
{
|
||||
parser_module_add_item_to_node (context_p,
|
||||
context_p->module_current_node_p,
|
||||
name_p,
|
||||
name_p,
|
||||
false);
|
||||
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
@@ -1678,56 +1672,121 @@ parser_parse_continue_statement (parser_context_t *context_p) /**< context */
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
/**
|
||||
* Parse import statement.
|
||||
* Note: See 15.2.2
|
||||
*/
|
||||
static void
|
||||
parser_parse_import_statement (parser_context_t *context_p) /**< context */
|
||||
parser_parse_import_statement (parser_context_t *context_p) /**< parser context */
|
||||
{
|
||||
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT);
|
||||
|
||||
parser_module_check_request_place (context_p);
|
||||
parser_module_context_init (context_p);
|
||||
|
||||
parser_module_node_t module_node;
|
||||
memset (&module_node, 0, sizeof (parser_module_node_t));
|
||||
ecma_module_node_t module_node;
|
||||
memset (&module_node, 0, sizeof (ecma_module_node_t));
|
||||
context_p->module_current_node_p = &module_node;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
switch (context_p->token.type)
|
||||
/* Check for a ModuleSpecifier*/
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| context_p->token.lit_location.type != LEXER_STRING_LITERAL)
|
||||
{
|
||||
case LEXER_LEFT_BRACE:
|
||||
if (!(context_p->token.type == LEXER_LEFT_BRACE
|
||||
|| context_p->token.type == LEXER_MULTIPLY
|
||||
|| (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL)
|
||||
{
|
||||
/* Handle ImportedDefaultBinding */
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
ecma_string_t *local_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
|
||||
if (parser_module_check_duplicate_import (context_p, local_name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING);
|
||||
}
|
||||
|
||||
ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT);
|
||||
parser_module_add_names_to_node (context_p, import_name_p, local_name_p);
|
||||
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (import_name_p);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_COMMA
|
||||
&& !lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_FROM_COMMA_EXPECTED);
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_COMMA)
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_module_parse_import_item_list (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_BRACE)
|
||||
if (context_p->token.type != LEXER_MULTIPLY
|
||||
&& context_p->token.type != LEXER_LEFT_BRACE)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context_p->token.type == LEXER_MULTIPLY)
|
||||
{
|
||||
/* NameSpaceImport*/
|
||||
lexer_next_token (context_p);
|
||||
if (context_p->token.type != LEXER_LITERAL
|
||||
|| !lexer_compare_raw_identifier_to_current (context_p, "as", 2))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_AS_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
break;
|
||||
if (context_p->token.type != LEXER_LITERAL)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
|
||||
}
|
||||
|
||||
case LEXER_MULTIPLY:
|
||||
case LEXER_LITERAL:
|
||||
lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
|
||||
|
||||
ecma_string_t *local_name_p = ecma_new_ecma_string_from_utf8 (context_p->lit_object.literal_p->u.char_p,
|
||||
context_p->lit_object.literal_p->prop.length);
|
||||
|
||||
if (parser_module_check_duplicate_import (context_p, local_name_p))
|
||||
{
|
||||
parser_module_parse_import_item_list (context_p);
|
||||
break;
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_IMPORT_BINDING);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED);
|
||||
ecma_string_t *import_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR);
|
||||
|
||||
parser_module_add_names_to_node (context_p, import_name_p, local_name_p);
|
||||
ecma_deref_ecma_string (local_name_p);
|
||||
ecma_deref_ecma_string (import_name_p);
|
||||
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
else if (context_p->token.type == LEXER_LEFT_BRACE)
|
||||
{
|
||||
/* Handle NamedImports */
|
||||
parser_module_parse_import_clause (context_p);
|
||||
}
|
||||
|
||||
if (context_p->token.type != LEXER_LITERAL || !lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
|
||||
}
|
||||
lexer_next_token (context_p);
|
||||
}
|
||||
|
||||
parser_module_handle_from_clause (context_p);
|
||||
parser_module_handle_module_specifier (context_p);
|
||||
parser_module_add_import_node_to_context (context_p);
|
||||
|
||||
context_p->module_current_node_p = NULL;
|
||||
@@ -1744,75 +1803,156 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
|
||||
parser_module_check_request_place (context_p);
|
||||
parser_module_context_init (context_p);
|
||||
|
||||
parser_module_node_t module_node;
|
||||
memset (&module_node, 0, sizeof (parser_module_node_t));
|
||||
ecma_module_node_t module_node;
|
||||
memset (&module_node, 0, sizeof (ecma_module_node_t));
|
||||
context_p->module_current_node_p = &module_node;
|
||||
|
||||
lexer_next_token (context_p);
|
||||
|
||||
switch (context_p->token.type)
|
||||
{
|
||||
case LEXER_LEFT_BRACE:
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
parser_module_parse_export_item_list (context_p);
|
||||
|
||||
if (context_p->token.type != LEXER_RIGHT_BRACE)
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
break;
|
||||
}
|
||||
|
||||
case LEXER_KEYW_DEFAULT:
|
||||
{
|
||||
/* TODO: This part is going to be implemented in the next part of the patch. */
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
break;
|
||||
}
|
||||
lexer_range_t range;
|
||||
parser_save_range (context_p, &range, context_p->source_end_p);
|
||||
|
||||
case LEXER_MULTIPLY:
|
||||
case LEXER_LITERAL:
|
||||
lexer_next_token (context_p);
|
||||
if (context_p->token.type == LEXER_KEYW_CLASS)
|
||||
{
|
||||
parser_module_parse_export_item_list (context_p);
|
||||
break;
|
||||
context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC;
|
||||
parser_parse_class (context_p, true);
|
||||
}
|
||||
|
||||
case LEXER_KEYW_FUNCTION:
|
||||
else if (context_p->token.type == LEXER_KEYW_FUNCTION)
|
||||
{
|
||||
context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC;
|
||||
parser_parse_function_statement (context_p);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Assignment expression */
|
||||
context_p->status_flags |= PARSER_MODULE_DEFAULT_EXPR;
|
||||
parser_set_range (context_p, &range);
|
||||
|
||||
/* 15.2.3.5 Use the synthetic name '*default*' as the identifier. */
|
||||
lexer_construct_literal_object (context_p,
|
||||
(lexer_lit_location_t *) &lexer_default_literal,
|
||||
lexer_default_literal.type);
|
||||
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
|
||||
|
||||
context_p->token.lit_location.type = LEXER_IDENT_LITERAL;
|
||||
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
|
||||
|
||||
context_p->module_identifier_lit_p = context_p->lit_object.literal_p;
|
||||
|
||||
/* Fake an assignment to the default identifier */
|
||||
context_p->token.type = LEXER_ASSIGN;
|
||||
|
||||
parser_parse_expression (context_p,
|
||||
PARSE_EXPR_STATEMENT | PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL);
|
||||
}
|
||||
|
||||
ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->module_identifier_lit_p->u.char_p,
|
||||
context_p->module_identifier_lit_p->prop.length);
|
||||
ecma_string_t *export_name_p = ecma_get_magic_string (LIT_MAGIC_STRING_DEFAULT);
|
||||
|
||||
if (parser_module_check_duplicate_export (context_p, export_name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
ecma_deref_ecma_string (export_name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
|
||||
}
|
||||
|
||||
parser_module_add_names_to_node (context_p,
|
||||
export_name_p,
|
||||
name_p);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
ecma_deref_ecma_string (export_name_p);
|
||||
context_p->status_flags &= (uint32_t) ~(PARSER_MODULE_DEFAULT_CLASS_OR_FUNC | PARSER_MODULE_DEFAULT_EXPR);
|
||||
break;
|
||||
}
|
||||
case LEXER_MULTIPLY:
|
||||
{
|
||||
lexer_next_token (context_p);
|
||||
if (!(context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4)))
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
|
||||
}
|
||||
|
||||
lexer_next_token (context_p);
|
||||
parser_module_handle_module_specifier (context_p);
|
||||
break;
|
||||
}
|
||||
case LEXER_KEYW_VAR:
|
||||
{
|
||||
parser_parse_var_statement (context_p);
|
||||
break;
|
||||
ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->module_identifier_lit_p->u.char_p,
|
||||
context_p->module_identifier_lit_p->prop.length);
|
||||
|
||||
if (parser_module_check_duplicate_export (context_p, name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
|
||||
}
|
||||
|
||||
parser_module_add_names_to_node (context_p,
|
||||
name_p,
|
||||
name_p);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
break;
|
||||
}
|
||||
case LEXER_KEYW_CLASS:
|
||||
{
|
||||
/* TODO: This part is going to be implemented in the next part of the patch. */
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
break;
|
||||
parser_parse_class (context_p, true);
|
||||
ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->module_identifier_lit_p->u.char_p,
|
||||
context_p->module_identifier_lit_p->prop.length);
|
||||
|
||||
if (parser_module_check_duplicate_export (context_p, name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED);
|
||||
parser_module_add_names_to_node (context_p,
|
||||
name_p,
|
||||
name_p);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
break;
|
||||
}
|
||||
case LEXER_KEYW_FUNCTION:
|
||||
{
|
||||
parser_parse_function_statement (context_p);
|
||||
ecma_string_t *name_p = ecma_new_ecma_string_from_utf8 (context_p->module_identifier_lit_p->u.char_p,
|
||||
context_p->module_identifier_lit_p->prop.length);
|
||||
|
||||
if (parser_module_check_duplicate_export (context_p, name_p))
|
||||
{
|
||||
ecma_deref_ecma_string (name_p);
|
||||
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER);
|
||||
}
|
||||
|
||||
parser_module_add_names_to_node (context_p,
|
||||
name_p,
|
||||
name_p);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
break;
|
||||
}
|
||||
case LEXER_LEFT_BRACE:
|
||||
{
|
||||
parser_module_parse_export_clause (context_p);
|
||||
|
||||
if (context_p->token.type == LEXER_LITERAL
|
||||
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4))
|
||||
{
|
||||
/* TODO: Import the requested properties from the given script and export
|
||||
them from the current to make a redirection.
|
||||
This part is going to be implemented in the next part of the patch. */
|
||||
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED);
|
||||
lexer_next_token (context_p);
|
||||
parser_module_handle_module_specifier (context_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parser_module_add_export_node_to_context (context_p);
|
||||
|
||||
@@ -1066,42 +1066,50 @@ parser_error_to_string (parser_error_t error) /**< error code */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
case PARSER_ERR_MODULE_REQUEST_NOT_FOUND:
|
||||
{
|
||||
return "Import request not found in the module.";
|
||||
}
|
||||
case PARSER_ERR_FILE_NOT_FOUND:
|
||||
{
|
||||
return "Requested module not found.";
|
||||
}
|
||||
case PARSER_ERR_NOT_IMPLEMENTED:
|
||||
{
|
||||
return "Requested feature is not implemented yet.";
|
||||
}
|
||||
case PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED:
|
||||
{
|
||||
return "Expected '{' or '*' or literal token.";
|
||||
}
|
||||
case PARSER_ERR_RIGHT_PAREN_COMMA_FROM_EXPECTED:
|
||||
{
|
||||
return "Expected '}' or 'as' or 'from' literal token.";
|
||||
}
|
||||
case PARSER_ERR_FROM_EXPECTED:
|
||||
{
|
||||
return "Expected 'from' token.";
|
||||
}
|
||||
case PARSER_ERR_FROM_COMMA_EXPECTED:
|
||||
{
|
||||
return "Expected 'from' or ',' token.";
|
||||
}
|
||||
case PARSER_ERR_AS_EXPECTED:
|
||||
{
|
||||
return "Expected 'as' token.";
|
||||
}
|
||||
case PARSER_ERR_STRING_EXPECTED:
|
||||
{
|
||||
return "Expected a string.";
|
||||
}
|
||||
case PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED:
|
||||
{
|
||||
return "Maximum module request count reached.";
|
||||
return "Expected a string literal.";
|
||||
}
|
||||
case PARSER_ERR_MODULE_UNEXPECTED:
|
||||
{
|
||||
return "Import and export statements must be in the global context.";
|
||||
}
|
||||
case PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED:
|
||||
{
|
||||
return "Expected '{' or '*' token.";
|
||||
}
|
||||
case PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED:
|
||||
{
|
||||
return "Expected '{' or '*' or literal token.";
|
||||
}
|
||||
case PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED:
|
||||
{
|
||||
return "Expected '}' or ',' token.";
|
||||
}
|
||||
case PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER:
|
||||
{
|
||||
return "Duplicate exported identifier.";
|
||||
}
|
||||
case PARSER_ERR_DUPLICATED_IMPORT_BINDING:
|
||||
{
|
||||
return "Duplicated imported binding name.";
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
default:
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-literal-storage.h"
|
||||
#include "ecma-module.h"
|
||||
#include "jcontext.h"
|
||||
#include "js-parser-internal.h"
|
||||
#include "ecma-module.h"
|
||||
|
||||
#ifndef JERRY_DISABLE_JS_PARSER
|
||||
|
||||
@@ -2399,7 +2399,7 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
context.status_flags |= parse_opts & PARSER_STRICT_MODE_MASK;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
context.module_context_p = NULL;
|
||||
context.module_current_node_p = NULL;
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_CLASS)
|
||||
@@ -2479,14 +2479,6 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
|
||||
JERRY_ASSERT (context.allocated_buffer_p == NULL);
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context.module_context_p != NULL)
|
||||
{
|
||||
parser_module_handle_requests (&context);
|
||||
ecma_module_load_modules (&context);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
compiled_code_p = parser_post_processing (&context);
|
||||
parser_list_free (&context.literal_pool);
|
||||
|
||||
@@ -2513,6 +2505,14 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
context.allocated_buffer_size);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context.module_current_node_p != NULL
|
||||
&& context.module_current_node_p->module_names_p != NULL)
|
||||
{
|
||||
ecma_module_release_module_names (context.module_current_node_p->module_names_p);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (error_location_p != NULL)
|
||||
{
|
||||
error_location_p->error = context.error;
|
||||
@@ -2535,9 +2535,6 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
}
|
||||
#endif /* PARSER_DUMP_BYTE_CODE */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
parser_module_context_cleanup (&context);
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
parser_stack_free (&context);
|
||||
|
||||
return compiled_code_p;
|
||||
@@ -2866,13 +2863,6 @@ void
|
||||
parser_raise_error (parser_context_t *context_p, /**< context */
|
||||
parser_error_t error) /**< error code */
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (context_p->module_context_p != NULL)
|
||||
{
|
||||
parser_module_free_saved_names (context_p->module_current_node_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
parser_saved_context_t *saved_context_p = context_p->last_context_p;
|
||||
|
||||
while (saved_context_p != NULL)
|
||||
@@ -2943,6 +2933,12 @@ parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
|
||||
|
||||
if (!*bytecode_data_p)
|
||||
{
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL)
|
||||
{
|
||||
ecma_module_cleanup ();
|
||||
}
|
||||
#endif
|
||||
#ifdef JERRY_DEBUGGER
|
||||
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
||||
{
|
||||
@@ -2983,6 +2979,22 @@ parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
|
||||
#endif /* JERRY_ENABLE_ERROR_MESSAGES */
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL)
|
||||
{
|
||||
ecma_value_t ret_value = ecma_module_parse_modules ();
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_bytecode_deref (*bytecode_data_p);
|
||||
*bytecode_data_p = NULL;
|
||||
ecma_module_cleanup ();
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
#ifdef JERRY_DEBUGGER
|
||||
if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
|
||||
== (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
|
||||
|
||||
@@ -130,15 +130,17 @@ typedef enum
|
||||
PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
PARSER_ERR_RIGHT_PAREN_COMMA_FROM_EXPECTED, /**< rigth paren or comma or from expected */
|
||||
PARSER_ERR_FILE_NOT_FOUND, /**< file not found*/
|
||||
PARSER_ERR_FROM_EXPECTED, /**< from expected */
|
||||
PARSER_ERR_FROM_COMMA_EXPECTED, /**< from or comma expected */
|
||||
PARSER_ERR_AS_EXPECTED, /**< as expected */
|
||||
PARSER_ERR_STRING_EXPECTED, /**< string literal expected */
|
||||
PARSER_ERR_MODULE_REQUEST_NOT_FOUND, /**< not found imported variable in module */
|
||||
PARSER_ERR_FILE_NOT_FOUND, /**< not found given file in the import statement */
|
||||
PARSER_ERR_NOT_IMPLEMENTED, /**< feature not implemented yet */
|
||||
PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED, /**< maximum number of requests reached */
|
||||
PARSER_ERR_MODULE_UNEXPECTED, /**< unexpected import or export statement */
|
||||
PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED, /**< left paren or multiply or literal expected */
|
||||
PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED, /**< left brace or multiply or literal expected */
|
||||
PARSER_ERR_LEFT_BRACE_MULTIPLY_EXPECTED, /**< left brace or multiply expected */
|
||||
PARSER_ERR_RIGHT_BRACE_COMMA_EXPECTED, /**< right brace or comma expected */
|
||||
PARSER_ERR_DUPLICATED_EXPORT_IDENTIFIER, /**< duplicated export identifier name */
|
||||
PARSER_ERR_DUPLICATED_IMPORT_BINDING, /**< duplicated import binding name */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
PARSER_ERR_NON_STRICT_ARG_DEFINITION /**< non-strict argument definition */
|
||||
|
||||
+21
-9
@@ -239,21 +239,14 @@ ecma_value_t
|
||||
vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode to run */
|
||||
ecma_object_t *lex_env_p) /**< pointer to the specified lexenv to run in */
|
||||
{
|
||||
ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL);
|
||||
ecma_object_t *glob_obj_p = ecma_builtin_get_global ();
|
||||
|
||||
ecma_value_t ret_value = vm_run (bytecode_p,
|
||||
return vm_run (bytecode_p,
|
||||
ecma_make_object_value (glob_obj_p),
|
||||
lex_env_p,
|
||||
false,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ret_value = ecma_create_error_reference_from_context ();
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* vm_run_module */
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
@@ -3588,6 +3581,25 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade
|
||||
JERRY_VLA (ecma_value_t, stack, JERRY_MAX (call_stack_size, 1));
|
||||
frame_ctx.registers_p = stack;
|
||||
|
||||
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL)
|
||||
{
|
||||
ecma_value_t ret_value = ecma_module_connect_imports ();
|
||||
|
||||
if (ecma_is_value_empty (ret_value))
|
||||
{
|
||||
ret_value = ecma_module_check_indirect_exports ();
|
||||
}
|
||||
|
||||
ecma_module_cleanup ();
|
||||
|
||||
if (!ecma_is_value_empty (ret_value))
|
||||
{
|
||||
return ret_value;
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
|
||||
|
||||
return vm_execute (&frame_ctx, arg_list_p, arg_list_len);
|
||||
} /* vm_run */
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jerryscript-port.h"
|
||||
#include "jerryscript-port-default.h"
|
||||
@@ -194,3 +195,24 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
{
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size) /**< size of output buffer */
|
||||
{
|
||||
/* TODO: implement path normalization */
|
||||
size_t len = strlen (in_path_p);
|
||||
if (len + 1 > out_buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy (out_buf_p, in_path_p);
|
||||
return len;
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
@@ -558,6 +558,27 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size) /**< size of output buffer */
|
||||
{
|
||||
size_t len = strlen (in_path_p);
|
||||
if (len + 1 > out_buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the original string. */
|
||||
strcpy (out_buf_p, in_path_p);
|
||||
return len;
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
/**
|
||||
* Dummy function to get the time zone adjustment.
|
||||
*
|
||||
|
||||
@@ -573,6 +573,27 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
|
||||
free (buffer_p);
|
||||
} /* jerry_port_release_source */
|
||||
|
||||
/**
|
||||
* Normalize a file path
|
||||
*
|
||||
* @return length of the path written to the output buffer
|
||||
*/
|
||||
size_t
|
||||
jerry_port_normalize_path (const char *in_path_p, /**< input file path */
|
||||
char *out_buf_p, /**< output buffer */
|
||||
size_t out_buf_size) /**< size of output buffer */
|
||||
{
|
||||
size_t len = strlen (in_path_p);
|
||||
if (len + 1 > out_buf_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the original string. */
|
||||
strcpy (out_buf_p, in_path_p);
|
||||
return len;
|
||||
} /* jerry_port_normalize_path */
|
||||
|
||||
/**
|
||||
* Main program.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {};
|
||||
export {a as aa,};
|
||||
export {b as bb, c as cc};
|
||||
export {d};
|
||||
export var x = 42;
|
||||
export function f(a) {return a;};
|
||||
export class Dog {
|
||||
constructor (name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
speak() {
|
||||
return this.name + " barks."
|
||||
}
|
||||
};
|
||||
export default "default";
|
||||
|
||||
var a = "a";
|
||||
var b = 5;
|
||||
var c = function(a) { return 2 * a;}
|
||||
var d = [1,2,3];
|
||||
|
||||
assert (x === 42);
|
||||
assert (f(1) === 1);
|
||||
var dog = new Dog("Pluto")
|
||||
assert(dog.speak() === "Pluto barks.")
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {} from "tests/jerry/es2015/module-export-01.js";
|
||||
export {aa,} from "tests/jerry/es2015/module-export-01.js";
|
||||
export {bb as b_, cc as c_} from "tests/jerry/es2015/module-export-01.js";
|
||||
export * from "tests/jerry/es2015/module-export-01.js";
|
||||
export default function () {return "default"};
|
||||
@@ -13,19 +13,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function getString (prefix) {
|
||||
return prefix + "String";
|
||||
export default class {
|
||||
constructor(num) {
|
||||
this.num = num
|
||||
}
|
||||
|
||||
function getAreaOfCircle (radius) {
|
||||
return radius * radius * pi;
|
||||
incr() {
|
||||
return ++(this.num);
|
||||
}
|
||||
}
|
||||
|
||||
export getAreaOfCircle as getArea;
|
||||
|
||||
import { pi } from "tests/jerry/es2015/module-imported-3.js";
|
||||
assert (pi === 3.14);
|
||||
|
||||
export pi as b;
|
||||
|
||||
assert (true);
|
||||
export * from "tests/jerry/es2015/module-export-02.js"
|
||||
@@ -13,19 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var a = 1;
|
||||
|
||||
function b () {
|
||||
return 2;
|
||||
}
|
||||
|
||||
export var c = 3;
|
||||
|
||||
export function d () {
|
||||
return 4;
|
||||
}
|
||||
|
||||
export { a as e, b }
|
||||
export var f = "str";
|
||||
|
||||
assert (true);
|
||||
export var x = 41
|
||||
export default a = "str"
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from "tests/jerry/es2015/module-export-01.js";
|
||||
export * from "tests/jerry/es2015/module-export-04.js";
|
||||
export default a = "str"
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {}
|
||||
export {} from "tests/jerry/es2015/module-export-01.js";
|
||||
export {};
|
||||
export {} from "tests/jerry/es2015/module-export-04.js"
|
||||
@@ -13,6 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export var pi = 3.14;
|
||||
|
||||
assert (true);
|
||||
export default x = y = z = "default";
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import "tests/jerry/es2015/module-export-01.js";
|
||||
import def from "tests/jerry/es2015/module-export-01.js";
|
||||
import {} from "tests/jerry/es2015/module-export-01.js";
|
||||
import {aa as a,} from "tests/jerry/es2015/module-export-01.js";
|
||||
import {bb as b, cc as c} from "tests/jerry/es2015/module-export-01.js";
|
||||
import {x} from "tests/jerry/es2015/module-export-01.js";
|
||||
import * as mod from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
assert (def === "default");
|
||||
assert (a === "a");
|
||||
assert (b === 5);
|
||||
assert (c(b) === 10);
|
||||
assert (Array.isArray(mod.d))
|
||||
assert (x === 42)
|
||||
assert (mod.f("str") === "str")
|
||||
|
||||
dog = new mod.Dog("Oddie")
|
||||
assert (dog.speak() === "Oddie barks.")
|
||||
@@ -13,23 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { b, c, d, e, f as g } from "tests/jerry/es2015/module-imported.js"
|
||||
import def, * as mod from "tests/jerry/es2015/module-export-02.js";
|
||||
import {b_, c_,} from "tests/jerry/es2015/module-export-02.js";
|
||||
|
||||
import
|
||||
{
|
||||
b as pi,
|
||||
getString,
|
||||
getArea
|
||||
} from "tests/jerry/es2015/module-imported-2.js"
|
||||
|
||||
var str = "str";
|
||||
|
||||
assert (b () === 2);
|
||||
assert (c === 3);
|
||||
assert (d () === 4);
|
||||
assert (e === 1);
|
||||
assert (g === str);
|
||||
|
||||
assert (pi === 3.14);
|
||||
assert (getArea (2) == 12.56);
|
||||
assert (getString (str) === "strString")
|
||||
assert (def() === "default")
|
||||
assert (mod.aa === "a")
|
||||
assert (b_ === 5)
|
||||
assert (c_(b_) === 10)
|
||||
assert (mod.x === 42)
|
||||
assert (Array.isArray(mod.d))
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import incrementer, {aa, c_, x,} from "tests/jerry/es2015/module-export-03.js"
|
||||
var i = new incrementer(3);
|
||||
assert(i.incr() === 4);
|
||||
assert(i.incr() === 5);
|
||||
assert(i.incr() === 6);
|
||||
|
||||
assert (aa === "a");
|
||||
assert (x === 42);
|
||||
assert (c_(x) == 84);
|
||||
@@ -13,4 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { , as b } from "tests/jerry/es2015/module-imported.js";
|
||||
import { , as b } from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import , as b from "tests/jerry/es2015/module-imported.js";
|
||||
import , as b from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
@@ -13,4 +13,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { b as , } from "tests/jerry/es2015/module-imported.js";
|
||||
import { b as , } from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import b as , from "tests/jerry/es2015/module-imported.js";
|
||||
/* Named imports must be in a NamedImports block. */
|
||||
import b as , from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { as as as } from "tests/jerry/es2015/module-imported.js";
|
||||
/* Can't have reserved words for the referenced bindings. */
|
||||
export { yield as y };
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { from as as } from "tests/jerry/es2015/module-imported.js";
|
||||
/* Module requests must always be evaluated. */
|
||||
import "tests/jerry/fail/module-sideeffect.js"
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* A string literal must always follow the 'from' keyword. */
|
||||
import { b } from
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* A string literal must always follow the 'from' keyword. */
|
||||
import { b } from 3
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { c as a, d as a } from "tests/jerry/es2015/module-imported.js";
|
||||
/* Can't have duplicate local bindings */
|
||||
import { c as a, d as a } from "tests/jerry/es2015/module-export-01.js";
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Import/export statements must be in the global scope. */
|
||||
if (true) {
|
||||
import { c } from "tests/jerry/es2015/module-imported.js";
|
||||
import { c } from "tests/jerry/es2015/module-export-01.js";
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Import/export statements must be in the global scope. */
|
||||
function someFunction() {
|
||||
import { c } from "tests/jerry/es2015/module-imported.js";
|
||||
import { c } from "tests/jerry/es2015/module-export-01.js";
|
||||
}
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
eval ("import { c } from 'tests/jerry/es2015/module-imported.js';");
|
||||
/* Import/export statements must be in the global scope. */
|
||||
eval ('import { c } from "tests/jerry/es2015/module-export-01.js";');
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// File does not exist.
|
||||
import { a } from "tests/jerry/fail/module-exports.js"
|
||||
/* NamedImports must always be followed by a FromClause. */
|
||||
import { b }, from "tests/jerry/es2015/module-export-01.js"
|
||||
|
||||
@@ -13,8 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function getString () {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
assert (getString());
|
||||
/* An import statement can have either a NameSpaceImport or NamedIpmorts */
|
||||
import * as mod, { b } from "tests/jerry/es2015/module-export-01.js"
|
||||
|
||||
@@ -13,4 +13,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* An ImportClause must be followed by a FromClause. */
|
||||
import { c }
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* '*' is not valid inside NamedImports. */
|
||||
import { *, d } from "tests/jerry/es2015/module-imported-01.js"
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Can't have duplicated local bindings. */
|
||||
import { b } from "tests/jerry/es2015/module-export-01.js"
|
||||
import { b } from "tests/jerry/es2015/module-export-02.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* FromClause must follow an ImportClause. */
|
||||
import from "tests/jerry/es2015/module-export-02.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Namespace imports must have a local name. */
|
||||
import * from "tests/jerry/es2015/module-export-01.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Star exports can't have an export name. */
|
||||
export * as star from "tests/jerry/es2015/module-export-01.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Indirect exports must be checked if they are resolvable. */
|
||||
export { l } from "tests/jerry/es2015/module-export-01.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Can't have circular imports/exports. */
|
||||
export { b } from "tests/jerry/fail/module-027.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Can't have circular imports/exports. */
|
||||
export { b } from "tests/jerry/fail/module-026.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Ambiguous import */
|
||||
import { x } from "tests/jerry/es2015/module-export-05.js"
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Import/export statements must be in the global scope. */
|
||||
Function('','import { c } from "tests/jerry/es2015/module-export-01.js";')
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* No default export found. */
|
||||
import def from "tests/jerry/es2015/module-export-06.js"
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
throw new Error("side-effect")
|
||||
Reference in New Issue
Block a user