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:
Daniel Vince
2019-04-25 14:57:17 +02:00
committed by Robert Fancsik
parent 938e9c7530
commit 37b7645e6a
59 changed files with 2209 additions and 991 deletions
+17 -1
View File
@@ -85,7 +85,8 @@ void jerry_port_print_char (char c);
### ES2015 Module system helper functions ### 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 ```c
/** /**
@@ -108,6 +109,21 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
{ {
free (buffer_p); free (buffer_p);
} /* jerry_port_release_source */ } /* 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 ## Date
+65 -39
View File
@@ -1,34 +1,48 @@
# ES6 module support for JerryScript # 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). The standard's relevant part can be found [here](https://www.ecma-international.org/ecma-262/6.0/#sec-modules).
## General ## 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 main.js
```js ```js
import { secret_number } from "./module.js" import { exported_value } from "./module.js"
print (secret_number); print (exported_value);
``` ```
module.js module.js
```js ```js
var secret_number = 42; var exported_value = 42;
export secret_number; export exported_value;
``` ```
## Supported features ## Supported features
* import variable or function * exporting identifiers from the module's lexical environment
* add alias name to the imported variable (function) * specifying export names for the exported values
* export variable or function * importing exported identifiers from a module
* add alias name to the exported variable (function) * 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 ### Example
@@ -69,22 +83,20 @@ export function getFeatureDetails() {
} }
``` ```
## Unsupported features ### Module namespace import statements
* **snapshot** 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.
* 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)` )
### 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 ```js
import { a, b } from 'module.js' import { a, b } from 'module.js'
@@ -105,28 +117,42 @@ export var b = 40;
### Default imports and exports ### Default imports and exports
TODO: This part is going to be written in the next part of the patch. 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.
### 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.
```js ```js
import { * as m } from "./module.js" import defaultExport, { b as c } from 'module.js'
print (m.secret_number); print (defaultExport); // 2
print (m.getPrettifiedNumber()); print (c ()); // 42
print (m.api.version);
``` ```
```js ```js
// module.js // module.js
var secret_number = 42; export default 2;
export secret_number; export function b () {
return 42;
export function getPrettifiedNumber() {
return "*** " + secret_number + " ***";
} }
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) ecma_finalize (void)
{ {
jmem_unregister_free_unused_memory_callback (ecma_free_unused_memory); 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_global_lex_env ();
ecma_finalize_builtins (); ecma_finalize_builtins ();
ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW); ecma_gc_run (JMEM_FREE_UNUSED_MEMORY_SEVERITY_LOW);
File diff suppressed because it is too large Load Diff
+116 -3
View File
@@ -16,12 +16,125 @@
#ifndef ECMA_MODULE_H #ifndef ECMA_MODULE_H
#define ECMA_MODULE_H #define ECMA_MODULE_H
#include "js-parser-internal.h"
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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 /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
#endif /* !ECMA_MODULE_H */ #endif /* !ECMA_MODULE_H */
-40
View File
@@ -68,46 +68,6 @@ ecma_get_global_environment (void)
return JERRY_CONTEXT (ecma_global_lex_env_p); return JERRY_CONTEXT (ecma_global_lex_env_p);
} /* ecma_get_global_environment */ } /* 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) */
/** /**
* @} * @}
*/ */
+20 -4
View File
@@ -199,11 +199,11 @@ void jerry_port_print_char (char c);
* is enabled. The path is specified in the import statement's 'from "..."' * is enabled. The path is specified in the import statement's 'from "..."'
* section. * section.
* *
* @param file_name_p Path that points to the EcmaScript file in the * @param file_name_p Path that points to the EcmaScript file in the
* filesystem. * filesystem.
* @param out_size_p The opened file's size in bytes. * @param out_size_p The opened file's size in bytes.
* *
* @return the pointer to the buffer which contains the content of the file. * @return the pointer to the buffer which contains the content of the file.
*/ */
uint8_t *jerry_port_read_source (const char *file_name_p, size_t *out_size_p); uint8_t *jerry_port_read_source (const char *file_name_p, size_t *out_size_p);
@@ -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); 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);
/** /**
* @} * @}
*/ */
+2 -13
View File
@@ -67,17 +67,6 @@ typedef struct jerry_context_data_header
*/ */
#define JERRY_CONTEXT_FIRST_MEMBER ecma_builtin_objects #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 * JerryScript context
* *
@@ -116,8 +105,8 @@ struct jerry_context_t
ecma_object_t *ecma_global_lex_env_p; /**< global lexical environment */ ecma_object_t *ecma_global_lex_env_p; /**< global lexical environment */
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
ecma_module_lex_envs_t *ecma_module_lex_envs_p; /**< list of module's lexical environments */ ecma_module_t *ecma_modules_p; /**< list of referenced modules */
parser_module_context_t *module_top_context_p; /**< top (current) module parser context */ ecma_module_context_t *module_top_context_p; /**< top (current) module parser context */
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */ vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */
+6
View File
@@ -22,6 +22,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ")
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_PAREN, ")") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_PAREN, ")")
#endif #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, ",") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",")
#if ENABLED (JERRY_BUILTIN_REGEXP) #if ENABLED (JERRY_BUILTIN_REGEXP)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/") 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) #if ENABLED (JERRY_BUILTIN_ANNEXB) && ENABLED (JERRY_BUILTIN_REGEXP)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile")
#endif #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) #if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENTRIES, "entries")
#endif #endif
+2
View File
@@ -23,6 +23,7 @@
[LIT_MAGIC_STRINGS] [LIT_MAGIC_STRINGS]
LIT_MAGIC_STRING__EMPTY = "" LIT_MAGIC_STRING__EMPTY = ""
LIT_MAGIC_STRING_ASTERIX_CHAR = "*"
LIT_MAGIC_STRING_SPACE_CHAR = " " LIT_MAGIC_STRING_SPACE_CHAR = " "
LIT_MAGIC_STRING_RIGHT_PAREN = ")" LIT_MAGIC_STRING_RIGHT_PAREN = ")"
LIT_MAGIC_STRING_COMMA_CHAR = "," 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_SYMBOL_DOT_UL = "Symbol."
LIT_MAGIC_STRING_BOOLEAN = "boolean" LIT_MAGIC_STRING_BOOLEAN = "boolean"
LIT_MAGIC_STRING_COMPILE = "compile" LIT_MAGIC_STRING_COMPILE = "compile"
LIT_MAGIC_STRING_DEFAULT = "default"
LIT_MAGIC_STRING_FOR_EACH_UL = "forEach" LIT_MAGIC_STRING_FOR_EACH_UL = "forEach"
LIT_MAGIC_STRING_GET_DATE_UL = "getDate" LIT_MAGIC_STRING_GET_DATE_UL = "getDate"
LIT_MAGIC_STRING_GET_INT8_UL = "getInt8" LIT_MAGIC_STRING_GET_INT8_UL = "getInt8"
+15
View File
@@ -2277,6 +2277,21 @@ lexer_expect_identifier (parser_context_t *context_p, /**< context */
return; 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); parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
} /* lexer_expect_identifier */ } /* lexer_expect_identifier */
+19
View File
@@ -17,6 +17,8 @@
#ifndef JERRY_DISABLE_JS_PARSER #ifndef JERRY_DISABLE_JS_PARSER
#include "jcontext.h" #include "jcontext.h"
#include "ecma-helpers.h"
#include "lit-char-helpers.h" #include "lit-char-helpers.h"
/** \addtogroup parser Parser /** \addtogroup parser Parser
@@ -568,6 +570,14 @@ parser_parse_class (parser_context_t *context_p, /**< context */
class_ident_index = context_p->lit_object.index; class_ident_index = context_p->lit_object.index;
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR; 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); lexer_next_token (context_p);
} }
else else
@@ -1266,6 +1276,15 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
lexer_construct_literal_object (context_p, lexer_construct_literal_object (context_p,
&context_p->token.lit_location, &context_p->token.lit_location,
context_p->token.lit_location.type); 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) else if (context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)
{ {
+20 -71
View File
@@ -24,6 +24,8 @@
#include "js-parser-limits.h" #include "js-parser-limits.h"
#include "js-lexer.h" #include "js-lexer.h"
#include "ecma-module.h"
/** \addtogroup parser Parser /** \addtogroup parser Parser
* @{ * @{
* *
@@ -78,6 +80,10 @@ typedef enum
PARSER_CLASS_STATIC_FUNCTION = (1u << 23), /**< this function is a static class method */ 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 */ PARSER_CLASS_SUPER_PROP_REFERENCE = (1u << 24), /**< super property call or assignment */
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #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; } parser_general_flags_t;
/** /**
@@ -296,59 +302,6 @@ typedef struct
#endif /* JERRY_DEBUGGER */ #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 * Those members of a context which needs
* to be saved when a sub-function is parsed. * to be saved when a sub-function is parsed.
@@ -396,8 +349,8 @@ typedef struct
parser_stack_iterator_t last_statement; /**< last statement position */ parser_stack_iterator_t last_statement; /**< last statement position */
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
parser_module_context_t *module_context_p; /**< shared module context inside the parser */ ecma_module_node_t *module_current_node_p; /**< import / export node that is being processed */
parser_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) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
/* Lexer members. */ /* 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_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_add_import_node_to_context (parser_context_t *context_p);
void parser_module_check_request_place (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_context_init (parser_context_t *context_p);
void parser_module_free_saved_names (parser_module_node_t *module_node_p); void parser_module_handle_module_specifier (parser_context_t *context_p);
void parser_module_handle_from_clause (parser_context_t *context_p);
void parser_module_handle_requests (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_clause (parser_context_t *context_p);
void parser_module_parse_export_item_list (parser_context_t *context_p); void parser_module_parse_import_clause (parser_context_t *context_p);
void parser_module_parse_import_item_list (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,
parser_module_node_t *parser_module_create_module_node (parser_context_t *context_p, ecma_module_node_t *template_node_p);
parser_module_node_t *template_node_p); bool parser_module_check_duplicate_import (parser_context_t *context_p, ecma_string_t *local_name_p);
parser_module_node_t *parser_module_get_export_node (parser_context_t *context_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,
void parser_module_add_item_to_node (parser_context_t *context_p, ecma_string_t *imex_name_p,
parser_module_node_t *module_node_p, ecma_string_t *local_name_p);
lexer_literal_t *import_name_p,
lexer_literal_t *local_name_p,
bool is_import_item);
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
+312 -402
View File
@@ -19,114 +19,121 @@
#include "jcontext.h" #include "jcontext.h"
#include "jerryscript-port.h" #include "jerryscript-port.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h" #include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h" #include "ecma-helpers.h"
#include "ecma-literal-storage.h"
#include "ecma-lex-env.h" #include "ecma-lex-env.h"
#include "ecma-module.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. * Check for duplicated imported binding names.
* @return true - if the given item is duplicated entry in the current node *
* @return true - if the given name is a duplicate
* false - otherwise * false - otherwise
*/ */
static bool bool
parser_module_check_for_duplicates_in_node (parser_module_node_t *module_node_p, /**< module node */ parser_module_check_duplicate_import (parser_context_t *context_p, /**< parser context */
lexer_literal_t *import_name_p) /**< newly imported name */ ecma_string_t *local_name_p) /**< newly imported name */
{ {
JERRY_ASSERT (import_name_p != NULL); ecma_module_names_t *module_names_p = context_p->module_current_node_p->module_names_p;
while (module_names_p != NULL)
parser_module_names_t *import_names_p = module_node_p->module_names_p;
while (import_names_p != NULL)
{ {
uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; if (ecma_compare_ecma_strings (module_names_p->local_name_p, local_name_p))
lit_utf8_size_t current_length = 0;
const uint8_t *current_p = ecma_string_get_chars (import_names_p->import_name_p, &current_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)
{ {
return true; 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; return false;
} /* parser_module_check_for_duplicates_in_node */ } /* parser_module_check_duplicate_import */
/** /**
* Check duplicates in the whole module context. * Check for duplicated exported bindings.
* @return true - if the given item is duplicated entry * @return - true - if the exported name is a duplicate
* false - otherwise * false - otherwise
*/ */
static bool bool
parser_module_check_for_duplicates (parser_context_t *context_p, /**< parser context */ parser_module_check_duplicate_export (parser_context_t *context_p, /**< parser context */
parser_module_node_t *module_node_p, /**< module noda */ ecma_string_t *export_name_p) /**< exported identifier */
lexer_literal_t *import_name_p) /**< newly imported name */
{ {
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)
{ {
return false; if (ecma_compare_ecma_strings (current_names_p->imex_name_p, export_name_p))
{
return true;
}
current_names_p = current_names_p->next_p;
} }
bool hasDuplicate = parser_module_check_for_duplicates_in_node (module_node_p, ecma_module_node_t *export_node_p = JERRY_CONTEXT (module_top_context_p)->local_exports_p;
import_name_p); if (export_node_p != NULL)
if (!hasDuplicate)
{ {
parser_module_node_t *node_p = context_p->module_context_p->imports_p; JERRY_ASSERT (export_node_p->next_p == NULL);
while (node_p != NULL && !hasDuplicate) ecma_module_names_t *name_p = export_node_p->module_names_p;
while (name_p != NULL)
{ {
hasDuplicate = parser_module_check_for_duplicates_in_node (node_p, if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
import_name_p); {
node_p = node_p->next_p; return true;
}
name_p = name_p->next_p;
} }
} }
return hasDuplicate; export_node_p = JERRY_CONTEXT (module_top_context_p)->indirect_exports_p;
} /* parser_module_check_for_duplicates */ while (export_node_p != NULL)
/**
* 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; ecma_module_names_t *name_p = export_node_p->module_names_p;
}
parser_module_names_t *current_p = module_node_p->module_names_p; while (name_p != NULL)
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); if (ecma_compare_ecma_strings (name_p->imex_name_p, export_name_p))
current_p->import_name_p = NULL; {
return true;
}
name_p = name_p->next_p;
} }
if (current_p->local_name_p != NULL) export_node_p = export_node_p->next_p;
{
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 */
/* Star exports don't have any names associated with them, so no need to check those. */
return false;
} /* parser_module_check_duplicate_export */
/** /**
* Add export node to parser context. * Add export node to parser context.
@@ -134,37 +141,56 @@ parser_module_free_saved_names (parser_module_node_t *module_node_p) /**< module
void void
parser_module_add_export_node_to_context (parser_context_t *context_p) /**< parser context */ 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; ecma_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 **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)
for (uint16_t i = 0; i < module_node_p->module_request_count - 1 ; i++)
{ {
module_names_p = module_names_p->next_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);
module_names_p->next_p = exports_p->module_names_p;
exports_p->module_names_p = module_node_p->module_names_p;
int request_count = exports_p->module_request_count + module_node_p->module_request_count;
if ((uint16_t) request_count < MAX_IMPORT_COUNT)
{
exports_p->module_request_count = (uint16_t) request_count;
} }
else else
{ {
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED); export_list_p = &(JERRY_CONTEXT (module_top_context_p)->indirect_exports_p);
} }
} }
else else
{ {
parser_module_node_t *export_node_p = parser_module_create_module_node (context_p, module_node_p); /* If there is no module request, then it's a local export. */
context_p->module_context_p->exports_p = export_node_p; export_list_p = &(JERRY_CONTEXT (module_top_context_p)->local_exports_p);
} }
/* 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 = stored_exports_p->module_names_p;
stored_exports_p->module_names_p = module_node_p->module_names_p;
}
return;
}
stored_exports_p = stored_exports_p->next_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 */ } /* 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 void
parser_module_add_import_node_to_context (parser_context_t *context_p) /**< parser context */ 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; ecma_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; ecma_module_node_t *stored_imports = JERRY_CONTEXT (module_top_context_p)->imports_p;
bool is_stored_module = false;
/* Check if we have a node with the same module request, append to it if we do. */
while (stored_imports != NULL) while (stored_imports != NULL)
{ {
if (stored_imports->script_path.length == module_node_p->script_path.length if (stored_imports->module_request_p == module_node_p->module_request_p)
&& memcmp (stored_imports->script_path.value_p,
module_node_p->script_path.value_p,
stored_imports->script_path.length) == 0)
{ {
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; if (module_names_p != NULL)
is_stored_module = true;
for (uint16_t i = 0; i < module_node_p->module_request_count - 1; i++)
{ {
module_names_p = module_names_p->next_p; 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; module_names_p->next_p = stored_imports->module_names_p;
stored_imports->module_names_p = module_node_p->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 return;
{
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED);
}
break;
} }
stored_imports = stored_imports->next_p; stored_imports = stored_imports->next_p;
} }
if (!is_stored_module) 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;
parser_module_node_t *permanent_node_p = parser_module_create_module_node (context_p, module_node_p); JERRY_CONTEXT (module_top_context_p)->imports_p = permanent_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 */ } /* parser_module_add_import_node_to_context */
/** /**
* Add import or export item to module node. * Add module names to current module node.
*/ */
void void
parser_module_add_item_to_node (parser_context_t *context_p, /**< parser context */ parser_module_add_names_to_node (parser_context_t *context_p, /**< parser context */
parser_module_node_t *module_node_p, /**< current module node */ ecma_string_t *imex_name_p, /**< import/export name */
lexer_literal_t *import_name_p, /**< import name */ ecma_string_t *local_name_p) /**< local name */
lexer_literal_t *local_name_p, /**< local name */
bool is_import_item) /**< given item is import item */
{ {
if (is_import_item ecma_module_names_t *new_names_p = (ecma_module_names_t *) parser_malloc (context_p,
&& parser_module_check_for_duplicates (context_p, module_node_p, import_name_p)) sizeof (ecma_module_names_t));
{ memset (new_names_p, 0, sizeof (ecma_module_names_t));
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));
ecma_module_node_t *module_node_p = context_p->module_current_node_p;
new_names_p->next_p = module_node_p->module_names_p; 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 = new_names_p;
module_node_p->module_names_p->import_name_p = ecma_new_ecma_string_from_utf8 (import_name_p->u.char_p, JERRY_ASSERT (imex_name_p != NULL);
import_name_p->prop.length); ecma_ref_ecma_string (imex_name_p);
new_names_p->imex_name_p = imex_name_p;
module_node_p->module_names_p->local_name_p = ecma_new_ecma_string_from_utf8 (local_name_p->u.char_p, JERRY_ASSERT (local_name_p != NULL);
local_name_p->prop.length); ecma_ref_ecma_string (local_name_p);
new_names_p->local_name_p = local_name_p;
module_node_p->module_request_count++; } /* parser_module_add_names_to_node */
} /* parser_module_add_item_to_node */
/** /**
* Cleanup the whole module context from parser context. * Create module context if needed.
*/
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;
}
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 */
/**
* Create module context and bind to the parser context.
*/ */
void void
parser_module_context_init (parser_context_t *context_p) /**< parser context */ 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, ecma_module_context_t *module_context_p;
sizeof (parser_module_context_t)); 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 */ } /* 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. * @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_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) if (template_node_p != NULL)
{ {
node->module_names_p = template_node_p->module_names_p; node_p->module_names_p = template_node_p->module_names_p;
node->module_request_count = template_node_p->module_request_count; node_p->module_request_p = template_node_p->module_request_p;
node_p->next_p = NULL;
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;
} }
else 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 */ } /* parser_module_create_module_node */
/** /**
* Create export node or get the previously created one. * Parse an ExportClause.
* @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.
*/ */
void 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 JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4)) lexer_next_token (context_p);
{
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;
while (true) while (true)
{ {
if (has_export_name if (context_p->token.type == LEXER_RIGHT_BRACE)
&& 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)))
{ {
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); lexer_next_token (context_p);
}
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; break;
} }
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))
{
/* 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);
}
/* 15.2.3.1 The referenced binding cannot be a reserved word. */
if (context_p->token.type != LEXER_LITERAL if (context_p->token.type != LEXER_LITERAL
|| lexer_compare_raw_identifier_to_current (context_p, "from", 4) || context_p->token.lit_location.type != LEXER_IDENT_LITERAL
|| lexer_compare_raw_identifier_to_current (context_p, "as", 2)) || context_p->token.literal_is_reserved)
{ {
parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER); 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); lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
if (has_import_name) 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);
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_ref_ecma_string (local_name_p);
export_name_p = local_name_p;
lexer_next_token (context_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_RIGHT_BRACE if (context_p->token.type != LEXER_LITERAL
|| (context_p->token.type == LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_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)
{
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_IDENTIFIER_EXPECTED);
} }
has_import_name = true; lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
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);
} }
else
if (parser_module_check_duplicate_export (context_p, export_name_p))
{ {
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_COMMA_FROM_EXPECTED); ecma_deref_ecma_string (local_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, 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_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);
} }
lexer_next_token (context_p);
} }
} /* parser_module_parse_import_item_list */ } /* parser_module_parse_export_clause */
/** /**
* Handle import requests. * Parse an ImportClause
* Check if imported variables are exported in the appropriate module.
* Raise parser error if imported item is not exported.
*/ */
void 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; if (context_p->token.type == LEXER_RIGHT_BRACE)
}
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)
{
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)) lexer_next_token (context_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;
break; break;
} }
import_name_p = import_name_p->next_p; if (context_p->token.type != LEXER_LITERAL
} || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
*module_context_p->exports_p = *context_p->module_context_p->exports_p; ecma_string_t *import_name_p = NULL;
parser_free (context_p->module_context_p->exports_p, sizeof (parser_module_node_t)); ecma_string_t *local_name_p = NULL;
if (throw_error) lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_IDENT_LITERAL);
{
parser_raise_error (context_p, PARSER_ERR_MODULE_REQUEST_NOT_FOUND); 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_handle_requests */ } /* parser_module_parse_import_clause */
/** /**
* Raises parser error if the import or export statement is not in the global scope. * 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 if (context_p->last_context_p != NULL
|| context_p->stack_top_uint8 != 0 || 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_raise_error (context_p, PARSER_ERR_MODULE_UNEXPECTED);
} }
} /* parser_module_check_request_place */ } /* 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 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; ecma_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->token.type != LEXER_LITERAL
|| context_p->token.lit_location.type != LEXER_STRING_LITERAL
if (context_p->lit_object.literal_p->prop.length == 0) || 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); lexer_construct_literal_object (context_p, &context_p->token.lit_location, LEXER_STRING_LITERAL);
module_node_p->script_path.value_p = (uint8_t *) parser_malloc (context_p,
module_node_p->script_path.length * sizeof (uint8_t));
memcpy (module_node_p->script_path.value_p, 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->u.char_p, context_p->lit_object.literal_p->prop.length);
module_node_p->script_path.length);
module_node_p->script_path.value_p[module_node_p->script_path.length - 1] = '\0';
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); lexer_next_token (context_p);
} /* parser_module_handle_from_clause */ } /* parser_module_handle_module_specifier */
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
+219 -79
View File
@@ -17,6 +17,8 @@
#ifndef JERRY_DISABLE_JS_PARSER #ifndef JERRY_DISABLE_JS_PARSER
#include "jcontext.h" #include "jcontext.h"
#include "ecma-helpers.h"
#include "lit-char-helpers.h" #include "lit-char-helpers.h"
/** \addtogroup parser Parser /** \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; context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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_identifier_lit_p = context_p->lit_object.literal_p;
context_p->module_current_node_p,
context_p->lit_object.literal_p,
context_p->lit_object.literal_p,
false);
} }
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #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; name_p = context_p->lit_object.literal_p;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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_identifier_lit_p = context_p->lit_object.literal_p;
context_p->module_current_node_p,
name_p,
name_p,
false);
} }
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #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) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
/** /**
* Parse import statement. * Parse import statement.
* Note: See 15.2.2
*/ */
static void 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); JERRY_ASSERT (context_p->token.type == LEXER_KEYW_IMPORT);
parser_module_check_request_place (context_p); parser_module_check_request_place (context_p);
parser_module_context_init (context_p); parser_module_context_init (context_p);
parser_module_node_t module_node; ecma_module_node_t module_node;
memset (&module_node, 0, sizeof (parser_module_node_t)); memset (&module_node, 0, sizeof (ecma_module_node_t));
context_p->module_current_node_p = &module_node; context_p->module_current_node_p = &module_node;
lexer_next_token (context_p); 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)))
{ {
lexer_next_token (context_p); parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED);
parser_module_parse_import_item_list (context_p); }
if (context_p->token.type != LEXER_RIGHT_BRACE) 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))
{ {
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); 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);
if (context_p->token.type != LEXER_MULTIPLY
&& context_p->token.type != LEXER_LEFT_BRACE)
{
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); lexer_next_token (context_p);
break; if (context_p->token.type != LEXER_LITERAL)
{
parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
}
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_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);
} }
case LEXER_MULTIPLY: if (context_p->token.type != LEXER_LITERAL || !lexer_compare_raw_identifier_to_current (context_p, "from", 4))
case LEXER_LITERAL:
{ {
parser_module_parse_import_item_list (context_p); parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
break;
}
default:
{
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED);
} }
lexer_next_token (context_p);
} }
if (context_p->token.type != LEXER_LITERAL ||!lexer_compare_raw_identifier_to_current (context_p, "from", 4)) parser_module_handle_module_specifier (context_p);
{
parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
}
parser_module_handle_from_clause (context_p);
parser_module_add_import_node_to_context (context_p); parser_module_add_import_node_to_context (context_p);
context_p->module_current_node_p = NULL; context_p->module_current_node_p = NULL;
@@ -1744,77 +1803,158 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
parser_module_check_request_place (context_p); parser_module_check_request_place (context_p);
parser_module_context_init (context_p); parser_module_context_init (context_p);
parser_module_node_t module_node; ecma_module_node_t module_node;
memset (&module_node, 0, sizeof (parser_module_node_t)); memset (&module_node, 0, sizeof (ecma_module_node_t));
context_p->module_current_node_p = &module_node; context_p->module_current_node_p = &module_node;
lexer_next_token (context_p); lexer_next_token (context_p);
switch (context_p->token.type) switch (context_p->token.type)
{ {
case LEXER_LEFT_BRACE: case LEXER_KEYW_DEFAULT:
{
lexer_range_t range;
parser_save_range (context_p, &range, context_p->source_end_p);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_KEYW_CLASS)
{
context_p->status_flags |= PARSER_MODULE_DEFAULT_CLASS_OR_FUNC;
parser_parse_class (context_p, true);
}
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);
}
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); lexer_next_token (context_p);
parser_module_parse_export_item_list (context_p); if (!(context_p->token.type == LEXER_LITERAL
&& lexer_compare_raw_identifier_to_current (context_p, "from", 4)))
if (context_p->token.type != LEXER_RIGHT_BRACE)
{ {
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED); parser_raise_error (context_p, PARSER_ERR_FROM_EXPECTED);
} }
lexer_next_token (context_p); lexer_next_token (context_p);
parser_module_handle_module_specifier (context_p);
break; 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;
}
case LEXER_MULTIPLY:
case LEXER_LITERAL:
{
parser_module_parse_export_item_list (context_p);
break;
}
case LEXER_KEYW_FUNCTION:
{
parser_parse_function_statement (context_p);
break;
}
case LEXER_KEYW_VAR: case LEXER_KEYW_VAR:
{ {
parser_parse_var_statement (context_p); parser_parse_var_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; break;
} }
case LEXER_KEYW_CLASS: case LEXER_KEYW_CLASS:
{ {
/* TODO: This part is going to be implemented in the next part of the patch. */ parser_parse_class (context_p, true);
parser_raise_error (context_p, PARSER_ERR_NOT_IMPLEMENTED); 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; 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))
{
lexer_next_token (context_p);
parser_module_handle_module_specifier (context_p);
}
break;
}
default: default:
{ {
parser_raise_error (context_p, PARSER_ERR_LEFT_PAREN_MULTIPLY_LITERAL_EXPECTED); parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_MULTIPLY_LITERAL_EXPECTED);
break; break;
} }
} }
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);
}
parser_module_add_export_node_to_context (context_p); parser_module_add_export_node_to_context (context_p);
context_p->module_current_node_p = NULL; context_p->module_current_node_p = NULL;
} /* parser_parse_export_statement */ } /* parser_parse_export_statement */
+29 -21
View File
@@ -1066,42 +1066,50 @@ parser_error_to_string (parser_error_t error) /**< error code */
} }
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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: case PARSER_ERR_FILE_NOT_FOUND:
{ {
return "Requested module 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: case PARSER_ERR_FROM_EXPECTED:
{ {
return "Expected 'from' token."; 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: case PARSER_ERR_STRING_EXPECTED:
{ {
return "Expected a string."; return "Expected a string literal.";
}
case PARSER_ERR_MODULE_REQUEST_LIMIT_REACHED:
{
return "Maximum module request count reached.";
} }
case PARSER_ERR_MODULE_UNEXPECTED: case PARSER_ERR_MODULE_UNEXPECTED:
{ {
return "Import and export statements must be in the global context."; 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) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
default: default:
+32 -20
View File
@@ -17,9 +17,9 @@
#include "ecma-exceptions.h" #include "ecma-exceptions.h"
#include "ecma-helpers.h" #include "ecma-helpers.h"
#include "ecma-literal-storage.h" #include "ecma-literal-storage.h"
#include "ecma-module.h"
#include "jcontext.h" #include "jcontext.h"
#include "js-parser-internal.h" #include "js-parser-internal.h"
#include "ecma-module.h"
#ifndef JERRY_DISABLE_JS_PARSER #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; context.status_flags |= parse_opts & PARSER_STRICT_MODE_MASK;
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
context.module_context_p = NULL; context.module_current_node_p = NULL;
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
#if ENABLED (JERRY_ES2015_CLASS) #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.last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
JERRY_ASSERT (context.allocated_buffer_p == NULL); 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); compiled_code_p = parser_post_processing (&context);
parser_list_free (&context.literal_pool); 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); 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) if (error_location_p != NULL)
{ {
error_location_p->error = context.error; 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 */ #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); parser_stack_free (&context);
return compiled_code_p; return compiled_code_p;
@@ -2866,13 +2863,6 @@ void
parser_raise_error (parser_context_t *context_p, /**< context */ parser_raise_error (parser_context_t *context_p, /**< context */
parser_error_t error) /**< error code */ 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; parser_saved_context_t *saved_context_p = context_p->last_context_p;
while (saved_context_p != NULL) 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 (!*bytecode_data_p)
{ {
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
if (JERRY_CONTEXT (module_top_context_p) != NULL)
{
ecma_module_cleanup ();
}
#endif
#ifdef JERRY_DEBUGGER #ifdef JERRY_DEBUGGER
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) 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 */ #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 #ifdef JERRY_DEBUGGER
if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT)) if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
== (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT)) == (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
+9 -7
View File
@@ -130,18 +130,20 @@ typedef enum
PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */ PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) #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_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_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_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) */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
PARSER_ERR_NON_STRICT_ARG_DEFINITION /**< non-strict argument definition */ PARSER_ERR_NON_STRICT_ARG_DEFINITION /**< non-strict argument definition */
} parser_error_t; } parser_error_t;
/** /**
+26 -14
View File
@@ -239,21 +239,14 @@ ecma_value_t
vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode to run */ 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 *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), ecma_make_object_value (glob_obj_p),
lex_env_p, lex_env_p,
false, false,
NULL, NULL,
0); 0);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
ret_value = ecma_create_error_reference_from_context ();
}
return ret_value;
} /* vm_run_module */ } /* vm_run_module */
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ #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)); JERRY_VLA (ecma_value_t, stack, JERRY_MAX (call_stack_size, 1));
frame_ctx.registers_p = stack; 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); return vm_execute (&frame_ctx, arg_list_p, arg_list_len);
} /* vm_run */ } /* vm_run */
+22
View File
@@ -15,6 +15,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "jerryscript-port.h" #include "jerryscript-port.h"
#include "jerryscript-port-default.h" #include "jerryscript-port-default.h"
@@ -194,3 +195,24 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
{ {
free (buffer_p); free (buffer_p);
} /* jerry_port_release_source */ } /* 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 */
+21
View File
@@ -558,6 +558,27 @@ jerry_port_release_source (uint8_t *buffer_p) /**< buffer to free */
free (buffer_p); free (buffer_p);
} /* jerry_port_release_source */ } /* 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. * 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); free (buffer_p);
} /* jerry_port_release_source */ } /* 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. * Main program.
* *
+41
View File
@@ -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.")
+20
View File
@@ -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. * limitations under the License.
*/ */
export function getString (prefix) { export default class {
return prefix + "String"; constructor(num) {
this.num = num
}
incr() {
return ++(this.num);
}
} }
function getAreaOfCircle (radius) { export * from "tests/jerry/es2015/module-export-02.js"
return radius * radius * pi;
}
export getAreaOfCircle as getArea;
import { pi } from "tests/jerry/es2015/module-imported-3.js";
assert (pi === 3.14);
export pi as b;
assert (true);
@@ -13,19 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
var a = 1; export var x = 41
export default a = "str"
function b () {
return 2;
}
export var c = 3;
export function d () {
return 4;
}
export { a as e, b }
export var f = "str";
assert (true);
+18
View File
@@ -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"
+19
View File
@@ -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. * limitations under the License.
*/ */
export var pi = 3.14; export default x = y = z = "default";
assert (true);
+33
View File
@@ -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. * 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 assert (def() === "default")
{ assert (mod.aa === "a")
b as pi, assert (b_ === 5)
getString, assert (c_(b_) === 10)
getArea assert (mod.x === 42)
} from "tests/jerry/es2015/module-imported-2.js" assert (Array.isArray(mod.d))
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")
+24
View File
@@ -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);
+1 -1
View File
@@ -13,4 +13,4 @@
* limitations under the License. * 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";
+1 -1
View File
@@ -13,4 +13,4 @@
* limitations under the License. * 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";
+1 -1
View File
@@ -13,4 +13,4 @@
* limitations under the License. * 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";
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * 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";
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * 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 };
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * 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"
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
import { b } from /* A string literal must always follow the 'from' keyword. */
import { b } from
+1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
/* A string literal must always follow the 'from' keyword. */
import { b } from 3 import { b } from 3
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * 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";
+2 -1
View File
@@ -13,6 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* Import/export statements must be in the global scope. */
if (true) { if (true) {
import { c } from "tests/jerry/es2015/module-imported.js"; import { c } from "tests/jerry/es2015/module-export-01.js";
} }
+2 -1
View File
@@ -13,6 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* Import/export statements must be in the global scope. */
function someFunction() { function someFunction() {
import { c } from "tests/jerry/es2015/module-imported.js"; import { c } from "tests/jerry/es2015/module-export-01.js";
} }
+2 -1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * 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";');
+2 -2
View File
@@ -13,5 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
// File does not exist. /* NamedImports must always be followed by a FromClause. */
import { a } from "tests/jerry/fail/module-exports.js" import { b }, from "tests/jerry/es2015/module-export-01.js"
+2 -5
View File
@@ -13,8 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
export function getString () { /* An import statement can have either a NameSpaceImport or NamedIpmorts */
return prefix; import * as mod, { b } from "tests/jerry/es2015/module-export-01.js"
}
assert (getString());
+1
View File
@@ -13,4 +13,5 @@
* limitations under the License. * limitations under the License.
*/ */
/* An ImportClause must be followed by a FromClause. */
import { c } import { c }
+17
View File
@@ -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"
+18
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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"
+17
View File
@@ -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";')
+17
View File
@@ -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"
+16
View File
@@ -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")