Skip to content

Commit 210b631

Browse files
authored
Fix iterator position calculation for array patterns (#3494)
This patch fixes #3455. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
1 parent c8ce7d8 commit 210b631

7 files changed

Lines changed: 75 additions & 17 deletions

File tree

jerry-core/include/jerryscript-snapshot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C"
3030
/**
3131
* Jerry snapshot format version.
3232
*/
33-
#define JERRY_SNAPSHOT_VERSION (36u)
33+
#define JERRY_SNAPSHOT_VERSION (37u)
3434

3535
/**
3636
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.

jerry-core/parser/js/byte-code.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@
652652
VM_OC_APPEND_ARRAY) \
653653
CBC_OPCODE (CBC_EXT_REST_INITIALIZER, CBC_NO_FLAG, 1, \
654654
VM_OC_REST_INITIALIZER) \
655-
CBC_OPCODE (CBC_EXT_REST_INITIALIZER_PROP, CBC_NO_FLAG, 1, \
655+
CBC_OPCODE (CBC_EXT_REST_INITIALIZER_2, CBC_NO_FLAG, 1, \
656+
VM_OC_REST_INITIALIZER) \
657+
CBC_OPCODE (CBC_EXT_REST_INITIALIZER_3, CBC_NO_FLAG, 1, \
656658
VM_OC_REST_INITIALIZER) \
657659
CBC_OPCODE (CBC_EXT_INITIALIZER_PUSH_PROP_LITERAL, CBC_HAS_LITERAL_ARG, 1, \
658660
VM_OC_INITIALIZER_PUSH_PROP | VM_OC_GET_LITERAL) \
@@ -664,7 +666,9 @@
664666
VM_OC_GET_ITERATOR) \
665667
CBC_OPCODE (CBC_EXT_ITERATOR_STEP, CBC_NO_FLAG, 1, \
666668
VM_OC_ITERATOR_STEP) \
667-
CBC_OPCODE (CBC_EXT_ITERATOR_STEP_PROP, CBC_NO_FLAG, 1, \
669+
CBC_OPCODE (CBC_EXT_ITERATOR_STEP_2, CBC_NO_FLAG, 1, \
670+
VM_OC_ITERATOR_STEP) \
671+
CBC_OPCODE (CBC_EXT_ITERATOR_STEP_3, CBC_NO_FLAG, 1, \
668672
VM_OC_ITERATOR_STEP) \
669673
CBC_OPCODE (CBC_EXT_ITERATOR_CLOSE, CBC_NO_FLAG, -1, \
670674
VM_OC_ITERATOR_CLOSE | VM_OC_GET_STACK) \

jerry-core/parser/js/js-parser-expr.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2665,6 +2665,8 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
26652665
}
26662666
else
26672667
{
2668+
parser_flush_cbc (context_p);
2669+
uint16_t stack_depth_before = context_p->stack_depth;
26682670
parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA | PARSE_EXPR_LEFT_HAND_SIDE);
26692671

26702672
if (!PARSER_IS_PUSH_LITERAL (context_p->last_cbc_opcode))
@@ -2675,17 +2677,23 @@ parser_pattern_process_assignment (parser_context_t *context_p, /**< context */
26752677
parser_raise_error (context_p, PARSER_ERR_INVALID_DESTRUCTURING_PATTERN);
26762678
}
26772679

2678-
if (context_p->last_cbc_opcode == CBC_PUSH_PROP_THIS_LITERAL)
2679-
{
2680-
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2681-
uint16_t lit_index = context_p->last_cbc.literal_index;
2682-
parser_emit_cbc (context_p, CBC_PUSH_THIS);
2683-
parser_emit_cbc_literal (context_p, CBC_PUSH_PROP_LITERAL, lit_index);
2684-
}
2685-
26862680
if (end_type == LEXER_RIGHT_SQUARE)
26872681
{
2688-
PARSER_PLUS_EQUAL_U16 (rhs_opcode, 1);
2682+
/* LHS expression parsing may increases the stack depth, therefore rhs opcode may transforms:
2683+
Example: [a.b.c]
2684+
CBC_EXT_ITERATOR_STEP -> CBC_EXT_ITERATOR_STEP_2
2685+
CBC_EXT_REST_INITIALIZER -> CBC_EXT_ITERATOR_STEP_2 */
2686+
uint16_t stack_difference = (uint16_t) (context_p->stack_depth - stack_depth_before);
2687+
2688+
if (context_p->last_cbc_opcode == CBC_PUSH_PROP_LITERAL_LITERAL)
2689+
{
2690+
/* Example: [a.b]
2691+
CBC_EXT_ITERATOR_STEP -> CBC_EXT_ITERATOR_STEP_3
2692+
CBC_EXT_REST_INITIALIZER -> CBC_EXT_ITERATOR_STEP_3 */
2693+
PARSER_PLUS_EQUAL_U16 (stack_difference, 2);
2694+
}
2695+
2696+
PARSER_PLUS_EQUAL_U16 (rhs_opcode, stack_difference);
26892697
}
26902698
}
26912699
}

jerry-core/vm/vm.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,8 +1948,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
19481948
}
19491949
case VM_OC_ITERATOR_STEP:
19501950
{
1951-
const int8_t index = (opcode == CBC_EXT_ITERATOR_STEP) ? -1 : -3;
1952-
result = ecma_op_iterator_step (stack_top_p[index]);
1951+
JERRY_ASSERT (opcode >= CBC_EXT_ITERATOR_STEP && opcode <= CBC_EXT_ITERATOR_STEP_3);
1952+
const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_ITERATOR_STEP));
1953+
result = ecma_op_iterator_step (stack_top_p[-index]);
19531954

19541955
if (ECMA_IS_VALUE_ERROR (result))
19551956
{
@@ -1999,9 +2000,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
19992000
}
20002001
case VM_OC_REST_INITIALIZER:
20012002
{
2002-
const int8_t iterator_index = (opcode == CBC_EXT_REST_INITIALIZER) ? -1 : -3;
2003+
JERRY_ASSERT (opcode >= CBC_EXT_REST_INITIALIZER && opcode <= CBC_EXT_REST_INITIALIZER_3);
2004+
const uint8_t iterator_index = (uint8_t) (1 + (opcode - CBC_EXT_REST_INITIALIZER));
20032005
ecma_object_t *array_p = ecma_op_new_fast_array_object (0);
2004-
ecma_value_t iterator = stack_top_p[iterator_index];
2006+
ecma_value_t iterator = stack_top_p[-iterator_index];
20052007
uint32_t index = 0;
20062008

20072009
while (true)

tests/jerry/fail/regression-test-issue-3437.js renamed to tests/jerry/es2015/regression-test-issue-3437.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@
1313
// limitations under the License.
1414

1515
[...RegExp.prototype.compile] = ([]);
16+
17+
assert(RegExp.prototype.compile.length === 0);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
try {
16+
[...RegExp.$.$] = String();
17+
assert(false);
18+
} catch (e) {
19+
assert(e instanceof TypeError);
20+
}
21+
22+
var o = { a : { b : { c : { d: { e : { } } } } } };
23+
24+
[...o.a.b.c.d.e] = "foo";
25+
26+
assert(o.a.b.c.d.e.length === 3);
27+
assert(o.a.b.c.d.e[0] === "f");
28+
assert(o.a.b.c.d.e[1] === "o");
29+
assert(o.a.b.c.d.e[2] === "o");
30+
31+
[o.a.b.c.d.e] = "foo";
32+
33+
assert(o.a.b.c.d.e === "f");
34+
35+
[this.o.a.b.c.d.e] = "bar";
36+
assert(this.o.a.b.c.d.e === "b");
37+
38+
[...this.o.a.b.c.d.e] = "bar";
39+
assert(this.o.a.b.c.d.e.length === 3);
40+
assert(this.o.a.b.c.d.e[0] === "b");
41+
assert(this.o.a.b.c.d.e[1] === "a");
42+
assert(this.o.a.b.c.d.e[2] === "r");

tests/unit-core/test-snapshot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ main (void)
223223
/* Check the snapshot data. Unused bytes should be filled with zeroes */
224224
const uint8_t expected_data[] =
225225
{
226-
0x4A, 0x52, 0x52, 0x59, 0x24, 0x00, 0x00, 0x00,
226+
0x4A, 0x52, 0x52, 0x59, 0x25, 0x00, 0x00, 0x00,
227227
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
228228
0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
229229
0x03, 0x00, 0x01, 0x00, 0x41, 0x00, 0x01, 0x00,

0 commit comments

Comments
 (0)