diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c
index aa1105517..816a1614b 100644
--- a/jerry-core/parser/js/js-parser-expr.c
+++ b/jerry-core/parser/js/js-parser-expr.c
@@ -3091,10 +3091,7 @@ parser_pattern_get_target (parser_context_t *context_p, /**< context */
}
else
{
- if (context_p->next_scanner_info_p->type != SCANNER_TYPE_INITIALIZER)
- {
- parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
- }
+ JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
scanner_get_location (&start_location, context_p);
scanner_set_location (context_p, &((scanner_location_info_t *) context_p->next_scanner_info_p)->location);
@@ -3205,7 +3202,7 @@ parser_pattern_form_assignment (parser_context_t *context_p, /**< context */
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
- if (context_p->token.type == LEXER_ASSIGN)
+ if (context_p->token.type == LEXER_ASSIGN && !(flags & PARSER_PATTERN_REST_ELEMENT))
{
parser_branch_t skip_init;
lexer_next_token (context_p);
@@ -3273,12 +3270,23 @@ parser_pattern_process_nested_pattern (parser_context_t *context_p, /**< context
| PARSER_PATTERN_LET
| PARSER_PATTERN_CONST
| PARSER_PATTERN_LOCAL
- | PARSER_PATTERN_REST_ELEMENT
| PARSER_PATTERN_ARGUMENTS)));
- if (context_p->next_scanner_info_p->source_p == context_p->source_p)
+ JERRY_ASSERT (context_p->next_scanner_info_p->source_p != context_p->source_p
+ || context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER
+ || context_p->next_scanner_info_p->type == SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER);
+
+ if (context_p->next_scanner_info_p->source_p == context_p->source_p
+ && context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER)
{
- options |= PARSER_PATTERN_TARGET_DEFAULT;
+ if (!(flags & PARSER_PATTERN_REST_ELEMENT))
+ {
+ options |= PARSER_PATTERN_TARGET_DEFAULT;
+ }
+ else
+ {
+ scanner_release_next (context_p, sizeof (scanner_location_info_t));
+ }
}
parser_pattern_emit_rhs (context_p, rhs_opcode, literal_index);
diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c
index 9d3d142a2..8f3774e0d 100644
--- a/jerry-core/parser/js/js-parser-statm.c
+++ b/jerry-core/parser/js/js-parser-statm.c
@@ -1324,6 +1324,11 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
if (token_type == LEXER_EOS)
{
lexer_next_token (context_p);
+
+ if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
+ {
+ token_type = context_p->token.type;
+ }
}
#else /* !ENABLED (JERRY_ESNEXT) */
lexer_next_token (context_p);
@@ -1411,6 +1416,25 @@ parser_parse_for_statement_start (parser_context_t *context_p) /**< context */
#endif /* ENABLED (JERRY_ESNEXT) */
break;
}
+#if ENABLED (JERRY_ESNEXT)
+ case LEXER_LEFT_BRACE:
+ case LEXER_LEFT_SQUARE:
+ {
+ if (context_p->next_scanner_info_p->source_p == context_p->source_p
+ && context_p->next_scanner_info_p->type == SCANNER_TYPE_FOR_PATTERN)
+ {
+ parser_emit_cbc_ext (context_p, is_for_in ? CBC_EXT_FOR_IN_GET_NEXT
+ : CBC_EXT_FOR_OF_GET_NEXT);
+
+ scanner_release_next (context_p, sizeof (scanner_info_t));
+ parser_parse_initializer (context_p, PARSER_PATTERN_TARGET_ON_STACK);
+ /* Pop the value returned by GET_NEXT. */
+ parser_emit_cbc (context_p, CBC_POP);
+ break;
+ }
+ /* FALLTHRU */
+ }
+#endif /* ENABLED (JERRY_ESNEXT) */
default:
{
uint16_t opcode;
diff --git a/jerry-core/parser/js/js-scanner-internal.h b/jerry-core/parser/js/js-scanner-internal.h
index 77cef99c1..b9fffa099 100644
--- a/jerry-core/parser/js/js-scanner-internal.h
+++ b/jerry-core/parser/js/js-scanner-internal.h
@@ -114,6 +114,7 @@ typedef enum
SCAN_STACK_CLASS_EXPRESSION, /**< class expression */
SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */
SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */
+ SCAN_STACK_FOR_START_PATTERN, /**< possible assignment pattern for "for" iterator */
SCAN_STACK_USE_ASYNC, /**< an "async" identifier is used */
SCAN_STACK_OBJECT_LITERAL_WITH_SUPER, /**< object literal with inner super reference */
#endif /* ENABLED (JERRY_ESNEXT) */
diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c
index 01e992585..6ce91b5d1 100644
--- a/jerry-core/parser/js/js-scanner-util.c
+++ b/jerry-core/parser/js/js-scanner-util.c
@@ -1679,6 +1679,7 @@ scanner_cleanup (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_ESNEXT)
JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
|| scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
+ || scanner_info_p->type == SCANNER_TYPE_FOR_PATTERN
|| scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
|| scanner_info_p->type == SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER
|| scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
diff --git a/jerry-core/parser/js/js-scanner.c b/jerry-core/parser/js/js-scanner.c
index bd371933b..438a00bb9 100644
--- a/jerry-core/parser/js/js-scanner.c
+++ b/jerry-core/parser/js/js-scanner.c
@@ -873,6 +873,20 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
return SCAN_NEXT_TOKEN;
}
+ if (context_p->stack_top_uint8 == SCAN_STACK_FOR_START_PATTERN)
+ {
+ JERRY_ASSERT (binding_type == SCANNER_BINDING_NONE);
+
+ parser_stack_change_last_uint8 (context_p, SCAN_STACK_FOR_START);
+
+ if (context_p->token.type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ())
+ {
+ scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
+ info_p->type = SCANNER_TYPE_FOR_PATTERN;
+ return SCAN_KEEP_TOKEN;
+ }
+ }
+
if (context_p->token.type != LEXER_ASSIGN)
{
if (SCANNER_NEEDS_BINDING_LIST (binding_type))
@@ -1243,6 +1257,12 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
break;
}
#if ENABLED (JERRY_ESNEXT)
+ case LEXER_LEFT_BRACE:
+ case LEXER_LEFT_SQUARE:
+ {
+ stack_mode = SCAN_STACK_FOR_START_PATTERN;
+ break;
+ }
case LEXER_LITERAL:
{
if (!lexer_token_is_let (context_p))
@@ -3515,16 +3535,16 @@ scan_completed:
print_location = true;
break;
}
- case SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER:
+ case SCANNER_TYPE_FOR_PATTERN:
{
- JERRY_DEBUG_MSG (" OBJECT-LITERAL-WITH-SUPER: source:%d\n",
+ JERRY_DEBUG_MSG (" SCANNER_TYPE_FOR_PATTERN: source:%d\n",
(int) (info_p->source_p - source_start_p));
print_location = false;
break;
}
case SCANNER_TYPE_CLASS_CONSTRUCTOR:
{
- JERRY_DEBUG_MSG (" CLASS-CONSTRUCTOR: source:%d\n",
+ JERRY_DEBUG_MSG (" CLASS_CONSTRUCTOR: source:%d\n",
(int) (info_p->source_p - source_start_p));
print_location = false;
break;
@@ -3547,6 +3567,13 @@ scan_completed:
(int) (info_p->source_p - source_start_p));
break;
}
+ case SCANNER_TYPE_OBJECT_LITERAL_WITH_SUPER:
+ {
+ JERRY_DEBUG_MSG (" OBJECT_LITERAL_WITH_SUPER: source:%d\n",
+ (int) (info_p->source_p - source_start_p));
+ print_location = false;
+ break;
+ }
#endif /* ENABLED (JERRY_ESNEXT) */
}
diff --git a/jerry-core/parser/js/js-scanner.h b/jerry-core/parser/js/js-scanner.h
index 298f645fc..fb24ac807 100644
--- a/jerry-core/parser/js/js-scanner.h
+++ b/jerry-core/parser/js/js-scanner.h
@@ -46,6 +46,7 @@ typedef enum
SCANNER_TYPE_CASE, /**< case statement */
#if ENABLED (JERRY_ESNEXT)
SCANNER_TYPE_INITIALIZER, /**< destructuring binding or assignment pattern with initializer */
+ SCANNER_TYPE_FOR_PATTERN, /**< assignment pattern for for-in or for-of interators */
SCANNER_TYPE_CLASS_CONSTRUCTOR, /**< class constructor */
SCANNER_TYPE_LET_EXPRESSION, /**< let expression */
SCANNER_TYPE_ERR_REDECLARED, /**< syntax error: a variable is redeclared */
diff --git a/tests/jerry/es.next/array-pattern.js b/tests/jerry/es.next/array-pattern.js
index ff7a75d52..86b1969be 100644
--- a/tests/jerry/es.next/array-pattern.js
+++ b/tests/jerry/es.next/array-pattern.js
@@ -60,6 +60,9 @@ checkSyntax ("[()] = []");
checkSyntax ("try { let [$] = $;");
checkSyntax ("let a, [ b.c ] = [6];");
checkSyntax ("let [(a)] = [1]");
+checkSyntax ("[...a = []] = [1]");
+checkSyntax ("[...[a] = []] = [1]");
+checkSyntax ("[...[a, [...b] = []] = []] = [1]");
mustThrow ("var [a] = 4");
mustThrow ("var [a] = 5");
diff --git a/tests/jerry/es.next/for-pattern.js b/tests/jerry/es.next/for-pattern.js
index bbcb4da75..f08ab959c 100644
--- a/tests/jerry/es.next/for-pattern.js
+++ b/tests/jerry/es.next/for-pattern.js
@@ -12,6 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+function check_syntax_error (code)
+{
+ try {
+ eval (code)
+ assert (false)
+ } catch (e) {
+ assert (e instanceof SyntaxError)
+ }
+}
+
var idx = 0;
for (var [a,b] of [[1,2], [3,4]])
{
@@ -69,9 +79,41 @@ for (let [a,b] of [[11,12], [13,14]])
assert(a === 3);
assert(b === 4);
-try {
- eval("for (let [a,b] = [1,2] of [[3,4]]) {}");
- assert(false);
-} catch (e) {
- assert(e instanceof SyntaxError);
+check_syntax_error("for (let [a,b] = [1,2] of [[3,4]]) {}")
+
+idx = 0;
+for ([a,b] of [[10,true], ["x",null]])
+{
+ if (idx == 0)
+ {
+ assert(a === 10);
+ assert(b === true);
+ idx = 1;
+ }
+ else
+ {
+ assert(a === "x");
+ assert(b === null);
+ }
}
+
+assert(a === "x");
+assert(b === null);
+
+check_syntax_error("for ([a,b] = [1,2] of [[3,4]]) {}")
+
+var o = {}
+for ([a, b] = [o,false]; false; )
+{
+ assert(false);
+}
+
+assert(a === o);
+assert(b === false);
+
+for ([a, b] + [a, b]; false; )
+{
+ assert(false);
+}
+
+check_syntax_error("for ([a,b] + 1 of [[3,4]]) {}")
diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml
index e59d6dbad..8fdcc9345 100644
--- a/tests/test262-es6-excludelist.xml
+++ b/tests/test262-es6-excludelist.xml
@@ -256,7 +256,6 @@
No longer a SyntaxError in ES11
-
@@ -330,8 +329,6 @@
-
-
ES2018 change: next method must be cached
diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml
index 3fc3ef330..54f814cbf 100644
--- a/tests/test262-esnext-excludelist.xml
+++ b/tests/test262-esnext-excludelist.xml
@@ -3980,9 +3980,7 @@
-
-
@@ -4030,7 +4028,6 @@
-
@@ -4508,9 +4505,7 @@
-
-
@@ -4518,9 +4513,7 @@
-
-
@@ -4528,9 +4521,7 @@
-
-
@@ -4538,9 +4529,7 @@
-
-
@@ -6499,9 +6488,7 @@
-
-
@@ -6515,9 +6502,7 @@
-
-
@@ -6606,9 +6591,7 @@
-
-
@@ -6616,9 +6599,7 @@
-
-
@@ -7576,9 +7557,7 @@
-
-
@@ -7586,9 +7565,7 @@
-
-
@@ -7596,9 +7573,7 @@
-
-
@@ -7606,9 +7581,7 @@
-
-
@@ -9180,7 +9153,6 @@
-
@@ -9191,123 +9163,19 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -9430,134 +9298,35 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -9702,244 +9471,59 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -9959,7 +9543,6 @@
-
@@ -9980,17 +9563,14 @@
-
-
-
@@ -10007,9 +9587,7 @@
-
-
@@ -10022,9 +9600,7 @@
-
-
@@ -10056,7 +9632,6 @@
-
@@ -10105,7 +9680,6 @@
-
@@ -10115,7 +9689,6 @@
-