Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #include <stdio.h>
29 : #include <stdlib.h>
30 : #include <string.h>
31 :
32 : #include <memory>
33 :
34 : #include "src/v8.h"
35 :
36 : #include "src/api-inl.h"
37 : #include "src/ast/ast-value-factory.h"
38 : #include "src/ast/ast.h"
39 : #include "src/base/enum-set.h"
40 : #include "src/compiler.h"
41 : #include "src/execution.h"
42 : #include "src/flags.h"
43 : #include "src/isolate.h"
44 : #include "src/objects-inl.h"
45 : #include "src/objects.h"
46 : #include "src/parsing/parse-info.h"
47 : #include "src/parsing/parser.h"
48 : #include "src/parsing/parsing.h"
49 : #include "src/parsing/preparser.h"
50 : #include "src/parsing/rewriter.h"
51 : #include "src/parsing/scanner-character-streams.h"
52 : #include "src/parsing/token.h"
53 : #include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
54 :
55 : #include "test/cctest/cctest.h"
56 : #include "test/cctest/scope-test-helper.h"
57 : #include "test/cctest/unicode-helpers.h"
58 :
59 : namespace v8 {
60 : namespace internal {
61 : namespace test_parsing {
62 :
63 : namespace {
64 :
65 : int* global_use_counts = nullptr;
66 :
67 30 : void MockUseCounterCallback(v8::Isolate* isolate,
68 : v8::Isolate::UseCounterFeature feature) {
69 30 : ++global_use_counts[feature];
70 30 : }
71 :
72 : } // namespace
73 :
74 0 : bool TokenIsAutoSemicolon(Token::Value token) {
75 560 : switch (token) {
76 : case Token::SEMICOLON:
77 : case Token::EOS:
78 : case Token::RBRACE:
79 : return true;
80 : default:
81 0 : return false;
82 : }
83 : }
84 :
85 25880 : TEST(AutoSemicolonToken) {
86 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
87 : Token::Value token = static_cast<Token::Value>(i);
88 1120 : CHECK_EQ(TokenIsAutoSemicolon(token), Token::IsAutoSemicolon(token));
89 : }
90 5 : }
91 :
92 0 : bool TokenIsAnyIdentifier(Token::Value token) {
93 560 : switch (token) {
94 : case Token::IDENTIFIER:
95 : case Token::GET:
96 : case Token::SET:
97 : case Token::ASYNC:
98 : case Token::AWAIT:
99 : case Token::YIELD:
100 : case Token::LET:
101 : case Token::STATIC:
102 : case Token::FUTURE_STRICT_RESERVED_WORD:
103 : case Token::ESCAPED_STRICT_RESERVED_WORD:
104 : return true;
105 : default:
106 0 : return false;
107 : }
108 : }
109 :
110 25880 : TEST(AnyIdentifierToken) {
111 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
112 : Token::Value token = static_cast<Token::Value>(i);
113 1120 : CHECK_EQ(TokenIsAnyIdentifier(token), Token::IsAnyIdentifier(token));
114 : }
115 5 : }
116 :
117 0 : bool TokenIsCallable(Token::Value token) {
118 560 : switch (token) {
119 : case Token::SUPER:
120 : case Token::IDENTIFIER:
121 : case Token::GET:
122 : case Token::SET:
123 : case Token::ASYNC:
124 : case Token::AWAIT:
125 : case Token::YIELD:
126 : case Token::LET:
127 : case Token::STATIC:
128 : case Token::FUTURE_STRICT_RESERVED_WORD:
129 : case Token::ESCAPED_STRICT_RESERVED_WORD:
130 : return true;
131 : default:
132 0 : return false;
133 : }
134 : }
135 :
136 25880 : TEST(CallableToken) {
137 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
138 : Token::Value token = static_cast<Token::Value>(i);
139 1120 : CHECK_EQ(TokenIsCallable(token), Token::IsCallable(token));
140 : }
141 5 : }
142 :
143 0 : bool TokenIsValidIdentifier(Token::Value token, LanguageMode language_mode,
144 : bool is_generator, bool disallow_await) {
145 4480 : switch (token) {
146 : case Token::IDENTIFIER:
147 : case Token::GET:
148 : case Token::SET:
149 : case Token::ASYNC:
150 : return true;
151 : case Token::YIELD:
152 40 : return !is_generator && is_sloppy(language_mode);
153 : case Token::AWAIT:
154 40 : return !disallow_await;
155 : case Token::LET:
156 : case Token::STATIC:
157 : case Token::FUTURE_STRICT_RESERVED_WORD:
158 : case Token::ESCAPED_STRICT_RESERVED_WORD:
159 0 : return is_sloppy(language_mode);
160 : default:
161 0 : return false;
162 : }
163 : UNREACHABLE();
164 : }
165 :
166 25880 : TEST(IsValidIdentifierToken) {
167 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
168 : Token::Value token = static_cast<Token::Value>(i);
169 1120 : for (size_t raw_language_mode = 0; raw_language_mode < LanguageModeSize;
170 : raw_language_mode++) {
171 1120 : LanguageMode mode = static_cast<LanguageMode>(raw_language_mode);
172 3360 : for (int is_generator = 0; is_generator < 2; is_generator++) {
173 4480 : for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
174 8960 : CHECK_EQ(
175 : TokenIsValidIdentifier(token, mode, is_generator, disallow_await),
176 : Token::IsValidIdentifier(token, mode, is_generator,
177 : disallow_await));
178 : }
179 : }
180 : }
181 : }
182 5 : }
183 :
184 0 : bool TokenIsStrictReservedWord(Token::Value token) {
185 560 : switch (token) {
186 : case Token::LET:
187 : case Token::YIELD:
188 : case Token::STATIC:
189 : case Token::FUTURE_STRICT_RESERVED_WORD:
190 : case Token::ESCAPED_STRICT_RESERVED_WORD:
191 : return true;
192 : default:
193 0 : return false;
194 : }
195 : UNREACHABLE();
196 : }
197 :
198 25880 : TEST(IsStrictReservedWord) {
199 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
200 : Token::Value token = static_cast<Token::Value>(i);
201 1120 : CHECK_EQ(TokenIsStrictReservedWord(token),
202 : Token::IsStrictReservedWord(token));
203 : }
204 5 : }
205 :
206 0 : bool TokenIsLiteral(Token::Value token) {
207 560 : switch (token) {
208 : case Token::NULL_LITERAL:
209 : case Token::TRUE_LITERAL:
210 : case Token::FALSE_LITERAL:
211 : case Token::NUMBER:
212 : case Token::SMI:
213 : case Token::BIGINT:
214 : case Token::STRING:
215 : return true;
216 : default:
217 0 : return false;
218 : }
219 : UNREACHABLE();
220 : }
221 :
222 25880 : TEST(IsLiteralToken) {
223 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
224 : Token::Value token = static_cast<Token::Value>(i);
225 1120 : CHECK_EQ(TokenIsLiteral(token), Token::IsLiteral(token));
226 : }
227 5 : }
228 :
229 0 : bool TokenIsAssignmentOp(Token::Value token) {
230 1115 : switch (token) {
231 : case Token::INIT:
232 : case Token::ASSIGN:
233 : #define T(name, string, precedence) case Token::name:
234 : BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_ASSIGN_TOKEN)
235 : #undef T
236 : return true;
237 : default:
238 0 : return false;
239 : }
240 : }
241 :
242 25880 : TEST(AssignmentOp) {
243 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
244 : Token::Value token = static_cast<Token::Value>(i);
245 1120 : CHECK_EQ(TokenIsAssignmentOp(token), Token::IsAssignmentOp(token));
246 : }
247 5 : }
248 :
249 0 : bool TokenIsArrowOrAssignmentOp(Token::Value token) {
250 1115 : return token == Token::ARROW || TokenIsAssignmentOp(token);
251 : }
252 :
253 25880 : TEST(ArrowOrAssignmentOp) {
254 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
255 : Token::Value token = static_cast<Token::Value>(i);
256 1120 : CHECK_EQ(TokenIsArrowOrAssignmentOp(token),
257 : Token::IsArrowOrAssignmentOp(token));
258 : }
259 5 : }
260 :
261 0 : bool TokenIsBinaryOp(Token::Value token) {
262 560 : switch (token) {
263 : case Token::COMMA:
264 : case Token::OR:
265 : case Token::AND:
266 : #define T(name, string, precedence) case Token::name:
267 : BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_TOKEN)
268 : #undef T
269 : return true;
270 : default:
271 0 : return false;
272 : }
273 : }
274 :
275 25880 : TEST(BinaryOp) {
276 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
277 : Token::Value token = static_cast<Token::Value>(i);
278 1120 : CHECK_EQ(TokenIsBinaryOp(token), Token::IsBinaryOp(token));
279 : }
280 5 : }
281 :
282 0 : bool TokenIsCompareOp(Token::Value token) {
283 560 : switch (token) {
284 : case Token::EQ:
285 : case Token::EQ_STRICT:
286 : case Token::NE:
287 : case Token::NE_STRICT:
288 : case Token::LT:
289 : case Token::GT:
290 : case Token::LTE:
291 : case Token::GTE:
292 : case Token::INSTANCEOF:
293 : case Token::IN:
294 : return true;
295 : default:
296 0 : return false;
297 : }
298 : }
299 :
300 25880 : TEST(CompareOp) {
301 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
302 : Token::Value token = static_cast<Token::Value>(i);
303 1120 : CHECK_EQ(TokenIsCompareOp(token), Token::IsCompareOp(token));
304 : }
305 5 : }
306 :
307 0 : bool TokenIsOrderedRelationalCompareOp(Token::Value token) {
308 560 : switch (token) {
309 : case Token::LT:
310 : case Token::GT:
311 : case Token::LTE:
312 : case Token::GTE:
313 : return true;
314 : default:
315 0 : return false;
316 : }
317 : }
318 :
319 25880 : TEST(IsOrderedRelationalCompareOp) {
320 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
321 : Token::Value token = static_cast<Token::Value>(i);
322 1120 : CHECK_EQ(TokenIsOrderedRelationalCompareOp(token),
323 : Token::IsOrderedRelationalCompareOp(token));
324 : }
325 5 : }
326 :
327 0 : bool TokenIsEqualityOp(Token::Value token) {
328 560 : switch (token) {
329 : case Token::EQ:
330 : case Token::EQ_STRICT:
331 : return true;
332 : default:
333 0 : return false;
334 : }
335 : }
336 :
337 25880 : TEST(IsEqualityOp) {
338 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
339 : Token::Value token = static_cast<Token::Value>(i);
340 1120 : CHECK_EQ(TokenIsEqualityOp(token), Token::IsEqualityOp(token));
341 : }
342 5 : }
343 :
344 0 : bool TokenIsBitOp(Token::Value token) {
345 : switch (token) {
346 : case Token::BIT_OR:
347 : case Token::BIT_XOR:
348 : case Token::BIT_AND:
349 : case Token::SHL:
350 : case Token::SAR:
351 : case Token::SHR:
352 : case Token::BIT_NOT:
353 : return true;
354 : default:
355 0 : return false;
356 : }
357 : }
358 :
359 25880 : TEST(IsBitOp) {
360 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
361 : Token::Value token = static_cast<Token::Value>(i);
362 1120 : CHECK_EQ(TokenIsBitOp(token), Token::IsBitOp(token));
363 : }
364 5 : }
365 :
366 0 : bool TokenIsUnaryOp(Token::Value token) {
367 1120 : switch (token) {
368 : case Token::NOT:
369 : case Token::BIT_NOT:
370 : case Token::DELETE:
371 : case Token::TYPEOF:
372 : case Token::VOID:
373 : case Token::ADD:
374 : case Token::SUB:
375 : return true;
376 : default:
377 0 : return false;
378 : }
379 : }
380 :
381 25880 : TEST(IsUnaryOp) {
382 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
383 : Token::Value token = static_cast<Token::Value>(i);
384 1120 : CHECK_EQ(TokenIsUnaryOp(token), Token::IsUnaryOp(token));
385 : }
386 5 : }
387 :
388 0 : bool TokenIsPropertyOrCall(Token::Value token) {
389 560 : switch (token) {
390 : case Token::TEMPLATE_SPAN:
391 : case Token::TEMPLATE_TAIL:
392 : case Token::PERIOD:
393 : case Token::LBRACK:
394 : case Token::LPAREN:
395 : return true;
396 : default:
397 0 : return false;
398 : }
399 : }
400 :
401 25880 : TEST(IsPropertyOrCall) {
402 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
403 : Token::Value token = static_cast<Token::Value>(i);
404 1120 : CHECK_EQ(TokenIsPropertyOrCall(token), Token::IsPropertyOrCall(token));
405 : }
406 5 : }
407 :
408 0 : bool TokenIsMember(Token::Value token) {
409 560 : switch (token) {
410 : case Token::TEMPLATE_SPAN:
411 : case Token::TEMPLATE_TAIL:
412 : case Token::PERIOD:
413 : case Token::LBRACK:
414 : return true;
415 : default:
416 0 : return false;
417 : }
418 : }
419 :
420 0 : bool TokenIsTemplate(Token::Value token) {
421 560 : switch (token) {
422 : case Token::TEMPLATE_SPAN:
423 : case Token::TEMPLATE_TAIL:
424 : return true;
425 : default:
426 0 : return false;
427 : }
428 : }
429 :
430 0 : bool TokenIsProperty(Token::Value token) {
431 560 : switch (token) {
432 : case Token::PERIOD:
433 : case Token::LBRACK:
434 : return true;
435 : default:
436 0 : return false;
437 : }
438 : }
439 :
440 25880 : TEST(IsMember) {
441 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
442 : Token::Value token = static_cast<Token::Value>(i);
443 1120 : CHECK_EQ(TokenIsMember(token), Token::IsMember(token));
444 : }
445 5 : }
446 :
447 25880 : TEST(IsTemplate) {
448 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
449 : Token::Value token = static_cast<Token::Value>(i);
450 1120 : CHECK_EQ(TokenIsTemplate(token), Token::IsTemplate(token));
451 : }
452 5 : }
453 :
454 25880 : TEST(IsProperty) {
455 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
456 : Token::Value token = static_cast<Token::Value>(i);
457 1120 : CHECK_EQ(TokenIsProperty(token), Token::IsProperty(token));
458 : }
459 5 : }
460 :
461 0 : bool TokenIsCountOp(Token::Value token) {
462 1085 : switch (token) {
463 : case Token::INC:
464 : case Token::DEC:
465 : return true;
466 : default:
467 0 : return false;
468 : }
469 : }
470 :
471 25880 : TEST(IsCountOp) {
472 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
473 : Token::Value token = static_cast<Token::Value>(i);
474 1120 : CHECK_EQ(TokenIsCountOp(token), Token::IsCountOp(token));
475 : }
476 5 : }
477 :
478 25880 : TEST(IsUnaryOrCountOp) {
479 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
480 : Token::Value token = static_cast<Token::Value>(i);
481 1645 : CHECK_EQ(TokenIsUnaryOp(token) || TokenIsCountOp(token),
482 : Token::IsUnaryOrCountOp(token));
483 : }
484 5 : }
485 :
486 0 : bool TokenIsShiftOp(Token::Value token) {
487 560 : switch (token) {
488 : case Token::SHL:
489 : case Token::SAR:
490 : case Token::SHR:
491 : return true;
492 : default:
493 0 : return false;
494 : }
495 : }
496 :
497 25880 : TEST(IsShiftOp) {
498 565 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
499 : Token::Value token = static_cast<Token::Value>(i);
500 1120 : CHECK_EQ(TokenIsShiftOp(token), Token::IsShiftOp(token));
501 : }
502 5 : }
503 :
504 25880 : TEST(ScanKeywords) {
505 : struct KeywordToken {
506 : const char* keyword;
507 : i::Token::Value token;
508 : };
509 :
510 : static const KeywordToken keywords[] = {
511 : #define KEYWORD(t, s, d) { s, i::Token::t },
512 : TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
513 : #undef KEYWORD
514 : {nullptr, i::Token::IDENTIFIER}};
515 :
516 : KeywordToken key_token;
517 : char buffer[32];
518 220 : for (int i = 0; (key_token = keywords[i]).keyword != nullptr; i++) {
519 : const char* keyword = key_token.keyword;
520 215 : size_t length = strlen(key_token.keyword);
521 215 : CHECK(static_cast<int>(sizeof(buffer)) >= length);
522 : {
523 215 : auto stream = i::ScannerStream::ForTesting(keyword, length);
524 430 : i::Scanner scanner(stream.get(), false);
525 215 : scanner.Initialize();
526 215 : CHECK_EQ(key_token.token, scanner.Next());
527 215 : CHECK_EQ(i::Token::EOS, scanner.Next());
528 : }
529 : // Removing characters will make keyword matching fail.
530 : {
531 215 : auto stream = i::ScannerStream::ForTesting(keyword, length - 1);
532 430 : i::Scanner scanner(stream.get(), false);
533 215 : scanner.Initialize();
534 215 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
535 215 : CHECK_EQ(i::Token::EOS, scanner.Next());
536 : }
537 : // Adding characters will make keyword matching fail.
538 : static const char chars_to_append[] = { 'z', '0', '_' };
539 860 : for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
540 : i::MemMove(buffer, keyword, length);
541 645 : buffer[length] = chars_to_append[j];
542 645 : auto stream = i::ScannerStream::ForTesting(buffer, length + 1);
543 1290 : i::Scanner scanner(stream.get(), false);
544 645 : scanner.Initialize();
545 645 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
546 645 : CHECK_EQ(i::Token::EOS, scanner.Next());
547 : }
548 : // Replacing characters will make keyword matching fail.
549 : {
550 : i::MemMove(buffer, keyword, length);
551 215 : buffer[length - 1] = '_';
552 215 : auto stream = i::ScannerStream::ForTesting(buffer, length);
553 430 : i::Scanner scanner(stream.get(), false);
554 215 : scanner.Initialize();
555 215 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
556 215 : CHECK_EQ(i::Token::EOS, scanner.Next());
557 : }
558 : }
559 5 : }
560 :
561 :
562 25880 : TEST(ScanHTMLEndComments) {
563 5 : v8::V8::Initialize();
564 5 : v8::Isolate* isolate = CcTest::isolate();
565 360 : i::Isolate* i_isolate = CcTest::i_isolate();
566 5 : v8::HandleScope handles(isolate);
567 :
568 : // Regression test. See:
569 : // http://code.google.com/p/chromium/issues/detail?id=53548
570 : // Tests that --> is correctly interpreted as comment-to-end-of-line if there
571 : // is only whitespace before it on the line (with comments considered as
572 : // whitespace, even a multiline-comment containing a newline).
573 : // This was not the case if it occurred before the first real token
574 : // in the input.
575 : // clang-format off
576 : const char* tests[] = {
577 : // Before first real token.
578 : "-->",
579 : "--> is eol-comment",
580 : "--> is eol-comment\nvar y = 37;\n",
581 : "\n --> is eol-comment\nvar y = 37;\n",
582 : "\n-->is eol-comment\nvar y = 37;\n",
583 : "\n-->\nvar y = 37;\n",
584 : "/* precomment */ --> is eol-comment\nvar y = 37;\n",
585 : "/* precomment */-->eol-comment\nvar y = 37;\n",
586 : "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
587 : "\n/*precomment*/-->eol-comment\nvar y = 37;\n",
588 : // After first real token.
589 : "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
590 : "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
591 : "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
592 : "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
593 : "var x = 42;/*\n*/-->is eol-comment\nvar y = 37;\n",
594 : // With multiple comments preceding HTMLEndComment
595 : "/* MLC \n */ /* SLDC */ --> is eol-comment\nvar y = 37;\n",
596 : "/* MLC \n */ /* SLDC1 */ /* SLDC2 */ --> is eol-comment\nvar y = 37;\n",
597 : "/* MLC1 \n */ /* MLC2 \n */ --> is eol-comment\nvar y = 37;\n",
598 : "/* SLDC */ /* MLC \n */ --> is eol-comment\nvar y = 37;\n",
599 : "/* MLC1 \n */ /* SLDC1 */ /* MLC2 \n */ /* SLDC2 */ --> is eol-comment\n"
600 : "var y = 37;\n",
601 : nullptr
602 5 : };
603 :
604 : const char* fail_tests[] = {
605 : "x --> is eol-comment\nvar y = 37;\n",
606 : "\"\\n\" --> is eol-comment\nvar y = 37;\n",
607 : "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
608 : "var x = 42; --> is eol-comment\nvar y = 37;\n",
609 : nullptr
610 5 : };
611 : // clang-format on
612 :
613 : // Parser/Scanner needs a stack limit.
614 5 : i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
615 5 : 128 * 1024);
616 5 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
617 105 : for (int i = 0; tests[i]; i++) {
618 : const char* source = tests[i];
619 100 : auto stream = i::ScannerStream::ForTesting(source);
620 200 : i::Scanner scanner(stream.get(), false);
621 100 : scanner.Initialize();
622 200 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
623 : i::AstValueFactory ast_value_factory(
624 200 : &zone, i_isolate->ast_string_constants(), HashSeed(i_isolate));
625 : i::PendingCompilationErrorHandler pending_error_handler;
626 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
627 : &pending_error_handler,
628 : i_isolate->counters()->runtime_call_stats(),
629 200 : i_isolate->logger());
630 100 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
631 100 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
632 100 : CHECK(!pending_error_handler.has_pending_error());
633 : }
634 :
635 20 : for (int i = 0; fail_tests[i]; i++) {
636 : const char* source = fail_tests[i];
637 20 : auto stream = i::ScannerStream::ForTesting(source);
638 40 : i::Scanner scanner(stream.get(), false);
639 20 : scanner.Initialize();
640 40 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
641 : i::AstValueFactory ast_value_factory(
642 40 : &zone, i_isolate->ast_string_constants(), HashSeed(i_isolate));
643 : i::PendingCompilationErrorHandler pending_error_handler;
644 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
645 : &pending_error_handler,
646 : i_isolate->counters()->runtime_call_stats(),
647 40 : i_isolate->logger());
648 20 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
649 : // Even in the case of a syntax error, kPreParseSuccess is returned.
650 20 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
651 20 : CHECK(pending_error_handler.has_pending_error() ||
652 : pending_error_handler.has_error_unidentifiable_by_preparser());
653 5 : }
654 5 : }
655 :
656 25880 : TEST(ScanHtmlComments) {
657 : const char* src = "a <!-- b --> c";
658 : // Disallow HTML comments.
659 : {
660 5 : auto stream = i::ScannerStream::ForTesting(src);
661 10 : i::Scanner scanner(stream.get(), true);
662 5 : scanner.Initialize();
663 5 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
664 5 : CHECK_EQ(i::Token::ILLEGAL, scanner.Next());
665 : }
666 :
667 : // Skip HTML comments:
668 : {
669 5 : auto stream = i::ScannerStream::ForTesting(src);
670 10 : i::Scanner scanner(stream.get(), false);
671 5 : scanner.Initialize();
672 5 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
673 5 : CHECK_EQ(i::Token::EOS, scanner.Next());
674 : }
675 5 : }
676 :
677 0 : class ScriptResource : public v8::String::ExternalOneByteStringResource {
678 : public:
679 : ScriptResource(const char* data, size_t length)
680 : : data_(data), length_(length) { }
681 :
682 0 : const char* data() const override { return data_; }
683 0 : size_t length() const override { return length_; }
684 :
685 : private:
686 : const char* data_;
687 : size_t length_;
688 : };
689 :
690 :
691 25880 : TEST(StandAlonePreParser) {
692 5 : v8::V8::Initialize();
693 90 : i::Isolate* i_isolate = CcTest::i_isolate();
694 :
695 5 : i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
696 5 : 128 * 1024);
697 :
698 : const char* programs[] = {"{label: 42}",
699 : "var x = 42;",
700 : "function foo(x, y) { return x + y; }",
701 : "%ArgleBargle(glop);",
702 : "var x = new new Function('this.x = 42');",
703 : "var f = (x, y) => x + y;",
704 5 : nullptr};
705 :
706 5 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
707 35 : for (int i = 0; programs[i]; i++) {
708 30 : auto stream = i::ScannerStream::ForTesting(programs[i]);
709 60 : i::Scanner scanner(stream.get(), false);
710 30 : scanner.Initialize();
711 :
712 60 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
713 : i::AstValueFactory ast_value_factory(
714 60 : &zone, i_isolate->ast_string_constants(), HashSeed(i_isolate));
715 : i::PendingCompilationErrorHandler pending_error_handler;
716 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
717 : &pending_error_handler,
718 : i_isolate->counters()->runtime_call_stats(),
719 60 : i_isolate->logger());
720 : preparser.set_allow_natives(true);
721 30 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
722 30 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
723 30 : CHECK(!pending_error_handler.has_pending_error());
724 : }
725 5 : }
726 :
727 :
728 25880 : TEST(StandAlonePreParserNoNatives) {
729 5 : v8::V8::Initialize();
730 :
731 30 : i::Isolate* isolate = CcTest::i_isolate();
732 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
733 5 : 128 * 1024);
734 :
735 : const char* programs[] = {"%ArgleBargle(glop);", "var x = %_IsSmi(42);",
736 5 : nullptr};
737 :
738 5 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
739 15 : for (int i = 0; programs[i]; i++) {
740 10 : auto stream = i::ScannerStream::ForTesting(programs[i]);
741 20 : i::Scanner scanner(stream.get(), false);
742 10 : scanner.Initialize();
743 :
744 : // Preparser defaults to disallowing natives syntax.
745 20 : i::Zone zone(isolate->allocator(), ZONE_NAME);
746 : i::AstValueFactory ast_value_factory(&zone, isolate->ast_string_constants(),
747 20 : HashSeed(isolate));
748 : i::PendingCompilationErrorHandler pending_error_handler;
749 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
750 : &pending_error_handler,
751 : isolate->counters()->runtime_call_stats(),
752 20 : isolate->logger());
753 10 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
754 10 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
755 10 : CHECK(pending_error_handler.has_pending_error() ||
756 : pending_error_handler.has_error_unidentifiable_by_preparser());
757 : }
758 5 : }
759 :
760 :
761 25880 : TEST(RegressChromium62639) {
762 5 : v8::V8::Initialize();
763 15 : i::Isolate* isolate = CcTest::i_isolate();
764 :
765 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
766 5 : 128 * 1024);
767 :
768 : const char* program = "var x = 'something';\n"
769 : "escape: function() {}";
770 : // Fails parsing expecting an identifier after "function".
771 : // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
772 : // and then used the invalid currently scanned literal. This always
773 : // failed in debug mode, and sometimes crashed in release mode.
774 :
775 5 : auto stream = i::ScannerStream::ForTesting(program);
776 10 : i::Scanner scanner(stream.get(), false);
777 5 : scanner.Initialize();
778 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
779 : i::AstValueFactory ast_value_factory(&zone, isolate->ast_string_constants(),
780 10 : HashSeed(isolate));
781 : i::PendingCompilationErrorHandler pending_error_handler;
782 : i::PreParser preparser(&zone, &scanner, isolate->stack_guard()->real_climit(),
783 : &ast_value_factory, &pending_error_handler,
784 : isolate->counters()->runtime_call_stats(),
785 10 : isolate->logger());
786 5 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
787 : // Even in the case of a syntax error, kPreParseSuccess is returned.
788 5 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
789 5 : CHECK(pending_error_handler.has_pending_error() ||
790 : pending_error_handler.has_error_unidentifiable_by_preparser());
791 5 : }
792 :
793 :
794 25880 : TEST(PreParseOverflow) {
795 5 : v8::V8::Initialize();
796 15 : i::Isolate* isolate = CcTest::i_isolate();
797 :
798 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
799 5 : 128 * 1024);
800 :
801 : size_t kProgramSize = 1024 * 1024;
802 5 : std::unique_ptr<char[]> program(i::NewArray<char>(kProgramSize + 1));
803 : memset(program.get(), '(', kProgramSize);
804 5 : program[kProgramSize] = '\0';
805 :
806 5 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
807 :
808 5 : auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize);
809 10 : i::Scanner scanner(stream.get(), false);
810 5 : scanner.Initialize();
811 :
812 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
813 : i::AstValueFactory ast_value_factory(&zone, isolate->ast_string_constants(),
814 10 : HashSeed(isolate));
815 : i::PendingCompilationErrorHandler pending_error_handler;
816 : i::PreParser preparser(
817 : &zone, &scanner, stack_limit, &ast_value_factory, &pending_error_handler,
818 10 : isolate->counters()->runtime_call_stats(), isolate->logger());
819 5 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
820 5 : CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
821 5 : }
822 :
823 35 : void TestStreamScanner(i::Utf16CharacterStream* stream,
824 : i::Token::Value* expected_tokens,
825 : int skip_pos = 0, // Zero means not skipping.
826 : int skip_to = 0) {
827 35 : i::Scanner scanner(stream, false);
828 35 : scanner.Initialize();
829 :
830 : int i = 0;
831 190 : do {
832 190 : i::Token::Value expected = expected_tokens[i];
833 190 : i::Token::Value actual = scanner.Next();
834 190 : CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
835 190 : if (scanner.location().end_pos == skip_pos) {
836 30 : scanner.SeekForward(skip_to);
837 : }
838 190 : i++;
839 225 : } while (expected_tokens[i] != i::Token::ILLEGAL);
840 35 : }
841 :
842 :
843 25880 : TEST(StreamScanner) {
844 5 : v8::V8::Initialize();
845 : const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
846 : std::unique_ptr<i::Utf16CharacterStream> stream1(
847 5 : i::ScannerStream::ForTesting(str1));
848 : i::Token::Value expectations1[] = {
849 : i::Token::LBRACE, i::Token::IDENTIFIER, i::Token::GET, i::Token::FOR,
850 : i::Token::COLON, i::Token::MUL, i::Token::DIV, i::Token::LT,
851 5 : i::Token::SUB, i::Token::IDENTIFIER, i::Token::EOS, i::Token::ILLEGAL};
852 5 : TestStreamScanner(stream1.get(), expectations1, 0, 0);
853 :
854 : const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
855 : std::unique_ptr<i::Utf16CharacterStream> stream2(
856 5 : i::ScannerStream::ForTesting(str2));
857 : i::Token::Value expectations2[] = {
858 : i::Token::CASE,
859 : i::Token::DEFAULT,
860 : i::Token::CONST,
861 : i::Token::LBRACE,
862 : // Skipped part here
863 : i::Token::RBRACE,
864 : i::Token::DO,
865 : i::Token::EOS,
866 : i::Token::ILLEGAL
867 5 : };
868 : CHECK_EQ('{', str2[19]);
869 : CHECK_EQ('}', str2[37]);
870 5 : TestStreamScanner(stream2.get(), expectations2, 20, 37);
871 :
872 : const char* str3 = "{}}}}";
873 : i::Token::Value expectations3[] = {
874 : i::Token::LBRACE,
875 : i::Token::RBRACE,
876 : i::Token::RBRACE,
877 : i::Token::RBRACE,
878 : i::Token::RBRACE,
879 : i::Token::EOS,
880 : i::Token::ILLEGAL
881 5 : };
882 : // Skip zero-four RBRACEs.
883 35 : for (int i = 0; i <= 4; i++) {
884 25 : expectations3[6 - i] = i::Token::ILLEGAL;
885 25 : expectations3[5 - i] = i::Token::EOS;
886 : std::unique_ptr<i::Utf16CharacterStream> stream3(
887 25 : i::ScannerStream::ForTesting(str3));
888 50 : TestStreamScanner(stream3.get(), expectations3, 1, 1 + i);
889 : }
890 5 : }
891 :
892 110 : void TestScanRegExp(const char* re_source, const char* expected) {
893 110 : auto stream = i::ScannerStream::ForTesting(re_source);
894 : i::HandleScope scope(CcTest::i_isolate());
895 220 : i::Scanner scanner(stream.get(), false);
896 110 : scanner.Initialize();
897 :
898 : i::Token::Value start = scanner.peek();
899 110 : CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
900 110 : CHECK(scanner.ScanRegExpPattern());
901 110 : scanner.Next(); // Current token is now the regexp literal.
902 220 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
903 : i::AstValueFactory ast_value_factory(
904 : &zone, CcTest::i_isolate()->ast_string_constants(),
905 220 : HashSeed(CcTest::i_isolate()));
906 110 : const i::AstRawString* current_symbol =
907 110 : scanner.CurrentSymbol(&ast_value_factory);
908 110 : ast_value_factory.Internalize(CcTest::i_isolate());
909 : i::Handle<i::String> val = current_symbol->string();
910 : i::DisallowHeapAllocation no_alloc;
911 110 : i::String::FlatContent content = val->GetFlatContent(no_alloc);
912 110 : CHECK(content.IsOneByte());
913 110 : i::Vector<const uint8_t> actual = content.ToOneByteVector();
914 510 : for (int i = 0; i < actual.length(); i++) {
915 400 : CHECK_NE('\0', expected[i]);
916 800 : CHECK_EQ(expected[i], actual[i]);
917 : }
918 110 : }
919 :
920 :
921 25880 : TEST(RegExpScanning) {
922 5 : v8::V8::Initialize();
923 :
924 : // RegExp token with added garbage at the end. The scanner should only
925 : // scan the RegExp until the terminating slash just before "flipperwald".
926 5 : TestScanRegExp("/b/flipperwald", "b");
927 : // Incomplete escape sequences doesn't hide the terminating slash.
928 5 : TestScanRegExp("/\\x/flipperwald", "\\x");
929 5 : TestScanRegExp("/\\u/flipperwald", "\\u");
930 5 : TestScanRegExp("/\\u1/flipperwald", "\\u1");
931 5 : TestScanRegExp("/\\u12/flipperwald", "\\u12");
932 5 : TestScanRegExp("/\\u123/flipperwald", "\\u123");
933 5 : TestScanRegExp("/\\c/flipperwald", "\\c");
934 5 : TestScanRegExp("/\\c//flipperwald", "\\c");
935 : // Slashes inside character classes are not terminating.
936 5 : TestScanRegExp("/[/]/flipperwald", "[/]");
937 5 : TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
938 : // Incomplete escape sequences inside a character class doesn't hide
939 : // the end of the character class.
940 5 : TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
941 5 : TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
942 5 : TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
943 5 : TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
944 5 : TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
945 5 : TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
946 5 : TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
947 5 : TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
948 : // Escaped ']'s wont end the character class.
949 5 : TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
950 : // Escaped slashes are not terminating.
951 5 : TestScanRegExp("/\\//flipperwald", "\\/");
952 : // Starting with '=' works too.
953 5 : TestScanRegExp("/=/", "=");
954 5 : TestScanRegExp("/=?/", "=?");
955 5 : }
956 :
957 25880 : TEST(ScopeUsesArgumentsSuperThis) {
958 : static const struct {
959 : const char* prefix;
960 : const char* suffix;
961 : } surroundings[] = {
962 : { "function f() {", "}" },
963 : { "var f = () => {", "};" },
964 : { "class C { constructor() {", "} }" },
965 : };
966 :
967 : enum Expected {
968 : NONE = 0,
969 : ARGUMENTS = 1,
970 : SUPER_PROPERTY = 1 << 1,
971 : THIS = 1 << 2,
972 : EVAL = 1 << 4
973 : };
974 :
975 : // clang-format off
976 : static const struct {
977 : const char* body;
978 : int expected;
979 : } source_data[] = {
980 : {"", NONE},
981 : {"return this", THIS},
982 : {"return arguments", ARGUMENTS},
983 : {"return super.x", SUPER_PROPERTY},
984 : {"return arguments[0]", ARGUMENTS},
985 : {"return this + arguments[0]", ARGUMENTS | THIS},
986 : {"return this + arguments[0] + super.x",
987 : ARGUMENTS | SUPER_PROPERTY | THIS},
988 : {"return x => this + x", THIS},
989 : {"return x => super.f() + x", SUPER_PROPERTY},
990 : {"this.foo = 42;", THIS},
991 : {"this.foo();", THIS},
992 : {"if (foo()) { this.f() }", THIS},
993 : {"if (foo()) { super.f() }", SUPER_PROPERTY},
994 : {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
995 : {"while (true) { this.f() }", THIS},
996 : {"while (true) { super.f() }", SUPER_PROPERTY},
997 : {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
998 : // Multiple nesting levels must work as well.
999 : {"while (true) { while (true) { while (true) return this } }", THIS},
1000 : {"while (true) { while (true) { while (true) return super.f() } }",
1001 : SUPER_PROPERTY},
1002 : {"if (1) { return () => { while (true) new this() } }", THIS},
1003 : {"return function (x) { return this + x }", NONE},
1004 : {"return { m(x) { return super.m() + x } }", NONE},
1005 : {"var x = function () { this.foo = 42 };", NONE},
1006 : {"var x = { m() { super.foo = 42 } };", NONE},
1007 : {"if (1) { return function () { while (true) new this() } }", NONE},
1008 : {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1009 : {"return function (x) { return () => this }", NONE},
1010 : {"return { m(x) { return () => super.m() } }", NONE},
1011 : // Flags must be correctly set when using block scoping.
1012 : {"\"use strict\"; while (true) { let x; this, arguments; }",
1013 : THIS},
1014 : {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1015 : SUPER_PROPERTY | THIS},
1016 : {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
1017 : {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
1018 : {"\"use strict\"; if (1) {"
1019 : " let x; return { m() { return this + super.m() + arguments } }"
1020 : "}",
1021 : NONE},
1022 : {"eval(42)", EVAL},
1023 : {"if (1) { eval(42) }", EVAL},
1024 : {"eval('super.x')", EVAL},
1025 : {"eval('this.x')", EVAL},
1026 : {"eval('arguments')", EVAL},
1027 : };
1028 : // clang-format on
1029 :
1030 : i::Isolate* isolate = CcTest::i_isolate();
1031 : i::Factory* factory = isolate->factory();
1032 :
1033 5 : v8::HandleScope handles(CcTest::isolate());
1034 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1035 : v8::Context::Scope context_scope(context);
1036 :
1037 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1038 5 : 128 * 1024);
1039 :
1040 20 : for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1041 570 : for (unsigned i = 0; i < arraysize(source_data); ++i) {
1042 : // Super property is only allowed in constructor and method.
1043 570 : if (((source_data[i].expected & SUPER_PROPERTY) ||
1044 270 : (source_data[i].expected == NONE)) && j != 2) {
1045 180 : continue;
1046 : }
1047 780 : int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1048 390 : i::StrLength(surroundings[j].suffix) +
1049 780 : i::StrLength(source_data[i].body);
1050 390 : i::ScopedVector<char> program(kProgramByteSize + 1);
1051 : i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1052 390 : source_data[i].body, surroundings[j].suffix);
1053 : i::Handle<i::String> source =
1054 : factory->NewStringFromUtf8(i::CStrVector(program.start()))
1055 780 : .ToHandleChecked();
1056 390 : i::Handle<i::Script> script = factory->NewScript(source);
1057 780 : i::ParseInfo info(isolate, script);
1058 : // The information we're checking is only produced when eager parsing.
1059 : info.set_allow_lazy_parsing(false);
1060 390 : CHECK(i::parsing::ParseProgram(&info, isolate));
1061 390 : CHECK(i::Rewriter::Rewrite(&info));
1062 390 : info.ast_value_factory()->Internalize(isolate);
1063 390 : CHECK(i::DeclarationScope::Analyze(&info));
1064 390 : i::DeclarationScope::AllocateScopeInfos(&info, isolate);
1065 390 : CHECK_NOT_NULL(info.literal());
1066 :
1067 390 : i::DeclarationScope* script_scope = info.literal()->scope();
1068 390 : CHECK(script_scope->is_script_scope());
1069 :
1070 190 : i::Scope* scope = script_scope->inner_scope();
1071 : DCHECK_NOT_NULL(scope);
1072 : DCHECK_NULL(scope->sibling());
1073 : // Adjust for constructor scope.
1074 390 : if (j == 2) {
1075 : scope = scope->inner_scope();
1076 : DCHECK_NOT_NULL(scope);
1077 : DCHECK_NULL(scope->sibling());
1078 : }
1079 : // Arrows themselves never get an arguments object.
1080 470 : if ((source_data[i].expected & ARGUMENTS) != 0 &&
1081 80 : !scope->AsDeclarationScope()->is_arrow_scope()) {
1082 55 : CHECK_NOT_NULL(scope->AsDeclarationScope()->arguments());
1083 : }
1084 780 : if (IsClassConstructor(scope->AsDeclarationScope()->function_kind())) {
1085 190 : CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0 ||
1086 : (source_data[i].expected & EVAL) != 0,
1087 : scope->AsDeclarationScope()->NeedsHomeObject());
1088 : } else {
1089 200 : CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1090 : scope->AsDeclarationScope()->NeedsHomeObject());
1091 : }
1092 390 : if ((source_data[i].expected & THIS) != 0) {
1093 : // Currently the is_used() flag is conservative; all variables in a
1094 : // script scope are marked as used.
1095 410 : CHECK(scope->GetReceiverScope()->receiver()->is_used());
1096 : }
1097 390 : if (is_sloppy(scope->language_mode())) {
1098 360 : CHECK_EQ((source_data[i].expected & EVAL) != 0,
1099 : scope->AsDeclarationScope()->calls_sloppy_eval());
1100 : }
1101 : }
1102 5 : }
1103 5 : }
1104 :
1105 75 : static void CheckParsesToNumber(const char* source) {
1106 75 : v8::V8::Initialize();
1107 75 : HandleAndZoneScope handles;
1108 :
1109 : i::Isolate* isolate = CcTest::i_isolate();
1110 : i::Factory* factory = isolate->factory();
1111 :
1112 75 : std::string full_source = "function f() { return ";
1113 : full_source += source;
1114 : full_source += "; }";
1115 :
1116 : i::Handle<i::String> source_code =
1117 : factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1118 150 : .ToHandleChecked();
1119 :
1120 75 : i::Handle<i::Script> script = factory->NewScript(source_code);
1121 :
1122 150 : i::ParseInfo info(isolate, script);
1123 : info.set_allow_lazy_parsing(false);
1124 : info.set_toplevel(true);
1125 :
1126 75 : CHECK(i::parsing::ParseProgram(&info, isolate));
1127 :
1128 150 : CHECK_EQ(1, info.scope()->declarations()->LengthForTest());
1129 75 : i::Declaration* decl = info.scope()->declarations()->AtForTest(0);
1130 150 : i::FunctionLiteral* fun = decl->AsFunctionDeclaration()->fun();
1131 75 : CHECK_EQ(fun->body()->length(), 1);
1132 150 : CHECK(fun->body()->at(0)->IsReturnStatement());
1133 150 : i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1134 75 : i::Literal* lit = ret->expression()->AsLiteral();
1135 150 : CHECK(lit->IsNumberLiteral());
1136 75 : }
1137 :
1138 :
1139 25880 : TEST(ParseNumbers) {
1140 5 : CheckParsesToNumber("1.");
1141 5 : CheckParsesToNumber("1.34");
1142 5 : CheckParsesToNumber("134");
1143 5 : CheckParsesToNumber("134e44");
1144 5 : CheckParsesToNumber("134.e44");
1145 5 : CheckParsesToNumber("134.44e44");
1146 5 : CheckParsesToNumber(".44");
1147 :
1148 5 : CheckParsesToNumber("-1.");
1149 5 : CheckParsesToNumber("-1.0");
1150 5 : CheckParsesToNumber("-1.34");
1151 5 : CheckParsesToNumber("-134");
1152 5 : CheckParsesToNumber("-134e44");
1153 5 : CheckParsesToNumber("-134.e44");
1154 5 : CheckParsesToNumber("-134.44e44");
1155 5 : CheckParsesToNumber("-.44");
1156 5 : }
1157 :
1158 :
1159 25880 : TEST(ScopePositions) {
1160 : // Test the parser for correctly setting the start and end positions
1161 : // of a scope. We check the scope positions of exactly one scope
1162 : // nested in the global scope of a program. 'inner source' is the
1163 : // source code that determines the part of the source belonging
1164 : // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1165 : // parts of the source that belong to the global scope.
1166 : struct SourceData {
1167 : const char* outer_prefix;
1168 : const char* inner_source;
1169 : const char* outer_suffix;
1170 : i::ScopeType scope_type;
1171 : i::LanguageMode language_mode;
1172 : };
1173 :
1174 : const SourceData source_data[] = {
1175 : {" with ({}) ", "{ block; }", " more;", i::WITH_SCOPE,
1176 : i::LanguageMode::kSloppy},
1177 : {" with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE,
1178 : i::LanguageMode::kSloppy},
1179 : {" with ({}) ",
1180 : "{\n"
1181 : " block;\n"
1182 : " }",
1183 : "\n"
1184 : " more;",
1185 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1186 : {" with ({}) ", "statement;", " more;", i::WITH_SCOPE,
1187 : i::LanguageMode::kSloppy},
1188 : {" with ({}) ", "statement",
1189 : "\n"
1190 : " more;",
1191 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1192 : {" with ({})\n"
1193 : " ",
1194 : "statement;",
1195 : "\n"
1196 : " more;",
1197 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1198 : {" try {} catch ", "(e) { block; }", " more;", i::CATCH_SCOPE,
1199 : i::LanguageMode::kSloppy},
1200 : {" try {} catch ", "(e) { block; }", "; more;", i::CATCH_SCOPE,
1201 : i::LanguageMode::kSloppy},
1202 : {" try {} catch ",
1203 : "(e) {\n"
1204 : " block;\n"
1205 : " }",
1206 : "\n"
1207 : " more;",
1208 : i::CATCH_SCOPE, i::LanguageMode::kSloppy},
1209 : {" try {} catch ", "(e) { block; }", " finally { block; } more;",
1210 : i::CATCH_SCOPE, i::LanguageMode::kSloppy},
1211 : {" start;\n"
1212 : " ",
1213 : "{ let block; }", " more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1214 : {" start;\n"
1215 : " ",
1216 : "{ let block; }", "; more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1217 : {" start;\n"
1218 : " ",
1219 : "{\n"
1220 : " let block;\n"
1221 : " }",
1222 : "\n"
1223 : " more;",
1224 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1225 : {" start;\n"
1226 : " function fun",
1227 : "(a,b) { infunction; }", " more;", i::FUNCTION_SCOPE,
1228 : i::LanguageMode::kSloppy},
1229 : {" start;\n"
1230 : " function fun",
1231 : "(a,b) {\n"
1232 : " infunction;\n"
1233 : " }",
1234 : "\n"
1235 : " more;",
1236 : i::FUNCTION_SCOPE, i::LanguageMode::kSloppy},
1237 : {" start;\n", "(a,b) => a + b", "; more;", i::FUNCTION_SCOPE,
1238 : i::LanguageMode::kSloppy},
1239 : {" start;\n", "(a,b) => { return a+b; }", "\nmore;", i::FUNCTION_SCOPE,
1240 : i::LanguageMode::kSloppy},
1241 : {" start;\n"
1242 : " (function fun",
1243 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1244 : i::LanguageMode::kSloppy},
1245 : {" for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
1246 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1247 : {" for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
1248 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1249 : {" for ",
1250 : "(let x = 1 ; x < 10; ++ x) {\n"
1251 : " block;\n"
1252 : " }",
1253 : "\n"
1254 : " more;",
1255 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1256 : {" for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
1257 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1258 : {" for ", "(let x = 1 ; x < 10; ++ x) statement",
1259 : "\n"
1260 : " more;",
1261 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1262 : {" for ",
1263 : "(let x = 1 ; x < 10; ++ x)\n"
1264 : " statement;",
1265 : "\n"
1266 : " more;",
1267 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1268 : {" for ", "(let x in {}) { block; }", " more;", i::BLOCK_SCOPE,
1269 : i::LanguageMode::kStrict},
1270 : {" for ", "(let x in {}) { block; }", "; more;", i::BLOCK_SCOPE,
1271 : i::LanguageMode::kStrict},
1272 : {" for ",
1273 : "(let x in {}) {\n"
1274 : " block;\n"
1275 : " }",
1276 : "\n"
1277 : " more;",
1278 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1279 : {" for ", "(let x in {}) statement;", " more;", i::BLOCK_SCOPE,
1280 : i::LanguageMode::kStrict},
1281 : {" for ", "(let x in {}) statement",
1282 : "\n"
1283 : " more;",
1284 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1285 : {" for ",
1286 : "(let x in {})\n"
1287 : " statement;",
1288 : "\n"
1289 : " more;",
1290 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1291 : // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1292 : // the preparser off in terms of byte offsets.
1293 : // 2 surrogates, encode a character that doesn't need a surrogate.
1294 : {" 'foo\xED\xA0\x81\xED\xB0\x89';\n"
1295 : " (function fun",
1296 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1297 : i::LanguageMode::kSloppy},
1298 : // 4-byte encoding.
1299 : {" 'foo\xF0\x90\x90\x8A';\n"
1300 : " (function fun",
1301 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1302 : i::LanguageMode::kSloppy},
1303 : // 3-byte encoding of \u0FFF.
1304 : {" 'foo\xE0\xBF\xBF';\n"
1305 : " (function fun",
1306 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1307 : i::LanguageMode::kSloppy},
1308 : // 3-byte surrogate, followed by broken 2-byte surrogate w/ impossible 2nd
1309 : // byte and last byte missing.
1310 : {" 'foo\xED\xA0\x81\xED\x89';\n"
1311 : " (function fun",
1312 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1313 : i::LanguageMode::kSloppy},
1314 : // Broken 3-byte encoding of \u0FFF with missing last byte.
1315 : {" 'foo\xE0\xBF';\n"
1316 : " (function fun",
1317 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1318 : i::LanguageMode::kSloppy},
1319 : // Broken 3-byte encoding of \u0FFF with missing 2 last bytes.
1320 : {" 'foo\xE0';\n"
1321 : " (function fun",
1322 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1323 : i::LanguageMode::kSloppy},
1324 : // Broken 3-byte encoding of \u00FF should be a 2-byte encoding.
1325 : {" 'foo\xE0\x83\xBF';\n"
1326 : " (function fun",
1327 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1328 : i::LanguageMode::kSloppy},
1329 : // Broken 3-byte encoding of \u007F should be a 2-byte encoding.
1330 : {" 'foo\xE0\x81\xBF';\n"
1331 : " (function fun",
1332 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1333 : i::LanguageMode::kSloppy},
1334 : // Unpaired lead surrogate.
1335 : {" 'foo\xED\xA0\x81';\n"
1336 : " (function fun",
1337 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1338 : i::LanguageMode::kSloppy},
1339 : // Unpaired lead surrogate where the following code point is a 3-byte
1340 : // sequence.
1341 : {" 'foo\xED\xA0\x81\xE0\xBF\xBF';\n"
1342 : " (function fun",
1343 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1344 : i::LanguageMode::kSloppy},
1345 : // Unpaired lead surrogate where the following code point is a 4-byte
1346 : // encoding of a trail surrogate.
1347 : {" 'foo\xED\xA0\x81\xF0\x8D\xB0\x89';\n"
1348 : " (function fun",
1349 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1350 : i::LanguageMode::kSloppy},
1351 : // Unpaired trail surrogate.
1352 : {" 'foo\xED\xB0\x89';\n"
1353 : " (function fun",
1354 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1355 : i::LanguageMode::kSloppy},
1356 : // 2-byte encoding of \u00FF.
1357 : {" 'foo\xC3\xBF';\n"
1358 : " (function fun",
1359 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1360 : i::LanguageMode::kSloppy},
1361 : // Broken 2-byte encoding of \u00FF with missing last byte.
1362 : {" 'foo\xC3';\n"
1363 : " (function fun",
1364 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1365 : i::LanguageMode::kSloppy},
1366 : // Broken 2-byte encoding of \u007F should be a 1-byte encoding.
1367 : {" 'foo\xC1\xBF';\n"
1368 : " (function fun",
1369 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1370 : i::LanguageMode::kSloppy},
1371 : // Illegal 5-byte encoding.
1372 : {" 'foo\xF8\xBF\xBF\xBF\xBF';\n"
1373 : " (function fun",
1374 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1375 : i::LanguageMode::kSloppy},
1376 : // Illegal 6-byte encoding.
1377 : {" 'foo\xFC\xBF\xBF\xBF\xBF\xBF';\n"
1378 : " (function fun",
1379 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1380 : i::LanguageMode::kSloppy},
1381 : // Illegal 0xFE byte
1382 : {" 'foo\xFE\xBF\xBF\xBF\xBF\xBF\xBF';\n"
1383 : " (function fun",
1384 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1385 : i::LanguageMode::kSloppy},
1386 : // Illegal 0xFF byte
1387 : {" 'foo\xFF\xBF\xBF\xBF\xBF\xBF\xBF\xBF';\n"
1388 : " (function fun",
1389 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1390 : i::LanguageMode::kSloppy},
1391 : {" 'foo';\n"
1392 : " (function fun",
1393 : "(a,b) { 'bar\xED\xA0\x81\xED\xB0\x8B'; }", ")();", i::FUNCTION_SCOPE,
1394 : i::LanguageMode::kSloppy},
1395 : {" 'foo';\n"
1396 : " (function fun",
1397 : "(a,b) { 'bar\xF0\x90\x90\x8C'; }", ")();", i::FUNCTION_SCOPE,
1398 : i::LanguageMode::kSloppy},
1399 5 : {nullptr, nullptr, nullptr, i::EVAL_SCOPE, i::LanguageMode::kSloppy}};
1400 :
1401 : i::Isolate* isolate = CcTest::i_isolate();
1402 : i::Factory* factory = isolate->factory();
1403 :
1404 5 : v8::HandleScope handles(CcTest::isolate());
1405 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1406 : v8::Context::Scope context_scope(context);
1407 :
1408 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1409 5 : 128 * 1024);
1410 :
1411 260 : for (int i = 0; source_data[i].outer_prefix; i++) {
1412 255 : int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1413 255 : int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1414 255 : int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1415 : int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1416 : int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1417 : int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1418 255 : int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1419 255 : int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1420 255 : i::ScopedVector<char> program(kProgramByteSize + 1);
1421 : i::SNPrintF(program, "%s%s%s",
1422 : source_data[i].outer_prefix,
1423 : source_data[i].inner_source,
1424 255 : source_data[i].outer_suffix);
1425 :
1426 : // Parse program source.
1427 : i::Handle<i::String> source = factory->NewStringFromUtf8(
1428 510 : i::CStrVector(program.start())).ToHandleChecked();
1429 255 : CHECK_EQ(source->length(), kProgramSize);
1430 255 : i::Handle<i::Script> script = factory->NewScript(source);
1431 510 : i::ParseInfo info(isolate, script);
1432 255 : info.set_language_mode(source_data[i].language_mode);
1433 255 : i::parsing::ParseProgram(&info, isolate);
1434 255 : CHECK_NOT_NULL(info.literal());
1435 :
1436 : // Check scope types and positions.
1437 1020 : i::Scope* scope = info.literal()->scope();
1438 255 : CHECK(scope->is_script_scope());
1439 255 : CHECK_EQ(0, scope->start_position());
1440 255 : CHECK_EQ(scope->end_position(), kProgramSize);
1441 :
1442 765 : i::Scope* inner_scope = scope->inner_scope();
1443 : DCHECK_NOT_NULL(inner_scope);
1444 : DCHECK_NULL(inner_scope->sibling());
1445 510 : CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1446 255 : CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1447 : // The end position of a token is one position after the last
1448 : // character belonging to that token.
1449 255 : CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1450 5 : }
1451 5 : }
1452 :
1453 :
1454 25880 : TEST(DiscardFunctionBody) {
1455 : // Test that inner function bodies are discarded if possible.
1456 : // See comments in ParseFunctionLiteral in parser.cc.
1457 : const char* discard_sources[] = {
1458 : "(function f() { function g() { var a; } })();",
1459 : "(function f() { function g() { { function h() { } } } })();",
1460 : /* TODO(conradw): In future it may be possible to apply this optimisation
1461 : * to these productions.
1462 : "(function f() { 0, function g() { var a; } })();",
1463 : "(function f() { 0, { g() { var a; } } })();",
1464 : "(function f() { 0, class c { g() { var a; } } })();", */
1465 5 : nullptr};
1466 :
1467 : i::Isolate* isolate = CcTest::i_isolate();
1468 : i::Factory* factory = isolate->factory();
1469 5 : v8::HandleScope handles(CcTest::isolate());
1470 : i::FunctionLiteral* function;
1471 :
1472 15 : for (int i = 0; discard_sources[i]; i++) {
1473 : const char* source = discard_sources[i];
1474 : i::Handle<i::String> source_code =
1475 20 : factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
1476 10 : i::Handle<i::Script> script = factory->NewScript(source_code);
1477 10 : i::ParseInfo info(isolate, script);
1478 10 : i::parsing::ParseProgram(&info, isolate);
1479 10 : function = info.literal();
1480 10 : CHECK_NOT_NULL(function);
1481 10 : CHECK_EQ(1, function->body()->length());
1482 10 : i::FunctionLiteral* inner =
1483 20 : function->body()->first()->AsExpressionStatement()->expression()->
1484 20 : AsCall()->expression()->AsFunctionLiteral();
1485 : i::Scope* inner_scope = inner->scope();
1486 : i::FunctionLiteral* fun = nullptr;
1487 10 : if (!inner_scope->declarations()->is_empty()) {
1488 : fun = inner_scope->declarations()
1489 : ->AtForTest(0)
1490 : ->AsFunctionDeclaration()
1491 20 : ->fun();
1492 : } else {
1493 : // TODO(conradw): This path won't be hit until the other test cases can be
1494 : // uncommented.
1495 0 : UNREACHABLE();
1496 : CHECK(inner->ShouldEagerCompile());
1497 : CHECK_GE(2, inner->body()->length());
1498 : i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
1499 : expression()->AsBinaryOperation()->right();
1500 : if (exp->IsFunctionLiteral()) {
1501 : fun = exp->AsFunctionLiteral();
1502 : } else if (exp->IsObjectLiteral()) {
1503 : fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
1504 : AsFunctionLiteral();
1505 : } else {
1506 : fun = exp->AsClassLiteral()->properties()->at(0)->value()->
1507 : AsFunctionLiteral();
1508 : }
1509 : }
1510 10 : CHECK(!fun->ShouldEagerCompile());
1511 15 : }
1512 5 : }
1513 :
1514 :
1515 0 : const char* ReadString(unsigned* start) {
1516 0 : int length = start[0];
1517 0 : char* result = i::NewArray<char>(length + 1);
1518 0 : for (int i = 0; i < length; i++) {
1519 0 : result[i] = start[i + 1];
1520 : }
1521 0 : result[length] = '\0';
1522 0 : return result;
1523 : }
1524 :
1525 : enum ParserFlag {
1526 : kAllowLazy,
1527 : kAllowNatives,
1528 : kAllowHarmonyPublicFields,
1529 : kAllowHarmonyPrivateFields,
1530 : kAllowHarmonyPrivateMethods,
1531 : kAllowHarmonyStaticFields,
1532 : kAllowHarmonyDynamicImport,
1533 : kAllowHarmonyImportMeta,
1534 : kAllowHarmonyNumericSeparator
1535 : };
1536 :
1537 : enum ParserSyncTestResult {
1538 : kSuccessOrError,
1539 : kSuccess,
1540 : kError
1541 : };
1542 :
1543 521129 : void SetGlobalFlags(base::EnumSet<ParserFlag> flags) {
1544 521129 : i::FLAG_allow_natives_syntax = flags.contains(kAllowNatives);
1545 521129 : i::FLAG_harmony_public_fields = flags.contains(kAllowHarmonyPublicFields);
1546 521129 : i::FLAG_harmony_private_fields = flags.contains(kAllowHarmonyPrivateFields);
1547 521129 : i::FLAG_harmony_private_methods = flags.contains(kAllowHarmonyPrivateMethods);
1548 521129 : i::FLAG_harmony_static_fields = flags.contains(kAllowHarmonyStaticFields);
1549 521129 : i::FLAG_harmony_dynamic_import = flags.contains(kAllowHarmonyDynamicImport);
1550 521129 : i::FLAG_harmony_import_meta = flags.contains(kAllowHarmonyImportMeta);
1551 : i::FLAG_harmony_numeric_separator =
1552 521129 : flags.contains(kAllowHarmonyNumericSeparator);
1553 521129 : }
1554 :
1555 520149 : void SetParserFlags(i::PreParser* parser, base::EnumSet<ParserFlag> flags) {
1556 : parser->set_allow_natives(flags.contains(kAllowNatives));
1557 : parser->set_allow_harmony_public_fields(
1558 : flags.contains(kAllowHarmonyPublicFields));
1559 : parser->set_allow_harmony_private_fields(
1560 : flags.contains(kAllowHarmonyPrivateFields));
1561 : parser->set_allow_harmony_private_methods(
1562 : flags.contains(kAllowHarmonyPrivateMethods));
1563 : parser->set_allow_harmony_static_fields(
1564 : flags.contains(kAllowHarmonyStaticFields));
1565 : parser->set_allow_harmony_dynamic_import(
1566 : flags.contains(kAllowHarmonyDynamicImport));
1567 : parser->set_allow_harmony_import_meta(
1568 : flags.contains(kAllowHarmonyImportMeta));
1569 : parser->set_allow_harmony_numeric_separator(
1570 : flags.contains(kAllowHarmonyNumericSeparator));
1571 520149 : }
1572 :
1573 521129 : void TestParserSyncWithFlags(i::Handle<i::String> source,
1574 : base::EnumSet<ParserFlag> flags,
1575 : ParserSyncTestResult result,
1576 : bool is_module = false, bool test_preparser = true,
1577 : bool ignore_error_msg = false) {
1578 1560447 : i::Isolate* isolate = CcTest::i_isolate();
1579 : i::Factory* factory = isolate->factory();
1580 :
1581 521129 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1582 :
1583 : // Preparse the data.
1584 : i::PendingCompilationErrorHandler pending_error_handler;
1585 521129 : if (test_preparser) {
1586 : std::unique_ptr<i::Utf16CharacterStream> stream(
1587 520149 : i::ScannerStream::For(isolate, source));
1588 1040298 : i::Scanner scanner(stream.get(), is_module);
1589 1040298 : i::Zone zone(isolate->allocator(), ZONE_NAME);
1590 : i::AstValueFactory ast_value_factory(&zone, isolate->ast_string_constants(),
1591 1040298 : HashSeed(isolate));
1592 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
1593 : &pending_error_handler,
1594 : isolate->counters()->runtime_call_stats(),
1595 1040298 : isolate->logger(), -1, is_module);
1596 520149 : SetParserFlags(&preparser, flags);
1597 520149 : scanner.Initialize();
1598 520149 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
1599 520149 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1600 : }
1601 :
1602 : // Parse the data
1603 : i::FunctionLiteral* function;
1604 : {
1605 521129 : SetGlobalFlags(flags);
1606 521129 : i::Handle<i::Script> script = factory->NewScript(source);
1607 521129 : i::ParseInfo info(isolate, script);
1608 : info.set_allow_lazy_parsing(flags.contains(kAllowLazy));
1609 521129 : if (is_module) info.set_module();
1610 521129 : i::parsing::ParseProgram(&info, isolate);
1611 521129 : function = info.literal();
1612 : }
1613 :
1614 : // Check that preparsing fails iff parsing fails.
1615 521129 : if (function == nullptr) {
1616 : // Extract exception from the parser.
1617 272590 : CHECK(isolate->has_pending_exception());
1618 : i::Handle<i::JSObject> exception_handle(
1619 : i::JSObject::cast(isolate->pending_exception()), isolate);
1620 : i::Handle<i::String> message_string = i::Handle<i::String>::cast(
1621 272590 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1622 545180 : .ToHandleChecked());
1623 272590 : isolate->clear_pending_exception();
1624 :
1625 272590 : if (result == kSuccess) {
1626 0 : FATAL(
1627 : "Parser failed on:\n"
1628 : "\t%s\n"
1629 : "with error:\n"
1630 : "\t%s\n"
1631 : "However, we expected no error.",
1632 0 : source->ToCString().get(), message_string->ToCString().get());
1633 : }
1634 :
1635 272590 : if (test_preparser && !pending_error_handler.has_pending_error() &&
1636 0 : !pending_error_handler.has_error_unidentifiable_by_preparser()) {
1637 0 : FATAL(
1638 : "Parser failed on:\n"
1639 : "\t%s\n"
1640 : "with error:\n"
1641 : "\t%s\n"
1642 : "However, the preparser succeeded",
1643 0 : source->ToCString().get(), message_string->ToCString().get());
1644 : }
1645 : // Check that preparser and parser produce the same error, except for cases
1646 : // where we do not track errors in the preparser.
1647 532940 : if (test_preparser && !ignore_error_msg &&
1648 260350 : !pending_error_handler.has_error_unidentifiable_by_preparser()) {
1649 : i::Handle<i::String> preparser_message =
1650 2502 : pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate());
1651 2502 : if (!i::String::Equals(isolate, message_string, preparser_message)) {
1652 0 : FATAL(
1653 : "Expected parser and preparser to produce the same error on:\n"
1654 : "\t%s\n"
1655 : "However, found the following error messages\n"
1656 : "\tparser: %s\n"
1657 : "\tpreparser: %s\n",
1658 : source->ToCString().get(), message_string->ToCString().get(),
1659 0 : preparser_message->ToCString().get());
1660 : }
1661 : }
1662 248539 : } else if (test_preparser && pending_error_handler.has_pending_error()) {
1663 0 : FATAL(
1664 : "Preparser failed on:\n"
1665 : "\t%s\n"
1666 : "with error:\n"
1667 : "\t%s\n"
1668 : "However, the parser succeeded",
1669 : source->ToCString().get(),
1670 : pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate())
1671 : ->ToCString()
1672 0 : .get());
1673 248539 : } else if (result == kError) {
1674 0 : FATAL(
1675 : "Expected error on:\n"
1676 : "\t%s\n"
1677 : "However, parser and preparser succeeded",
1678 0 : source->ToCString().get());
1679 : }
1680 521129 : }
1681 :
1682 133173 : void TestParserSync(const char* source, const ParserFlag* varying_flags,
1683 : size_t varying_flags_length,
1684 : ParserSyncTestResult result = kSuccessOrError,
1685 : const ParserFlag* always_true_flags = nullptr,
1686 : size_t always_true_flags_length = 0,
1687 : const ParserFlag* always_false_flags = nullptr,
1688 : size_t always_false_flags_length = 0,
1689 : bool is_module = false, bool test_preparser = true,
1690 : bool ignore_error_msg = false) {
1691 : i::Handle<i::String> str =
1692 : CcTest::i_isolate()
1693 : ->factory()
1694 266346 : ->NewStringFromUtf8(Vector<const char>(source, strlen(source)))
1695 266346 : .ToHandleChecked();
1696 654302 : for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1697 : base::EnumSet<ParserFlag> flags;
1698 1032972 : for (size_t flag_index = 0; flag_index < varying_flags_length;
1699 : ++flag_index) {
1700 1032972 : if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1701 : }
1702 147250 : for (size_t flag_index = 0; flag_index < always_true_flags_length;
1703 : ++flag_index) {
1704 147250 : flags.Add(always_true_flags[flag_index]);
1705 : }
1706 0 : for (size_t flag_index = 0; flag_index < always_false_flags_length;
1707 : ++flag_index) {
1708 0 : flags.Remove(always_false_flags[flag_index]);
1709 : }
1710 : TestParserSyncWithFlags(str, flags, result, is_module, test_preparser,
1711 521129 : ignore_error_msg);
1712 : }
1713 133173 : }
1714 :
1715 :
1716 25876 : TEST(ParserSync) {
1717 : const char* context_data[][2] = {{"", ""},
1718 : {"{", "}"},
1719 : {"if (true) ", " else {}"},
1720 : {"if (true) {} else ", ""},
1721 : {"if (true) ", ""},
1722 : {"do ", " while (false)"},
1723 : {"while (false) ", ""},
1724 : {"for (;;) ", ""},
1725 : {"with ({})", ""},
1726 : {"switch (12) { case 12: ", "}"},
1727 : {"switch (12) { default: ", "}"},
1728 : {"switch (12) { ", "case 12: }"},
1729 : {"label2: ", ""},
1730 1 : {nullptr, nullptr}};
1731 :
1732 : const char* statement_data[] = {
1733 : "{}", "var x", "var x = 1", "const x", "const x = 1", ";", "12",
1734 : "if (false) {} else ;", "if (false) {} else {}", "if (false) {} else 12",
1735 : "if (false) ;", "if (false) {}", "if (false) 12", "do {} while (false)",
1736 : "for (;;) ;", "for (;;) {}", "for (;;) 12", "continue", "continue label",
1737 : "continue\nlabel", "break", "break label", "break\nlabel",
1738 : // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1739 : // "return",
1740 : // "return 12",
1741 : // "return\n12",
1742 : "with ({}) ;", "with ({}) {}", "with ({}) 12", "switch ({}) { default: }",
1743 : "label3: ", "throw", "throw 12", "throw\n12", "try {} catch(e) {}",
1744 : "try {} finally {}", "try {} catch(e) {} finally {}", "debugger",
1745 1 : nullptr};
1746 :
1747 1 : const char* termination_data[] = {"", ";", "\n", ";\n", "\n;", nullptr};
1748 :
1749 1 : v8::HandleScope handles(CcTest::isolate());
1750 1 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1751 : v8::Context::Scope context_scope(context);
1752 :
1753 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1754 2 : i::GetCurrentStackPosition() - 128 * 1024);
1755 :
1756 14 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1757 455 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1758 2275 : for (int k = 0; termination_data[k] != nullptr; ++k) {
1759 : int kPrefixLen = i::StrLength(context_data[i][0]);
1760 : int kStatementLen = i::StrLength(statement_data[j]);
1761 : int kTerminationLen = i::StrLength(termination_data[k]);
1762 2275 : int kSuffixLen = i::StrLength(context_data[i][1]);
1763 2275 : int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1764 2275 : + kSuffixLen + i::StrLength("label: for (;;) { }");
1765 :
1766 : // Plug the source code pieces together.
1767 2275 : i::ScopedVector<char> program(kProgramSize + 1);
1768 : int length = i::SNPrintF(program,
1769 : "label: for (;;) { %s%s%s%s }",
1770 : context_data[i][0],
1771 : statement_data[j],
1772 : termination_data[k],
1773 2275 : context_data[i][1]);
1774 2275 : CHECK_EQ(length, kProgramSize);
1775 2275 : TestParserSync(program.start(), nullptr, 0);
1776 : }
1777 : }
1778 : }
1779 :
1780 : // Neither Harmony numeric literals nor our natives syntax have any
1781 : // interaction with the flags above, so test these separately to reduce
1782 : // the combinatorial explosion.
1783 1 : TestParserSync("0o1234", nullptr, 0);
1784 1 : TestParserSync("0b1011", nullptr, 0);
1785 :
1786 : static const ParserFlag flags3[] = { kAllowNatives };
1787 2 : TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1788 1 : }
1789 :
1790 :
1791 25880 : TEST(StrictOctal) {
1792 : // Test that syntax error caused by octal literal is reported correctly as
1793 : // such (issue 2220).
1794 5 : v8::V8::Initialize();
1795 5 : v8::Isolate* isolate = CcTest::isolate();
1796 5 : v8::HandleScope scope(isolate);
1797 10 : v8::Context::Scope context_scope(v8::Context::New(isolate));
1798 :
1799 10 : v8::TryCatch try_catch(isolate);
1800 : const char* script =
1801 : "\"use strict\"; \n"
1802 : "a = function() { \n"
1803 : " b = function() { \n"
1804 : " 01; \n"
1805 : " }; \n"
1806 : "}; \n";
1807 5 : v8_compile(v8_str(script));
1808 5 : CHECK(try_catch.HasCaught());
1809 10 : v8::String::Utf8Value exception(isolate, try_catch.Exception());
1810 5 : CHECK_EQ(0,
1811 : strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1812 5 : *exception));
1813 5 : }
1814 :
1815 1570 : void RunParserSyncTest(
1816 : const char* context_data[][2], const char* statement_data[],
1817 : ParserSyncTestResult result, const ParserFlag* flags = nullptr,
1818 : int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
1819 : int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
1820 : int always_false_len = 0, bool is_module = false,
1821 : bool test_preparser = true, bool ignore_error_msg = false) {
1822 1570 : v8::HandleScope handles(CcTest::isolate());
1823 1570 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1824 : v8::Context::Scope context_scope(context);
1825 :
1826 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1827 3140 : i::GetCurrentStackPosition() - 128 * 1024);
1828 :
1829 : // Experimental feature flags should not go here; pass the flags as
1830 : // always_true_flags if the test needs them.
1831 : static const ParserFlag default_flags[] = {
1832 : kAllowLazy,
1833 : kAllowNatives,
1834 : };
1835 : ParserFlag* generated_flags = nullptr;
1836 1570 : if (flags == nullptr) {
1837 : flags = default_flags;
1838 : flags_len = arraysize(default_flags);
1839 1550 : if (always_true_flags != nullptr || always_false_flags != nullptr) {
1840 : // Remove always_true/false_flags from default_flags (if present).
1841 185 : CHECK((always_true_flags != nullptr) == (always_true_len > 0));
1842 185 : CHECK((always_false_flags != nullptr) == (always_false_len > 0));
1843 185 : generated_flags = new ParserFlag[flags_len + always_true_len];
1844 : int flag_index = 0;
1845 555 : for (int i = 0; i < flags_len; ++i) {
1846 : bool use_flag = true;
1847 560 : for (int j = 0; use_flag && j < always_true_len; ++j) {
1848 560 : if (flags[i] == always_true_flags[j]) use_flag = false;
1849 : }
1850 0 : for (int j = 0; use_flag && j < always_false_len; ++j) {
1851 0 : if (flags[i] == always_false_flags[j]) use_flag = false;
1852 : }
1853 370 : if (use_flag) generated_flags[flag_index++] = flags[i];
1854 : }
1855 : flags_len = flag_index;
1856 : flags = generated_flags;
1857 : }
1858 : }
1859 8365 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1860 130895 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1861 130895 : int kPrefixLen = i::StrLength(context_data[i][0]);
1862 : int kStatementLen = i::StrLength(statement_data[j]);
1863 130895 : int kSuffixLen = i::StrLength(context_data[i][1]);
1864 130895 : int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1865 :
1866 : // Plug the source code pieces together.
1867 130895 : i::ScopedVector<char> program(kProgramSize + 1);
1868 : int length = i::SNPrintF(program,
1869 : "%s%s%s",
1870 : context_data[i][0],
1871 : statement_data[j],
1872 130895 : context_data[i][1]);
1873 130895 : PrintF("%s\n", program.start());
1874 130895 : CHECK_EQ(length, kProgramSize);
1875 : TestParserSync(program.start(), flags, flags_len, result,
1876 : always_true_flags, always_true_len, always_false_flags,
1877 : always_false_len, is_module, test_preparser,
1878 130895 : ignore_error_msg);
1879 : }
1880 : }
1881 3140 : delete[] generated_flags;
1882 1570 : }
1883 :
1884 0 : void RunModuleParserSyncTest(
1885 : const char* context_data[][2], const char* statement_data[],
1886 : ParserSyncTestResult result, const ParserFlag* flags = nullptr,
1887 : int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
1888 : int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
1889 : int always_false_len = 0, bool test_preparser = true,
1890 : bool ignore_error_msg = false) {
1891 : RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1892 : always_true_flags, always_true_len, always_false_flags,
1893 95 : always_false_len, true, test_preparser, ignore_error_msg);
1894 0 : }
1895 :
1896 25880 : TEST(NumericSeparator) {
1897 5 : v8::HandleScope handles(CcTest::isolate());
1898 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1899 : v8::Context::Scope context_scope(context);
1900 :
1901 : const char* context_data[][2] = {
1902 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1903 : const char* statement_data[] = {
1904 : "1_0_0_0", "1_0e+1", "1_0e+1_0", "0xF_F_FF", "0o7_7_7", "0b0_1_0_1_0",
1905 5 : ".3_2_1", "0.0_2_1", "1_0.0_1", ".0_1_2", nullptr};
1906 :
1907 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1908 : RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0, flags,
1909 5 : 1);
1910 :
1911 10 : RunParserSyncTest(context_data, statement_data, kError);
1912 5 : }
1913 :
1914 25880 : TEST(NumericSeparatorErrors) {
1915 5 : v8::HandleScope handles(CcTest::isolate());
1916 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1917 : v8::Context::Scope context_scope(context);
1918 :
1919 : const char* context_data[][2] = {
1920 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1921 : const char* statement_data[] = {
1922 : "1_0_0_0_", "1e_1", "1e+_1", "1_e+1", "1__0", "0x_1",
1923 : "0x1__1", "0x1_", "0_x1", "0_x_1", "0b_0101", "0b11_",
1924 : "0b1__1", "0_b1", "0_b_1", "0o777_", "0o_777", "0o7__77",
1925 5 : "0.0_2_1_", "0.0__21", "0_.01", "0._01", nullptr};
1926 :
1927 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1928 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
1929 5 : nullptr, 0, false, true, true);
1930 :
1931 10 : RunParserSyncTest(context_data, statement_data, kError);
1932 5 : }
1933 :
1934 25880 : TEST(NumericSeparatorImplicitOctalsErrors) {
1935 5 : v8::HandleScope handles(CcTest::isolate());
1936 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1937 : v8::Context::Scope context_scope(context);
1938 :
1939 : const char* context_data[][2] = {
1940 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1941 : const char* statement_data[] = {"00_122", "0_012", "07_7_7",
1942 : "0_7_7_7", "0_777", "07_7_7_",
1943 5 : "07__77", "0__777", nullptr};
1944 :
1945 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1946 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
1947 5 : nullptr, 0, false, true, true);
1948 :
1949 10 : RunParserSyncTest(context_data, statement_data, kError);
1950 5 : }
1951 :
1952 25880 : TEST(NumericSeparatorUnicodeEscapeSequencesErrors) {
1953 5 : v8::HandleScope handles(CcTest::isolate());
1954 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1955 : v8::Context::Scope context_scope(context);
1956 :
1957 : const char* context_data[][2] = {
1958 5 : {"", ""}, {"'use strict'", ""}, {nullptr, nullptr}};
1959 : // https://github.com/tc39/proposal-numeric-separator/issues/25
1960 5 : const char* statement_data[] = {"\\u{10_FFFF}", nullptr};
1961 :
1962 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1963 5 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1);
1964 :
1965 10 : RunParserSyncTest(context_data, statement_data, kError);
1966 5 : }
1967 :
1968 25880 : TEST(ErrorsEvalAndArguments) {
1969 : // Tests that both preparsing and parsing produce the right kind of errors for
1970 : // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1971 : // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1972 : // isn't.
1973 : const char* context_data[][2] = {
1974 : {"\"use strict\";", ""},
1975 : {"var eval; function test_func() {\"use strict\"; ", "}"},
1976 5 : {nullptr, nullptr}};
1977 :
1978 : const char* statement_data[] = {"var eval;",
1979 : "var arguments",
1980 : "var foo, eval;",
1981 : "var foo, arguments;",
1982 : "try { } catch (eval) { }",
1983 : "try { } catch (arguments) { }",
1984 : "function eval() { }",
1985 : "function arguments() { }",
1986 : "function foo(eval) { }",
1987 : "function foo(arguments) { }",
1988 : "function foo(bar, eval) { }",
1989 : "function foo(bar, arguments) { }",
1990 : "(eval) => { }",
1991 : "(arguments) => { }",
1992 : "(foo, eval) => { }",
1993 : "(foo, arguments) => { }",
1994 : "eval = 1;",
1995 : "arguments = 1;",
1996 : "var foo = eval = 1;",
1997 : "var foo = arguments = 1;",
1998 : "++eval;",
1999 : "++arguments;",
2000 : "eval++;",
2001 : "arguments++;",
2002 5 : nullptr};
2003 :
2004 5 : RunParserSyncTest(context_data, statement_data, kError);
2005 5 : }
2006 :
2007 :
2008 25880 : TEST(NoErrorsEvalAndArgumentsSloppy) {
2009 : // Tests that both preparsing and parsing accept "eval" and "arguments" as
2010 : // identifiers when needed.
2011 : const char* context_data[][2] = {
2012 5 : {"", ""}, {"function test_func() {", "}"}, {nullptr, nullptr}};
2013 :
2014 : const char* statement_data[] = {"var eval;",
2015 : "var arguments",
2016 : "var foo, eval;",
2017 : "var foo, arguments;",
2018 : "try { } catch (eval) { }",
2019 : "try { } catch (arguments) { }",
2020 : "function eval() { }",
2021 : "function arguments() { }",
2022 : "function foo(eval) { }",
2023 : "function foo(arguments) { }",
2024 : "function foo(bar, eval) { }",
2025 : "function foo(bar, arguments) { }",
2026 : "eval = 1;",
2027 : "arguments = 1;",
2028 : "var foo = eval = 1;",
2029 : "var foo = arguments = 1;",
2030 : "++eval;",
2031 : "++arguments;",
2032 : "eval++;",
2033 : "arguments++;",
2034 5 : nullptr};
2035 :
2036 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2037 5 : }
2038 :
2039 :
2040 25880 : TEST(NoErrorsEvalAndArgumentsStrict) {
2041 : const char* context_data[][2] = {
2042 : {"\"use strict\";", ""},
2043 : {"function test_func() { \"use strict\";", "}"},
2044 : {"() => { \"use strict\"; ", "}"},
2045 5 : {nullptr, nullptr}};
2046 :
2047 : const char* statement_data[] = {"eval;",
2048 : "arguments;",
2049 : "var foo = eval;",
2050 : "var foo = arguments;",
2051 : "var foo = { eval: 1 };",
2052 : "var foo = { arguments: 1 };",
2053 : "var foo = { }; foo.eval = {};",
2054 : "var foo = { }; foo.arguments = {};",
2055 5 : nullptr};
2056 :
2057 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2058 5 : }
2059 :
2060 : #define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2061 : V(implements) \
2062 : V(interface) \
2063 : V(package) \
2064 : V(private) \
2065 : V(protected) \
2066 : V(public) \
2067 : V(static) \
2068 : V(yield)
2069 :
2070 : #define FUTURE_STRICT_RESERVED_WORDS(V) \
2071 : V(let) \
2072 : FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
2073 :
2074 : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2075 : V(implements) \
2076 : V(static) \
2077 : V(yield)
2078 :
2079 : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
2080 : V(let) \
2081 : LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
2082 :
2083 : #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2084 : "var " #NAME ";", \
2085 : "var foo, " #NAME ";", \
2086 : "try { } catch (" #NAME ") { }", \
2087 : "function " #NAME "() { }", \
2088 : "(function " #NAME "() { })", \
2089 : "function foo(" #NAME ") { }", \
2090 : "function foo(bar, " #NAME ") { }", \
2091 : #NAME " = 1;", \
2092 : #NAME " += 1;", \
2093 : "var foo = " #NAME " = 1;", \
2094 : "++" #NAME ";", \
2095 : #NAME " ++;",
2096 :
2097 : // clang-format off
2098 : #define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
2099 : "let " #NAME ";", \
2100 : "for (let " #NAME "; false; ) {}", \
2101 : "for (let " #NAME " in {}) {}", \
2102 : "for (let " #NAME " of []) {}", \
2103 : "const " #NAME " = null;", \
2104 : "for (const " #NAME " = null; false; ) {}", \
2105 : "for (const " #NAME " in {}) {}", \
2106 : "for (const " #NAME " of []) {}",
2107 : // clang-format on
2108 :
2109 25880 : TEST(ErrorsFutureStrictReservedWords) {
2110 : // Tests that both preparsing and parsing produce the right kind of errors for
2111 : // using future strict reserved words as identifiers. Without the strict mode,
2112 : // it's ok to use future strict reserved words as identifiers. With the strict
2113 : // mode, it isn't.
2114 : const char* strict_contexts[][2] = {
2115 : {"function test_func() {\"use strict\"; ", "}"},
2116 : {"() => { \"use strict\"; ", "}"},
2117 5 : {nullptr, nullptr}};
2118 :
2119 : // clang-format off
2120 : const char* statement_data[] {
2121 : LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
2122 : LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
2123 : nullptr
2124 5 : };
2125 : // clang-format on
2126 :
2127 5 : RunParserSyncTest(strict_contexts, statement_data, kError);
2128 :
2129 : // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
2130 : //
2131 : // > LexicalDeclaration : LetOrConst BindingList ;
2132 : // >
2133 : // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
2134 : const char* non_strict_contexts[][2] = {{"", ""},
2135 : {"function test_func() {", "}"},
2136 : {"() => {", "}"},
2137 5 : {nullptr, nullptr}};
2138 : const char* invalid_statements[] = {
2139 5 : FUTURE_STRICT_RESERVED_LEX_BINDINGS(let) nullptr};
2140 :
2141 5 : RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
2142 5 : }
2143 :
2144 : #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2145 :
2146 :
2147 25880 : TEST(NoErrorsFutureStrictReservedWords) {
2148 : const char* context_data[][2] = {{"", ""},
2149 : {"function test_func() {", "}"},
2150 : {"() => {", "}"},
2151 5 : {nullptr, nullptr}};
2152 :
2153 : // clang-format off
2154 : const char* statement_data[] = {
2155 : FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
2156 : FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
2157 : nullptr
2158 5 : };
2159 : // clang-format on
2160 :
2161 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2162 5 : }
2163 :
2164 :
2165 25880 : TEST(ErrorsReservedWords) {
2166 : // Tests that both preparsing and parsing produce the right kind of errors for
2167 : // using future reserved words as identifiers. These tests don't depend on the
2168 : // strict mode.
2169 : const char* context_data[][2] = {
2170 : {"", ""},
2171 : {"\"use strict\";", ""},
2172 : {"var eval; function test_func() {", "}"},
2173 : {"var eval; function test_func() {\"use strict\"; ", "}"},
2174 : {"var eval; () => {", "}"},
2175 : {"var eval; () => {\"use strict\"; ", "}"},
2176 5 : {nullptr, nullptr}};
2177 :
2178 : const char* statement_data[] = {"var super;",
2179 : "var foo, super;",
2180 : "try { } catch (super) { }",
2181 : "function super() { }",
2182 : "function foo(super) { }",
2183 : "function foo(bar, super) { }",
2184 : "(super) => { }",
2185 : "(bar, super) => { }",
2186 : "super = 1;",
2187 : "var foo = super = 1;",
2188 : "++super;",
2189 : "super++;",
2190 : "function foo super",
2191 5 : nullptr};
2192 :
2193 5 : RunParserSyncTest(context_data, statement_data, kError);
2194 5 : }
2195 :
2196 :
2197 25880 : TEST(NoErrorsLetSloppyAllModes) {
2198 : // In sloppy mode, it's okay to use "let" as identifier.
2199 : const char* context_data[][2] = {{"", ""},
2200 : {"function f() {", "}"},
2201 : {"(function f() {", "})"},
2202 5 : {nullptr, nullptr}};
2203 :
2204 : const char* statement_data[] = {
2205 : "var let;",
2206 : "var foo, let;",
2207 : "try { } catch (let) { }",
2208 : "function let() { }",
2209 : "(function let() { })",
2210 : "function foo(let) { }",
2211 : "function foo(bar, let) { }",
2212 : "let = 1;",
2213 : "var foo = let = 1;",
2214 : "let * 2;",
2215 : "++let;",
2216 : "let++;",
2217 : "let: 34",
2218 : "function let(let) { let: let(let + let(0)); }",
2219 : "({ let: 1 })",
2220 : "({ get let() { 1 } })",
2221 : "let(100)",
2222 : "L: let\nx",
2223 : "L: let\n{x}",
2224 5 : nullptr};
2225 :
2226 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2227 5 : }
2228 :
2229 :
2230 25880 : TEST(NoErrorsYieldSloppyAllModes) {
2231 : // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2232 : // generator (see other test).
2233 : const char* context_data[][2] = {{"", ""},
2234 : {"function not_gen() {", "}"},
2235 : {"(function not_gen() {", "})"},
2236 5 : {nullptr, nullptr}};
2237 :
2238 : const char* statement_data[] = {
2239 : "var yield;",
2240 : "var foo, yield;",
2241 : "try { } catch (yield) { }",
2242 : "function yield() { }",
2243 : "(function yield() { })",
2244 : "function foo(yield) { }",
2245 : "function foo(bar, yield) { }",
2246 : "yield = 1;",
2247 : "var foo = yield = 1;",
2248 : "yield * 2;",
2249 : "++yield;",
2250 : "yield++;",
2251 : "yield: 34",
2252 : "function yield(yield) { yield: yield (yield + yield(0)); }",
2253 : "({ yield: 1 })",
2254 : "({ get yield() { 1 } })",
2255 : "yield(100)",
2256 : "yield[100]",
2257 5 : nullptr};
2258 :
2259 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2260 5 : }
2261 :
2262 :
2263 25880 : TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2264 : // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2265 : // generator (see next test).
2266 : const char* context_data[][2] = {
2267 : {"", ""},
2268 : {"function not_gen() {", "}"},
2269 : {"function * gen() { function not_gen() {", "} }"},
2270 : {"(function not_gen() {", "})"},
2271 : {"(function * gen() { (function not_gen() {", "}) })"},
2272 5 : {nullptr, nullptr}};
2273 :
2274 : const char* statement_data[] = {
2275 : "var yield;",
2276 : "var foo, yield;",
2277 : "try { } catch (yield) { }",
2278 : "function yield() { }",
2279 : "(function yield() { })",
2280 : "function foo(yield) { }",
2281 : "function foo(bar, yield) { }",
2282 : "function * yield() { }",
2283 : "yield = 1;",
2284 : "var foo = yield = 1;",
2285 : "yield * 2;",
2286 : "++yield;",
2287 : "yield++;",
2288 : "yield: 34",
2289 : "function yield(yield) { yield: yield (yield + yield(0)); }",
2290 : "({ yield: 1 })",
2291 : "({ get yield() { 1 } })",
2292 : "yield(100)",
2293 : "yield[100]",
2294 5 : nullptr};
2295 :
2296 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2297 5 : }
2298 :
2299 :
2300 25880 : TEST(ErrorsYieldStrict) {
2301 : const char* context_data[][2] = {
2302 : {"\"use strict\";", ""},
2303 : {"\"use strict\"; function not_gen() {", "}"},
2304 : {"function test_func() {\"use strict\"; ", "}"},
2305 : {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2306 : {"\"use strict\"; (function not_gen() {", "})"},
2307 : {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2308 : {"() => {\"use strict\"; ", "}"},
2309 5 : {nullptr, nullptr}};
2310 :
2311 : const char* statement_data[] = {"var yield;",
2312 : "var foo, yield;",
2313 : "try { } catch (yield) { }",
2314 : "function yield() { }",
2315 : "(function yield() { })",
2316 : "function foo(yield) { }",
2317 : "function foo(bar, yield) { }",
2318 : "function * yield() { }",
2319 : "(function * yield() { })",
2320 : "yield = 1;",
2321 : "var foo = yield = 1;",
2322 : "++yield;",
2323 : "yield++;",
2324 : "yield: 34;",
2325 5 : nullptr};
2326 :
2327 5 : RunParserSyncTest(context_data, statement_data, kError);
2328 5 : }
2329 :
2330 :
2331 25880 : TEST(ErrorsYieldSloppy) {
2332 : const char* context_data[][2] = {{"", ""},
2333 : {"function not_gen() {", "}"},
2334 : {"(function not_gen() {", "})"},
2335 5 : {nullptr, nullptr}};
2336 :
2337 5 : const char* statement_data[] = {"(function * yield() { })", nullptr};
2338 :
2339 5 : RunParserSyncTest(context_data, statement_data, kError);
2340 5 : }
2341 :
2342 :
2343 25880 : TEST(NoErrorsGenerator) {
2344 : // clang-format off
2345 : const char* context_data[][2] = {
2346 : { "function * gen() {", "}" },
2347 : { "(function * gen() {", "})" },
2348 : { "(function * () {", "})" },
2349 : { nullptr, nullptr }
2350 5 : };
2351 :
2352 : const char* statement_data[] = {
2353 : // A generator without a body is valid.
2354 : ""
2355 : // Valid yield expressions inside generators.
2356 : "yield 2;",
2357 : "yield * 2;",
2358 : "yield * \n 2;",
2359 : "yield yield 1;",
2360 : "yield * yield * 1;",
2361 : "yield 3 + (yield 4);",
2362 : "yield * 3 + (yield * 4);",
2363 : "(yield * 3) + (yield * 4);",
2364 : "yield 3; yield 4;",
2365 : "yield * 3; yield * 4;",
2366 : "(function (yield) { })",
2367 : "(function yield() { })",
2368 : "yield { yield: 12 }",
2369 : "yield /* comment */ { yield: 12 }",
2370 : "yield * \n { yield: 12 }",
2371 : "yield /* comment */ * \n { yield: 12 }",
2372 : // You can return in a generator.
2373 : "yield 1; return",
2374 : "yield * 1; return",
2375 : "yield 1; return 37",
2376 : "yield * 1; return 37",
2377 : "yield 1; return 37; yield 'dead';",
2378 : "yield * 1; return 37; yield * 'dead';",
2379 : // Yield is still a valid key in object literals.
2380 : "({ yield: 1 })",
2381 : "({ get yield() { } })",
2382 : // And in assignment pattern computed properties
2383 : "({ [yield]: x } = { })",
2384 : // Yield without RHS.
2385 : "yield;",
2386 : "yield",
2387 : "yield\n",
2388 : "yield /* comment */"
2389 : "yield // comment\n"
2390 : "(yield)",
2391 : "[yield]",
2392 : "{yield}",
2393 : "yield, yield",
2394 : "yield; yield",
2395 : "(yield) ? yield : yield",
2396 : "(yield) \n ? yield : yield",
2397 : // If there is a newline before the next token, we don't look for RHS.
2398 : "yield\nfor (;;) {}",
2399 : "x = class extends (yield) {}",
2400 : "x = class extends f(yield) {}",
2401 : "x = class extends (null, yield) { }",
2402 : "x = class extends (a ? null : yield) { }",
2403 : nullptr
2404 5 : };
2405 : // clang-format on
2406 :
2407 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2408 5 : }
2409 :
2410 :
2411 25880 : TEST(ErrorsYieldGenerator) {
2412 : // clang-format off
2413 : const char* context_data[][2] = {
2414 : { "function * gen() {", "}" },
2415 : { "\"use strict\"; function * gen() {", "}" },
2416 : { nullptr, nullptr }
2417 5 : };
2418 :
2419 : const char* statement_data[] = {
2420 : // Invalid yield expressions inside generators.
2421 : "var yield;",
2422 : "var foo, yield;",
2423 : "try { } catch (yield) { }",
2424 : "function yield() { }",
2425 : // The name of the NFE is bound in the generator, which does not permit
2426 : // yield to be an identifier.
2427 : "(function * yield() { })",
2428 : // Yield isn't valid as a formal parameter for generators.
2429 : "function * foo(yield) { }",
2430 : "(function * foo(yield) { })",
2431 : "yield = 1;",
2432 : "var foo = yield = 1;",
2433 : "++yield;",
2434 : "yield++;",
2435 : "yield *",
2436 : "(yield *)",
2437 : // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2438 : // is invalid.
2439 : "yield 3 + yield 4;",
2440 : "yield: 34",
2441 : "yield ? 1 : 2",
2442 : // Parses as yield (/ yield): invalid.
2443 : "yield / yield",
2444 : "+ yield",
2445 : "+ yield 3",
2446 : // Invalid (no newline allowed between yield and *).
2447 : "yield\n*3",
2448 : // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2449 : // object literal, and yield is not a valid label).
2450 : "yield\n{yield: 42}",
2451 : "yield /* comment */\n {yield: 42}",
2452 : "yield //comment\n {yield: 42}",
2453 : // Destructuring binding and assignment are both disallowed
2454 : "var [yield] = [42];",
2455 : "var {foo: yield} = {a: 42};",
2456 : "[yield] = [42];",
2457 : "({a: yield} = {a: 42});",
2458 : // Also disallow full yield expressions on LHS
2459 : "var [yield 24] = [42];",
2460 : "var {foo: yield 24} = {a: 42};",
2461 : "[yield 24] = [42];",
2462 : "({a: yield 24} = {a: 42});",
2463 : "for (yield 'x' in {});",
2464 : "for (yield 'x' of {});",
2465 : "for (yield 'x' in {} in {});",
2466 : "for (yield 'x' in {} of {});",
2467 : "class C extends yield { }",
2468 : nullptr
2469 5 : };
2470 : // clang-format on
2471 :
2472 5 : RunParserSyncTest(context_data, statement_data, kError);
2473 5 : }
2474 :
2475 :
2476 25880 : TEST(ErrorsNameOfStrictFunction) {
2477 : // Tests that illegal tokens as names of a strict function produce the correct
2478 : // errors.
2479 : const char* context_data[][2] = {{"function ", ""},
2480 : {"\"use strict\"; function", ""},
2481 : {"function * ", ""},
2482 : {"\"use strict\"; function * ", ""},
2483 5 : {nullptr, nullptr}};
2484 :
2485 : const char* statement_data[] = {
2486 : "eval() {\"use strict\";}", "arguments() {\"use strict\";}",
2487 : "interface() {\"use strict\";}", "yield() {\"use strict\";}",
2488 : // Future reserved words are always illegal
2489 5 : "super() { }", "super() {\"use strict\";}", nullptr};
2490 :
2491 5 : RunParserSyncTest(context_data, statement_data, kError);
2492 5 : }
2493 :
2494 :
2495 25880 : TEST(NoErrorsNameOfStrictFunction) {
2496 5 : const char* context_data[][2] = {{"function ", ""}, {nullptr, nullptr}};
2497 :
2498 : const char* statement_data[] = {"eval() { }", "arguments() { }",
2499 5 : "interface() { }", "yield() { }", nullptr};
2500 :
2501 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2502 5 : }
2503 :
2504 :
2505 25880 : TEST(NoErrorsNameOfStrictGenerator) {
2506 5 : const char* context_data[][2] = {{"function * ", ""}, {nullptr, nullptr}};
2507 :
2508 : const char* statement_data[] = {"eval() { }", "arguments() { }",
2509 5 : "interface() { }", "yield() { }", nullptr};
2510 :
2511 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2512 5 : }
2513 :
2514 :
2515 25880 : TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2516 : // Using future reserved words as labels is always an error.
2517 : const char* context_data[][2] = {{"", ""},
2518 : {"function test_func() {", "}"},
2519 : {"() => {", "}"},
2520 5 : {nullptr, nullptr}};
2521 :
2522 : const char* statement_data[] = {"super: while(true) { break super; }",
2523 5 : nullptr};
2524 :
2525 5 : RunParserSyncTest(context_data, statement_data, kError);
2526 5 : }
2527 :
2528 :
2529 25880 : TEST(ErrorsIllegalWordsAsLabelsStrict) {
2530 : // Tests that illegal tokens as labels produce the correct errors.
2531 : const char* context_data[][2] = {
2532 : {"\"use strict\";", ""},
2533 : {"function test_func() {\"use strict\"; ", "}"},
2534 : {"() => {\"use strict\"; ", "}"},
2535 5 : {nullptr, nullptr}};
2536 :
2537 : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2538 : const char* statement_data[] = {
2539 : "super: while(true) { break super; }",
2540 5 : FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
2541 : #undef LABELLED_WHILE
2542 :
2543 5 : RunParserSyncTest(context_data, statement_data, kError);
2544 5 : }
2545 :
2546 :
2547 25880 : TEST(NoErrorsIllegalWordsAsLabels) {
2548 : // Using eval and arguments as labels is legal even in strict mode.
2549 : const char* context_data[][2] = {
2550 : {"", ""},
2551 : {"function test_func() {", "}"},
2552 : {"() => {", "}"},
2553 : {"\"use strict\";", ""},
2554 : {"\"use strict\"; function test_func() {", "}"},
2555 : {"\"use strict\"; () => {", "}"},
2556 5 : {nullptr, nullptr}};
2557 :
2558 : const char* statement_data[] = {"mylabel: while(true) { break mylabel; }",
2559 : "eval: while(true) { break eval; }",
2560 : "arguments: while(true) { break arguments; }",
2561 5 : nullptr};
2562 :
2563 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2564 5 : }
2565 :
2566 :
2567 25880 : TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2568 : const char* context_data[][2] = {{"", ""},
2569 : {"function test_func() {", "}"},
2570 : {"() => {", "}"},
2571 5 : {nullptr, nullptr}};
2572 :
2573 : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2574 : const char* statement_data[]{
2575 5 : FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
2576 : #undef LABELLED_WHILE
2577 :
2578 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2579 5 : }
2580 :
2581 :
2582 25880 : TEST(ErrorsParenthesizedLabels) {
2583 : // Parenthesized identifiers shouldn't be recognized as labels.
2584 : const char* context_data[][2] = {{"", ""},
2585 : {"function test_func() {", "}"},
2586 : {"() => {", "}"},
2587 5 : {nullptr, nullptr}};
2588 :
2589 : const char* statement_data[] = {"(mylabel): while(true) { break mylabel; }",
2590 5 : nullptr};
2591 :
2592 5 : RunParserSyncTest(context_data, statement_data, kError);
2593 5 : }
2594 :
2595 :
2596 25880 : TEST(NoErrorsParenthesizedDirectivePrologue) {
2597 : // Parenthesized directive prologue shouldn't be recognized.
2598 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2599 :
2600 5 : const char* statement_data[] = {"(\"use strict\"); var eval;", nullptr};
2601 :
2602 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2603 5 : }
2604 :
2605 :
2606 25880 : TEST(ErrorsNotAnIdentifierName) {
2607 : const char* context_data[][2] = {
2608 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
2609 :
2610 : const char* statement_data[] = {"var foo = {}; foo.{;",
2611 : "var foo = {}; foo.};",
2612 : "var foo = {}; foo.=;",
2613 : "var foo = {}; foo.888;",
2614 : "var foo = {}; foo.-;",
2615 : "var foo = {}; foo.--;",
2616 5 : nullptr};
2617 :
2618 5 : RunParserSyncTest(context_data, statement_data, kError);
2619 5 : }
2620 :
2621 :
2622 25880 : TEST(NoErrorsIdentifierNames) {
2623 : // Keywords etc. are valid as property names.
2624 : const char* context_data[][2] = {
2625 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
2626 :
2627 : const char* statement_data[] = {"var foo = {}; foo.if;",
2628 : "var foo = {}; foo.yield;",
2629 : "var foo = {}; foo.super;",
2630 : "var foo = {}; foo.interface;",
2631 : "var foo = {}; foo.eval;",
2632 : "var foo = {}; foo.arguments;",
2633 5 : nullptr};
2634 :
2635 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2636 5 : }
2637 :
2638 25880 : TEST(FunctionDeclaresItselfStrict) {
2639 : // Tests that we produce the right kinds of errors when a function declares
2640 : // itself strict (we cannot produce there errors as soon as we see the
2641 : // offending identifiers, because we don't know at that point whether the
2642 : // function is strict or not).
2643 : const char* context_data[][2] = {{"function eval() {", "}"},
2644 : {"function arguments() {", "}"},
2645 : {"function yield() {", "}"},
2646 : {"function interface() {", "}"},
2647 : {"function foo(eval) {", "}"},
2648 : {"function foo(arguments) {", "}"},
2649 : {"function foo(yield) {", "}"},
2650 : {"function foo(interface) {", "}"},
2651 : {"function foo(bar, eval) {", "}"},
2652 : {"function foo(bar, arguments) {", "}"},
2653 : {"function foo(bar, yield) {", "}"},
2654 : {"function foo(bar, interface) {", "}"},
2655 : {"function foo(bar, bar) {", "}"},
2656 5 : {nullptr, nullptr}};
2657 :
2658 5 : const char* strict_statement_data[] = {"\"use strict\";", nullptr};
2659 :
2660 5 : const char* non_strict_statement_data[] = {";", nullptr};
2661 :
2662 5 : RunParserSyncTest(context_data, strict_statement_data, kError);
2663 5 : RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2664 5 : }
2665 :
2666 :
2667 25880 : TEST(ErrorsTryWithoutCatchOrFinally) {
2668 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2669 :
2670 : const char* statement_data[] = {"try { }", "try { } foo();",
2671 : "try { } catch (e) foo();",
2672 5 : "try { } finally foo();", nullptr};
2673 :
2674 5 : RunParserSyncTest(context_data, statement_data, kError);
2675 5 : }
2676 :
2677 :
2678 25880 : TEST(NoErrorsTryCatchFinally) {
2679 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2680 :
2681 : const char* statement_data[] = {"try { } catch (e) { }",
2682 : "try { } catch (e) { } finally { }",
2683 5 : "try { } finally { }", nullptr};
2684 :
2685 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2686 5 : }
2687 :
2688 25880 : TEST(OptionalCatchBinding) {
2689 : // clang-format off
2690 : const char* context_data[][2] = {
2691 : {"", ""},
2692 : {"'use strict';", ""},
2693 : {"try {", "} catch (e) { }"},
2694 : {"try {} catch (e) {", "}"},
2695 : {"try {", "} catch ({e}) { }"},
2696 : {"try {} catch ({e}) {", "}"},
2697 : {"function f() {", "}"},
2698 : { nullptr, nullptr }
2699 5 : };
2700 :
2701 : const char* statement_data[] = {
2702 : "try { } catch { }",
2703 : "try { } catch { } finally { }",
2704 : "try { let e; } catch { let e; }",
2705 : "try { let e; } catch { let e; } finally { let e; }",
2706 : nullptr
2707 5 : };
2708 : // clang-format on
2709 :
2710 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2711 5 : }
2712 :
2713 25880 : TEST(ErrorsRegexpLiteral) {
2714 5 : const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
2715 :
2716 5 : const char* statement_data[] = {"/unterminated", nullptr};
2717 :
2718 5 : RunParserSyncTest(context_data, statement_data, kError);
2719 5 : }
2720 :
2721 :
2722 25880 : TEST(NoErrorsRegexpLiteral) {
2723 5 : const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
2724 :
2725 5 : const char* statement_data[] = {"/foo/", "/foo/g", nullptr};
2726 :
2727 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2728 5 : }
2729 :
2730 :
2731 25880 : TEST(NoErrorsNewExpression) {
2732 : const char* context_data[][2] = {
2733 5 : {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
2734 :
2735 : const char* statement_data[] = {
2736 : "new foo", "new foo();", "new foo(1);", "new foo(1, 2);",
2737 : // The first () will be processed as a part of the NewExpression and the
2738 : // second () will be processed as part of LeftHandSideExpression.
2739 : "new foo()();",
2740 : // The first () will be processed as a part of the inner NewExpression and
2741 : // the second () will be processed as a part of the outer NewExpression.
2742 : "new new foo()();", "new foo.bar;", "new foo.bar();", "new foo.bar.baz;",
2743 : "new foo.bar().baz;", "new foo[bar];", "new foo[bar]();",
2744 : "new foo[bar][baz];", "new foo[bar]()[baz];",
2745 : "new foo[bar].baz(baz)()[bar].baz;",
2746 : "new \"foo\"", // Runtime error
2747 : "new 1", // Runtime error
2748 : // This even runs:
2749 : "(new new Function(\"this.x = 1\")).x;",
2750 5 : "new new Test_Two(String, 2).v(0123).length;", nullptr};
2751 :
2752 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2753 5 : }
2754 :
2755 :
2756 25880 : TEST(ErrorsNewExpression) {
2757 : const char* context_data[][2] = {
2758 5 : {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
2759 :
2760 : const char* statement_data[] = {"new foo bar", "new ) foo", "new ++foo",
2761 5 : "new foo ++", nullptr};
2762 :
2763 5 : RunParserSyncTest(context_data, statement_data, kError);
2764 5 : }
2765 :
2766 :
2767 25880 : TEST(StrictObjectLiteralChecking) {
2768 : const char* context_data[][2] = {{"\"use strict\"; var myobject = {", "};"},
2769 : {"\"use strict\"; var myobject = {", ",};"},
2770 : {"var myobject = {", "};"},
2771 : {"var myobject = {", ",};"},
2772 5 : {nullptr, nullptr}};
2773 :
2774 : // These are only errors in strict mode.
2775 : const char* statement_data[] = {
2776 : "foo: 1, foo: 2", "\"foo\": 1, \"foo\": 2", "foo: 1, \"foo\": 2",
2777 : "1: 1, 1: 2", "1: 1, \"1\": 2",
2778 : "get: 1, get: 2", // Not a getter for real, just a property called get.
2779 : "set: 1, set: 2", // Not a setter for real, just a property called set.
2780 5 : nullptr};
2781 :
2782 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2783 5 : }
2784 :
2785 :
2786 25880 : TEST(ErrorsObjectLiteralChecking) {
2787 : // clang-format off
2788 : const char* context_data[][2] = {
2789 : {"\"use strict\"; var myobject = {", "};"},
2790 : {"var myobject = {", "};"},
2791 : { nullptr, nullptr }
2792 5 : };
2793 :
2794 : const char* statement_data[] = {
2795 : ",",
2796 : // Wrong number of parameters
2797 : "get bar(x) {}",
2798 : "get bar(x, y) {}",
2799 : "set bar() {}",
2800 : "set bar(x, y) {}",
2801 : // Parsing FunctionLiteral for getter or setter fails
2802 : "get foo( +",
2803 : "get foo() \"error\"",
2804 : // Various forbidden forms
2805 : "static x: 0",
2806 : "static x(){}",
2807 : "static async x(){}",
2808 : "static get x(){}",
2809 : "static get x : 0",
2810 : "static x",
2811 : "static 0",
2812 : "*x: 0",
2813 : "*x",
2814 : "*get x(){}",
2815 : "*set x(y){}",
2816 : "get *x(){}",
2817 : "set *x(y){}",
2818 : "get x*(){}",
2819 : "set x*(y){}",
2820 : "x = 0",
2821 : "* *x(){}",
2822 : "x*(){}",
2823 : "static async x(){}",
2824 : "static async x : 0",
2825 : "static async get x : 0",
2826 : "async static x(){}",
2827 : "*async x(){}",
2828 : "async x*(){}",
2829 : "async x : 0",
2830 : "async 0 : 0",
2831 : "async get x(){}",
2832 : "async get *x(){}",
2833 : "async set x(y){}",
2834 : "async get : 0",
2835 : nullptr
2836 5 : };
2837 : // clang-format on
2838 :
2839 5 : RunParserSyncTest(context_data, statement_data, kError);
2840 5 : }
2841 :
2842 :
2843 25880 : TEST(NoErrorsObjectLiteralChecking) {
2844 : // clang-format off
2845 : const char* context_data[][2] = {
2846 : {"var myobject = {", "};"},
2847 : {"var myobject = {", ",};"},
2848 : {"\"use strict\"; var myobject = {", "};"},
2849 : {"\"use strict\"; var myobject = {", ",};"},
2850 : { nullptr, nullptr }
2851 5 : };
2852 :
2853 : const char* statement_data[] = {
2854 : "foo: 1, get foo() {}",
2855 : "foo: 1, set foo(v) {}",
2856 : "\"foo\": 1, get \"foo\"() {}",
2857 : "\"foo\": 1, set \"foo\"(v) {}",
2858 : "1: 1, get 1() {}",
2859 : "1: 1, set 1(v) {}",
2860 : "get foo() {}, get foo() {}",
2861 : "set foo(_) {}, set foo(v) {}",
2862 : "foo: 1, get \"foo\"() {}",
2863 : "foo: 1, set \"foo\"(v) {}",
2864 : "\"foo\": 1, get foo() {}",
2865 : "\"foo\": 1, set foo(v) {}",
2866 : "1: 1, get \"1\"() {}",
2867 : "1: 1, set \"1\"(v) {}",
2868 : "\"1\": 1, get 1() {}",
2869 : "\"1\": 1, set 1(v) {}",
2870 : "foo: 1, bar: 2",
2871 : "\"foo\": 1, \"bar\": 2",
2872 : "1: 1, 2: 2",
2873 : // Syntax: IdentifierName ':' AssignmentExpression
2874 : "foo: bar = 5 + baz",
2875 : // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2876 : "get foo() {}",
2877 : "get \"foo\"() {}",
2878 : "get 1() {}",
2879 : // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2880 : // '{' FunctionBody '}'
2881 : "set foo(v) {}",
2882 : "set \"foo\"(v) {}",
2883 : "set 1(v) {}",
2884 : // Non-colliding getters and setters -> no errors
2885 : "foo: 1, get bar() {}",
2886 : "foo: 1, set bar(v) {}",
2887 : "\"foo\": 1, get \"bar\"() {}",
2888 : "\"foo\": 1, set \"bar\"(v) {}",
2889 : "1: 1, get 2() {}",
2890 : "1: 1, set 2(v) {}",
2891 : "get: 1, get foo() {}",
2892 : "set: 1, set foo(_) {}",
2893 : // Potentially confusing cases
2894 : "get(){}",
2895 : "set(){}",
2896 : "static(){}",
2897 : "async(){}",
2898 : "*get() {}",
2899 : "*set() {}",
2900 : "*static() {}",
2901 : "*async(){}",
2902 : "get : 0",
2903 : "set : 0",
2904 : "static : 0",
2905 : "async : 0",
2906 : // Keywords, future reserved and strict future reserved are also allowed as
2907 : // property names.
2908 : "if: 4",
2909 : "interface: 5",
2910 : "super: 6",
2911 : "eval: 7",
2912 : "arguments: 8",
2913 : "async x(){}",
2914 : "async 0(){}",
2915 : "async get(){}",
2916 : "async set(){}",
2917 : "async static(){}",
2918 : "async async(){}",
2919 : "async : 0",
2920 : "async(){}",
2921 : "*async(){}",
2922 : nullptr
2923 5 : };
2924 : // clang-format on
2925 :
2926 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2927 5 : }
2928 :
2929 :
2930 25880 : TEST(TooManyArguments) {
2931 5 : const char* context_data[][2] = {{"foo(", "0)"}, {nullptr, nullptr}};
2932 :
2933 : using v8::internal::Code;
2934 : char statement[Code::kMaxArguments * 2 + 1];
2935 327675 : for (int i = 0; i < Code::kMaxArguments; ++i) {
2936 327670 : statement[2 * i] = '0';
2937 327670 : statement[2 * i + 1] = ',';
2938 : }
2939 5 : statement[Code::kMaxArguments * 2] = 0;
2940 :
2941 5 : const char* statement_data[] = {statement, nullptr};
2942 :
2943 : // The test is quite slow, so run it with a reduced set of flags.
2944 : static const ParserFlag empty_flags[] = {kAllowLazy};
2945 5 : RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2946 5 : }
2947 :
2948 :
2949 25880 : TEST(StrictDelete) {
2950 : // "delete <Identifier>" is not allowed in strict mode.
2951 : const char* strict_context_data[][2] = {{"\"use strict\"; ", ""},
2952 5 : {nullptr, nullptr}};
2953 :
2954 5 : const char* sloppy_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2955 :
2956 : // These are errors in the strict mode.
2957 : const char* sloppy_statement_data[] = {"delete foo;", "delete foo + 1;",
2958 : "delete (foo);", "delete eval;",
2959 5 : "delete interface;", nullptr};
2960 :
2961 : // These are always OK
2962 : const char* good_statement_data[] = {"delete this;",
2963 : "delete 1;",
2964 : "delete 1 + 2;",
2965 : "delete foo();",
2966 : "delete foo.bar;",
2967 : "delete foo[bar];",
2968 : "delete foo--;",
2969 : "delete --foo;",
2970 : "delete new foo();",
2971 : "delete new foo(bar);",
2972 5 : nullptr};
2973 :
2974 : // These are always errors
2975 5 : const char* bad_statement_data[] = {"delete if;", nullptr};
2976 :
2977 5 : RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
2978 5 : RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
2979 :
2980 5 : RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
2981 5 : RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
2982 :
2983 5 : RunParserSyncTest(strict_context_data, bad_statement_data, kError);
2984 5 : RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
2985 5 : }
2986 :
2987 :
2988 25880 : TEST(NoErrorsDeclsInCase) {
2989 : const char* context_data[][2] = {
2990 : {"'use strict'; switch(x) { case 1:", "}"},
2991 : {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
2992 : {"'use strict'; switch(x) { case 1: case 2:", "}"},
2993 : {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
2994 : {"'use strict'; switch(x) { default:", "}"},
2995 : {"function foo() {'use strict'; switch(x) { default:", "}}"},
2996 : {"'use strict'; switch(x) { case 1: default:", "}"},
2997 : {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
2998 : { nullptr, nullptr }
2999 5 : };
3000 :
3001 : const char* statement_data[] = {
3002 : "function f() { }",
3003 : "class C { }",
3004 : "class C extends Q {}",
3005 : "function f() { } class C {}",
3006 : "function f() { }; class C {}",
3007 : "class C {}; function f() {}",
3008 : nullptr
3009 5 : };
3010 :
3011 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
3012 5 : }
3013 :
3014 :
3015 25880 : TEST(InvalidLeftHandSide) {
3016 : const char* assignment_context_data[][2] = {
3017 5 : {"", " = 1;"}, {"\"use strict\"; ", " = 1;"}, {nullptr, nullptr}};
3018 :
3019 : const char* prefix_context_data[][2] = {
3020 : {"++", ";"}, {"\"use strict\"; ++", ";"}, {nullptr, nullptr},
3021 5 : };
3022 :
3023 : const char* postfix_context_data[][2] = {
3024 5 : {"", "++;"}, {"\"use strict\"; ", "++;"}, {nullptr, nullptr}};
3025 :
3026 : // Good left hand sides for assigment or prefix / postfix operations.
3027 : const char* good_statement_data[] = {"foo",
3028 : "foo.bar",
3029 : "foo[bar]",
3030 : "foo()[bar]",
3031 : "foo().bar",
3032 : "this.foo",
3033 : "this[foo]",
3034 : "new foo()[bar]",
3035 : "new foo().bar",
3036 : "foo()",
3037 : "foo(bar)",
3038 : "foo[bar]()",
3039 : "foo.bar()",
3040 : "this()",
3041 : "this.foo()",
3042 : "this[foo].bar()",
3043 : "this.foo[foo].bar(this)(bar)[foo]()",
3044 5 : nullptr};
3045 :
3046 : // Bad left hand sides for assigment or prefix / postfix operations.
3047 : const char* bad_statement_data_common[] = {
3048 : "2",
3049 : "new foo",
3050 : "new foo()",
3051 : "null",
3052 : "if", // Unexpected token
3053 : "{x: 1}", // Unexpected token
3054 : "this",
3055 : "\"bar\"",
3056 : "(foo + bar)",
3057 : "new new foo()[bar]", // means: new (new foo()[bar])
3058 : "new new foo().bar", // means: new (new foo()[bar])
3059 5 : nullptr};
3060 :
3061 : // These are not okay for assignment, but okay for prefix / postix.
3062 : const char* bad_statement_data_for_assignment[] = {"++foo", "foo++",
3063 5 : "foo + bar", nullptr};
3064 :
3065 5 : RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3066 5 : RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3067 : RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3068 5 : kError);
3069 :
3070 5 : RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3071 5 : RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3072 :
3073 5 : RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3074 5 : RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3075 5 : }
3076 :
3077 :
3078 25880 : TEST(FuncNameInferrerBasic) {
3079 : // Tests that function names are inferred properly.
3080 5 : i::FLAG_allow_natives_syntax = true;
3081 5 : v8::Isolate* isolate = CcTest::isolate();
3082 5 : v8::HandleScope scope(isolate);
3083 10 : LocalContext env;
3084 : CompileRun("var foo1 = function() {}; "
3085 : "var foo2 = function foo3() {}; "
3086 : "function not_ctor() { "
3087 : " var foo4 = function() {}; "
3088 : " return %FunctionGetInferredName(foo4); "
3089 : "} "
3090 : "function Ctor() { "
3091 : " var foo5 = function() {}; "
3092 : " return %FunctionGetInferredName(foo5); "
3093 : "} "
3094 : "var obj1 = { foo6: function() {} }; "
3095 : "var obj2 = { 'foo7': function() {} }; "
3096 : "var obj3 = {}; "
3097 : "obj3[1] = function() {}; "
3098 : "var obj4 = {}; "
3099 : "obj4[1] = function foo8() {}; "
3100 : "var obj5 = {}; "
3101 : "obj5['foo9'] = function() {}; "
3102 : "var obj6 = { obj7 : { foo10: function() {} } };");
3103 5 : ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3104 : // foo2 is not unnamed -> its name is not inferred.
3105 5 : ExpectString("%FunctionGetInferredName(foo2)", "");
3106 5 : ExpectString("not_ctor()", "foo4");
3107 5 : ExpectString("Ctor()", "Ctor.foo5");
3108 5 : ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3109 5 : ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3110 : ExpectString("%FunctionGetInferredName(obj3[1])",
3111 5 : "obj3.(anonymous function)");
3112 5 : ExpectString("%FunctionGetInferredName(obj4[1])", "");
3113 5 : ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3114 10 : ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3115 5 : }
3116 :
3117 :
3118 25880 : TEST(FuncNameInferrerTwoByte) {
3119 : // Tests function name inferring in cases where some parts of the inferred
3120 : // function name are two-byte strings.
3121 5 : i::FLAG_allow_natives_syntax = true;
3122 5 : v8::Isolate* isolate = CcTest::isolate();
3123 5 : v8::HandleScope scope(isolate);
3124 10 : LocalContext env;
3125 : uint16_t* two_byte_source = AsciiToTwoByteString(
3126 : "var obj1 = { oXj2 : { foo1: function() {} } }; "
3127 5 : "%FunctionGetInferredName(obj1.oXj2.foo1)");
3128 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3129 : // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3130 5 : two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010D;
3131 : v8::Local<v8::String> source =
3132 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3133 : v8::NewStringType::kNormal)
3134 10 : .ToLocalChecked();
3135 5 : v8::Local<v8::Value> result = CompileRun(source);
3136 5 : CHECK(result->IsString());
3137 : v8::Local<v8::String> expected_name =
3138 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3139 : v8::NewStringType::kNormal)
3140 5 : .ToLocalChecked();
3141 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3142 : i::DeleteArray(two_byte_source);
3143 5 : i::DeleteArray(two_byte_name);
3144 5 : }
3145 :
3146 :
3147 25880 : TEST(FuncNameInferrerEscaped) {
3148 : // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3149 : // character as a Unicode escape.
3150 5 : i::FLAG_allow_natives_syntax = true;
3151 5 : v8::Isolate* isolate = CcTest::isolate();
3152 5 : v8::HandleScope scope(isolate);
3153 10 : LocalContext env;
3154 : uint16_t* two_byte_source = AsciiToTwoByteString(
3155 : "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3156 5 : "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3157 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3158 : // Fix to correspond to the non-ASCII name in two_byte_source.
3159 5 : two_byte_name[6] = 0x010D;
3160 : v8::Local<v8::String> source =
3161 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3162 : v8::NewStringType::kNormal)
3163 10 : .ToLocalChecked();
3164 5 : v8::Local<v8::Value> result = CompileRun(source);
3165 5 : CHECK(result->IsString());
3166 : v8::Local<v8::String> expected_name =
3167 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3168 : v8::NewStringType::kNormal)
3169 5 : .ToLocalChecked();
3170 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3171 : i::DeleteArray(two_byte_source);
3172 5 : i::DeleteArray(two_byte_name);
3173 5 : }
3174 :
3175 :
3176 25880 : TEST(RegressionLazyFunctionWithErrorWithArg) {
3177 : // Test only applies when lazy parsing.
3178 5 : if (!i::FLAG_lazy) return;
3179 :
3180 : // The bug occurred when a lazy function had an error which requires a
3181 : // parameter (such as "unknown label" here). The error message was processed
3182 : // before the AstValueFactory containing the error message string was
3183 : // internalized.
3184 5 : v8::Isolate* isolate = CcTest::isolate();
3185 5 : v8::HandleScope scope(isolate);
3186 10 : LocalContext env;
3187 5 : i::FLAG_lazy = true;
3188 : CompileRun("function this_is_lazy() {\n"
3189 : " break p;\n"
3190 : "}\n"
3191 5 : "this_is_lazy();\n");
3192 : }
3193 :
3194 :
3195 25880 : TEST(SerializationOfMaybeAssignmentFlag) {
3196 5 : i::Isolate* isolate = CcTest::i_isolate();
3197 : i::Factory* factory = isolate->factory();
3198 : i::HandleScope scope(isolate);
3199 10 : LocalContext env;
3200 :
3201 : const char* src =
3202 : "function h() {"
3203 : " var result = [];"
3204 : " function f() {"
3205 : " result.push(2);"
3206 : " }"
3207 : " function assertResult(r) {"
3208 : " f();"
3209 : " result = [];"
3210 : " }"
3211 : " assertResult([2]);"
3212 : " assertResult([2]);"
3213 : " return f;"
3214 : "};"
3215 : "h();";
3216 :
3217 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3218 5 : i::SNPrintF(program, "%s", src);
3219 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3220 10 : source->PrintOn(stdout);
3221 : printf("\n");
3222 10 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
3223 : v8::Local<v8::Value> v = CompileRun(src);
3224 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3225 5 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3226 5 : i::Context context = f->context();
3227 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3228 10 : HashSeed(isolate));
3229 10 : const i::AstRawString* name = avf.GetOneByteString("result");
3230 5 : avf.Internalize(isolate);
3231 : i::Handle<i::String> str = name->string();
3232 10 : CHECK(str->IsInternalizedString());
3233 : i::DeclarationScope* script_scope =
3234 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3235 : i::Scope* s = i::Scope::DeserializeScopeChain(
3236 : isolate, &zone, context->scope_info(), script_scope, &avf,
3237 5 : i::Scope::DeserializationMode::kIncludingVariables);
3238 5 : CHECK(s != script_scope);
3239 5 : CHECK_NOT_NULL(name);
3240 :
3241 : // Get result from h's function context (that is f's context)
3242 5 : i::Variable* var = s->LookupForTesting(name);
3243 :
3244 5 : CHECK_NOT_NULL(var);
3245 : // Maybe assigned should survive deserialization
3246 5 : CHECK_EQ(var->maybe_assigned(), i::kMaybeAssigned);
3247 : // TODO(sigurds) Figure out if is_used should survive context serialization.
3248 5 : }
3249 :
3250 :
3251 25880 : TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3252 10 : i::Isolate* isolate = CcTest::i_isolate();
3253 : i::Factory* factory = isolate->factory();
3254 : i::HandleScope scope(isolate);
3255 10 : LocalContext env;
3256 :
3257 : const char* src =
3258 : "function f(x) {"
3259 : " var a = arguments;"
3260 : " function g(i) {"
3261 : " ++a[0];"
3262 : " };"
3263 : " return g;"
3264 : " }"
3265 : "f(0);";
3266 :
3267 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3268 5 : i::SNPrintF(program, "%s", src);
3269 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3270 10 : source->PrintOn(stdout);
3271 : printf("\n");
3272 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
3273 : v8::Local<v8::Value> v = CompileRun(src);
3274 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3275 5 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3276 5 : i::Context context = f->context();
3277 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3278 10 : HashSeed(isolate));
3279 5 : const i::AstRawString* name_x = avf.GetOneByteString("x");
3280 5 : avf.Internalize(isolate);
3281 :
3282 : i::DeclarationScope* script_scope =
3283 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3284 : i::Scope* s = i::Scope::DeserializeScopeChain(
3285 : isolate, &zone, context->scope_info(), script_scope, &avf,
3286 5 : i::Scope::DeserializationMode::kIncludingVariables);
3287 5 : CHECK(s != script_scope);
3288 :
3289 : // Get result from f's function context (that is g's outer context)
3290 5 : i::Variable* var_x = s->LookupForTesting(name_x);
3291 5 : CHECK_NOT_NULL(var_x);
3292 5 : CHECK_EQ(var_x->maybe_assigned(), i::kMaybeAssigned);
3293 5 : }
3294 :
3295 :
3296 25880 : TEST(InnerAssignment) {
3297 : i::Isolate* isolate = CcTest::i_isolate();
3298 : i::Factory* factory = isolate->factory();
3299 : i::HandleScope scope(isolate);
3300 10 : LocalContext env;
3301 :
3302 : const char* prefix = "function f() {";
3303 : const char* midfix = " function g() {";
3304 : const char* suffix = "}}; f";
3305 : struct {
3306 : const char* source;
3307 : bool assigned;
3308 : bool strict;
3309 : } outers[] = {
3310 : // Actual assignments.
3311 : {"var x; var x = 5;", true, false},
3312 : {"var x; { var x = 5; }", true, false},
3313 : {"'use strict'; let x; x = 6;", true, true},
3314 : {"var x = 5; function x() {}", true, false},
3315 : {"var x = 4; var x = 5;", true, false},
3316 : {"var [x, x] = [4, 5];", true, false},
3317 : {"var x; [x, x] = [4, 5];", true, false},
3318 : {"var {a: x, b: x} = {a: 4, b: 5};", true, false},
3319 : {"var x = {a: 4, b: (x = 5)};", true, false},
3320 : {"var {x=1} = {a: 4, b: (x = 5)};", true, false},
3321 : {"var {x} = {x: 4, b: (x = 5)};", true, false},
3322 : // Actual non-assignments.
3323 : {"var x;", false, false},
3324 : {"var x = 5;", false, false},
3325 : {"'use strict'; let x;", false, true},
3326 : {"'use strict'; let x = 6;", false, true},
3327 : {"'use strict'; var x = 0; { let x = 6; }", false, true},
3328 : {"'use strict'; var x = 0; { let x; x = 6; }", false, true},
3329 : {"'use strict'; let x = 0; { let x = 6; }", false, true},
3330 : {"'use strict'; let x = 0; { let x; x = 6; }", false, true},
3331 : {"var x; try {} catch (x) { x = 5; }", false, false},
3332 : {"function x() {}", false, false},
3333 : // Eval approximation.
3334 : {"var x; eval('');", true, false},
3335 : {"eval(''); var x;", true, false},
3336 : {"'use strict'; let x; eval('');", true, true},
3337 : {"'use strict'; eval(''); let x;", true, true},
3338 : // Non-assignments not recognized, because the analysis is approximative.
3339 : {"var x; var x;", true, false},
3340 : {"var x = 5; var x;", true, false},
3341 : {"var x; { var x; }", true, false},
3342 : {"var x; function x() {}", true, false},
3343 : {"function x() {}; var x;", true, false},
3344 : {"var x; try {} catch (x) { var x = 5; }", true, false},
3345 5 : };
3346 :
3347 : // We set allow_error_in_inner_function to true in cases where our handling of
3348 : // assigned variables in lazy inner functions is currently overly pessimistic.
3349 : // FIXME(marja): remove it when no longer needed.
3350 : struct {
3351 : const char* source;
3352 : bool assigned;
3353 : bool with;
3354 : bool allow_error_in_inner_function;
3355 : } inners[] = {
3356 : // Actual assignments.
3357 : {"x = 1;", true, false, false},
3358 : {"x++;", true, false, false},
3359 : {"++x;", true, false, false},
3360 : {"x--;", true, false, false},
3361 : {"--x;", true, false, false},
3362 : {"{ x = 1; }", true, false, false},
3363 : {"'use strict'; { let x; }; x = 0;", true, false, false},
3364 : {"'use strict'; { const x = 1; }; x = 0;", true, false, false},
3365 : {"'use strict'; { function x() {} }; x = 0;", true, false, false},
3366 : {"with ({}) { x = 1; }", true, true, false},
3367 : {"eval('');", true, false, false},
3368 : {"'use strict'; { let y; eval('') }", true, false, false},
3369 : {"function h() { x = 0; }", true, false, false},
3370 : {"(function() { x = 0; })", true, false, false},
3371 : {"(function() { x = 0; })", true, false, false},
3372 : {"with ({}) (function() { x = 0; })", true, true, false},
3373 : {"for (x of [1,2,3]) {}", true, false, false},
3374 : {"for (x in {a: 1}) {}", true, false, false},
3375 : {"for ([x] of [[1],[2],[3]]) {}", true, false, false},
3376 : {"for ([x] in {ab: 1}) {}", true, false, false},
3377 : {"for ([...x] in {ab: 1}) {}", true, false, false},
3378 : {"[x] = [1]", true, false, false},
3379 : // Actual non-assignments.
3380 : {"", false, false, false},
3381 : {"x;", false, false, false},
3382 : {"var x;", false, false, false},
3383 : {"var x = 8;", false, false, false},
3384 : {"var x; x = 8;", false, false, false},
3385 : {"'use strict'; let x;", false, false, false},
3386 : {"'use strict'; let x = 8;", false, false, false},
3387 : {"'use strict'; let x; x = 8;", false, false, false},
3388 : {"'use strict'; const x = 8;", false, false, false},
3389 : {"function x() {}", false, false, false},
3390 : {"function x() { x = 0; }", false, false, true},
3391 : {"function h(x) { x = 0; }", false, false, false},
3392 : {"'use strict'; { let x; x = 0; }", false, false, false},
3393 : {"{ var x; }; x = 0;", false, false, false},
3394 : {"with ({}) {}", false, true, false},
3395 : {"var x; { with ({}) { x = 1; } }", false, true, false},
3396 : {"try {} catch(x) { x = 0; }", false, false, true},
3397 : {"try {} catch(x) { with ({}) { x = 1; } }", false, true, true},
3398 : // Eval approximation.
3399 : {"eval('');", true, false, false},
3400 : {"function h() { eval(''); }", true, false, false},
3401 : {"(function() { eval(''); })", true, false, false},
3402 : // Shadowing not recognized because of eval approximation.
3403 : {"var x; eval('');", true, false, false},
3404 : {"'use strict'; let x; eval('');", true, false, false},
3405 : {"try {} catch(x) { eval(''); }", true, false, false},
3406 : {"function x() { eval(''); }", true, false, false},
3407 : {"(function(x) { eval(''); })", true, false, false},
3408 5 : };
3409 :
3410 5 : int prefix_len = Utf8LengthHelper(prefix);
3411 5 : int midfix_len = Utf8LengthHelper(midfix);
3412 5 : int suffix_len = Utf8LengthHelper(suffix);
3413 160 : for (unsigned i = 0; i < arraysize(outers); ++i) {
3414 155 : const char* outer = outers[i].source;
3415 155 : int outer_len = Utf8LengthHelper(outer);
3416 7595 : for (unsigned j = 0; j < arraysize(inners); ++j) {
3417 14880 : for (unsigned lazy = 0; lazy < 2; ++lazy) {
3418 15330 : if (outers[i].strict && inners[j].with) continue;
3419 14430 : const char* inner = inners[j].source;
3420 14430 : int inner_len = Utf8LengthHelper(inner);
3421 :
3422 14430 : int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len;
3423 14430 : i::ScopedVector<char> program(len + 1);
3424 :
3425 : i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner,
3426 14430 : suffix);
3427 :
3428 : std::unique_ptr<i::ParseInfo> info;
3429 14430 : if (lazy) {
3430 : printf("%s\n", program.start());
3431 : v8::Local<v8::Value> v = CompileRun(program.start());
3432 7215 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3433 7215 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3434 : i::Handle<i::SharedFunctionInfo> shared =
3435 14430 : i::handle(f->shared(), isolate);
3436 14430 : info =
3437 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3438 7215 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3439 : } else {
3440 : i::Handle<i::String> source =
3441 7215 : factory->InternalizeUtf8String(program.start());
3442 14430 : source->PrintOn(stdout);
3443 : printf("\n");
3444 7215 : i::Handle<i::Script> script = factory->NewScript(source);
3445 14430 : info =
3446 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3447 : info->set_allow_lazy_parsing(false);
3448 7215 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3449 : }
3450 14430 : CHECK(i::Compiler::Analyze(info.get()));
3451 14430 : CHECK_NOT_NULL(info->literal());
3452 :
3453 21645 : i::Scope* scope = info->literal()->scope();
3454 14430 : if (!lazy) {
3455 : scope = scope->inner_scope();
3456 : }
3457 : DCHECK_NOT_NULL(scope);
3458 : DCHECK_NULL(scope->sibling());
3459 : DCHECK(scope->is_function_scope());
3460 : const i::AstRawString* var_name =
3461 14430 : info->ast_value_factory()->GetOneByteString("x");
3462 14430 : i::Variable* var = scope->LookupForTesting(var_name);
3463 14430 : bool expected = outers[i].assigned || inners[j].assigned;
3464 14430 : CHECK_NOT_NULL(var);
3465 14430 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3466 14430 : CHECK(is_maybe_assigned == expected ||
3467 : (is_maybe_assigned && inners[j].allow_error_in_inner_function));
3468 : }
3469 : }
3470 : }
3471 5 : }
3472 :
3473 25880 : TEST(MaybeAssignedParameters) {
3474 : i::Isolate* isolate = CcTest::i_isolate();
3475 : i::HandleScope scope(isolate);
3476 10 : LocalContext env;
3477 :
3478 : struct {
3479 : bool arg_assigned;
3480 : const char* source;
3481 : } tests[] = {
3482 : {false, "function f(arg) {}"},
3483 : {false, "function f(arg) {g(arg)}"},
3484 : {false, "function f(arg) {function h() { g(arg) }; h()}"},
3485 : {false, "function f(arg) {function h() { g(arg) }; return h}"},
3486 : {false, "function f(arg=1) {}"},
3487 : {false, "function f(arg=1) {g(arg)}"},
3488 : {false, "function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3489 : {false,
3490 : "function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3491 : {false,
3492 : "function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)}"},
3493 : {false, "function f(...arg) {g(arg); arguments[0] = 42; g(arg)}"},
3494 : {false,
3495 : "function f(arg) {g(arg); g(function() {arguments[0] = 42}); g(arg)}"},
3496 :
3497 : // strict arguments object
3498 : {false, "function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)}"},
3499 : {false, "function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)}"},
3500 : {false, "function f(arg=1) {g(arg); arguments[0] = 42; g(arg)}"},
3501 : {false,
3502 : "function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)}"},
3503 : {false, "function f(arg) {g(arg); f.arguments[0] = 42; g(arg)}"},
3504 : {false, "function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)}"},
3505 :
3506 : {true, "function f(arg) {g(arg); arg = 42; g(arg)}"},
3507 : {true, "function f(arg) {g(arg); eval('arg = 42'); g(arg)}"},
3508 : {true, "function f(arg) {g(arg); var arg = 42; g(arg)}"},
3509 : {true, "function f(arg, x=1) {g(arg); arg = 42; g(arg)}"},
3510 : {true, "function f(arg, ...x) {g(arg); arg = 42; g(arg)}"},
3511 : {true, "function f(arg=1) {g(arg); arg = 42; g(arg)}"},
3512 : {true, "function f(arg) {'use strict'; g(arg); arg = 42; g(arg)}"},
3513 : {true, "function f(arg, {a=(g(arg), arg=42)}) {g(arg)}"},
3514 : {true, "function f(arg) {g(arg); g(function() {arg = 42}); g(arg)}"},
3515 : {true,
3516 : "function f(arg) {g(arg); g(function() {eval('arg = 42')}); g(arg)}"},
3517 : {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"},
3518 : {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"},
3519 : {true, "function f(...arg) {g(arg); eval('arg = 42'); g(arg)}"},
3520 :
3521 : // sloppy arguments object
3522 : {true, "function f(arg) {g(arg); arguments[0] = 42; g(arg)}"},
3523 : {true, "function f(arg) {g(arg); h(arguments); g(arg)}"},
3524 : {true,
3525 : "function f(arg) {((args) => {arguments[0] = 42})(arguments); "
3526 : "g(arg)}"},
3527 : {true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"},
3528 : {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
3529 5 : };
3530 :
3531 : const char* suffix = "; f";
3532 :
3533 180 : for (unsigned i = 0; i < arraysize(tests); ++i) {
3534 175 : bool assigned = tests[i].arg_assigned;
3535 175 : const char* source = tests[i].source;
3536 525 : for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) {
3537 700 : i::ScopedVector<char> program(Utf8LengthHelper(source) +
3538 700 : Utf8LengthHelper(suffix) + 1);
3539 350 : i::SNPrintF(program, "%s%s", source, suffix);
3540 : std::unique_ptr<i::ParseInfo> info;
3541 : printf("%s\n", program.start());
3542 : v8::Local<v8::Value> v = CompileRun(program.start());
3543 350 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3544 350 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3545 700 : i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
3546 350 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3547 : info->set_allow_lazy_parsing(allow_lazy);
3548 350 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3549 350 : CHECK(i::Compiler::Analyze(info.get()));
3550 350 : CHECK_NOT_NULL(info->literal());
3551 :
3552 1050 : i::Scope* scope = info->literal()->scope();
3553 700 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3554 350 : CHECK_NULL(scope->sibling());
3555 350 : CHECK(scope->is_function_scope());
3556 : const i::AstRawString* var_name =
3557 350 : info->ast_value_factory()->GetOneByteString("arg");
3558 350 : i::Variable* var = scope->LookupForTesting(var_name);
3559 350 : CHECK(var->is_used() || !assigned);
3560 350 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3561 350 : CHECK_EQ(is_maybe_assigned, assigned);
3562 : }
3563 : }
3564 5 : }
3565 :
3566 65800 : struct Input {
3567 : bool assigned;
3568 : std::string source;
3569 : std::vector<unsigned> location; // "Directions" to the relevant scope.
3570 : };
3571 :
3572 15000 : static void TestMaybeAssigned(Input input, const char* variable, bool module,
3573 : bool allow_lazy_parsing) {
3574 : i::Isolate* isolate = CcTest::i_isolate();
3575 : i::Factory* factory = isolate->factory();
3576 : i::Handle<i::String> string =
3577 15000 : factory->InternalizeUtf8String(input.source.c_str());
3578 30000 : string->PrintOn(stdout);
3579 : printf("\n");
3580 15000 : i::Handle<i::Script> script = factory->NewScript(string);
3581 :
3582 : std::unique_ptr<i::ParseInfo> info;
3583 15000 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3584 : info->set_module(module);
3585 : info->set_allow_lazy_parsing(allow_lazy_parsing);
3586 :
3587 15000 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3588 15000 : CHECK(i::Compiler::Analyze(info.get()));
3589 :
3590 15000 : CHECK_NOT_NULL(info->literal());
3591 45000 : i::Scope* scope = info->literal()->scope();
3592 30000 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3593 15000 : CHECK_NULL(scope->sibling());
3594 30000 : CHECK(module ? scope->is_module_scope() : scope->is_script_scope());
3595 :
3596 26400 : i::Variable* var;
3597 : {
3598 : // Find the variable.
3599 15000 : scope = i::ScopeTestHelper::FindScope(scope, input.location);
3600 : const i::AstRawString* var_name =
3601 15000 : info->ast_value_factory()->GetOneByteString(variable);
3602 : var = scope->LookupForTesting(var_name);
3603 : }
3604 :
3605 15000 : CHECK_NOT_NULL(var);
3606 26400 : CHECK_IMPLIES(input.assigned, var->is_used());
3607 : STATIC_ASSERT(true == i::kMaybeAssigned);
3608 15000 : CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
3609 15000 : }
3610 :
3611 4200 : static Input wrap(Input input) {
3612 : Input result;
3613 4200 : result.assigned = input.assigned;
3614 16800 : result.source = "function WRAPPED() { " + input.source + " }";
3615 8400 : result.location.push_back(0);
3616 11780 : for (auto n : input.location) {
3617 3380 : result.location.push_back(n);
3618 : }
3619 4200 : return result;
3620 : }
3621 :
3622 25880 : TEST(MaybeAssignedInsideLoop) {
3623 : i::Isolate* isolate = CcTest::i_isolate();
3624 : i::HandleScope scope(isolate);
3625 10 : LocalContext env;
3626 :
3627 : std::vector<unsigned> top; // Can't use {} in initializers below.
3628 :
3629 : Input module_and_script_tests[] = {
3630 : {true, "for (j=x; j<10; ++j) { foo = j }", top},
3631 : {true, "for (j=x; j<10; ++j) { [foo] = [j] }", top},
3632 : {true, "for (j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3633 : {true, "for (j=x; j<10; ++j) { var foo = j }", top},
3634 : {true, "for (j=x; j<10; ++j) { var [foo] = [j] }", top},
3635 : {true, "for (j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3636 : {true, "for (j=x; j<10; ++j) { var foo; foo = j }", top},
3637 : {true, "for (j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3638 : {true, "for (j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3639 : {true, "for (j=x; j<10; ++j) { let foo; foo = j }", {0}},
3640 : {true, "for (j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3641 : {true, "for (j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3642 : {false, "for (j=x; j<10; ++j) { let foo = j }", {0}},
3643 : {false, "for (j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3644 : {false, "for (j=x; j<10; ++j) { const foo = j }", {0}},
3645 : {false, "for (j=x; j<10; ++j) { const [foo] = [j] }", {0}},
3646 : {false, "for (j=x; j<10; ++j) { function foo() {return j} }", {0}},
3647 :
3648 : {true, "for ({j}=x; j<10; ++j) { foo = j }", top},
3649 : {true, "for ({j}=x; j<10; ++j) { [foo] = [j] }", top},
3650 : {true, "for ({j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3651 : {true, "for ({j}=x; j<10; ++j) { var foo = j }", top},
3652 : {true, "for ({j}=x; j<10; ++j) { var [foo] = [j] }", top},
3653 : {true, "for ({j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3654 : {true, "for ({j}=x; j<10; ++j) { var foo; foo = j }", top},
3655 : {true, "for ({j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3656 : {true, "for ({j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3657 : {true, "for ({j}=x; j<10; ++j) { let foo; foo = j }", {0}},
3658 : {true, "for ({j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3659 : {true, "for ({j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3660 : {false, "for ({j}=x; j<10; ++j) { let foo = j }", {0}},
3661 : {false, "for ({j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3662 : {false, "for ({j}=x; j<10; ++j) { const foo = j }", {0}},
3663 : {false, "for ({j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
3664 : {false, "for ({j}=x; j<10; ++j) { function foo() {return j} }", {0}},
3665 :
3666 : {true, "for (var j=x; j<10; ++j) { foo = j }", top},
3667 : {true, "for (var j=x; j<10; ++j) { [foo] = [j] }", top},
3668 : {true, "for (var j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3669 : {true, "for (var j=x; j<10; ++j) { var foo = j }", top},
3670 : {true, "for (var j=x; j<10; ++j) { var [foo] = [j] }", top},
3671 : {true, "for (var j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3672 : {true, "for (var j=x; j<10; ++j) { var foo; foo = j }", top},
3673 : {true, "for (var j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3674 : {true, "for (var j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3675 : {true, "for (var j=x; j<10; ++j) { let foo; foo = j }", {0}},
3676 : {true, "for (var j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3677 : {true, "for (var j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3678 : {false, "for (var j=x; j<10; ++j) { let foo = j }", {0}},
3679 : {false, "for (var j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3680 : {false, "for (var j=x; j<10; ++j) { const foo = j }", {0}},
3681 : {false, "for (var j=x; j<10; ++j) { const [foo] = [j] }", {0}},
3682 : {false, "for (var j=x; j<10; ++j) { function foo() {return j} }", {0}},
3683 :
3684 : {true, "for (var {j}=x; j<10; ++j) { foo = j }", top},
3685 : {true, "for (var {j}=x; j<10; ++j) { [foo] = [j] }", top},
3686 : {true, "for (var {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3687 : {true, "for (var {j}=x; j<10; ++j) { var foo = j }", top},
3688 : {true, "for (var {j}=x; j<10; ++j) { var [foo] = [j] }", top},
3689 : {true, "for (var {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3690 : {true, "for (var {j}=x; j<10; ++j) { var foo; foo = j }", top},
3691 : {true, "for (var {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3692 : {true, "for (var {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3693 : {true, "for (var {j}=x; j<10; ++j) { let foo; foo = j }", {0}},
3694 : {true, "for (var {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3695 : {true, "for (var {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3696 : {false, "for (var {j}=x; j<10; ++j) { let foo = j }", {0}},
3697 : {false, "for (var {j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3698 : {false, "for (var {j}=x; j<10; ++j) { const foo = j }", {0}},
3699 : {false, "for (var {j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
3700 : {false, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", {0}},
3701 :
3702 : {true, "for (let j=x; j<10; ++j) { foo = j }", top},
3703 : {true, "for (let j=x; j<10; ++j) { [foo] = [j] }", top},
3704 : {true, "for (let j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3705 : {true, "for (let j=x; j<10; ++j) { var foo = j }", top},
3706 : {true, "for (let j=x; j<10; ++j) { var [foo] = [j] }", top},
3707 : {true, "for (let j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3708 : {true, "for (let j=x; j<10; ++j) { var foo; foo = j }", top},
3709 : {true, "for (let j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3710 : {true, "for (let j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3711 : {true, "for (let j=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
3712 : {true, "for (let j=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
3713 : {true, "for (let j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0, 0}},
3714 : {false, "for (let j=x; j<10; ++j) { let foo = j }", {0, 0}},
3715 : {false, "for (let j=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
3716 : {false, "for (let j=x; j<10; ++j) { const foo = j }", {0, 0}},
3717 : {false, "for (let j=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3718 : {false,
3719 : "for (let j=x; j<10; ++j) { function foo() {return j} }",
3720 : {0, 0, 0}},
3721 :
3722 : {true, "for (let {j}=x; j<10; ++j) { foo = j }", top},
3723 : {true, "for (let {j}=x; j<10; ++j) { [foo] = [j] }", top},
3724 : {true, "for (let {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3725 : {true, "for (let {j}=x; j<10; ++j) { var foo = j }", top},
3726 : {true, "for (let {j}=x; j<10; ++j) { var [foo] = [j] }", top},
3727 : {true, "for (let {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3728 : {true, "for (let {j}=x; j<10; ++j) { var foo; foo = j }", top},
3729 : {true, "for (let {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3730 : {true, "for (let {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3731 : {true, "for (let {j}=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
3732 : {true, "for (let {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
3733 : {true,
3734 : "for (let {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }",
3735 : {0, 0}},
3736 : {false, "for (let {j}=x; j<10; ++j) { let foo = j }", {0, 0}},
3737 : {false, "for (let {j}=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
3738 : {false, "for (let {j}=x; j<10; ++j) { const foo = j }", {0, 0}},
3739 : {false, "for (let {j}=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3740 : {false,
3741 : "for (let {j}=x; j<10; ++j) { function foo(){return j} }",
3742 : {0, 0, 0}},
3743 :
3744 : {true, "for (j of x) { foo = j }", top},
3745 : {true, "for (j of x) { [foo] = [j] }", top},
3746 : {true, "for (j of x) { [[foo]=[42]] = [] }", top},
3747 : {true, "for (j of x) { var foo = j }", top},
3748 : {true, "for (j of x) { var [foo] = [j] }", top},
3749 : {true, "for (j of x) { var [[foo]=[42]] = [] }", top},
3750 : {true, "for (j of x) { var foo; foo = j }", top},
3751 : {true, "for (j of x) { var foo; [foo] = [j] }", top},
3752 : {true, "for (j of x) { var foo; [[foo]=[42]] = [] }", top},
3753 : {true, "for (j of x) { let foo; foo = j }", {0}},
3754 : {true, "for (j of x) { let foo; [foo] = [j] }", {0}},
3755 : {true, "for (j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3756 : {false, "for (j of x) { let foo = j }", {0}},
3757 : {false, "for (j of x) { let [foo] = [j] }", {0}},
3758 : {false, "for (j of x) { const foo = j }", {0}},
3759 : {false, "for (j of x) { const [foo] = [j] }", {0}},
3760 : {false, "for (j of x) { function foo() {return j} }", {0}},
3761 :
3762 : {true, "for ({j} of x) { foo = j }", top},
3763 : {true, "for ({j} of x) { [foo] = [j] }", top},
3764 : {true, "for ({j} of x) { [[foo]=[42]] = [] }", top},
3765 : {true, "for ({j} of x) { var foo = j }", top},
3766 : {true, "for ({j} of x) { var [foo] = [j] }", top},
3767 : {true, "for ({j} of x) { var [[foo]=[42]] = [] }", top},
3768 : {true, "for ({j} of x) { var foo; foo = j }", top},
3769 : {true, "for ({j} of x) { var foo; [foo] = [j] }", top},
3770 : {true, "for ({j} of x) { var foo; [[foo]=[42]] = [] }", top},
3771 : {true, "for ({j} of x) { let foo; foo = j }", {0}},
3772 : {true, "for ({j} of x) { let foo; [foo] = [j] }", {0}},
3773 : {true, "for ({j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3774 : {false, "for ({j} of x) { let foo = j }", {0}},
3775 : {false, "for ({j} of x) { let [foo] = [j] }", {0}},
3776 : {false, "for ({j} of x) { const foo = j }", {0}},
3777 : {false, "for ({j} of x) { const [foo] = [j] }", {0}},
3778 : {false, "for ({j} of x) { function foo() {return j} }", {0}},
3779 :
3780 : {true, "for (var j of x) { foo = j }", top},
3781 : {true, "for (var j of x) { [foo] = [j] }", top},
3782 : {true, "for (var j of x) { [[foo]=[42]] = [] }", top},
3783 : {true, "for (var j of x) { var foo = j }", top},
3784 : {true, "for (var j of x) { var [foo] = [j] }", top},
3785 : {true, "for (var j of x) { var [[foo]=[42]] = [] }", top},
3786 : {true, "for (var j of x) { var foo; foo = j }", top},
3787 : {true, "for (var j of x) { var foo; [foo] = [j] }", top},
3788 : {true, "for (var j of x) { var foo; [[foo]=[42]] = [] }", top},
3789 : {true, "for (var j of x) { let foo; foo = j }", {0}},
3790 : {true, "for (var j of x) { let foo; [foo] = [j] }", {0}},
3791 : {true, "for (var j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3792 : {false, "for (var j of x) { let foo = j }", {0}},
3793 : {false, "for (var j of x) { let [foo] = [j] }", {0}},
3794 : {false, "for (var j of x) { const foo = j }", {0}},
3795 : {false, "for (var j of x) { const [foo] = [j] }", {0}},
3796 : {false, "for (var j of x) { function foo() {return j} }", {0}},
3797 :
3798 : {true, "for (var {j} of x) { foo = j }", top},
3799 : {true, "for (var {j} of x) { [foo] = [j] }", top},
3800 : {true, "for (var {j} of x) { [[foo]=[42]] = [] }", top},
3801 : {true, "for (var {j} of x) { var foo = j }", top},
3802 : {true, "for (var {j} of x) { var [foo] = [j] }", top},
3803 : {true, "for (var {j} of x) { var [[foo]=[42]] = [] }", top},
3804 : {true, "for (var {j} of x) { var foo; foo = j }", top},
3805 : {true, "for (var {j} of x) { var foo; [foo] = [j] }", top},
3806 : {true, "for (var {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3807 : {true, "for (var {j} of x) { let foo; foo = j }", {0}},
3808 : {true, "for (var {j} of x) { let foo; [foo] = [j] }", {0}},
3809 : {true, "for (var {j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3810 : {false, "for (var {j} of x) { let foo = j }", {0}},
3811 : {false, "for (var {j} of x) { let [foo] = [j] }", {0}},
3812 : {false, "for (var {j} of x) { const foo = j }", {0}},
3813 : {false, "for (var {j} of x) { const [foo] = [j] }", {0}},
3814 : {false, "for (var {j} of x) { function foo() {return j} }", {0}},
3815 :
3816 : {true, "for (let j of x) { foo = j }", top},
3817 : {true, "for (let j of x) { [foo] = [j] }", top},
3818 : {true, "for (let j of x) { [[foo]=[42]] = [] }", top},
3819 : {true, "for (let j of x) { var foo = j }", top},
3820 : {true, "for (let j of x) { var [foo] = [j] }", top},
3821 : {true, "for (let j of x) { var [[foo]=[42]] = [] }", top},
3822 : {true, "for (let j of x) { var foo; foo = j }", top},
3823 : {true, "for (let j of x) { var foo; [foo] = [j] }", top},
3824 : {true, "for (let j of x) { var foo; [[foo]=[42]] = [] }", top},
3825 : {true, "for (let j of x) { let foo; foo = j }", {0, 0, 0}},
3826 : {true, "for (let j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3827 : {true, "for (let j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3828 : {false, "for (let j of x) { let foo = j }", {0, 0, 0}},
3829 : {false, "for (let j of x) { let [foo] = [j] }", {0, 0, 0}},
3830 : {false, "for (let j of x) { const foo = j }", {0, 0, 0}},
3831 : {false, "for (let j of x) { const [foo] = [j] }", {0, 0, 0}},
3832 : {false, "for (let j of x) { function foo() {return j} }", {0, 0, 0}},
3833 :
3834 : {true, "for (let {j} of x) { foo = j }", top},
3835 : {true, "for (let {j} of x) { [foo] = [j] }", top},
3836 : {true, "for (let {j} of x) { [[foo]=[42]] = [] }", top},
3837 : {true, "for (let {j} of x) { var foo = j }", top},
3838 : {true, "for (let {j} of x) { var [foo] = [j] }", top},
3839 : {true, "for (let {j} of x) { var [[foo]=[42]] = [] }", top},
3840 : {true, "for (let {j} of x) { var foo; foo = j }", top},
3841 : {true, "for (let {j} of x) { var foo; [foo] = [j] }", top},
3842 : {true, "for (let {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3843 : {true, "for (let {j} of x) { let foo; foo = j }", {0, 0, 0}},
3844 : {true, "for (let {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3845 : {true, "for (let {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3846 : {false, "for (let {j} of x) { let foo = j }", {0, 0, 0}},
3847 : {false, "for (let {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3848 : {false, "for (let {j} of x) { const foo = j }", {0, 0, 0}},
3849 : {false, "for (let {j} of x) { const [foo] = [j] }", {0, 0, 0}},
3850 : {false, "for (let {j} of x) { function foo() {return j} }", {0, 0, 0}},
3851 :
3852 : {true, "for (const j of x) { foo = j }", top},
3853 : {true, "for (const j of x) { [foo] = [j] }", top},
3854 : {true, "for (const j of x) { [[foo]=[42]] = [] }", top},
3855 : {true, "for (const j of x) { var foo = j }", top},
3856 : {true, "for (const j of x) { var [foo] = [j] }", top},
3857 : {true, "for (const j of x) { var [[foo]=[42]] = [] }", top},
3858 : {true, "for (const j of x) { var foo; foo = j }", top},
3859 : {true, "for (const j of x) { var foo; [foo] = [j] }", top},
3860 : {true, "for (const j of x) { var foo; [[foo]=[42]] = [] }", top},
3861 : {true, "for (const j of x) { let foo; foo = j }", {0, 0, 0}},
3862 : {true, "for (const j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3863 : {true, "for (const j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3864 : {false, "for (const j of x) { let foo = j }", {0, 0, 0}},
3865 : {false, "for (const j of x) { let [foo] = [j] }", {0, 0, 0}},
3866 : {false, "for (const j of x) { const foo = j }", {0, 0, 0}},
3867 : {false, "for (const j of x) { const [foo] = [j] }", {0, 0, 0}},
3868 : {false, "for (const j of x) { function foo() {return j} }", {0, 0, 0}},
3869 :
3870 : {true, "for (const {j} of x) { foo = j }", top},
3871 : {true, "for (const {j} of x) { [foo] = [j] }", top},
3872 : {true, "for (const {j} of x) { [[foo]=[42]] = [] }", top},
3873 : {true, "for (const {j} of x) { var foo = j }", top},
3874 : {true, "for (const {j} of x) { var [foo] = [j] }", top},
3875 : {true, "for (const {j} of x) { var [[foo]=[42]] = [] }", top},
3876 : {true, "for (const {j} of x) { var foo; foo = j }", top},
3877 : {true, "for (const {j} of x) { var foo; [foo] = [j] }", top},
3878 : {true, "for (const {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3879 : {true, "for (const {j} of x) { let foo; foo = j }", {0, 0, 0}},
3880 : {true, "for (const {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3881 : {true, "for (const {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3882 : {false, "for (const {j} of x) { let foo = j }", {0, 0, 0}},
3883 : {false, "for (const {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3884 : {false, "for (const {j} of x) { const foo = j }", {0, 0, 0}},
3885 : {false, "for (const {j} of x) { const [foo] = [j] }", {0, 0, 0}},
3886 : {false, "for (const {j} of x) { function foo() {return j} }", {0, 0, 0}},
3887 :
3888 : {true, "for (j in x) { foo = j }", top},
3889 : {true, "for (j in x) { [foo] = [j] }", top},
3890 : {true, "for (j in x) { [[foo]=[42]] = [] }", top},
3891 : {true, "for (j in x) { var foo = j }", top},
3892 : {true, "for (j in x) { var [foo] = [j] }", top},
3893 : {true, "for (j in x) { var [[foo]=[42]] = [] }", top},
3894 : {true, "for (j in x) { var foo; foo = j }", top},
3895 : {true, "for (j in x) { var foo; [foo] = [j] }", top},
3896 : {true, "for (j in x) { var foo; [[foo]=[42]] = [] }", top},
3897 : {true, "for (j in x) { let foo; foo = j }", {0}},
3898 : {true, "for (j in x) { let foo; [foo] = [j] }", {0}},
3899 : {true, "for (j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3900 : {false, "for (j in x) { let foo = j }", {0}},
3901 : {false, "for (j in x) { let [foo] = [j] }", {0}},
3902 : {false, "for (j in x) { const foo = j }", {0}},
3903 : {false, "for (j in x) { const [foo] = [j] }", {0}},
3904 : {false, "for (j in x) { function foo() {return j} }", {0}},
3905 :
3906 : {true, "for ({j} in x) { foo = j }", top},
3907 : {true, "for ({j} in x) { [foo] = [j] }", top},
3908 : {true, "for ({j} in x) { [[foo]=[42]] = [] }", top},
3909 : {true, "for ({j} in x) { var foo = j }", top},
3910 : {true, "for ({j} in x) { var [foo] = [j] }", top},
3911 : {true, "for ({j} in x) { var [[foo]=[42]] = [] }", top},
3912 : {true, "for ({j} in x) { var foo; foo = j }", top},
3913 : {true, "for ({j} in x) { var foo; [foo] = [j] }", top},
3914 : {true, "for ({j} in x) { var foo; [[foo]=[42]] = [] }", top},
3915 : {true, "for ({j} in x) { let foo; foo = j }", {0}},
3916 : {true, "for ({j} in x) { let foo; [foo] = [j] }", {0}},
3917 : {true, "for ({j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3918 : {false, "for ({j} in x) { let foo = j }", {0}},
3919 : {false, "for ({j} in x) { let [foo] = [j] }", {0}},
3920 : {false, "for ({j} in x) { const foo = j }", {0}},
3921 : {false, "for ({j} in x) { const [foo] = [j] }", {0}},
3922 : {false, "for ({j} in x) { function foo() {return j} }", {0}},
3923 :
3924 : {true, "for (var j in x) { foo = j }", top},
3925 : {true, "for (var j in x) { [foo] = [j] }", top},
3926 : {true, "for (var j in x) { [[foo]=[42]] = [] }", top},
3927 : {true, "for (var j in x) { var foo = j }", top},
3928 : {true, "for (var j in x) { var [foo] = [j] }", top},
3929 : {true, "for (var j in x) { var [[foo]=[42]] = [] }", top},
3930 : {true, "for (var j in x) { var foo; foo = j }", top},
3931 : {true, "for (var j in x) { var foo; [foo] = [j] }", top},
3932 : {true, "for (var j in x) { var foo; [[foo]=[42]] = [] }", top},
3933 : {true, "for (var j in x) { let foo; foo = j }", {0}},
3934 : {true, "for (var j in x) { let foo; [foo] = [j] }", {0}},
3935 : {true, "for (var j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3936 : {false, "for (var j in x) { let foo = j }", {0}},
3937 : {false, "for (var j in x) { let [foo] = [j] }", {0}},
3938 : {false, "for (var j in x) { const foo = j }", {0}},
3939 : {false, "for (var j in x) { const [foo] = [j] }", {0}},
3940 : {false, "for (var j in x) { function foo() {return j} }", {0}},
3941 :
3942 : {true, "for (var {j} in x) { foo = j }", top},
3943 : {true, "for (var {j} in x) { [foo] = [j] }", top},
3944 : {true, "for (var {j} in x) { [[foo]=[42]] = [] }", top},
3945 : {true, "for (var {j} in x) { var foo = j }", top},
3946 : {true, "for (var {j} in x) { var [foo] = [j] }", top},
3947 : {true, "for (var {j} in x) { var [[foo]=[42]] = [] }", top},
3948 : {true, "for (var {j} in x) { var foo; foo = j }", top},
3949 : {true, "for (var {j} in x) { var foo; [foo] = [j] }", top},
3950 : {true, "for (var {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3951 : {true, "for (var {j} in x) { let foo; foo = j }", {0}},
3952 : {true, "for (var {j} in x) { let foo; [foo] = [j] }", {0}},
3953 : {true, "for (var {j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3954 : {false, "for (var {j} in x) { let foo = j }", {0}},
3955 : {false, "for (var {j} in x) { let [foo] = [j] }", {0}},
3956 : {false, "for (var {j} in x) { const foo = j }", {0}},
3957 : {false, "for (var {j} in x) { const [foo] = [j] }", {0}},
3958 : {false, "for (var {j} in x) { function foo() {return j} }", {0}},
3959 :
3960 : {true, "for (let j in x) { foo = j }", top},
3961 : {true, "for (let j in x) { [foo] = [j] }", top},
3962 : {true, "for (let j in x) { [[foo]=[42]] = [] }", top},
3963 : {true, "for (let j in x) { var foo = j }", top},
3964 : {true, "for (let j in x) { var [foo] = [j] }", top},
3965 : {true, "for (let j in x) { var [[foo]=[42]] = [] }", top},
3966 : {true, "for (let j in x) { var foo; foo = j }", top},
3967 : {true, "for (let j in x) { var foo; [foo] = [j] }", top},
3968 : {true, "for (let j in x) { var foo; [[foo]=[42]] = [] }", top},
3969 : {true, "for (let j in x) { let foo; foo = j }", {0, 0, 0}},
3970 : {true, "for (let j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
3971 : {true, "for (let j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3972 : {false, "for (let j in x) { let foo = j }", {0, 0, 0}},
3973 : {false, "for (let j in x) { let [foo] = [j] }", {0, 0, 0}},
3974 : {false, "for (let j in x) { const foo = j }", {0, 0, 0}},
3975 : {false, "for (let j in x) { const [foo] = [j] }", {0, 0, 0}},
3976 : {false, "for (let j in x) { function foo() {return j} }", {0, 0, 0}},
3977 :
3978 : {true, "for (let {j} in x) { foo = j }", top},
3979 : {true, "for (let {j} in x) { [foo] = [j] }", top},
3980 : {true, "for (let {j} in x) { [[foo]=[42]] = [] }", top},
3981 : {true, "for (let {j} in x) { var foo = j }", top},
3982 : {true, "for (let {j} in x) { var [foo] = [j] }", top},
3983 : {true, "for (let {j} in x) { var [[foo]=[42]] = [] }", top},
3984 : {true, "for (let {j} in x) { var foo; foo = j }", top},
3985 : {true, "for (let {j} in x) { var foo; [foo] = [j] }", top},
3986 : {true, "for (let {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3987 : {true, "for (let {j} in x) { let foo; foo = j }", {0, 0, 0}},
3988 : {true, "for (let {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
3989 : {true, "for (let {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3990 : {false, "for (let {j} in x) { let foo = j }", {0, 0, 0}},
3991 : {false, "for (let {j} in x) { let [foo] = [j] }", {0, 0, 0}},
3992 : {false, "for (let {j} in x) { const foo = j }", {0, 0, 0}},
3993 : {false, "for (let {j} in x) { const [foo] = [j] }", {0, 0, 0}},
3994 : {false, "for (let {j} in x) { function foo() {return j} }", {0, 0, 0}},
3995 :
3996 : {true, "for (const j in x) { foo = j }", top},
3997 : {true, "for (const j in x) { [foo] = [j] }", top},
3998 : {true, "for (const j in x) { [[foo]=[42]] = [] }", top},
3999 : {true, "for (const j in x) { var foo = j }", top},
4000 : {true, "for (const j in x) { var [foo] = [j] }", top},
4001 : {true, "for (const j in x) { var [[foo]=[42]] = [] }", top},
4002 : {true, "for (const j in x) { var foo; foo = j }", top},
4003 : {true, "for (const j in x) { var foo; [foo] = [j] }", top},
4004 : {true, "for (const j in x) { var foo; [[foo]=[42]] = [] }", top},
4005 : {true, "for (const j in x) { let foo; foo = j }", {0, 0, 0}},
4006 : {true, "for (const j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4007 : {true, "for (const j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4008 : {false, "for (const j in x) { let foo = j }", {0, 0, 0}},
4009 : {false, "for (const j in x) { let [foo] = [j] }", {0, 0, 0}},
4010 : {false, "for (const j in x) { const foo = j }", {0, 0, 0}},
4011 : {false, "for (const j in x) { const [foo] = [j] }", {0, 0, 0}},
4012 : {false, "for (const j in x) { function foo() {return j} }", {0, 0, 0}},
4013 :
4014 : {true, "for (const {j} in x) { foo = j }", top},
4015 : {true, "for (const {j} in x) { [foo] = [j] }", top},
4016 : {true, "for (const {j} in x) { [[foo]=[42]] = [] }", top},
4017 : {true, "for (const {j} in x) { var foo = j }", top},
4018 : {true, "for (const {j} in x) { var [foo] = [j] }", top},
4019 : {true, "for (const {j} in x) { var [[foo]=[42]] = [] }", top},
4020 : {true, "for (const {j} in x) { var foo; foo = j }", top},
4021 : {true, "for (const {j} in x) { var foo; [foo] = [j] }", top},
4022 : {true, "for (const {j} in x) { var foo; [[foo]=[42]] = [] }", top},
4023 : {true, "for (const {j} in x) { let foo; foo = j }", {0, 0, 0}},
4024 : {true, "for (const {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4025 : {true, "for (const {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4026 : {false, "for (const {j} in x) { let foo = j }", {0, 0, 0}},
4027 : {false, "for (const {j} in x) { let [foo] = [j] }", {0, 0, 0}},
4028 : {false, "for (const {j} in x) { const foo = j }", {0, 0, 0}},
4029 : {false, "for (const {j} in x) { const [foo] = [j] }", {0, 0, 0}},
4030 : {false, "for (const {j} in x) { function foo() {return j} }", {0, 0, 0}},
4031 :
4032 : {true, "while (j) { foo = j }", top},
4033 : {true, "while (j) { [foo] = [j] }", top},
4034 : {true, "while (j) { [[foo]=[42]] = [] }", top},
4035 : {true, "while (j) { var foo = j }", top},
4036 : {true, "while (j) { var [foo] = [j] }", top},
4037 : {true, "while (j) { var [[foo]=[42]] = [] }", top},
4038 : {true, "while (j) { var foo; foo = j }", top},
4039 : {true, "while (j) { var foo; [foo] = [j] }", top},
4040 : {true, "while (j) { var foo; [[foo]=[42]] = [] }", top},
4041 : {true, "while (j) { let foo; foo = j }", {0}},
4042 : {true, "while (j) { let foo; [foo] = [j] }", {0}},
4043 : {true, "while (j) { let foo; [[foo]=[42]] = [] }", {0}},
4044 : {false, "while (j) { let foo = j }", {0}},
4045 : {false, "while (j) { let [foo] = [j] }", {0}},
4046 : {false, "while (j) { const foo = j }", {0}},
4047 : {false, "while (j) { const [foo] = [j] }", {0}},
4048 : {false, "while (j) { function foo() {return j} }", {0}},
4049 :
4050 : {true, "do { foo = j } while (j)", top},
4051 : {true, "do { [foo] = [j] } while (j)", top},
4052 : {true, "do { [[foo]=[42]] = [] } while (j)", top},
4053 : {true, "do { var foo = j } while (j)", top},
4054 : {true, "do { var [foo] = [j] } while (j)", top},
4055 : {true, "do { var [[foo]=[42]] = [] } while (j)", top},
4056 : {true, "do { var foo; foo = j } while (j)", top},
4057 : {true, "do { var foo; [foo] = [j] } while (j)", top},
4058 : {true, "do { var foo; [[foo]=[42]] = [] } while (j)", top},
4059 : {true, "do { let foo; foo = j } while (j)", {0}},
4060 : {true, "do { let foo; [foo] = [j] } while (j)", {0}},
4061 : {true, "do { let foo; [[foo]=[42]] = [] } while (j)", {0}},
4062 : {false, "do { let foo = j } while (j)", {0}},
4063 : {false, "do { let [foo] = [j] } while (j)", {0}},
4064 : {false, "do { const foo = j } while (j)", {0}},
4065 : {false, "do { const [foo] = [j] } while (j)", {0}},
4066 : {false, "do { function foo() {return j} } while (j)", {0}},
4067 3010 : };
4068 :
4069 : Input script_only_tests[] = {
4070 : {true, "for (j=x; j<10; ++j) { function foo() {return j} }", top},
4071 : {true, "for ({j}=x; j<10; ++j) { function foo() {return j} }", top},
4072 : {true, "for (var j=x; j<10; ++j) { function foo() {return j} }", top},
4073 : {true, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", top},
4074 : {true, "for (let j=x; j<10; ++j) { function foo() {return j} }", top},
4075 : {true, "for (let {j}=x; j<10; ++j) { function foo() {return j} }", top},
4076 : {true, "for (j of x) { function foo() {return j} }", top},
4077 : {true, "for ({j} of x) { function foo() {return j} }", top},
4078 : {true, "for (var j of x) { function foo() {return j} }", top},
4079 : {true, "for (var {j} of x) { function foo() {return j} }", top},
4080 : {true, "for (let j of x) { function foo() {return j} }", top},
4081 : {true, "for (let {j} of x) { function foo() {return j} }", top},
4082 : {true, "for (const j of x) { function foo() {return j} }", top},
4083 : {true, "for (const {j} of x) { function foo() {return j} }", top},
4084 : {true, "for (j in x) { function foo() {return j} }", top},
4085 : {true, "for ({j} in x) { function foo() {return j} }", top},
4086 : {true, "for (var j in x) { function foo() {return j} }", top},
4087 : {true, "for (var {j} in x) { function foo() {return j} }", top},
4088 : {true, "for (let j in x) { function foo() {return j} }", top},
4089 : {true, "for (let {j} in x) { function foo() {return j} }", top},
4090 : {true, "for (const j in x) { function foo() {return j} }", top},
4091 : {true, "for (const {j} in x) { function foo() {return j} }", top},
4092 : {true, "while (j) { function foo() {return j} }", top},
4093 : {true, "do { function foo() {return j} } while (j)", top},
4094 130 : };
4095 :
4096 2045 : for (unsigned i = 0; i < arraysize(module_and_script_tests); ++i) {
4097 2040 : Input input = module_and_script_tests[i];
4098 6120 : for (unsigned module = 0; module <= 1; ++module) {
4099 8160 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4100 : ++allow_lazy_parsing) {
4101 8160 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4102 : }
4103 4080 : TestMaybeAssigned(wrap(input), "foo", module, false);
4104 : }
4105 2040 : }
4106 :
4107 120 : for (unsigned i = 0; i < arraysize(script_only_tests); ++i) {
4108 120 : Input input = script_only_tests[i];
4109 360 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4110 : ++allow_lazy_parsing) {
4111 240 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4112 : }
4113 120 : TestMaybeAssigned(wrap(input), "foo", false, false);
4114 120 : }
4115 5 : }
4116 :
4117 25880 : TEST(MaybeAssignedTopLevel) {
4118 : i::Isolate* isolate = CcTest::i_isolate();
4119 : i::HandleScope scope(isolate);
4120 10 : LocalContext env;
4121 :
4122 : const char* prefixes[] = {
4123 : "let foo; ",
4124 : "let foo = 0; ",
4125 : "let [foo] = [1]; ",
4126 : "let {foo} = {foo: 2}; ",
4127 : "let {foo=3} = {}; ",
4128 : "var foo; ",
4129 : "var foo = 0; ",
4130 : "var [foo] = [1]; ",
4131 : "var {foo} = {foo: 2}; ",
4132 : "var {foo=3} = {}; ",
4133 : "{ var foo; }; ",
4134 : "{ var foo = 0; }; ",
4135 : "{ var [foo] = [1]; }; ",
4136 : "{ var {foo} = {foo: 2}; }; ",
4137 : "{ var {foo=3} = {}; }; ",
4138 : "function foo() {}; ",
4139 : "function* foo() {}; ",
4140 : "async function foo() {}; ",
4141 : "class foo {}; ",
4142 : "class foo extends null {}; ",
4143 5 : };
4144 :
4145 : const char* module_and_script_tests[] = {
4146 : "function bar() {foo = 42}; ext(bar); ext(foo)",
4147 : "ext(function() {foo++}); ext(foo)",
4148 : "bar = () => --foo; ext(bar); ext(foo)",
4149 : "function* bar() {eval(ext)}; ext(bar); ext(foo)",
4150 5 : };
4151 :
4152 : const char* script_only_tests[] = {
4153 : "",
4154 : "{ function foo() {}; }; ",
4155 : "{ function* foo() {}; }; ",
4156 : "{ async function foo() {}; }; ",
4157 5 : };
4158 :
4159 105 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4160 400 : for (unsigned j = 0; j < arraysize(module_and_script_tests); ++j) {
4161 400 : std::string source(prefixes[i]);
4162 400 : source += module_and_script_tests[j];
4163 : std::vector<unsigned> top;
4164 800 : Input input({true, source, top});
4165 1200 : for (unsigned module = 0; module <= 1; ++module) {
4166 1600 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4167 : ++allow_lazy_parsing) {
4168 1600 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4169 : }
4170 : }
4171 : }
4172 : }
4173 :
4174 100 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4175 400 : for (unsigned j = 0; j < arraysize(script_only_tests); ++j) {
4176 400 : std::string source(prefixes[i]);
4177 400 : source += script_only_tests[j];
4178 : std::vector<unsigned> top;
4179 800 : Input input({true, source, top});
4180 1200 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4181 : ++allow_lazy_parsing) {
4182 800 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4183 : }
4184 : }
4185 : }
4186 5 : }
4187 :
4188 : namespace {
4189 :
4190 10 : i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone,
4191 : i::Handle<i::JSObject> m, const char* name) {
4192 : i::AstValueFactory avf(zone, isolate->ast_string_constants(),
4193 10 : HashSeed(isolate));
4194 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(
4195 10 : i::JSReceiver::GetProperty(isolate, m, name).ToHandleChecked());
4196 : i::DeclarationScope* script_scope =
4197 5 : new (zone) i::DeclarationScope(zone, &avf);
4198 : i::Scope* s = i::Scope::DeserializeScopeChain(
4199 10 : isolate, zone, f->context()->scope_info(), script_scope, &avf,
4200 5 : i::Scope::DeserializationMode::kIncludingVariables);
4201 5 : return s;
4202 : }
4203 :
4204 : } // namespace
4205 :
4206 25880 : TEST(AsmModuleFlag) {
4207 5 : i::FLAG_validate_asm = false;
4208 5 : i::Isolate* isolate = CcTest::i_isolate();
4209 : i::HandleScope scope(isolate);
4210 10 : LocalContext env;
4211 :
4212 : const char* src =
4213 : "function m() {"
4214 : " 'use asm';"
4215 : " function f() { return 0 };"
4216 : " return { f:f };"
4217 : "}"
4218 : "m();";
4219 :
4220 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
4221 : v8::Local<v8::Value> v = CompileRun(src);
4222 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
4223 5 : i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o);
4224 :
4225 : // The asm.js module should be marked as such.
4226 5 : i::Scope* s = DeserializeFunctionScope(isolate, &zone, m, "f");
4227 10 : CHECK(s->IsAsmModule() && s->AsDeclarationScope()->is_asm_module());
4228 5 : }
4229 :
4230 :
4231 25880 : TEST(UseAsmUseCount) {
4232 : i::Isolate* isolate = CcTest::i_isolate();
4233 : i::HandleScope scope(isolate);
4234 10 : LocalContext env;
4235 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4236 5 : global_use_counts = use_counts;
4237 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4238 : CompileRun("\"use asm\";\n"
4239 : "var foo = 1;\n"
4240 : "function bar() { \"use asm\"; var baz = 1; }");
4241 5 : CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
4242 5 : }
4243 :
4244 :
4245 25880 : TEST(StrictModeUseCount) {
4246 : i::Isolate* isolate = CcTest::i_isolate();
4247 : i::HandleScope scope(isolate);
4248 10 : LocalContext env;
4249 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4250 5 : global_use_counts = use_counts;
4251 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4252 : CompileRun(
4253 : "\"use strict\";\n"
4254 : "function bar() { var baz = 1; }"); // strict mode inherits
4255 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4256 5 : CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
4257 5 : }
4258 :
4259 :
4260 25880 : TEST(SloppyModeUseCount) {
4261 : i::Isolate* isolate = CcTest::i_isolate();
4262 : i::HandleScope scope(isolate);
4263 10 : LocalContext env;
4264 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4265 5 : global_use_counts = use_counts;
4266 : // Force eager parsing (preparser doesn't update use counts).
4267 5 : i::FLAG_lazy = false;
4268 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4269 : CompileRun("function bar() { var baz = 1; }");
4270 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4271 5 : CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
4272 5 : }
4273 :
4274 :
4275 25880 : TEST(BothModesUseCount) {
4276 : i::Isolate* isolate = CcTest::i_isolate();
4277 : i::HandleScope scope(isolate);
4278 10 : LocalContext env;
4279 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4280 5 : global_use_counts = use_counts;
4281 : // Force eager parsing (preparser doesn't update use counts).
4282 5 : i::FLAG_lazy = false;
4283 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4284 : CompileRun("function bar() { 'use strict'; var baz = 1; }");
4285 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4286 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4287 5 : }
4288 :
4289 25880 : TEST(LineOrParagraphSeparatorAsLineTerminator) {
4290 : // Tests that both preparsing and parsing accept U+2028 LINE SEPARATOR and
4291 : // U+2029 PARAGRAPH SEPARATOR as LineTerminator symbols outside of string
4292 : // literals.
4293 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
4294 : const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // 1<U+2028>2
4295 : "\x31\xE2\x80\xA9\x32", // 1<U+2029>2
4296 5 : nullptr};
4297 :
4298 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4299 5 : }
4300 :
4301 25880 : TEST(LineOrParagraphSeparatorInStringLiteral) {
4302 : // Tests that both preparsing and parsing don't treat U+2028 LINE SEPARATOR
4303 : // and U+2029 PARAGRAPH SEPARATOR as line terminators within string literals.
4304 : // https://github.com/tc39/proposal-json-superset
4305 : const char* context_data[][2] = {
4306 5 : {"\"", "\""}, {"'", "'"}, {nullptr, nullptr}};
4307 : const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // 1<U+2028>2
4308 : "\x31\xE2\x80\xA9\x32", // 1<U+2029>2
4309 5 : nullptr};
4310 :
4311 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4312 5 : }
4313 :
4314 25880 : TEST(ErrorsArrowFormalParameters) {
4315 : const char* context_data[][2] = {
4316 : { "()", "=>{}" },
4317 : { "()", "=>{};" },
4318 : { "var x = ()", "=>{}" },
4319 : { "var x = ()", "=>{};" },
4320 :
4321 : { "a", "=>{}" },
4322 : { "a", "=>{};" },
4323 : { "var x = a", "=>{}" },
4324 : { "var x = a", "=>{};" },
4325 :
4326 : { "(a)", "=>{}" },
4327 : { "(a)", "=>{};" },
4328 : { "var x = (a)", "=>{}" },
4329 : { "var x = (a)", "=>{};" },
4330 :
4331 : { "(...a)", "=>{}" },
4332 : { "(...a)", "=>{};" },
4333 : { "var x = (...a)", "=>{}" },
4334 : { "var x = (...a)", "=>{};" },
4335 :
4336 : { "(a,b)", "=>{}" },
4337 : { "(a,b)", "=>{};" },
4338 : { "var x = (a,b)", "=>{}" },
4339 : { "var x = (a,b)", "=>{};" },
4340 :
4341 : { "(a,...b)", "=>{}" },
4342 : { "(a,...b)", "=>{};" },
4343 : { "var x = (a,...b)", "=>{}" },
4344 : { "var x = (a,...b)", "=>{};" },
4345 :
4346 : { nullptr, nullptr }
4347 5 : };
4348 : const char* assignment_expression_suffix_data[] = {
4349 : "?c:d=>{}",
4350 : "=c=>{}",
4351 : "()",
4352 : "(c)",
4353 : "[1]",
4354 : "[c]",
4355 : ".c",
4356 : "-c",
4357 : "+c",
4358 : "c++",
4359 : "`c`",
4360 : "`${c}`",
4361 : "`template-head${c}`",
4362 : "`${c}template-tail`",
4363 : "`template-head${c}template-tail`",
4364 : "`${c}template-tail`",
4365 : nullptr
4366 5 : };
4367 :
4368 5 : RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
4369 5 : }
4370 :
4371 :
4372 25880 : TEST(ErrorsArrowFunctions) {
4373 : // Tests that parser and preparser generate the same kind of errors
4374 : // on invalid arrow function syntax.
4375 :
4376 : // clang-format off
4377 : const char* context_data[][2] = {
4378 : {"", ";"},
4379 : {"v = ", ";"},
4380 : {"bar ? (", ") : baz;"},
4381 : {"bar ? baz : (", ");"},
4382 : {"bar[", "];"},
4383 : {"bar, ", ";"},
4384 : {"", ", bar;"},
4385 : {nullptr, nullptr}
4386 5 : };
4387 :
4388 : const char* statement_data[] = {
4389 : "=> 0",
4390 : "=>",
4391 : "() =>",
4392 : "=> {}",
4393 : ") => {}",
4394 : ", => {}",
4395 : "(,) => {}",
4396 : "return => {}",
4397 : "() => {'value': 42}",
4398 :
4399 : // Check that the early return introduced in ParsePrimaryExpression
4400 : // does not accept stray closing parentheses.
4401 : ")",
4402 : ") => 0",
4403 : "foo[()]",
4404 : "()",
4405 :
4406 : // Parameter lists with extra parens should be recognized as errors.
4407 : "(()) => 0",
4408 : "((x)) => 0",
4409 : "((x, y)) => 0",
4410 : "(x, (y)) => 0",
4411 : "((x, y, z)) => 0",
4412 : "(x, (y, z)) => 0",
4413 : "((x, y), z) => 0",
4414 :
4415 : // Arrow function formal parameters are parsed as StrictFormalParameters,
4416 : // which confusingly only implies that there are no duplicates. Words
4417 : // reserved in strict mode, and eval or arguments, are indeed valid in
4418 : // sloppy mode.
4419 : "eval => { 'use strict'; 0 }",
4420 : "arguments => { 'use strict'; 0 }",
4421 : "yield => { 'use strict'; 0 }",
4422 : "interface => { 'use strict'; 0 }",
4423 : "(eval) => { 'use strict'; 0 }",
4424 : "(arguments) => { 'use strict'; 0 }",
4425 : "(yield) => { 'use strict'; 0 }",
4426 : "(interface) => { 'use strict'; 0 }",
4427 : "(eval, bar) => { 'use strict'; 0 }",
4428 : "(bar, eval) => { 'use strict'; 0 }",
4429 : "(bar, arguments) => { 'use strict'; 0 }",
4430 : "(bar, yield) => { 'use strict'; 0 }",
4431 : "(bar, interface) => { 'use strict'; 0 }",
4432 : // TODO(aperez): Detecting duplicates does not work in PreParser.
4433 : // "(bar, bar) => {}",
4434 :
4435 : // The parameter list is parsed as an expression, but only
4436 : // a comma-separated list of identifier is valid.
4437 : "32 => {}",
4438 : "(32) => {}",
4439 : "(a, 32) => {}",
4440 : "if => {}",
4441 : "(if) => {}",
4442 : "(a, if) => {}",
4443 : "a + b => {}",
4444 : "(a + b) => {}",
4445 : "(a + b, c) => {}",
4446 : "(a, b - c) => {}",
4447 : "\"a\" => {}",
4448 : "(\"a\") => {}",
4449 : "(\"a\", b) => {}",
4450 : "(a, \"b\") => {}",
4451 : "-a => {}",
4452 : "(-a) => {}",
4453 : "(-a, b) => {}",
4454 : "(a, -b) => {}",
4455 : "{} => {}",
4456 : "a++ => {}",
4457 : "(a++) => {}",
4458 : "(a++, b) => {}",
4459 : "(a, b++) => {}",
4460 : "[] => {}",
4461 : "(foo ? bar : baz) => {}",
4462 : "(a, foo ? bar : baz) => {}",
4463 : "(foo ? bar : baz, a) => {}",
4464 : "(a.b, c) => {}",
4465 : "(c, a.b) => {}",
4466 : "(a['b'], c) => {}",
4467 : "(c, a['b']) => {}",
4468 : "(...a = b) => b",
4469 :
4470 : // crbug.com/582626
4471 : "(...rest - a) => b",
4472 : "(a, ...b - 10) => b",
4473 :
4474 : nullptr
4475 5 : };
4476 : // clang-format on
4477 :
4478 : // The test is quite slow, so run it with a reduced set of flags.
4479 : static const ParserFlag flags[] = {kAllowLazy};
4480 : RunParserSyncTest(context_data, statement_data, kError, flags,
4481 5 : arraysize(flags));
4482 :
4483 : // In a context where a concise arrow body is parsed with [~In] variant,
4484 : // ensure that an error is reported in both full parser and preparser.
4485 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4486 5 : {nullptr, nullptr}};
4487 5 : const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
4488 : RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
4489 5 : arraysize(flags));
4490 5 : }
4491 :
4492 :
4493 25880 : TEST(NoErrorsArrowFunctions) {
4494 : // Tests that parser and preparser accept valid arrow functions syntax.
4495 : // clang-format off
4496 : const char* context_data[][2] = {
4497 : {"", ";"},
4498 : {"bar ? (", ") : baz;"},
4499 : {"bar ? baz : (", ");"},
4500 : {"bar, ", ";"},
4501 : {"", ", bar;"},
4502 : {nullptr, nullptr}
4503 5 : };
4504 :
4505 : const char* statement_data[] = {
4506 : "() => {}",
4507 : "() => { return 42 }",
4508 : "x => { return x; }",
4509 : "(x) => { return x; }",
4510 : "(x, y) => { return x + y; }",
4511 : "(x, y, z) => { return x + y + z; }",
4512 : "(x, y) => { x.a = y; }",
4513 : "() => 42",
4514 : "x => x",
4515 : "x => x * x",
4516 : "(x) => x",
4517 : "(x) => x * x",
4518 : "(x, y) => x + y",
4519 : "(x, y, z) => x, y, z",
4520 : "(x, y) => x.a = y",
4521 : "() => ({'value': 42})",
4522 : "x => y => x + y",
4523 : "(x, y) => (u, v) => x*u + y*v",
4524 : "(x, y) => z => z * (x + y)",
4525 : "x => (y, z) => z * (x + y)",
4526 :
4527 : // Those are comma-separated expressions, with arrow functions as items.
4528 : // They stress the code for validating arrow function parameter lists.
4529 : "a, b => 0",
4530 : "a, b, (c, d) => 0",
4531 : "(a, b, (c, d) => 0)",
4532 : "(a, b) => 0, (c, d) => 1",
4533 : "(a, b => {}, a => a + 1)",
4534 : "((a, b) => {}, (a => a + 1))",
4535 : "(a, (a, (b, c) => 0))",
4536 :
4537 : // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
4538 : "foo ? bar : baz => {}",
4539 :
4540 : // Arrows with non-simple parameters.
4541 : "({}) => {}",
4542 : "(a, {}) => {}",
4543 : "({}, a) => {}",
4544 : "([]) => {}",
4545 : "(a, []) => {}",
4546 : "([], a) => {}",
4547 : "(a = b) => {}",
4548 : "(a = b, c) => {}",
4549 : "(a, b = c) => {}",
4550 : "({a}) => {}",
4551 : "(x = 9) => {}",
4552 : "(x, y = 9) => {}",
4553 : "(x = 9, y) => {}",
4554 : "(x, y = 9, z) => {}",
4555 : "(x, y = 9, z = 8) => {}",
4556 : "(...a) => {}",
4557 : "(x, ...a) => {}",
4558 : "(x = 9, ...a) => {}",
4559 : "(x, y = 9, ...a) => {}",
4560 : "(x, y = 9, {b}, z = 8, ...a) => {}",
4561 : "({a} = {}) => {}",
4562 : "([x] = []) => {}",
4563 : "({a = 42}) => {}",
4564 : "([x = 0]) => {}",
4565 : nullptr
4566 5 : };
4567 : // clang-format on
4568 :
4569 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4570 :
4571 : static const ParserFlag flags[] = {kAllowLazy};
4572 : // In a context where a concise arrow body is parsed with [~In] variant,
4573 : // ensure that nested expressions can still use the 'in' operator,
4574 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4575 5 : {nullptr, nullptr}};
4576 5 : const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
4577 : RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
4578 5 : arraysize(flags));
4579 5 : }
4580 :
4581 :
4582 25880 : TEST(ArrowFunctionsSloppyParameterNames) {
4583 : const char* strict_context_data[][2] = {{"'use strict'; ", ";"},
4584 : {"'use strict'; bar ? (", ") : baz;"},
4585 : {"'use strict'; bar ? baz : (", ");"},
4586 : {"'use strict'; bar, ", ";"},
4587 : {"'use strict'; ", ", bar;"},
4588 5 : {nullptr, nullptr}};
4589 :
4590 : const char* sloppy_context_data[][2] = {
4591 : {"", ";"}, {"bar ? (", ") : baz;"}, {"bar ? baz : (", ");"},
4592 5 : {"bar, ", ";"}, {"", ", bar;"}, {nullptr, nullptr}};
4593 :
4594 : const char* statement_data[] = {"eval => {}",
4595 : "arguments => {}",
4596 : "yield => {}",
4597 : "interface => {}",
4598 : "(eval) => {}",
4599 : "(arguments) => {}",
4600 : "(yield) => {}",
4601 : "(interface) => {}",
4602 : "(eval, bar) => {}",
4603 : "(bar, eval) => {}",
4604 : "(bar, arguments) => {}",
4605 : "(bar, yield) => {}",
4606 : "(bar, interface) => {}",
4607 : "(interface, eval) => {}",
4608 : "(interface, arguments) => {}",
4609 : "(eval, interface) => {}",
4610 : "(arguments, interface) => {}",
4611 5 : nullptr};
4612 :
4613 5 : RunParserSyncTest(strict_context_data, statement_data, kError);
4614 5 : RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
4615 5 : }
4616 :
4617 :
4618 25880 : TEST(ArrowFunctionsYieldParameterNameInGenerator) {
4619 : const char* sloppy_function_context_data[][2] = {
4620 5 : {"(function f() { (", "); });"}, {nullptr, nullptr}};
4621 :
4622 : const char* strict_function_context_data[][2] = {
4623 5 : {"(function f() {'use strict'; (", "); });"}, {nullptr, nullptr}};
4624 :
4625 : const char* generator_context_data[][2] = {
4626 : {"(function *g() {'use strict'; (", "); });"},
4627 : {"(function *g() { (", "); });"},
4628 5 : {nullptr, nullptr}};
4629 :
4630 : const char* arrow_data[] = {
4631 : "yield => {}", "(yield) => {}", "(a, yield) => {}",
4632 : "(yield, a) => {}", "(yield, ...a) => {}", "(a, ...yield) => {}",
4633 5 : "({yield}) => {}", "([yield]) => {}", nullptr};
4634 :
4635 5 : RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
4636 5 : RunParserSyncTest(strict_function_context_data, arrow_data, kError);
4637 5 : RunParserSyncTest(generator_context_data, arrow_data, kError);
4638 5 : }
4639 :
4640 :
4641 25880 : TEST(SuperNoErrors) {
4642 : // Tests that parser and preparser accept 'super' keyword in right places.
4643 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4644 : {"class C { m() { k = ", "; } }"},
4645 : {"class C { m() { foo(", "); } }"},
4646 : {"class C { m() { () => ", "; } }"},
4647 5 : {nullptr, nullptr}};
4648 :
4649 : const char* statement_data[] = {"super.x", "super[27]",
4650 : "new super.x", "new super.x()",
4651 : "new super[27]", "new super[27]()",
4652 : "z.super", // Ok, property lookup.
4653 5 : nullptr};
4654 :
4655 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4656 5 : }
4657 :
4658 :
4659 25880 : TEST(SuperErrors) {
4660 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4661 : {"class C { m() { k = ", "; } }"},
4662 : {"class C { m() { foo(", "); } }"},
4663 : {"class C { m() { () => ", "; } }"},
4664 5 : {nullptr, nullptr}};
4665 :
4666 : const char* expression_data[] = {"super",
4667 : "super = x",
4668 : "y = super",
4669 : "f(super)",
4670 : "new super",
4671 : "new super()",
4672 : "new super(12, 45)",
4673 : "new new super",
4674 : "new new super()",
4675 : "new new super()()",
4676 5 : nullptr};
4677 :
4678 5 : RunParserSyncTest(context_data, expression_data, kError);
4679 5 : }
4680 :
4681 25880 : TEST(ImportExpressionSuccess) {
4682 : // clang-format off
4683 : const char* context_data[][2] = {
4684 : {"", ""},
4685 : {nullptr, nullptr}
4686 5 : };
4687 :
4688 : const char* data[] = {
4689 : "import(1)",
4690 : "import(y=x)",
4691 : "f(...[import(y=x)])",
4692 : "x = {[import(y=x)]: 1}",
4693 : "var {[import(y=x)]: x} = {}",
4694 : "({[import(y=x)]: x} = {})",
4695 : "async () => { await import(x) }",
4696 : "() => { import(x) }",
4697 : "(import(y=x))",
4698 : "{import(y=x)}",
4699 : "import(import(x))",
4700 : "x = import(x)",
4701 : "var x = import(x)",
4702 : "let x = import(x)",
4703 : "for(x of import(x)) {}",
4704 : "import(x).then()",
4705 : nullptr
4706 5 : };
4707 :
4708 : // clang-format on
4709 :
4710 : // We ignore test error messages because the error message from the
4711 : // parser/preparser is different for the same data depending on the
4712 : // context.
4713 : // For example, a top level "import(" is parsed as an
4714 : // import declaration. The parser parses the import token correctly
4715 : // and then shows an "Unexpected token (" error message. The
4716 : // preparser does not understand the import keyword (this test is
4717 : // run without kAllowHarmonyDynamicImport flag), so this results in
4718 : // an "Unexpected token import" error.
4719 5 : RunParserSyncTest(context_data, data, kError);
4720 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4721 : nullptr, 0, true, true);
4722 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4723 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4724 5 : arraysize(flags));
4725 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4726 : arraysize(flags));
4727 5 : }
4728 :
4729 25880 : TEST(ImportExpressionErrors) {
4730 : {
4731 : // clang-format off
4732 : const char* context_data[][2] = {
4733 : {"", ""},
4734 : {"var ", ""},
4735 : {"let ", ""},
4736 : {"new ", ""},
4737 : {nullptr, nullptr}
4738 5 : };
4739 :
4740 : const char* data[] = {
4741 : "import(",
4742 : "import)",
4743 : "import()",
4744 : "import('x",
4745 : "import('x']",
4746 : "import['x')",
4747 : "import = x",
4748 : "import[",
4749 : "import[]",
4750 : "import]",
4751 : "import[x]",
4752 : "import{",
4753 : "import{x",
4754 : "import{x}",
4755 : "import(x, y)",
4756 : "import(...y)",
4757 : "import(x,)",
4758 : "import(,)",
4759 : "import(,y)",
4760 : "import(;)",
4761 : "[import]",
4762 : "{import}",
4763 : "import+",
4764 : "import = 1",
4765 : "import.wat",
4766 : "new import(x)",
4767 : nullptr
4768 5 : };
4769 :
4770 : // clang-format on
4771 5 : RunParserSyncTest(context_data, data, kError);
4772 : // We ignore the error messages for the reason explained in the
4773 : // ImportExpressionSuccess test.
4774 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4775 : nullptr, 0, true, true);
4776 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4777 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4778 5 : arraysize(flags));
4779 :
4780 : // We ignore test error messages because the error message from
4781 : // the parser/preparser is different for the same data depending
4782 : // on the context. For example, a top level "import{" is parsed
4783 : // as an import declaration. The parser parses the import token
4784 : // correctly and then shows an "Unexpected end of input" error
4785 : // message because of the '{'. The preparser shows an "Unexpected
4786 : // token {" because it's not a valid token in a CallExpression.
4787 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4788 : arraysize(flags), nullptr, 0, true, true);
4789 : }
4790 :
4791 : {
4792 : // clang-format off
4793 : const char* context_data[][2] = {
4794 : {"var ", ""},
4795 : {"let ", ""},
4796 : {nullptr, nullptr}
4797 5 : };
4798 :
4799 : const char* data[] = {
4800 : "import('x')",
4801 : nullptr
4802 5 : };
4803 :
4804 : // clang-format on
4805 5 : RunParserSyncTest(context_data, data, kError);
4806 : RunModuleParserSyncTest(context_data, data, kError);
4807 :
4808 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4809 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4810 5 : arraysize(flags));
4811 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4812 : arraysize(flags));
4813 : }
4814 :
4815 : // Import statements as arrow function params and destructuring targets.
4816 : {
4817 : // clang-format off
4818 : const char* context_data[][2] = {
4819 : {"(", ") => {}"},
4820 : {"(a, ", ") => {}"},
4821 : {"(1, ", ") => {}"},
4822 : {"let f = ", " => {}"},
4823 : {"[", "] = [1];"},
4824 : {"{", "} = {'a': 1};"},
4825 : {nullptr, nullptr}
4826 5 : };
4827 :
4828 : const char* data[] = {
4829 : "import(foo)",
4830 : "import(1)",
4831 : "import(y=x)",
4832 : "import(import(x))",
4833 : "import(x).then()",
4834 : nullptr
4835 5 : };
4836 :
4837 : // clang-format on
4838 5 : RunParserSyncTest(context_data, data, kError);
4839 : RunModuleParserSyncTest(context_data, data, kError);
4840 :
4841 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4842 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4843 5 : arraysize(flags));
4844 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4845 : arraysize(flags));
4846 : }
4847 5 : }
4848 :
4849 25880 : TEST(SuperCall) {
4850 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
4851 :
4852 : const char* success_data[] = {
4853 : "class C extends B { constructor() { super(); } }",
4854 5 : "class C extends B { constructor() { () => super(); } }", nullptr};
4855 :
4856 5 : RunParserSyncTest(context_data, success_data, kSuccess);
4857 :
4858 : const char* error_data[] = {"class C { constructor() { super(); } }",
4859 : "class C { method() { super(); } }",
4860 : "class C { method() { () => super(); } }",
4861 : "class C { *method() { super(); } }",
4862 : "class C { get x() { super(); } }",
4863 : "class C { set x(_) { super(); } }",
4864 : "({ method() { super(); } })",
4865 : "({ *method() { super(); } })",
4866 : "({ get x() { super(); } })",
4867 : "({ set x(_) { super(); } })",
4868 : "({ f: function() { super(); } })",
4869 : "(function() { super(); })",
4870 : "var f = function() { super(); }",
4871 : "({ f: function*() { super(); } })",
4872 : "(function*() { super(); })",
4873 : "var f = function*() { super(); }",
4874 5 : nullptr};
4875 :
4876 5 : RunParserSyncTest(context_data, error_data, kError);
4877 5 : }
4878 :
4879 :
4880 25880 : TEST(SuperNewNoErrors) {
4881 : const char* context_data[][2] = {{"class C { constructor() { ", " } }"},
4882 : {"class C { *method() { ", " } }"},
4883 : {"class C { get x() { ", " } }"},
4884 : {"class C { set x(_) { ", " } }"},
4885 : {"({ method() { ", " } })"},
4886 : {"({ *method() { ", " } })"},
4887 : {"({ get x() { ", " } })"},
4888 : {"({ set x(_) { ", " } })"},
4889 5 : {nullptr, nullptr}};
4890 :
4891 : const char* expression_data[] = {"new super.x;", "new super.x();",
4892 : "() => new super.x;", "() => new super.x();",
4893 5 : nullptr};
4894 :
4895 5 : RunParserSyncTest(context_data, expression_data, kSuccess);
4896 5 : }
4897 :
4898 :
4899 25880 : TEST(SuperNewErrors) {
4900 : const char* context_data[][2] = {{"class C { method() { ", " } }"},
4901 : {"class C { *method() { ", " } }"},
4902 : {"class C { get x() { ", " } }"},
4903 : {"class C { set x(_) { ", " } }"},
4904 : {"({ method() { ", " } })"},
4905 : {"({ *method() { ", " } })"},
4906 : {"({ get x() { ", " } })"},
4907 : {"({ set x(_) { ", " } })"},
4908 : {"({ f: function() { ", " } })"},
4909 : {"(function() { ", " })"},
4910 : {"var f = function() { ", " }"},
4911 : {"({ f: function*() { ", " } })"},
4912 : {"(function*() { ", " })"},
4913 : {"var f = function*() { ", " }"},
4914 5 : {nullptr, nullptr}};
4915 :
4916 : const char* statement_data[] = {"new super;", "new super();",
4917 : "() => new super;", "() => new super();",
4918 5 : nullptr};
4919 :
4920 5 : RunParserSyncTest(context_data, statement_data, kError);
4921 5 : }
4922 :
4923 :
4924 25880 : TEST(SuperErrorsNonMethods) {
4925 : // super is only allowed in methods, accessors and constructors.
4926 : const char* context_data[][2] = {{"", ";"},
4927 : {"k = ", ";"},
4928 : {"foo(", ");"},
4929 : {"if (", ") {}"},
4930 : {"if (true) {", "}"},
4931 : {"if (false) {} else {", "}"},
4932 : {"while (true) {", "}"},
4933 : {"function f() {", "}"},
4934 : {"class C extends (", ") {}"},
4935 : {"class C { m() { function f() {", "} } }"},
4936 : {"({ m() { function f() {", "} } })"},
4937 5 : {nullptr, nullptr}};
4938 :
4939 : const char* statement_data[] = {
4940 : "super", "super = x", "y = super", "f(super)",
4941 : "super.x", "super[27]", "super.x()", "super[27]()",
4942 : "super()", "new super.x", "new super.x()", "new super[27]",
4943 5 : "new super[27]()", nullptr};
4944 :
4945 5 : RunParserSyncTest(context_data, statement_data, kError);
4946 5 : }
4947 :
4948 :
4949 25880 : TEST(NoErrorsMethodDefinition) {
4950 : const char* context_data[][2] = {{"({", "});"},
4951 : {"'use strict'; ({", "});"},
4952 : {"({*", "});"},
4953 : {"'use strict'; ({*", "});"},
4954 5 : {nullptr, nullptr}};
4955 :
4956 : const char* object_literal_body_data[] = {
4957 : "m() {}", "m(x) { return x; }", "m(x, y) {}, n() {}",
4958 5 : "set(x, y) {}", "get(x, y) {}", nullptr};
4959 :
4960 5 : RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
4961 5 : }
4962 :
4963 :
4964 25880 : TEST(MethodDefinitionNames) {
4965 : const char* context_data[][2] = {{"({", "(x, y) {}});"},
4966 : {"'use strict'; ({", "(x, y) {}});"},
4967 : {"({*", "(x, y) {}});"},
4968 : {"'use strict'; ({*", "(x, y) {}});"},
4969 5 : {nullptr, nullptr}};
4970 :
4971 : const char* name_data[] = {
4972 : "m", "'m'", "\"m\"", "\"m n\"", "true", "false", "null", "0", "1.2",
4973 : "1e1", "1E1", "1e+1", "1e-1",
4974 :
4975 : // Keywords
4976 : "async", "await", "break", "case", "catch", "class", "const", "continue",
4977 : "debugger", "default", "delete", "do", "else", "enum", "export",
4978 : "extends", "finally", "for", "function", "if", "implements", "import",
4979 : "in", "instanceof", "interface", "let", "new", "package", "private",
4980 : "protected", "public", "return", "static", "super", "switch", "this",
4981 : "throw", "try", "typeof", "var", "void", "while", "with", "yield",
4982 5 : nullptr};
4983 :
4984 5 : RunParserSyncTest(context_data, name_data, kSuccess);
4985 5 : }
4986 :
4987 :
4988 25880 : TEST(MethodDefinitionStrictFormalParamereters) {
4989 : const char* context_data[][2] = {{"({method(", "){}});"},
4990 : {"'use strict'; ({method(", "){}});"},
4991 : {"({*method(", "){}});"},
4992 : {"'use strict'; ({*method(", "){}});"},
4993 5 : {nullptr, nullptr}};
4994 :
4995 5 : const char* params_data[] = {"x, x", "x, y, x", "var", "const", nullptr};
4996 :
4997 5 : RunParserSyncTest(context_data, params_data, kError);
4998 5 : }
4999 :
5000 :
5001 25880 : TEST(MethodDefinitionEvalArguments) {
5002 : const char* strict_context_data[][2] = {
5003 : {"'use strict'; ({method(", "){}});"},
5004 : {"'use strict'; ({*method(", "){}});"},
5005 5 : {nullptr, nullptr}};
5006 : const char* sloppy_context_data[][2] = {
5007 5 : {"({method(", "){}});"}, {"({*method(", "){}});"}, {nullptr, nullptr}};
5008 :
5009 5 : const char* data[] = {"eval", "arguments", nullptr};
5010 :
5011 : // Fail in strict mode
5012 5 : RunParserSyncTest(strict_context_data, data, kError);
5013 :
5014 : // OK in sloppy mode
5015 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
5016 5 : }
5017 :
5018 :
5019 25880 : TEST(MethodDefinitionDuplicateEvalArguments) {
5020 : const char* context_data[][2] = {{"'use strict'; ({method(", "){}});"},
5021 : {"'use strict'; ({*method(", "){}});"},
5022 : {"({method(", "){}});"},
5023 : {"({*method(", "){}});"},
5024 5 : {nullptr, nullptr}};
5025 :
5026 : const char* data[] = {"eval, eval", "eval, a, eval", "arguments, arguments",
5027 5 : "arguments, a, arguments", nullptr};
5028 :
5029 : // In strict mode, the error is using "eval" or "arguments" as parameter names
5030 : // In sloppy mode, the error is that eval / arguments are duplicated
5031 5 : RunParserSyncTest(context_data, data, kError);
5032 5 : }
5033 :
5034 :
5035 25880 : TEST(MethodDefinitionDuplicateProperty) {
5036 : const char* context_data[][2] = {{"'use strict'; ({", "});"},
5037 5 : {nullptr, nullptr}};
5038 :
5039 : const char* params_data[] = {"x: 1, x() {}",
5040 : "x() {}, x: 1",
5041 : "x() {}, get x() {}",
5042 : "x() {}, set x(_) {}",
5043 : "x() {}, x() {}",
5044 : "x() {}, y() {}, x() {}",
5045 : "x() {}, \"x\"() {}",
5046 : "x() {}, 'x'() {}",
5047 : "0() {}, '0'() {}",
5048 : "1.0() {}, 1: 1",
5049 :
5050 : "x: 1, *x() {}",
5051 : "*x() {}, x: 1",
5052 : "*x() {}, get x() {}",
5053 : "*x() {}, set x(_) {}",
5054 : "*x() {}, *x() {}",
5055 : "*x() {}, y() {}, *x() {}",
5056 : "*x() {}, *\"x\"() {}",
5057 : "*x() {}, *'x'() {}",
5058 : "*0() {}, *'0'() {}",
5059 : "*1.0() {}, 1: 1",
5060 :
5061 5 : nullptr};
5062 :
5063 5 : RunParserSyncTest(context_data, params_data, kSuccess);
5064 5 : }
5065 :
5066 :
5067 25880 : TEST(ClassExpressionNoErrors) {
5068 : const char* context_data[][2] = {
5069 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
5070 : const char* class_data[] = {"class {}",
5071 : "class name {}",
5072 : "class extends F {}",
5073 : "class name extends F {}",
5074 : "class extends (F, G) {}",
5075 : "class name extends (F, G) {}",
5076 : "class extends class {} {}",
5077 : "class name extends class {} {}",
5078 : "class extends class base {} {}",
5079 : "class name extends class base {} {}",
5080 5 : nullptr};
5081 :
5082 5 : RunParserSyncTest(context_data, class_data, kSuccess);
5083 5 : }
5084 :
5085 :
5086 25880 : TEST(ClassDeclarationNoErrors) {
5087 : const char* context_data[][2] = {{"'use strict'; ", ""},
5088 : {"'use strict'; {", "}"},
5089 : {"'use strict'; if (true) {", "}"},
5090 5 : {nullptr, nullptr}};
5091 : const char* statement_data[] = {"class name {}",
5092 : "class name extends F {}",
5093 : "class name extends (F, G) {}",
5094 : "class name extends class {} {}",
5095 : "class name extends class base {} {}",
5096 5 : nullptr};
5097 :
5098 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
5099 5 : }
5100 :
5101 :
5102 25880 : TEST(ClassBodyNoErrors) {
5103 : // clang-format off
5104 : // Tests that parser and preparser accept valid class syntax.
5105 : const char* context_data[][2] = {{"(class {", "});"},
5106 : {"(class extends Base {", "});"},
5107 : {"class C {", "}"},
5108 : {"class C extends Base {", "}"},
5109 5 : {nullptr, nullptr}};
5110 : const char* class_body_data[] = {
5111 : ";",
5112 : ";;",
5113 : "m() {}",
5114 : "m() {};",
5115 : "; m() {}",
5116 : "m() {}; n(x) {}",
5117 : "get x() {}",
5118 : "set x(v) {}",
5119 : "get() {}",
5120 : "set() {}",
5121 : "*g() {}",
5122 : "*g() {};",
5123 : "; *g() {}",
5124 : "*g() {}; *h(x) {}",
5125 : "async *x(){}",
5126 : "static() {}",
5127 : "get static() {}",
5128 : "set static(v) {}",
5129 : "static m() {}",
5130 : "static get x() {}",
5131 : "static set x(v) {}",
5132 : "static get() {}",
5133 : "static set() {}",
5134 : "static static() {}",
5135 : "static get static() {}",
5136 : "static set static(v) {}",
5137 : "*static() {}",
5138 : "static *static() {}",
5139 : "*get() {}",
5140 : "*set() {}",
5141 : "static *g() {}",
5142 : "async(){}",
5143 : "*async(){}",
5144 : "static async(){}",
5145 : "static *async(){}",
5146 : "static async *x(){}",
5147 :
5148 : // Escaped 'static' should be allowed anywhere
5149 : // static-as-PropertyName is.
5150 : "st\\u0061tic() {}",
5151 : "get st\\u0061tic() {}",
5152 : "set st\\u0061tic(v) {}",
5153 : "static st\\u0061tic() {}",
5154 : "static get st\\u0061tic() {}",
5155 : "static set st\\u0061tic(v) {}",
5156 : "*st\\u0061tic() {}",
5157 : "static *st\\u0061tic() {}",
5158 :
5159 : "static async x(){}",
5160 : "static async(){}",
5161 : "static *async(){}",
5162 : "async x(){}",
5163 : "async 0(){}",
5164 : "async get(){}",
5165 : "async set(){}",
5166 : "async static(){}",
5167 : "async async(){}",
5168 : "async(){}",
5169 : "*async(){}",
5170 5 : nullptr};
5171 : // clang-format on
5172 :
5173 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
5174 5 : }
5175 :
5176 :
5177 25880 : TEST(ClassPropertyNameNoErrors) {
5178 : const char* context_data[][2] = {{"(class {", "() {}});"},
5179 : {"(class { get ", "() {}});"},
5180 : {"(class { set ", "(v) {}});"},
5181 : {"(class { static ", "() {}});"},
5182 : {"(class { static get ", "() {}});"},
5183 : {"(class { static set ", "(v) {}});"},
5184 : {"(class { *", "() {}});"},
5185 : {"(class { static *", "() {}});"},
5186 : {"class C {", "() {}}"},
5187 : {"class C { get ", "() {}}"},
5188 : {"class C { set ", "(v) {}}"},
5189 : {"class C { static ", "() {}}"},
5190 : {"class C { static get ", "() {}}"},
5191 : {"class C { static set ", "(v) {}}"},
5192 : {"class C { *", "() {}}"},
5193 : {"class C { static *", "() {}}"},
5194 5 : {nullptr, nullptr}};
5195 : const char* name_data[] = {
5196 : "42", "42.5", "42e2", "42e+2", "42e-2", "null",
5197 : "false", "true", "'str'", "\"str\"", "static", "get",
5198 : "set", "var", "const", "let", "this", "class",
5199 : "function", "yield", "if", "else", "for", "while",
5200 5 : "do", "try", "catch", "finally", nullptr};
5201 :
5202 5 : RunParserSyncTest(context_data, name_data, kSuccess);
5203 5 : }
5204 :
5205 25880 : TEST(StaticClassFieldsNoErrors) {
5206 : // clang-format off
5207 : // Tests proposed class fields syntax.
5208 : const char* context_data[][2] = {{"(class {", "});"},
5209 : {"(class extends Base {", "});"},
5210 : {"class C {", "}"},
5211 : {"class C extends Base {", "}"},
5212 5 : {nullptr, nullptr}};
5213 : const char* class_body_data[] = {
5214 : // Basic syntax
5215 : "static a = 0;",
5216 : "static a = 0; b",
5217 : "static a = 0; b(){}",
5218 : "static a = 0; *b(){}",
5219 : "static a = 0; ['b'](){}",
5220 : "static a;",
5221 : "static a; b;",
5222 : "static a; b(){}",
5223 : "static a; *b(){}",
5224 : "static a; ['b'](){}",
5225 : "static ['a'] = 0;",
5226 : "static ['a'] = 0; b",
5227 : "static ['a'] = 0; b(){}",
5228 : "static ['a'] = 0; *b(){}",
5229 : "static ['a'] = 0; ['b'](){}",
5230 : "static ['a'];",
5231 : "static ['a']; b;",
5232 : "static ['a']; b(){}",
5233 : "static ['a']; *b(){}",
5234 : "static ['a']; ['b'](){}",
5235 :
5236 : "static 0 = 0;",
5237 : "static 0;",
5238 : "static 'a' = 0;",
5239 : "static 'a';",
5240 :
5241 : "static c = [c] = c",
5242 :
5243 : // ASI
5244 : "static a = 0\n",
5245 : "static a = 0\n b",
5246 : "static a = 0\n b(){}",
5247 : "static a\n",
5248 : "static a\n b\n",
5249 : "static a\n b(){}",
5250 : "static a\n *b(){}",
5251 : "static a\n ['b'](){}",
5252 : "static ['a'] = 0\n",
5253 : "static ['a'] = 0\n b",
5254 : "static ['a'] = 0\n b(){}",
5255 : "static ['a']\n",
5256 : "static ['a']\n b\n",
5257 : "static ['a']\n b(){}",
5258 : "static ['a']\n *b(){}",
5259 : "static ['a']\n ['b'](){}",
5260 :
5261 : "static a = function t() { arguments; }",
5262 : "static a = () => function t() { arguments; }",
5263 :
5264 : // ASI edge cases
5265 : "static a\n get",
5266 : "static get\n *a(){}",
5267 : "static a\n static",
5268 :
5269 : // Misc edge cases
5270 : "static yield",
5271 : "static yield = 0",
5272 : "static yield\n a",
5273 : "static async;",
5274 : "static async = 0;",
5275 : "static async",
5276 : "static async = 0",
5277 : "static async\n a(){}", // a field named async, and a method named a.
5278 : "static async\n a",
5279 : "static await;",
5280 : "static await = 0;",
5281 : "static await\n a",
5282 : nullptr
5283 5 : };
5284 : // clang-format on
5285 :
5286 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5287 : kAllowHarmonyStaticFields};
5288 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5289 5 : always_flags, arraysize(always_flags));
5290 :
5291 : // Without the static flag, all of these are errors
5292 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5293 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5294 5 : no_static_flags, arraysize(no_static_flags));
5295 5 : }
5296 :
5297 25880 : TEST(ClassFieldsNoErrors) {
5298 : // clang-format off
5299 : // Tests proposed class fields syntax.
5300 : const char* context_data[][2] = {{"(class {", "});"},
5301 : {"(class extends Base {", "});"},
5302 : {"class C {", "}"},
5303 : {"class C extends Base {", "}"},
5304 5 : {nullptr, nullptr}};
5305 : const char* class_body_data[] = {
5306 : // Basic syntax
5307 : "a = 0;",
5308 : "a = 0; b",
5309 : "a = 0; b(){}",
5310 : "a = 0; *b(){}",
5311 : "a = 0; ['b'](){}",
5312 : "a;",
5313 : "a; b;",
5314 : "a; b(){}",
5315 : "a; *b(){}",
5316 : "a; ['b'](){}",
5317 : "['a'] = 0;",
5318 : "['a'] = 0; b",
5319 : "['a'] = 0; b(){}",
5320 : "['a'] = 0; *b(){}",
5321 : "['a'] = 0; ['b'](){}",
5322 : "['a'];",
5323 : "['a']; b;",
5324 : "['a']; b(){}",
5325 : "['a']; *b(){}",
5326 : "['a']; ['b'](){}",
5327 :
5328 : "0 = 0;",
5329 : "0;",
5330 : "'a' = 0;",
5331 : "'a';",
5332 :
5333 : "c = [c] = c",
5334 :
5335 : // ASI
5336 : "a = 0\n",
5337 : "a = 0\n b",
5338 : "a = 0\n b(){}",
5339 : "a\n",
5340 : "a\n b\n",
5341 : "a\n b(){}",
5342 : "a\n *b(){}",
5343 : "a\n ['b'](){}",
5344 : "['a'] = 0\n",
5345 : "['a'] = 0\n b",
5346 : "['a'] = 0\n b(){}",
5347 : "['a']\n",
5348 : "['a']\n b\n",
5349 : "['a']\n b(){}",
5350 : "['a']\n *b(){}",
5351 : "['a']\n ['b'](){}",
5352 :
5353 : // ASI edge cases
5354 : "a\n get",
5355 : "get\n *a(){}",
5356 : "a\n static",
5357 :
5358 : "a = function t() { arguments; }",
5359 : "a = () => function() { arguments; }",
5360 :
5361 : // Misc edge cases
5362 : "yield",
5363 : "yield = 0",
5364 : "yield\n a",
5365 : "async;",
5366 : "async = 0;",
5367 : "async",
5368 : "async = 0",
5369 : "async\n a(){}", // a field named async, and a method named a.
5370 : "async\n a",
5371 : "await;",
5372 : "await = 0;",
5373 : "await\n a",
5374 : nullptr
5375 5 : };
5376 : // clang-format on
5377 :
5378 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5379 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5380 5 : always_flags, arraysize(always_flags));
5381 :
5382 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5383 : kAllowHarmonyStaticFields};
5384 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5385 5 : static_flags, arraysize(static_flags));
5386 5 : }
5387 :
5388 25880 : TEST(PrivateMethodsNoErrors) {
5389 : // clang-format off
5390 : // Tests proposed class methods syntax.
5391 : const char* context_data[][2] = {{"(class {", "});"},
5392 : {"(class extends Base {", "});"},
5393 : {"class C {", "}"},
5394 : {"class C extends Base {", "}"},
5395 5 : {nullptr, nullptr}};
5396 : const char* class_body_data[] = {
5397 : // Basic syntax
5398 : "#a() { }",
5399 : "get #a() { }",
5400 : "set #a(foo) { }",
5401 : "*#a() { }",
5402 : "async #a() { }",
5403 : "async *#a() { }",
5404 :
5405 : "#a() { } #b() {}",
5406 : "get #a() { } set #a(foo) {}",
5407 : "get #a() { } get #b() {} set #a(foo) {}",
5408 : "get #a() { } get #b() {} set #a(foo) {} set #b(foo) {}",
5409 : "set #a(foo) { } set #b(foo) {}",
5410 : "get #a() { } get #b() {}",
5411 :
5412 : "#a() { } static a() {}",
5413 : "#a() { } a() {}",
5414 : "#a() { } a() {} static a() {}",
5415 : "get #a() { } get a() {} static get a() {}",
5416 : "set #a(foo) { } set a(foo) {} static set a(foo) {}",
5417 :
5418 : "#a() { } get #b() {}",
5419 : "#a() { } async #b() {}",
5420 : "#a() { } async *#b() {}",
5421 :
5422 : // With arguments
5423 : "#a(...args) { }",
5424 : "#a(a = 1) { }",
5425 : "get #a() { }",
5426 : "set #a(a = (...args) => {}) { }",
5427 :
5428 : // Misc edge cases
5429 : "#get() {}",
5430 : "#set() {}",
5431 : "#yield() {}",
5432 : "#await() {}",
5433 : "#async() {}",
5434 : "#static() {}",
5435 : "#arguments() {}",
5436 : "get #yield() {}",
5437 : "get #await() {}",
5438 : "get #async() {}",
5439 : "get #get() {}",
5440 : "get #static() {}",
5441 : "get #arguments() {}",
5442 : "set #yield(test) {}",
5443 : "set #async(test) {}",
5444 : "set #await(test) {}",
5445 : "set #set(test) {}",
5446 : "set #static(test) {}",
5447 : "set #arguments(test) {}",
5448 : "async #yield() {}",
5449 : "async #async() {}",
5450 : "async #await() {}",
5451 : "async #get() {}",
5452 : "async #set() {}",
5453 : "async #static() {}",
5454 : "async #arguments() {}",
5455 : "*#async() {}",
5456 : "*#await() {}",
5457 : "*#yield() {}",
5458 : "*#get() {}",
5459 : "*#set() {}",
5460 : "*#static() {}",
5461 : "*#arguments() {}",
5462 : "async *#yield() {}",
5463 : "async *#async() {}",
5464 : "async *#await() {}",
5465 : "async *#get() {}",
5466 : "async *#set() {}",
5467 : "async *#static() {}",
5468 : "async *#arguments() {}",
5469 : nullptr
5470 5 : };
5471 : // clang-format on
5472 :
5473 5 : RunParserSyncTest(context_data, class_body_data, kError);
5474 :
5475 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5476 : kAllowHarmonyPrivateMethods};
5477 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5478 5 : private_methods, arraysize(private_methods));
5479 5 : }
5480 :
5481 25880 : TEST(PrivateMethodsAndFieldsNoErrors) {
5482 : // clang-format off
5483 : // Tests proposed class methods syntax in combination with fields
5484 : const char* context_data[][2] = {{"(class {", "});"},
5485 : {"(class extends Base {", "});"},
5486 : {"class C {", "}"},
5487 : {"class C extends Base {", "}"},
5488 5 : {nullptr, nullptr}};
5489 : const char* class_body_data[] = {
5490 : // Basic syntax
5491 : "#b;#a() { }",
5492 : "#b;get #a() { }",
5493 : "#b;set #a(foo) { }",
5494 : "#b;*#a() { }",
5495 : "#b;async #a() { }",
5496 : "#b;async *#a() { }",
5497 : "#b = 1;#a() { }",
5498 : "#b = 1;get #a() { }",
5499 : "#b = 1;set #a(foo) { }",
5500 : "#b = 1;*#a() { }",
5501 : "#b = 1;async #a() { }",
5502 : "#b = 1;async *#a() { }",
5503 :
5504 : // With public fields
5505 : "a;#a() { }",
5506 : "a;get #a() { }",
5507 : "a;set #a(foo) { }",
5508 : "a;*#a() { }",
5509 : "a;async #a() { }",
5510 : "a;async *#a() { }",
5511 : "a = 1;#a() { }",
5512 : "a = 1;get #a() { }",
5513 : "a = 1;set #a(foo) { }",
5514 : "a = 1;*#a() { }",
5515 : "a = 1;async #a() { }",
5516 : "a = 1;async *#a() { }",
5517 :
5518 : // ASI
5519 : "#a = 0\n #b(){}",
5520 : "#a\n *#b(){}",
5521 : "#a = 0\n get #b(){}",
5522 : "#a\n *#b(){}",
5523 :
5524 : "b = 0\n #b(){}",
5525 : "b\n *#b(){}",
5526 : "b = 0\n get #b(){}",
5527 : "b\n *#b(){}",
5528 : nullptr
5529 5 : };
5530 : // clang-format on
5531 :
5532 5 : RunParserSyncTest(context_data, class_body_data, kError);
5533 :
5534 : static const ParserFlag private_methods_and_fields[] = {
5535 : kAllowHarmonyPrivateFields, kAllowHarmonyPublicFields,
5536 : kAllowHarmonyPrivateMethods};
5537 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5538 : private_methods_and_fields,
5539 5 : arraysize(private_methods_and_fields));
5540 5 : }
5541 :
5542 25880 : TEST(PrivateMethodsErrors) {
5543 : // clang-format off
5544 : // Tests proposed class methods syntax in combination with fields
5545 : const char* context_data[][2] = {{"(class {", "});"},
5546 : {"(class extends Base {", "});"},
5547 : {"class C {", "}"},
5548 : {"class C extends Base {", "}"},
5549 5 : {nullptr, nullptr}};
5550 : const char* class_body_data[] = {
5551 : "#a() : 0",
5552 : "#a() =",
5553 : "#a() => {}",
5554 : "#a => {}",
5555 : "*#a() = 0",
5556 : "*#a() => 0",
5557 : "*#a() => {}",
5558 : "get #a()[]",
5559 : "yield #a()[]",
5560 : "yield #a => {}",
5561 : "async #a() = 0",
5562 : "async #a => {}",
5563 : "#a(arguments) {}",
5564 : "set #a(arguments) {}",
5565 :
5566 : "#['a']() { }",
5567 : "get #['a']() { }",
5568 : "set #['a'](foo) { }",
5569 : "*#['a']() { }",
5570 : "async #['a']() { }",
5571 : "async *#['a]() { }",
5572 :
5573 : // TODO(joyee): check duplicate accessors
5574 :
5575 : "#a\n#",
5576 : "#a() c",
5577 : "#a() #",
5578 : "#a(arg) c",
5579 : "#a(arg) #",
5580 : "#a(arg) #c",
5581 : "#a#",
5582 : "#a#b",
5583 : "#a#b(){}",
5584 : "#[test](){}",
5585 :
5586 : "async *#constructor() {}",
5587 : "*#constructor() {}",
5588 : "async #constructor() {}",
5589 : "set #constructor(test) {}",
5590 : "#constructor() {}",
5591 : "get #constructor() {}",
5592 : nullptr
5593 5 : };
5594 : // clang-format on
5595 :
5596 5 : RunParserSyncTest(context_data, class_body_data, kError);
5597 :
5598 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5599 : kAllowHarmonyPrivateMethods};
5600 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5601 5 : private_methods, arraysize(private_methods));
5602 5 : }
5603 :
5604 : // Test that private members do not parse outside class bodies
5605 25880 : TEST(PrivateMembersInNonClassNoErrors) {
5606 : // clang-format off
5607 : const char* context_data[][2] = {{"", ""},
5608 : {"({", "})"},
5609 : {"'use strict'; ({", "});"},
5610 : {"function() {", "}"},
5611 : {"() => {", "}"},
5612 : {"class C { test() {", "} }"},
5613 : {"const {", "} = {}"},
5614 : {"({", "} = {})"},
5615 5 : {nullptr, nullptr}};
5616 : const char* class_body_data[] = {
5617 : "#a = 1",
5618 : "#a = () => {}",
5619 : "#a",
5620 : "#a() { }",
5621 : "get #a() { }",
5622 : "set #a(foo) { }",
5623 : "*#a() { }",
5624 : "async #a() { }",
5625 : "async *#a() { }",
5626 : nullptr
5627 5 : };
5628 : // clang-format on
5629 :
5630 5 : RunParserSyncTest(context_data, class_body_data, kError);
5631 :
5632 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5633 : kAllowHarmonyPrivateMethods};
5634 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5635 5 : private_methods, arraysize(private_methods));
5636 5 : }
5637 :
5638 25880 : TEST(PrivateClassFieldsNoErrors) {
5639 : // clang-format off
5640 : // Tests proposed class fields syntax.
5641 : const char* context_data[][2] = {{"(class {", "});"},
5642 : {"(class extends Base {", "});"},
5643 : {"class C {", "}"},
5644 : {"class C extends Base {", "}"},
5645 5 : {nullptr, nullptr}};
5646 : const char* class_body_data[] = {
5647 : // Basic syntax
5648 : "#a = 0;",
5649 : "#a = 0; #b",
5650 : "#a = 0; b",
5651 : "#a = 0; b(){}",
5652 : "#a = 0; *b(){}",
5653 : "#a = 0; ['b'](){}",
5654 : "#a;",
5655 : "#a; #b;",
5656 : "#a; b;",
5657 : "#a; b(){}",
5658 : "#a; *b(){}",
5659 : "#a; ['b'](){}",
5660 :
5661 : // ASI
5662 : "#a = 0\n",
5663 : "#a = 0\n #b",
5664 : "#a = 0\n b",
5665 : "#a = 0\n b(){}",
5666 : "#a\n",
5667 : "#a\n #b\n",
5668 : "#a\n b\n",
5669 : "#a\n b(){}",
5670 : "#a\n *b(){}",
5671 : "#a\n ['b'](){}",
5672 :
5673 : // ASI edge cases
5674 : "#a\n get",
5675 : "#get\n *a(){}",
5676 : "#a\n static",
5677 :
5678 : "#a = function t() { arguments; }",
5679 : "#a = () => function() { arguments; }",
5680 :
5681 : // Misc edge cases
5682 : "#yield",
5683 : "#yield = 0",
5684 : "#yield\n a",
5685 : "#async;",
5686 : "#async = 0;",
5687 : "#async",
5688 : "#async = 0",
5689 : "#async\n a(){}", // a field named async, and a method named a.
5690 : "#async\n a",
5691 : "#await;",
5692 : "#await = 0;",
5693 : "#await\n a",
5694 : nullptr
5695 5 : };
5696 : // clang-format on
5697 :
5698 5 : RunParserSyncTest(context_data, class_body_data, kError);
5699 :
5700 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5701 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5702 5 : private_fields, arraysize(private_fields));
5703 5 : }
5704 :
5705 25880 : TEST(StaticClassFieldsErrors) {
5706 : // clang-format off
5707 : // Tests proposed class fields syntax.
5708 : const char* context_data[][2] = {{"(class {", "});"},
5709 : {"(class extends Base {", "});"},
5710 : {"class C {", "}"},
5711 : {"class C extends Base {", "}"},
5712 5 : {nullptr, nullptr}};
5713 : const char* class_body_data[] = {
5714 : "static a : 0",
5715 : "static a =",
5716 : "static constructor",
5717 : "static prototype",
5718 : "static *a = 0",
5719 : "static *a",
5720 : "static get a",
5721 : "static get\n a",
5722 : "static yield a",
5723 : "static async a = 0",
5724 : "static async a",
5725 :
5726 : "static a = arguments",
5727 : "static a = () => arguments",
5728 : "static a = () => { arguments }",
5729 : "static a = arguments[0]",
5730 : "static a = delete arguments[0]",
5731 : "static a = f(arguments)",
5732 : "static a = () => () => arguments",
5733 :
5734 : // ASI requires a linebreak
5735 : "static a b",
5736 : "static a = 0 b",
5737 :
5738 : "static c = [1] = [c]",
5739 :
5740 : // ASI requires that the next token is not part of any legal production
5741 : "static a = 0\n *b(){}",
5742 : "static a = 0\n ['b'](){}",
5743 : nullptr
5744 5 : };
5745 : // clang-format on
5746 :
5747 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5748 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5749 5 : no_static_flags, arraysize(no_static_flags));
5750 :
5751 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5752 : kAllowHarmonyStaticFields};
5753 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5754 5 : always_flags, arraysize(always_flags));
5755 5 : }
5756 :
5757 25880 : TEST(ClassFieldsErrors) {
5758 : // clang-format off
5759 : // Tests proposed class fields syntax.
5760 : const char* context_data[][2] = {{"(class {", "});"},
5761 : {"(class extends Base {", "});"},
5762 : {"class C {", "}"},
5763 : {"class C extends Base {", "}"},
5764 5 : {nullptr, nullptr}};
5765 : const char* class_body_data[] = {
5766 : "a : 0",
5767 : "a =",
5768 : "constructor",
5769 : "*a = 0",
5770 : "*a",
5771 : "get a",
5772 : "yield a",
5773 : "async a = 0",
5774 : "async a",
5775 :
5776 : "a = arguments",
5777 : "a = () => arguments",
5778 : "a = () => { arguments }",
5779 : "a = arguments[0]",
5780 : "a = delete arguments[0]",
5781 : "a = f(arguments)",
5782 : "a = () => () => arguments",
5783 :
5784 : // ASI requires a linebreak
5785 : "a b",
5786 : "a = 0 b",
5787 :
5788 : "c = [1] = [c]",
5789 :
5790 : // ASI requires that the next token is not part of any legal production
5791 : "a = 0\n *b(){}",
5792 : "a = 0\n ['b'](){}",
5793 : "get\n a",
5794 : nullptr
5795 5 : };
5796 : // clang-format on
5797 :
5798 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5799 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5800 5 : always_flags, arraysize(always_flags));
5801 :
5802 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5803 : kAllowHarmonyStaticFields};
5804 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5805 5 : static_flags, arraysize(static_flags));
5806 5 : }
5807 :
5808 25880 : TEST(PrivateClassFieldsErrors) {
5809 : // clang-format off
5810 : // Tests proposed class fields syntax.
5811 : const char* context_data[][2] = {{"(class {", "});"},
5812 : {"(class extends Base {", "});"},
5813 : {"class C {", "}"},
5814 : {"class C extends Base {", "}"},
5815 5 : {nullptr, nullptr}};
5816 : const char* class_body_data[] = {
5817 : "#a : 0",
5818 : "#a =",
5819 : "#*a = 0",
5820 : "#*a",
5821 : "#get a",
5822 : "#yield a",
5823 : "#async a = 0",
5824 : "#async a",
5825 :
5826 : "#a; #a",
5827 : "#a = 1; #a",
5828 : "#a; #a = 1;",
5829 :
5830 : "#constructor",
5831 : "#constructor = function() {}",
5832 :
5833 : "# a = 0",
5834 : "#a() { }",
5835 : "get #a() { }",
5836 : "#get a() { }",
5837 : "set #a() { }",
5838 : "#set a() { }",
5839 : "*#a() { }",
5840 : "#*a() { }",
5841 : "async #a() { }",
5842 : "async *#a() { }",
5843 : "async #*a() { }",
5844 :
5845 : "#0 = 0;",
5846 : "#0;",
5847 : "#'a' = 0;",
5848 : "#'a';",
5849 :
5850 : "#['a']",
5851 : "#['a'] = 1",
5852 : "#[a]",
5853 : "#[a] = 1",
5854 :
5855 : "#a = arguments",
5856 : "#a = () => arguments",
5857 : "#a = () => { arguments }",
5858 : "#a = arguments[0]",
5859 : "#a = delete arguments[0]",
5860 : "#a = f(arguments)",
5861 : "#a = () => () => arguments",
5862 :
5863 : "foo() { delete this.#a }",
5864 : "foo() { delete this.x.#a }",
5865 : "foo() { delete this.x().#a }",
5866 :
5867 : "foo() { delete f.#a }",
5868 : "foo() { delete f.x.#a }",
5869 : "foo() { delete f.x().#a }",
5870 :
5871 : // ASI requires a linebreak
5872 : "#a b",
5873 : "#a = 0 b",
5874 :
5875 : // ASI requires that the next token is not part of any legal production
5876 : "#a = 0\n *b(){}",
5877 : "#a = 0\n ['b'](){}",
5878 : nullptr
5879 5 : };
5880 : // clang-format on
5881 :
5882 5 : RunParserSyncTest(context_data, class_body_data, kError);
5883 :
5884 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5885 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5886 5 : private_fields, arraysize(private_fields));
5887 5 : }
5888 :
5889 25880 : TEST(PrivateStaticClassFieldsNoErrors) {
5890 : // clang-format off
5891 : // Tests proposed class fields syntax.
5892 : const char* context_data[][2] = {{"(class {", "});"},
5893 : {"(class extends Base {", "});"},
5894 : {"class C {", "}"},
5895 : {"class C extends Base {", "}"},
5896 5 : {nullptr, nullptr}};
5897 : const char* class_body_data[] = {
5898 : // Basic syntax
5899 : "static #a = 0;",
5900 : "static #a = 0; b",
5901 : "static #a = 0; #b",
5902 : "static #a = 0; b(){}",
5903 : "static #a = 0; *b(){}",
5904 : "static #a = 0; ['b'](){}",
5905 : "static #a;",
5906 : "static #a; b;",
5907 : "static #a; b(){}",
5908 : "static #a; *b(){}",
5909 : "static #a; ['b'](){}",
5910 :
5911 : "#prototype",
5912 : "#prototype = function() {}",
5913 :
5914 : // ASI
5915 : "static #a = 0\n",
5916 : "static #a = 0\n b",
5917 : "static #a = 0\n #b",
5918 : "static #a = 0\n b(){}",
5919 : "static #a\n",
5920 : "static #a\n b\n",
5921 : "static #a\n #b\n",
5922 : "static #a\n b(){}",
5923 : "static #a\n *b(){}",
5924 : "static #a\n ['b'](){}",
5925 :
5926 : "static #a = function t() { arguments; }",
5927 : "static #a = () => function t() { arguments; }",
5928 :
5929 : // ASI edge cases
5930 : "static #a\n get",
5931 : "static #get\n *a(){}",
5932 : "static #a\n static",
5933 :
5934 : // Misc edge cases
5935 : "static #yield",
5936 : "static #yield = 0",
5937 : "static #yield\n a",
5938 : "static #async;",
5939 : "static #async = 0;",
5940 : "static #async",
5941 : "static #async = 0",
5942 : "static #async\n a(){}", // a field named async, and a method named a.
5943 : "static #async\n a",
5944 : "static #await;",
5945 : "static #await = 0;",
5946 : "static #await\n a",
5947 : nullptr
5948 5 : };
5949 : // clang-format on
5950 :
5951 5 : RunParserSyncTest(context_data, class_body_data, kError);
5952 :
5953 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
5954 : kAllowHarmonyStaticFields};
5955 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5956 5 : public_static_fields, arraysize(public_static_fields));
5957 :
5958 : static const ParserFlag private_static_fields[] = {
5959 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
5960 : kAllowHarmonyPrivateFields};
5961 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5962 5 : private_static_fields, arraysize(private_static_fields));
5963 5 : }
5964 :
5965 25880 : TEST(PrivateStaticClassFieldsErrors) {
5966 : // clang-format off
5967 : // Tests proposed class fields syntax.
5968 : const char* context_data[][2] = {{"(class {", "});"},
5969 : {"(class extends Base {", "});"},
5970 : {"class C {", "}"},
5971 : {"class C extends Base {", "}"},
5972 5 : {nullptr, nullptr}};
5973 : const char* class_body_data[] = {
5974 : // Basic syntax
5975 : "static #['a'] = 0;",
5976 : "static #['a'] = 0; b",
5977 : "static #['a'] = 0; #b",
5978 : "static #['a'] = 0; b(){}",
5979 : "static #['a'] = 0; *b(){}",
5980 : "static #['a'] = 0; ['b'](){}",
5981 : "static #['a'];",
5982 : "static #['a']; b;",
5983 : "static #['a']; #b;",
5984 : "static #['a']; b(){}",
5985 : "static #['a']; *b(){}",
5986 : "static #['a']; ['b'](){}",
5987 :
5988 : "static #0 = 0;",
5989 : "static #0;",
5990 : "static #'a' = 0;",
5991 : "static #'a';",
5992 :
5993 : "static # a = 0",
5994 : "static #get a() { }",
5995 : "static #set a() { }",
5996 : "static #*a() { }",
5997 : "static async #*a() { }",
5998 :
5999 : "#a = arguments",
6000 : "#a = () => arguments",
6001 : "#a = () => { arguments }",
6002 : "#a = arguments[0]",
6003 : "#a = delete arguments[0]",
6004 : "#a = f(arguments)",
6005 : "#a = () => () => arguments",
6006 :
6007 : "#a; static #a",
6008 : "static #a; #a",
6009 :
6010 : // TODO(joyee): support static private methods
6011 : "static #a() { }",
6012 : "static get #a() { }",
6013 : "static set #a() { }",
6014 : "static *#a() { }",
6015 : "static async #a() { }",
6016 : "static async *#a() { }",
6017 :
6018 : // ASI
6019 : "static #['a'] = 0\n",
6020 : "static #['a'] = 0\n b",
6021 : "static #['a'] = 0\n #b",
6022 : "static #['a'] = 0\n b(){}",
6023 : "static #['a']\n",
6024 : "static #['a']\n b\n",
6025 : "static #['a']\n #b\n",
6026 : "static #['a']\n b(){}",
6027 : "static #['a']\n *b(){}",
6028 : "static #['a']\n ['b'](){}",
6029 :
6030 : // ASI requires a linebreak
6031 : "static #a b",
6032 : "static #a = 0 b",
6033 :
6034 : // ASI requires that the next token is not part of any legal production
6035 : "static #a = 0\n *b(){}",
6036 : "static #a = 0\n ['b'](){}",
6037 :
6038 : "static #a : 0",
6039 : "static #a =",
6040 : "static #*a = 0",
6041 : "static #*a",
6042 : "static #get a",
6043 : "static #yield a",
6044 : "static #async a = 0",
6045 : "static #async a",
6046 : "static # a = 0",
6047 :
6048 : "#constructor",
6049 : "#constructor = function() {}",
6050 :
6051 : "foo() { delete this.#a }",
6052 : "foo() { delete this.x.#a }",
6053 : "foo() { delete this.x().#a }",
6054 :
6055 : "foo() { delete f.#a }",
6056 : "foo() { delete f.x.#a }",
6057 : "foo() { delete f.x().#a }",
6058 : nullptr
6059 5 : };
6060 : // clang-format on
6061 :
6062 5 : RunParserSyncTest(context_data, class_body_data, kError);
6063 :
6064 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
6065 : kAllowHarmonyStaticFields};
6066 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6067 5 : public_static_fields, arraysize(public_static_fields));
6068 :
6069 : static const ParserFlag private_static_fields[] = {
6070 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
6071 : kAllowHarmonyPrivateFields};
6072 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6073 5 : private_static_fields, arraysize(private_static_fields));
6074 5 : }
6075 :
6076 25880 : TEST(PrivateNameNoErrors) {
6077 : // clang-format off
6078 : const char* context_data[][2] = {
6079 : {"", ""},
6080 : {"\"use strict\";", ""},
6081 : {nullptr, nullptr}
6082 5 : };
6083 :
6084 : const char* statement_data[] = {
6085 : "this.#a",
6086 : "this.#a()",
6087 : "this.#b.#a",
6088 : "this.#b.#a()",
6089 :
6090 : "foo.#a",
6091 : "foo.#a()",
6092 : "foo.#b.#a",
6093 : "foo.#b.#a()",
6094 :
6095 : "foo().#a",
6096 : "foo().b.#a",
6097 : "foo().b().#a",
6098 : "foo().b().#a()",
6099 : "foo().b().#a.bar",
6100 : "foo().b().#a.bar()",
6101 :
6102 : "foo(this.#a)",
6103 : "foo(bar().#a)",
6104 :
6105 : "new foo.#a",
6106 : "new foo.#b.#a",
6107 : "new foo.#b.#a()",
6108 :
6109 : "foo.#if;",
6110 : "foo.#yield;",
6111 : "foo.#super;",
6112 : "foo.#interface;",
6113 : "foo.#eval;",
6114 : "foo.#arguments;",
6115 :
6116 : nullptr
6117 5 : };
6118 :
6119 : // clang-format on
6120 5 : RunParserSyncTest(context_data, statement_data, kError);
6121 :
6122 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6123 : RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
6124 5 : private_fields, arraysize(private_fields));
6125 5 : }
6126 :
6127 25880 : TEST(PrivateNameErrors) {
6128 : // clang-format off
6129 : const char* context_data[][2] = {
6130 : {"", ""},
6131 : {"\"use strict\";", ""},
6132 : {nullptr, nullptr}
6133 5 : };
6134 :
6135 : const char* statement_data[] = {
6136 : "#foo",
6137 : "#foo = 1",
6138 :
6139 : "# a;",
6140 : "#\n a;",
6141 : "a, # b",
6142 : "a, #, b;",
6143 :
6144 : "foo.#[a];",
6145 : "foo.#['a'];",
6146 :
6147 : "foo()#a",
6148 : "foo()#[a]",
6149 : "foo()#['a']",
6150 :
6151 : "super.#a;",
6152 : "super.#a = 1;",
6153 : "super.#['a']",
6154 : "super.#[a]",
6155 :
6156 : "new.#a",
6157 : "new.#[a]",
6158 :
6159 : "foo.#{;",
6160 : "foo.#};",
6161 : "foo.#=;",
6162 : "foo.#888;",
6163 : "foo.#-;",
6164 : "foo.#--;",
6165 : nullptr
6166 5 : };
6167 :
6168 : // clang-format on
6169 5 : RunParserSyncTest(context_data, statement_data, kError);
6170 :
6171 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6172 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0,
6173 5 : private_fields, arraysize(private_fields));
6174 5 : }
6175 :
6176 25880 : TEST(ClassExpressionErrors) {
6177 : const char* context_data[][2] = {
6178 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
6179 : const char* class_data[] = {
6180 : "class",
6181 : "class name",
6182 : "class name extends",
6183 : "class extends",
6184 : "class {",
6185 : "class { m }",
6186 : "class { m; n }",
6187 : "class { m: 1 }",
6188 : "class { m(); n() }",
6189 : "class { get m }",
6190 : "class { get m() }",
6191 : "class { get m() { }",
6192 : "class { set m() {} }", // Missing required parameter.
6193 : "class { m() {}, n() {} }", // No commas allowed.
6194 5 : nullptr};
6195 :
6196 5 : RunParserSyncTest(context_data, class_data, kError);
6197 5 : }
6198 :
6199 :
6200 25880 : TEST(ClassDeclarationErrors) {
6201 : const char* context_data[][2] = {
6202 5 : {"", ""}, {"{", "}"}, {"if (true) {", "}"}, {nullptr, nullptr}};
6203 : const char* class_data[] = {
6204 : "class",
6205 : "class name",
6206 : "class name extends",
6207 : "class extends",
6208 : "class name {",
6209 : "class name { m }",
6210 : "class name { m; n }",
6211 : "class name { m: 1 }",
6212 : "class name { m(); n() }",
6213 : "class name { get x }",
6214 : "class name { get x() }",
6215 : "class name { set x() {) }", // missing required param
6216 : "class {}", // Name is required for declaration
6217 : "class extends base {}",
6218 : "class name { *",
6219 : "class name { * }",
6220 : "class name { *; }",
6221 : "class name { *get x() {} }",
6222 : "class name { *set x(_) {} }",
6223 : "class name { *static m() {} }",
6224 5 : nullptr};
6225 :
6226 5 : RunParserSyncTest(context_data, class_data, kError);
6227 5 : }
6228 :
6229 25880 : TEST(ClassAsyncErrors) {
6230 : // clang-format off
6231 : const char* context_data[][2] = {{"(class {", "});"},
6232 : {"(class extends Base {", "});"},
6233 : {"class C {", "}"},
6234 : {"class C extends Base {", "}"},
6235 5 : {nullptr, nullptr}};
6236 : const char* async_data[] = {
6237 : "*async x(){}",
6238 : "async *(){}",
6239 : "async get x(){}",
6240 : "async set x(y){}",
6241 : "async x : 0",
6242 : "async : 0",
6243 :
6244 : "async static x(){}",
6245 :
6246 : "static *async x(){}",
6247 : "static async *(){}",
6248 : "static async get x(){}",
6249 : "static async set x(y){}",
6250 : "static async x : 0",
6251 : "static async : 0",
6252 : nullptr
6253 5 : };
6254 : // clang-format on
6255 :
6256 5 : RunParserSyncTest(context_data, async_data, kError);
6257 5 : }
6258 :
6259 25880 : TEST(ClassNameErrors) {
6260 : const char* context_data[][2] = {{"class ", "{}"},
6261 : {"(class ", "{});"},
6262 : {"'use strict'; class ", "{}"},
6263 : {"'use strict'; (class ", "{});"},
6264 5 : {nullptr, nullptr}};
6265 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6266 : "let", "package", "private", "protected",
6267 : "public", "static", "var", "yield",
6268 5 : nullptr};
6269 :
6270 5 : RunParserSyncTest(context_data, class_name, kError);
6271 5 : }
6272 :
6273 :
6274 25880 : TEST(ClassGetterParamNameErrors) {
6275 : const char* context_data[][2] = {
6276 : {"class C { get name(", ") {} }"},
6277 : {"(class { get name(", ") {} });"},
6278 : {"'use strict'; class C { get name(", ") {} }"},
6279 : {"'use strict'; (class { get name(", ") {} })"},
6280 5 : {nullptr, nullptr}};
6281 :
6282 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6283 : "let", "package", "private", "protected",
6284 : "public", "static", "var", "yield",
6285 5 : nullptr};
6286 :
6287 5 : RunParserSyncTest(context_data, class_name, kError);
6288 5 : }
6289 :
6290 :
6291 25880 : TEST(ClassStaticPrototypeErrors) {
6292 : const char* context_data[][2] = {
6293 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6294 :
6295 : const char* class_body_data[] = {"static prototype() {}",
6296 : "static get prototype() {}",
6297 : "static set prototype(_) {}",
6298 : "static *prototype() {}",
6299 : "static 'prototype'() {}",
6300 : "static *'prototype'() {}",
6301 : "static prot\\u006ftype() {}",
6302 : "static 'prot\\u006ftype'() {}",
6303 : "static get 'prot\\u006ftype'() {}",
6304 : "static set 'prot\\u006ftype'(_) {}",
6305 : "static *'prot\\u006ftype'() {}",
6306 5 : nullptr};
6307 :
6308 5 : RunParserSyncTest(context_data, class_body_data, kError);
6309 5 : }
6310 :
6311 :
6312 25880 : TEST(ClassSpecialConstructorErrors) {
6313 : const char* context_data[][2] = {
6314 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6315 :
6316 : const char* class_body_data[] = {"get constructor() {}",
6317 : "get constructor(_) {}",
6318 : "*constructor() {}",
6319 : "get 'constructor'() {}",
6320 : "*'constructor'() {}",
6321 : "get c\\u006fnstructor() {}",
6322 : "*c\\u006fnstructor() {}",
6323 : "get 'c\\u006fnstructor'() {}",
6324 : "get 'c\\u006fnstructor'(_) {}",
6325 : "*'c\\u006fnstructor'() {}",
6326 5 : nullptr};
6327 :
6328 5 : RunParserSyncTest(context_data, class_body_data, kError);
6329 5 : }
6330 :
6331 :
6332 25880 : TEST(ClassConstructorNoErrors) {
6333 : const char* context_data[][2] = {
6334 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6335 :
6336 : const char* class_body_data[] = {"constructor() {}",
6337 : "static constructor() {}",
6338 : "static get constructor() {}",
6339 : "static set constructor(_) {}",
6340 : "static *constructor() {}",
6341 5 : nullptr};
6342 :
6343 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6344 5 : }
6345 :
6346 :
6347 25880 : TEST(ClassMultipleConstructorErrors) {
6348 : const char* context_data[][2] = {
6349 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6350 :
6351 : const char* class_body_data[] = {"constructor() {}; constructor() {}",
6352 5 : nullptr};
6353 :
6354 5 : RunParserSyncTest(context_data, class_body_data, kError);
6355 5 : }
6356 :
6357 :
6358 25880 : TEST(ClassMultiplePropertyNamesNoErrors) {
6359 : const char* context_data[][2] = {
6360 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6361 :
6362 : const char* class_body_data[] = {
6363 : "constructor() {}; static constructor() {}",
6364 : "m() {}; static m() {}",
6365 : "m() {}; m() {}",
6366 : "static m() {}; static m() {}",
6367 : "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
6368 5 : nullptr};
6369 :
6370 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6371 5 : }
6372 :
6373 :
6374 25880 : TEST(ClassesAreStrictErrors) {
6375 5 : const char* context_data[][2] = {{"", ""}, {"(", ");"}, {nullptr, nullptr}};
6376 :
6377 : const char* class_body_data[] = {
6378 : "class C { method() { with ({}) {} } }",
6379 : "class C extends function() { with ({}) {} } {}",
6380 5 : "class C { *method() { with ({}) {} } }", nullptr};
6381 :
6382 5 : RunParserSyncTest(context_data, class_body_data, kError);
6383 5 : }
6384 :
6385 :
6386 25880 : TEST(ObjectLiteralPropertyShorthandKeywordsError) {
6387 : const char* context_data[][2] = {
6388 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6389 :
6390 : const char* name_data[] = {
6391 : "break", "case", "catch", "class", "const", "continue",
6392 : "debugger", "default", "delete", "do", "else", "enum",
6393 : "export", "extends", "false", "finally", "for", "function",
6394 : "if", "import", "in", "instanceof", "new", "null",
6395 : "return", "super", "switch", "this", "throw", "true",
6396 : "try", "typeof", "var", "void", "while", "with",
6397 5 : nullptr};
6398 :
6399 5 : RunParserSyncTest(context_data, name_data, kError);
6400 5 : }
6401 :
6402 :
6403 25880 : TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
6404 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
6405 :
6406 : const char* name_data[] = {"implements", "interface", "let", "package",
6407 : "private", "protected", "public", "static",
6408 5 : "yield", nullptr};
6409 :
6410 5 : RunParserSyncTest(context_data, name_data, kSuccess);
6411 :
6412 : const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
6413 5 : {nullptr, nullptr}};
6414 5 : RunParserSyncTest(context_strict_data, name_data, kError);
6415 5 : }
6416 :
6417 :
6418 25880 : TEST(ObjectLiteralPropertyShorthandError) {
6419 : const char* context_data[][2] = {
6420 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6421 :
6422 : const char* name_data[] = {"1", "1.2", "0", "0.1", "1.0",
6423 5 : "1e1", "0x1", "\"s\"", "'s'", nullptr};
6424 :
6425 5 : RunParserSyncTest(context_data, name_data, kError);
6426 5 : }
6427 :
6428 :
6429 25880 : TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
6430 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6431 :
6432 5 : const char* name_data[] = {"function* g() { ({yield}); }", nullptr};
6433 :
6434 5 : RunParserSyncTest(context_data, name_data, kError);
6435 5 : }
6436 :
6437 :
6438 25880 : TEST(ConstParsingInForIn) {
6439 : const char* context_data[][2] = {{"'use strict';", ""},
6440 : {"function foo(){ 'use strict';", "}"},
6441 5 : {nullptr, nullptr}};
6442 :
6443 : const char* data[] = {
6444 : "for(const x = 1; ; ) {}", "for(const x = 1, y = 2;;){}",
6445 5 : "for(const x in [1,2,3]) {}", "for(const x of [1,2,3]) {}", nullptr};
6446 5 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
6447 5 : }
6448 :
6449 :
6450 25880 : TEST(StatementParsingInForIn) {
6451 : const char* context_data[][2] = {{"", ""},
6452 : {"'use strict';", ""},
6453 : {"function foo(){ 'use strict';", "}"},
6454 5 : {nullptr, nullptr}};
6455 :
6456 : const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
6457 : "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
6458 5 : nullptr};
6459 :
6460 5 : RunParserSyncTest(context_data, data, kSuccess);
6461 5 : }
6462 :
6463 :
6464 25880 : TEST(ConstParsingInForInError) {
6465 : const char* context_data[][2] = {{"'use strict';", ""},
6466 : {"function foo(){ 'use strict';", "}"},
6467 5 : {nullptr, nullptr}};
6468 :
6469 : const char* data[] = {
6470 : "for(const x,y = 1; ; ) {}", "for(const x = 4 in [1,2,3]) {}",
6471 : "for(const x = 4, y in [1,2,3]) {}", "for(const x = 4 of [1,2,3]) {}",
6472 : "for(const x = 4, y of [1,2,3]) {}", "for(const x = 1, y = 2 in []) {}",
6473 : "for(const x,y in []) {}", "for(const x = 1, y = 2 of []) {}",
6474 5 : "for(const x,y of []) {}", nullptr};
6475 5 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
6476 5 : }
6477 :
6478 25880 : TEST(InitializedDeclarationsInForInOf) {
6479 : // https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads
6480 :
6481 : // Initialized declarations only allowed for
6482 : // - sloppy mode (not strict mode)
6483 : // - for-in (not for-of)
6484 : // - var (not let / const)
6485 :
6486 : // clang-format off
6487 : const char* strict_context[][2] = {{"'use strict';", ""},
6488 : {"function foo(){ 'use strict';", "}"},
6489 : {"function* foo(){ 'use strict';", "}"},
6490 5 : {nullptr, nullptr}};
6491 :
6492 : const char* sloppy_context[][2] = {{"", ""},
6493 : {"function foo(){ ", "}"},
6494 : {"function* foo(){ ", "}"},
6495 : {"function foo(){ var yield = 0; ", "}"},
6496 5 : {nullptr, nullptr}};
6497 :
6498 : const char* let_const_var_for_of[] = {
6499 : "for (let i = 1 of {}) {}",
6500 : "for (let i = void 0 of [1, 2, 3]) {}",
6501 : "for (const i = 1 of {}) {}",
6502 : "for (const i = void 0 of [1, 2, 3]) {}",
6503 : "for (var i = 1 of {}) {}",
6504 : "for (var i = void 0 of [1, 2, 3]) {}",
6505 5 : nullptr};
6506 :
6507 : const char* let_const_for_in[] = {
6508 : "for (let i = 1 in {}) {}",
6509 : "for (let i = void 0 in [1, 2, 3]) {}",
6510 : "for (const i = 1 in {}) {}",
6511 : "for (const i = void 0 in [1, 2, 3]) {}",
6512 5 : nullptr};
6513 :
6514 : const char* var_for_in[] = {
6515 : "for (var i = 1 in {}) {}",
6516 : "for (var i = void 0 in [1, 2, 3]) {}",
6517 : "for (var i = yield in [1, 2, 3]) {}",
6518 5 : nullptr};
6519 : // clang-format on
6520 :
6521 : // The only allowed case is sloppy + var + for-in.
6522 5 : RunParserSyncTest(sloppy_context, var_for_in, kSuccess);
6523 :
6524 : // Everything else is disallowed.
6525 5 : RunParserSyncTest(sloppy_context, let_const_var_for_of, kError);
6526 5 : RunParserSyncTest(sloppy_context, let_const_for_in, kError);
6527 :
6528 5 : RunParserSyncTest(strict_context, let_const_var_for_of, kError);
6529 5 : RunParserSyncTest(strict_context, let_const_for_in, kError);
6530 5 : RunParserSyncTest(strict_context, var_for_in, kError);
6531 5 : }
6532 :
6533 25880 : TEST(ForInMultipleDeclarationsError) {
6534 : const char* context_data[][2] = {{"", ""},
6535 : {"function foo(){", "}"},
6536 : {"'use strict';", ""},
6537 : {"function foo(){ 'use strict';", "}"},
6538 5 : {nullptr, nullptr}};
6539 :
6540 : const char* data[] = {"for (var i, j in {}) {}",
6541 : "for (var i, j in [1, 2, 3]) {}",
6542 : "for (var i, j = 1 in {}) {}",
6543 : "for (var i, j = void 0 in [1, 2, 3]) {}",
6544 :
6545 : "for (let i, j in {}) {}",
6546 : "for (let i, j in [1, 2, 3]) {}",
6547 : "for (let i, j = 1 in {}) {}",
6548 : "for (let i, j = void 0 in [1, 2, 3]) {}",
6549 :
6550 : "for (const i, j in {}) {}",
6551 : "for (const i, j in [1, 2, 3]) {}",
6552 : "for (const i, j = 1 in {}) {}",
6553 : "for (const i, j = void 0 in [1, 2, 3]) {}",
6554 5 : nullptr};
6555 5 : RunParserSyncTest(context_data, data, kError);
6556 5 : }
6557 :
6558 :
6559 25880 : TEST(ForOfMultipleDeclarationsError) {
6560 : const char* context_data[][2] = {{"", ""},
6561 : {"function foo(){", "}"},
6562 : {"'use strict';", ""},
6563 : {"function foo(){ 'use strict';", "}"},
6564 5 : {nullptr, nullptr}};
6565 :
6566 : const char* data[] = {"for (var i, j of {}) {}",
6567 : "for (var i, j of [1, 2, 3]) {}",
6568 : "for (var i, j = 1 of {}) {}",
6569 : "for (var i, j = void 0 of [1, 2, 3]) {}",
6570 :
6571 : "for (let i, j of {}) {}",
6572 : "for (let i, j of [1, 2, 3]) {}",
6573 : "for (let i, j = 1 of {}) {}",
6574 : "for (let i, j = void 0 of [1, 2, 3]) {}",
6575 :
6576 : "for (const i, j of {}) {}",
6577 : "for (const i, j of [1, 2, 3]) {}",
6578 : "for (const i, j = 1 of {}) {}",
6579 : "for (const i, j = void 0 of [1, 2, 3]) {}",
6580 5 : nullptr};
6581 5 : RunParserSyncTest(context_data, data, kError);
6582 5 : }
6583 :
6584 :
6585 25880 : TEST(ForInNoDeclarationsError) {
6586 : const char* context_data[][2] = {{"", ""},
6587 : {"function foo(){", "}"},
6588 : {"'use strict';", ""},
6589 : {"function foo(){ 'use strict';", "}"},
6590 5 : {nullptr, nullptr}};
6591 :
6592 5 : const char* data[] = {"for (var in {}) {}", "for (const in {}) {}", nullptr};
6593 5 : RunParserSyncTest(context_data, data, kError);
6594 5 : }
6595 :
6596 :
6597 25880 : TEST(ForOfNoDeclarationsError) {
6598 : const char* context_data[][2] = {{"", ""},
6599 : {"function foo(){", "}"},
6600 : {"'use strict';", ""},
6601 : {"function foo(){ 'use strict';", "}"},
6602 5 : {nullptr, nullptr}};
6603 :
6604 : const char* data[] = {"for (var of [1, 2, 3]) {}",
6605 5 : "for (const of [1, 2, 3]) {}", nullptr};
6606 5 : RunParserSyncTest(context_data, data, kError);
6607 5 : }
6608 :
6609 :
6610 25880 : TEST(ForOfInOperator) {
6611 : const char* context_data[][2] = {{"", ""},
6612 : {"'use strict';", ""},
6613 : {"function foo(){ 'use strict';", "}"},
6614 5 : {nullptr, nullptr}};
6615 :
6616 : const char* data[] = {"for(x of 'foo' in {}) {}",
6617 : "for(var x of 'foo' in {}) {}",
6618 : "for(let x of 'foo' in {}) {}",
6619 5 : "for(const x of 'foo' in {}) {}", nullptr};
6620 :
6621 5 : RunParserSyncTest(context_data, data, kSuccess);
6622 5 : }
6623 :
6624 :
6625 25880 : TEST(ForOfYieldIdentifier) {
6626 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6627 :
6628 : const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
6629 : "for(let x of yield) {}", "for(const x of yield) {}",
6630 5 : nullptr};
6631 :
6632 5 : RunParserSyncTest(context_data, data, kSuccess);
6633 5 : }
6634 :
6635 :
6636 25880 : TEST(ForOfYieldExpression) {
6637 : const char* context_data[][2] = {{"", ""},
6638 : {"'use strict';", ""},
6639 : {"function foo(){ 'use strict';", "}"},
6640 5 : {nullptr, nullptr}};
6641 :
6642 : const char* data[] = {"function* g() { for(x of yield) {} }",
6643 : "function* g() { for(var x of yield) {} }",
6644 : "function* g() { for(let x of yield) {} }",
6645 5 : "function* g() { for(const x of yield) {} }", nullptr};
6646 :
6647 5 : RunParserSyncTest(context_data, data, kSuccess);
6648 5 : }
6649 :
6650 :
6651 25880 : TEST(ForOfExpressionError) {
6652 : const char* context_data[][2] = {{"", ""},
6653 : {"'use strict';", ""},
6654 : {"function foo(){ 'use strict';", "}"},
6655 5 : {nullptr, nullptr}};
6656 :
6657 : const char* data[] = {
6658 : "for(x of [], []) {}", "for(var x of [], []) {}",
6659 : "for(let x of [], []) {}", "for(const x of [], []) {}",
6660 :
6661 : // AssignmentExpression should be validated statically:
6662 : "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
6663 5 : "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", nullptr};
6664 :
6665 5 : RunParserSyncTest(context_data, data, kError);
6666 5 : }
6667 :
6668 :
6669 25880 : TEST(InvalidUnicodeEscapes) {
6670 : const char* context_data[][2] = {
6671 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6672 : const char* data[] = {
6673 : "var foob\\u123r = 0;", "var \\u123roo = 0;", "\"foob\\u123rr\"",
6674 : // No escapes allowed in regexp flags
6675 : "/regex/\\u0069g", "/regex/\\u006g",
6676 : // Braces gone wrong
6677 : "var foob\\u{c481r = 0;", "var foob\\uc481}r = 0;", "var \\u{0052oo = 0;",
6678 : "var \\u0052}oo = 0;", "\"foob\\u{c481r\"", "var foob\\u{}ar = 0;",
6679 : // Too high value for the Unicode code point escape
6680 : "\"\\u{110000}\"",
6681 : // Not a Unicode code point escape
6682 : "var foob\\v1234r = 0;", "var foob\\U1234r = 0;",
6683 5 : "var foob\\v{1234}r = 0;", "var foob\\U{1234}r = 0;", nullptr};
6684 5 : RunParserSyncTest(context_data, data, kError);
6685 5 : }
6686 :
6687 :
6688 25880 : TEST(UnicodeEscapes) {
6689 : const char* context_data[][2] = {
6690 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6691 : const char* data[] = {
6692 : // Identifier starting with escape
6693 : "var \\u0052oo = 0;", "var \\u{0052}oo = 0;", "var \\u{52}oo = 0;",
6694 : "var \\u{00000000052}oo = 0;",
6695 : // Identifier with an escape but not starting with an escape
6696 : "var foob\\uc481r = 0;", "var foob\\u{c481}r = 0;",
6697 : // String with an escape
6698 : "\"foob\\uc481r\"", "\"foob\\{uc481}r\"",
6699 : // This character is a valid Unicode character, representable as a
6700 : // surrogate pair, not representable as 4 hex digits.
6701 : "\"foo\\u{10e6d}\"",
6702 : // Max value for the Unicode code point escape
6703 5 : "\"\\u{10ffff}\"", nullptr};
6704 5 : RunParserSyncTest(context_data, data, kSuccess);
6705 5 : }
6706 :
6707 25880 : TEST(OctalEscapes) {
6708 : const char* sloppy_context_data[][2] = {{"", ""}, // as a directive
6709 : {"0;", ""}, // as a string literal
6710 5 : {nullptr, nullptr}};
6711 :
6712 : const char* strict_context_data[][2] = {
6713 : {"'use strict';", ""}, // as a directive before 'use strict'
6714 : {"", ";'use strict';"}, // as a directive after 'use strict'
6715 : {"'use strict'; 0;", ""}, // as a string literal
6716 5 : {nullptr, nullptr}};
6717 :
6718 : // clang-format off
6719 : const char* data[] = {
6720 : "'\\1'",
6721 : "'\\01'",
6722 : "'\\001'",
6723 : "'\\08'",
6724 : "'\\09'",
6725 5 : nullptr};
6726 : // clang-format on
6727 :
6728 : // Permitted in sloppy mode
6729 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6730 :
6731 : // Error in strict mode
6732 5 : RunParserSyncTest(strict_context_data, data, kError);
6733 5 : }
6734 :
6735 25880 : TEST(ScanTemplateLiterals) {
6736 : const char* context_data[][2] = {{"'use strict';", ""},
6737 : {"function foo(){ 'use strict';"
6738 : " var a, b, c; return ",
6739 : "}"},
6740 5 : {nullptr, nullptr}};
6741 :
6742 : const char* data[] = {"``",
6743 : "`no-subst-template`",
6744 : "`template-head${a}`",
6745 : "`${a}`",
6746 : "`${a}template-tail`",
6747 : "`template-head${a}template-tail`",
6748 : "`${a}${b}${c}`",
6749 : "`a${a}b${b}c${c}`",
6750 : "`${a}a${b}b${c}c`",
6751 : "`foo\n\nbar\r\nbaz`",
6752 : "`foo\n\n${ bar }\r\nbaz`",
6753 : "`foo${a /* comment */}`",
6754 : "`foo${a // comment\n}`",
6755 : "`foo${a \n}`",
6756 : "`foo${a \r\n}`",
6757 : "`foo${a \r}`",
6758 : "`foo${/* comment */ a}`",
6759 : "`foo${// comment\na}`",
6760 : "`foo${\n a}`",
6761 : "`foo${\r\n a}`",
6762 : "`foo${\r a}`",
6763 : "`foo${'a' in a}`",
6764 5 : nullptr};
6765 5 : RunParserSyncTest(context_data, data, kSuccess);
6766 5 : }
6767 :
6768 :
6769 25880 : TEST(ScanTaggedTemplateLiterals) {
6770 : const char* context_data[][2] = {{"'use strict';", ""},
6771 : {"function foo(){ 'use strict';"
6772 : " function tag() {}"
6773 : " var a, b, c; return ",
6774 : "}"},
6775 5 : {nullptr, nullptr}};
6776 :
6777 : const char* data[] = {"tag ``",
6778 : "tag `no-subst-template`",
6779 : "tag`template-head${a}`",
6780 : "tag `${a}`",
6781 : "tag `${a}template-tail`",
6782 : "tag `template-head${a}template-tail`",
6783 : "tag\n`${a}${b}${c}`",
6784 : "tag\r\n`a${a}b${b}c${c}`",
6785 : "tag `${a}a${b}b${c}c`",
6786 : "tag\t`foo\n\nbar\r\nbaz`",
6787 : "tag\r`foo\n\n${ bar }\r\nbaz`",
6788 : "tag`foo${a /* comment */}`",
6789 : "tag`foo${a // comment\n}`",
6790 : "tag`foo${a \n}`",
6791 : "tag`foo${a \r\n}`",
6792 : "tag`foo${a \r}`",
6793 : "tag`foo${/* comment */ a}`",
6794 : "tag`foo${// comment\na}`",
6795 : "tag`foo${\n a}`",
6796 : "tag`foo${\r\n a}`",
6797 : "tag`foo${\r a}`",
6798 : "tag`foo${'a' in a}`",
6799 5 : nullptr};
6800 5 : RunParserSyncTest(context_data, data, kSuccess);
6801 5 : }
6802 :
6803 :
6804 25880 : TEST(TemplateMaterializedLiterals) {
6805 : const char* context_data[][2] = {{"'use strict';\n"
6806 : "function tag() {}\n"
6807 : "var a, b, c;\n"
6808 : "(",
6809 : ")"},
6810 5 : {nullptr, nullptr}};
6811 :
6812 : const char* data[] = {"tag``", "tag`a`", "tag`a${1}b`", "tag`a${1}b${2}c`",
6813 : "``", "`a`", "`a${1}b`", "`a${1}b${2}c`",
6814 5 : nullptr};
6815 :
6816 5 : RunParserSyncTest(context_data, data, kSuccess);
6817 5 : }
6818 :
6819 :
6820 25880 : TEST(ScanUnterminatedTemplateLiterals) {
6821 : const char* context_data[][2] = {{"'use strict';", ""},
6822 : {"function foo(){ 'use strict';"
6823 : " var a, b, c; return ",
6824 : "}"},
6825 5 : {nullptr, nullptr}};
6826 :
6827 : const char* data[] = {"`no-subst-template",
6828 : "`template-head${a}",
6829 : "`${a}template-tail",
6830 : "`template-head${a}template-tail",
6831 : "`${a}${b}${c}",
6832 : "`a${a}b${b}c${c}",
6833 : "`${a}a${b}b${c}c",
6834 : "`foo\n\nbar\r\nbaz",
6835 : "`foo\n\n${ bar }\r\nbaz",
6836 : "`foo${a /* comment } */`",
6837 : "`foo${a /* comment } `*/",
6838 : "`foo${a // comment}`",
6839 : "`foo${a \n`",
6840 : "`foo${a \r\n`",
6841 : "`foo${a \r`",
6842 : "`foo${/* comment */ a`",
6843 : "`foo${// commenta}`",
6844 : "`foo${\n a`",
6845 : "`foo${\r\n a`",
6846 : "`foo${\r a`",
6847 : "`foo${fn(}`",
6848 : "`foo${1 if}`",
6849 5 : nullptr};
6850 5 : RunParserSyncTest(context_data, data, kError);
6851 5 : }
6852 :
6853 :
6854 25880 : TEST(TemplateLiteralsIllegalTokens) {
6855 : const char* context_data[][2] = {{"'use strict';", ""},
6856 : {"function foo(){ 'use strict';"
6857 : " var a, b, c; return ",
6858 : "}"},
6859 5 : {nullptr, nullptr}};
6860 : const char* data[] = {
6861 : "`hello\\x`", "`hello\\x${1}`", "`hello${1}\\x`",
6862 : "`hello${1}\\x${2}`", "`hello\\x\n`", "`hello\\x\n${1}`",
6863 5 : "`hello${1}\\x\n`", "`hello${1}\\x\n${2}`", nullptr};
6864 :
6865 5 : RunParserSyncTest(context_data, data, kError);
6866 5 : }
6867 :
6868 :
6869 25880 : TEST(ParseRestParameters) {
6870 : const char* context_data[][2] = {{"'use strict';(function(",
6871 : "){ return args;})(1, [], /regexp/, 'str',"
6872 : "function(){});"},
6873 : {"(function(",
6874 : "){ return args;})(1, [],"
6875 : "/regexp/, 'str', function(){});"},
6876 5 : {nullptr, nullptr}};
6877 :
6878 : const char* data[] = {"...args",
6879 : "a, ...args",
6880 : "... args",
6881 : "a, ... args",
6882 : "...\targs",
6883 : "a, ...\targs",
6884 : "...\r\nargs",
6885 : "a, ...\r\nargs",
6886 : "...\rargs",
6887 : "a, ...\rargs",
6888 : "...\t\n\t\t\n args",
6889 : "a, ... \n \n args",
6890 : "...{ length, 0: a, 1: b}",
6891 : "...{}",
6892 : "...[a, b]",
6893 : "...[]",
6894 : "...[...[a, b, ...c]]",
6895 5 : nullptr};
6896 5 : RunParserSyncTest(context_data, data, kSuccess);
6897 5 : }
6898 :
6899 :
6900 25880 : TEST(ParseRestParametersErrors) {
6901 : const char* context_data[][2] = {{"'use strict';(function(",
6902 : "){ return args;}(1, [], /regexp/, 'str',"
6903 : "function(){});"},
6904 : {"(function(",
6905 : "){ return args;}(1, [],"
6906 : "/regexp/, 'str', function(){});"},
6907 5 : {nullptr, nullptr}};
6908 :
6909 : const char* data[] = {"...args, b",
6910 : "a, ...args, b",
6911 : "...args, b",
6912 : "a, ...args, b",
6913 : "...args,\tb",
6914 : "a,...args\t,b",
6915 : "...args\r\n, b",
6916 : "a, ... args,\r\nb",
6917 : "...args\r,b",
6918 : "a, ... args,\rb",
6919 : "...args\t\n\t\t\n, b",
6920 : "a, ... args, \n \n b",
6921 : "a, a, ...args",
6922 : "a,\ta, ...args",
6923 : "a,\ra, ...args",
6924 : "a,\na, ...args",
6925 5 : nullptr};
6926 5 : RunParserSyncTest(context_data, data, kError);
6927 5 : }
6928 :
6929 :
6930 25880 : TEST(RestParameterInSetterMethodError) {
6931 : const char* context_data[][2] = {
6932 : {"'use strict';({ set prop(", ") {} }).prop = 1;"},
6933 : {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
6934 : {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
6935 : {"({ set prop(", ") {} }).prop = 1;"},
6936 : {"(class { static set prop(", ") {} }).prop = 1;"},
6937 : {"(new (class { set prop(", ") {} })).prop = 1;"},
6938 5 : {nullptr, nullptr}};
6939 5 : const char* data[] = {"...a", "...arguments", "...eval", nullptr};
6940 :
6941 5 : RunParserSyncTest(context_data, data, kError);
6942 5 : }
6943 :
6944 :
6945 25880 : TEST(RestParametersEvalArguments) {
6946 : // clang-format off
6947 : const char* strict_context_data[][2] =
6948 : {{"'use strict';(function(",
6949 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6950 5 : {nullptr, nullptr}};
6951 : const char* sloppy_context_data[][2] =
6952 : {{"(function(",
6953 : "){ return;})(1, [],/regexp/, 'str', function(){});"},
6954 5 : {nullptr, nullptr}};
6955 :
6956 : const char* data[] = {
6957 : "...eval",
6958 : "eval, ...args",
6959 : "...arguments",
6960 : // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
6961 : // "arguments, ...args",
6962 5 : nullptr};
6963 : // clang-format on
6964 :
6965 : // Fail in strict mode
6966 5 : RunParserSyncTest(strict_context_data, data, kError);
6967 :
6968 : // OK in sloppy mode
6969 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6970 5 : }
6971 :
6972 :
6973 25880 : TEST(RestParametersDuplicateEvalArguments) {
6974 : const char* context_data[][2] = {
6975 : {"'use strict';(function(",
6976 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6977 : {"(function(", "){ return;})(1, [],/regexp/, 'str', function(){});"},
6978 5 : {nullptr, nullptr}};
6979 :
6980 : const char* data[] = {"eval, ...eval", "eval, eval, ...args",
6981 : "arguments, ...arguments",
6982 5 : "arguments, arguments, ...args", nullptr};
6983 :
6984 : // In strict mode, the error is using "eval" or "arguments" as parameter names
6985 : // In sloppy mode, the error is that eval / arguments are duplicated
6986 5 : RunParserSyncTest(context_data, data, kError);
6987 5 : }
6988 :
6989 :
6990 25880 : TEST(SpreadCall) {
6991 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
6992 : {"function fn() {} fn(", ");"},
6993 5 : {nullptr, nullptr}};
6994 :
6995 : const char* data[] = {"...([1, 2, 3])",
6996 : "...'123', ...'456'",
6997 : "...new Set([1, 2, 3]), 4",
6998 : "1, ...[2, 3], 4",
6999 : "...Array(...[1,2,3,4])",
7000 : "...NaN",
7001 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
7002 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
7003 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
7004 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]",
7005 5 : nullptr};
7006 :
7007 5 : RunParserSyncTest(context_data, data, kSuccess);
7008 5 : }
7009 :
7010 :
7011 25880 : TEST(SpreadCallErrors) {
7012 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
7013 : {"function fn() {} fn(", ");"},
7014 5 : {nullptr, nullptr}};
7015 :
7016 5 : const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", nullptr};
7017 :
7018 5 : RunParserSyncTest(context_data, data, kError);
7019 5 : }
7020 :
7021 :
7022 25880 : TEST(BadRestSpread) {
7023 : const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
7024 : {"function fn() { ", "} fn();"},
7025 5 : {nullptr, nullptr}};
7026 : const char* data[] = {"return ...[1,2,3];",
7027 : "var ...x = [1,2,3];",
7028 : "var [...x,] = [1,2,3];",
7029 : "var [...x, y] = [1,2,3];",
7030 : "var { x } = {x: ...[1,2,3]}",
7031 5 : nullptr};
7032 5 : RunParserSyncTest(context_data, data, kError);
7033 5 : }
7034 :
7035 :
7036 25880 : TEST(LexicalScopingSloppyMode) {
7037 : const char* context_data[][2] = {
7038 5 : {"", ""}, {"function f() {", "}"}, {"{", "}"}, {nullptr, nullptr}};
7039 :
7040 5 : const char* good_data[] = {"let = 1;", "for(let = 1;;){}", nullptr};
7041 5 : RunParserSyncTest(context_data, good_data, kSuccess);
7042 5 : }
7043 :
7044 :
7045 25880 : TEST(ComputedPropertyName) {
7046 : const char* context_data[][2] = {{"({[", "]: 1});"},
7047 : {"({get [", "]() {}});"},
7048 : {"({set [", "](_) {}});"},
7049 : {"({[", "]() {}});"},
7050 : {"({*[", "]() {}});"},
7051 : {"(class {get [", "]() {}});"},
7052 : {"(class {set [", "](_) {}});"},
7053 : {"(class {[", "]() {}});"},
7054 : {"(class {*[", "]() {}});"},
7055 5 : {nullptr, nullptr}};
7056 5 : const char* error_data[] = {"1, 2", "var name", nullptr};
7057 :
7058 5 : RunParserSyncTest(context_data, error_data, kError);
7059 :
7060 : const char* name_data[] = {"1", "1 + 2", "'name'", "\"name\"",
7061 5 : "[]", "{}", nullptr};
7062 :
7063 5 : RunParserSyncTest(context_data, name_data, kSuccess);
7064 5 : }
7065 :
7066 :
7067 25880 : TEST(ComputedPropertyNameShorthandError) {
7068 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
7069 5 : const char* error_data[] = {"a: 1, [2]", "[1], a: 1", nullptr};
7070 :
7071 5 : RunParserSyncTest(context_data, error_data, kError);
7072 5 : }
7073 :
7074 :
7075 25880 : TEST(BasicImportExportParsing) {
7076 : // clang-format off
7077 : const char* kSources[] = {
7078 : "export let x = 0;",
7079 : "export var y = 0;",
7080 : "export const z = 0;",
7081 : "export function func() { };",
7082 : "export class C { };",
7083 : "export { };",
7084 : "function f() {}; f(); export { f };",
7085 : "var a, b, c; export { a, b as baz, c };",
7086 : "var d, e; export { d as dreary, e, };",
7087 : "export default function f() {}",
7088 : "export default function() {}",
7089 : "export default function*() {}",
7090 : "export default class C {}",
7091 : "export default class {}",
7092 : "export default class extends C {}",
7093 : "export default 42",
7094 : "var x; export default x = 7",
7095 : "export { Q } from 'somemodule.js';",
7096 : "export * from 'somemodule.js';",
7097 : "var foo; export { foo as for };",
7098 : "export { arguments } from 'm.js';",
7099 : "export { for } from 'm.js';",
7100 : "export { yield } from 'm.js'",
7101 : "export { static } from 'm.js'",
7102 : "export { let } from 'm.js'",
7103 : "var a; export { a as b, a as c };",
7104 : "var a; export { a as await };",
7105 : "var a; export { a as enum };",
7106 :
7107 : "import 'somemodule.js';",
7108 : "import { } from 'm.js';",
7109 : "import { a } from 'm.js';",
7110 : "import { a, b as d, c, } from 'm.js';",
7111 : "import * as thing from 'm.js';",
7112 : "import thing from 'm.js';",
7113 : "import thing, * as rest from 'm.js';",
7114 : "import thing, { a, b, c } from 'm.js';",
7115 : "import { arguments as a } from 'm.js';",
7116 : "import { for as f } from 'm.js';",
7117 : "import { yield as y } from 'm.js';",
7118 : "import { static as s } from 'm.js';",
7119 : "import { let as l } from 'm.js';",
7120 :
7121 : "import thing from 'a.js'; export {thing};",
7122 : "export {thing}; import thing from 'a.js';",
7123 : "import {thing} from 'a.js'; export {thing};",
7124 : "export {thing}; import {thing} from 'a.js';",
7125 : "import * as thing from 'a.js'; export {thing};",
7126 : "export {thing}; import * as thing from 'a.js';",
7127 5 : };
7128 : // clang-format on
7129 :
7130 : i::Isolate* isolate = CcTest::i_isolate();
7131 : i::Factory* factory = isolate->factory();
7132 :
7133 5 : v8::HandleScope handles(CcTest::isolate());
7134 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7135 : v8::Context::Scope context_scope(context);
7136 :
7137 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7138 5 : 128 * 1024);
7139 :
7140 240 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7141 : i::Handle<i::String> source =
7142 235 : factory->NewStringFromAsciiChecked(kSources[i]);
7143 :
7144 : // Show that parsing as a module works
7145 : {
7146 235 : i::Handle<i::Script> script = factory->NewScript(source);
7147 235 : i::ParseInfo info(isolate, script);
7148 : info.set_module();
7149 235 : if (!i::parsing::ParseProgram(&info, isolate)) {
7150 : i::Handle<i::JSObject> exception_handle(
7151 : i::JSObject::cast(isolate->pending_exception()), isolate);
7152 : i::Handle<i::String> message_string = i::Handle<i::String>::cast(
7153 0 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
7154 0 : .ToHandleChecked());
7155 0 : isolate->clear_pending_exception();
7156 :
7157 0 : FATAL(
7158 : "Parser failed on:\n"
7159 : "\t%s\n"
7160 : "with error:\n"
7161 : "\t%s\n"
7162 : "However, we expected no error.",
7163 0 : source->ToCString().get(), message_string->ToCString().get());
7164 235 : }
7165 : }
7166 :
7167 : // And that parsing a script does not.
7168 : {
7169 235 : i::Handle<i::Script> script = factory->NewScript(source);
7170 235 : i::ParseInfo info(isolate, script);
7171 235 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7172 235 : isolate->clear_pending_exception();
7173 : }
7174 5 : }
7175 5 : }
7176 :
7177 25880 : TEST(NamespaceExportParsing) {
7178 : // clang-format off
7179 : const char* kSources[] = {
7180 : "export * as arguments from 'bar'",
7181 : "export * as await from 'bar'",
7182 : "export * as default from 'bar'",
7183 : "export * as enum from 'bar'",
7184 : "export * as foo from 'bar'",
7185 : "export * as for from 'bar'",
7186 : "export * as let from 'bar'",
7187 : "export * as static from 'bar'",
7188 : "export * as yield from 'bar'",
7189 5 : };
7190 : // clang-format on
7191 :
7192 5 : i::FLAG_harmony_namespace_exports = true;
7193 : i::Isolate* isolate = CcTest::i_isolate();
7194 : i::Factory* factory = isolate->factory();
7195 :
7196 5 : v8::HandleScope handles(CcTest::isolate());
7197 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7198 : v8::Context::Scope context_scope(context);
7199 :
7200 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7201 5 : 128 * 1024);
7202 :
7203 50 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7204 : i::Handle<i::String> source =
7205 45 : factory->NewStringFromAsciiChecked(kSources[i]);
7206 45 : i::Handle<i::Script> script = factory->NewScript(source);
7207 45 : i::ParseInfo info(isolate, script);
7208 : info.set_module();
7209 45 : CHECK(i::parsing::ParseProgram(&info, isolate));
7210 50 : }
7211 5 : }
7212 :
7213 25880 : TEST(ImportExportParsingErrors) {
7214 : // clang-format off
7215 : const char* kErrorSources[] = {
7216 : "export {",
7217 : "var a; export { a",
7218 : "var a; export { a,",
7219 : "var a; export { a, ;",
7220 : "var a; export { a as };",
7221 : "var a, b; export { a as , b};",
7222 : "export }",
7223 : "var foo, bar; export { foo bar };",
7224 : "export { foo };",
7225 : "export { , };",
7226 : "export default;",
7227 : "export default var x = 7;",
7228 : "export default let x = 7;",
7229 : "export default const x = 7;",
7230 : "export *;",
7231 : "export * from;",
7232 : "export { Q } from;",
7233 : "export default from 'module.js';",
7234 : "export { for }",
7235 : "export { for as foo }",
7236 : "export { arguments }",
7237 : "export { arguments as foo }",
7238 : "var a; export { a, a };",
7239 : "var a, b; export { a as b, b };",
7240 : "var a, b; export { a as c, b as c };",
7241 : "export default function f(){}; export default class C {};",
7242 : "export default function f(){}; var a; export { a as default };",
7243 : "export function() {}",
7244 : "export function*() {}",
7245 : "export class {}",
7246 : "export class extends C {}",
7247 :
7248 : "import from;",
7249 : "import from 'm.js';",
7250 : "import { };",
7251 : "import {;",
7252 : "import };",
7253 : "import { , };",
7254 : "import { , } from 'm.js';",
7255 : "import { a } from;",
7256 : "import { a } 'm.js';",
7257 : "import , from 'm.js';",
7258 : "import a , from 'm.js';",
7259 : "import a { b, c } from 'm.js';",
7260 : "import arguments from 'm.js';",
7261 : "import eval from 'm.js';",
7262 : "import { arguments } from 'm.js';",
7263 : "import { eval } from 'm.js';",
7264 : "import { a as arguments } from 'm.js';",
7265 : "import { for } from 'm.js';",
7266 : "import { y as yield } from 'm.js'",
7267 : "import { s as static } from 'm.js'",
7268 : "import { l as let } from 'm.js'",
7269 : "import { a as await } from 'm.js';",
7270 : "import { a as enum } from 'm.js';",
7271 : "import { x }, def from 'm.js';",
7272 : "import def, def2 from 'm.js';",
7273 : "import * as x, def from 'm.js';",
7274 : "import * as x, * as y from 'm.js';",
7275 : "import {x}, {y} from 'm.js';",
7276 : "import * as x, {y} from 'm.js';",
7277 :
7278 : "export *;",
7279 : "export * as;",
7280 : "export * as foo;",
7281 : "export * as foo from;",
7282 : "export * as foo from ';",
7283 : "export * as ,foo from 'bar'",
7284 5 : };
7285 : // clang-format on
7286 :
7287 : i::Isolate* isolate = CcTest::i_isolate();
7288 : i::Factory* factory = isolate->factory();
7289 :
7290 5 : v8::HandleScope handles(CcTest::isolate());
7291 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7292 : v8::Context::Scope context_scope(context);
7293 :
7294 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7295 5 : 128 * 1024);
7296 :
7297 335 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7298 : i::Handle<i::String> source =
7299 330 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7300 :
7301 330 : i::Handle<i::Script> script = factory->NewScript(source);
7302 330 : i::ParseInfo info(isolate, script);
7303 : info.set_module();
7304 330 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7305 330 : isolate->clear_pending_exception();
7306 335 : }
7307 5 : }
7308 :
7309 25880 : TEST(ModuleTopLevelFunctionDecl) {
7310 : // clang-format off
7311 : const char* kErrorSources[] = {
7312 : "function f() {} function f() {}",
7313 : "var f; function f() {}",
7314 : "function f() {} var f;",
7315 : "function* f() {} function* f() {}",
7316 : "var f; function* f() {}",
7317 : "function* f() {} var f;",
7318 : "function f() {} function* f() {}",
7319 : "function* f() {} function f() {}",
7320 5 : };
7321 : // clang-format on
7322 :
7323 : i::Isolate* isolate = CcTest::i_isolate();
7324 : i::Factory* factory = isolate->factory();
7325 :
7326 5 : v8::HandleScope handles(CcTest::isolate());
7327 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7328 : v8::Context::Scope context_scope(context);
7329 :
7330 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7331 5 : 128 * 1024);
7332 :
7333 45 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7334 : i::Handle<i::String> source =
7335 40 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7336 :
7337 40 : i::Handle<i::Script> script = factory->NewScript(source);
7338 40 : i::ParseInfo info(isolate, script);
7339 : info.set_module();
7340 40 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7341 40 : isolate->clear_pending_exception();
7342 45 : }
7343 5 : }
7344 :
7345 25880 : TEST(ModuleAwaitReserved) {
7346 : // clang-format off
7347 : const char* kErrorSources[] = {
7348 : "await;",
7349 : "await: ;",
7350 : "var await;",
7351 : "var [await] = [];",
7352 : "var { await } = {};",
7353 : "var { x: await } = {};",
7354 : "{ var await; }",
7355 : "let await;",
7356 : "let [await] = [];",
7357 : "let { await } = {};",
7358 : "let { x: await } = {};",
7359 : "{ let await; }",
7360 : "const await = null;",
7361 : "const [await] = [];",
7362 : "const { await } = {};",
7363 : "const { x: await } = {};",
7364 : "{ const await = null; }",
7365 : "function await() {}",
7366 : "function f(await) {}",
7367 : "function* await() {}",
7368 : "function* g(await) {}",
7369 : "(function await() {});",
7370 : "(function (await) {});",
7371 : "(function* await() {});",
7372 : "(function* (await) {});",
7373 : "(await) => {};",
7374 : "await => {};",
7375 : "class await {}",
7376 : "class C { constructor(await) {} }",
7377 : "class C { m(await) {} }",
7378 : "class C { static m(await) {} }",
7379 : "class C { *m(await) {} }",
7380 : "class C { static *m(await) {} }",
7381 : "(class await {})",
7382 : "(class { constructor(await) {} });",
7383 : "(class { m(await) {} });",
7384 : "(class { static m(await) {} });",
7385 : "(class { *m(await) {} });",
7386 : "(class { static *m(await) {} });",
7387 : "({ m(await) {} });",
7388 : "({ *m(await) {} });",
7389 : "({ set p(await) {} });",
7390 : "try {} catch (await) {}",
7391 : "try {} catch (await) {} finally {}",
7392 : nullptr
7393 5 : };
7394 : // clang-format on
7395 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7396 :
7397 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7398 5 : }
7399 :
7400 25880 : TEST(ModuleAwaitReservedPreParse) {
7401 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7402 5 : const char* error_data[] = {"function f() { var await = 0; }", nullptr};
7403 :
7404 : RunModuleParserSyncTest(context_data, error_data, kError);
7405 5 : }
7406 :
7407 25880 : TEST(ModuleAwaitPermitted) {
7408 : // clang-format off
7409 : const char* kValidSources[] = {
7410 : "({}).await;",
7411 : "({ await: null });",
7412 : "({ await() {} });",
7413 : "({ get await() {} });",
7414 : "({ set await(x) {} });",
7415 : "(class { await() {} });",
7416 : "(class { static await() {} });",
7417 : "(class { *await() {} });",
7418 : "(class { static *await() {} });",
7419 : nullptr
7420 5 : };
7421 : // clang-format on
7422 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7423 :
7424 : RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
7425 5 : }
7426 :
7427 25880 : TEST(EnumReserved) {
7428 : // clang-format off
7429 : const char* kErrorSources[] = {
7430 : "enum;",
7431 : "enum: ;",
7432 : "var enum;",
7433 : "var [enum] = [];",
7434 : "var { enum } = {};",
7435 : "var { x: enum } = {};",
7436 : "{ var enum; }",
7437 : "let enum;",
7438 : "let [enum] = [];",
7439 : "let { enum } = {};",
7440 : "let { x: enum } = {};",
7441 : "{ let enum; }",
7442 : "const enum = null;",
7443 : "const [enum] = [];",
7444 : "const { enum } = {};",
7445 : "const { x: enum } = {};",
7446 : "{ const enum = null; }",
7447 : "function enum() {}",
7448 : "function f(enum) {}",
7449 : "function* enum() {}",
7450 : "function* g(enum) {}",
7451 : "(function enum() {});",
7452 : "(function (enum) {});",
7453 : "(function* enum() {});",
7454 : "(function* (enum) {});",
7455 : "(enum) => {};",
7456 : "enum => {};",
7457 : "class enum {}",
7458 : "class C { constructor(enum) {} }",
7459 : "class C { m(enum) {} }",
7460 : "class C { static m(enum) {} }",
7461 : "class C { *m(enum) {} }",
7462 : "class C { static *m(enum) {} }",
7463 : "(class enum {})",
7464 : "(class { constructor(enum) {} });",
7465 : "(class { m(enum) {} });",
7466 : "(class { static m(enum) {} });",
7467 : "(class { *m(enum) {} });",
7468 : "(class { static *m(enum) {} });",
7469 : "({ m(enum) {} });",
7470 : "({ *m(enum) {} });",
7471 : "({ set p(enum) {} });",
7472 : "try {} catch (enum) {}",
7473 : "try {} catch (enum) {} finally {}",
7474 : nullptr
7475 5 : };
7476 : // clang-format on
7477 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7478 :
7479 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7480 5 : }
7481 :
7482 85 : static void CheckEntry(const i::ModuleDescriptor::Entry* entry,
7483 : const char* export_name, const char* local_name,
7484 : const char* import_name, int module_request) {
7485 85 : CHECK_NOT_NULL(entry);
7486 85 : if (export_name == nullptr) {
7487 35 : CHECK_NULL(entry->export_name);
7488 : } else {
7489 50 : CHECK(entry->export_name->IsOneByteEqualTo(export_name));
7490 : }
7491 85 : if (local_name == nullptr) {
7492 15 : CHECK_NULL(entry->local_name);
7493 : } else {
7494 70 : CHECK(entry->local_name->IsOneByteEqualTo(local_name));
7495 : }
7496 85 : if (import_name == nullptr) {
7497 55 : CHECK_NULL(entry->import_name);
7498 : } else {
7499 30 : CHECK(entry->import_name->IsOneByteEqualTo(import_name));
7500 : }
7501 85 : CHECK_EQ(entry->module_request, module_request);
7502 85 : }
7503 :
7504 25880 : TEST(ModuleParsingInternals) {
7505 : i::Isolate* isolate = CcTest::i_isolate();
7506 : i::Factory* factory = isolate->factory();
7507 5 : v8::HandleScope handles(CcTest::isolate());
7508 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7509 : v8::Context::Scope context_scope(context);
7510 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7511 5 : 128 * 1024);
7512 :
7513 : static const char kSource[] =
7514 : "let x = 5;"
7515 : "export { x as y };"
7516 : "import { q as z } from 'm.js';"
7517 : "import n from 'n.js';"
7518 : "export { a as b } from 'm.js';"
7519 : "export * from 'p.js';"
7520 : "export var foo;"
7521 : "export function goo() {};"
7522 : "export let hoo;"
7523 : "export const joo = 42;"
7524 : "export default (function koo() {});"
7525 : "import 'q.js';"
7526 : "let nonexport = 42;"
7527 : "import {m as mm} from 'm.js';"
7528 : "import {aa} from 'm.js';"
7529 : "export {aa as bb, x};"
7530 : "import * as loo from 'bar.js';"
7531 : "import * as foob from 'bar.js';"
7532 : "export {foob};";
7533 5 : i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
7534 5 : i::Handle<i::Script> script = factory->NewScript(source);
7535 10 : i::ParseInfo info(isolate, script);
7536 : info.set_module();
7537 5 : CHECK(i::parsing::ParseProgram(&info, isolate));
7538 5 : CHECK(i::Compiler::Analyze(&info));
7539 5 : i::FunctionLiteral* func = info.literal();
7540 10 : i::ModuleScope* module_scope = func->scope()->AsModuleScope();
7541 15 : i::Scope* outer_scope = module_scope->outer_scope();
7542 5 : CHECK(outer_scope->is_script_scope());
7543 5 : CHECK_NULL(outer_scope->outer_scope());
7544 5 : CHECK(module_scope->is_module_scope());
7545 : const i::ModuleDescriptor::Entry* entry;
7546 : i::Declaration::List* declarations = module_scope->declarations();
7547 5 : CHECK_EQ(13, declarations->LengthForTest());
7548 :
7549 5 : CHECK(declarations->AtForTest(0)->var()->raw_name()->IsOneByteEqualTo("x"));
7550 10 : CHECK(declarations->AtForTest(0)->var()->mode() == i::VariableMode::kLet);
7551 5 : CHECK(declarations->AtForTest(0)->var()->binding_needs_init());
7552 5 : CHECK(declarations->AtForTest(0)->var()->location() ==
7553 : i::VariableLocation::MODULE);
7554 :
7555 5 : CHECK(declarations->AtForTest(1)->var()->raw_name()->IsOneByteEqualTo("z"));
7556 10 : CHECK(declarations->AtForTest(1)->var()->mode() == i::VariableMode::kConst);
7557 5 : CHECK(declarations->AtForTest(1)->var()->binding_needs_init());
7558 10 : CHECK(declarations->AtForTest(1)->var()->location() ==
7559 : i::VariableLocation::MODULE);
7560 :
7561 5 : CHECK(declarations->AtForTest(2)->var()->raw_name()->IsOneByteEqualTo("n"));
7562 10 : CHECK(declarations->AtForTest(2)->var()->mode() == i::VariableMode::kConst);
7563 5 : CHECK(declarations->AtForTest(2)->var()->binding_needs_init());
7564 10 : CHECK(declarations->AtForTest(2)->var()->location() ==
7565 : i::VariableLocation::MODULE);
7566 :
7567 5 : CHECK(declarations->AtForTest(3)->var()->raw_name()->IsOneByteEqualTo("foo"));
7568 10 : CHECK(declarations->AtForTest(3)->var()->mode() == i::VariableMode::kVar);
7569 5 : CHECK(!declarations->AtForTest(3)->var()->binding_needs_init());
7570 10 : CHECK(declarations->AtForTest(3)->var()->location() ==
7571 : i::VariableLocation::MODULE);
7572 :
7573 5 : CHECK(declarations->AtForTest(4)->var()->raw_name()->IsOneByteEqualTo("goo"));
7574 10 : CHECK(declarations->AtForTest(4)->var()->mode() == i::VariableMode::kLet);
7575 5 : CHECK(!declarations->AtForTest(4)->var()->binding_needs_init());
7576 10 : CHECK(declarations->AtForTest(4)->var()->location() ==
7577 : i::VariableLocation::MODULE);
7578 :
7579 5 : CHECK(declarations->AtForTest(5)->var()->raw_name()->IsOneByteEqualTo("hoo"));
7580 10 : CHECK(declarations->AtForTest(5)->var()->mode() == i::VariableMode::kLet);
7581 5 : CHECK(declarations->AtForTest(5)->var()->binding_needs_init());
7582 10 : CHECK(declarations->AtForTest(5)->var()->location() ==
7583 : i::VariableLocation::MODULE);
7584 :
7585 5 : CHECK(declarations->AtForTest(6)->var()->raw_name()->IsOneByteEqualTo("joo"));
7586 10 : CHECK(declarations->AtForTest(6)->var()->mode() == i::VariableMode::kConst);
7587 5 : CHECK(declarations->AtForTest(6)->var()->binding_needs_init());
7588 10 : CHECK(declarations->AtForTest(6)->var()->location() ==
7589 : i::VariableLocation::MODULE);
7590 :
7591 5 : CHECK(declarations->AtForTest(7)->var()->raw_name()->IsOneByteEqualTo(
7592 : "*default*"));
7593 10 : CHECK(declarations->AtForTest(7)->var()->mode() == i::VariableMode::kConst);
7594 5 : CHECK(declarations->AtForTest(7)->var()->binding_needs_init());
7595 10 : CHECK(declarations->AtForTest(7)->var()->location() ==
7596 : i::VariableLocation::MODULE);
7597 :
7598 5 : CHECK(declarations->AtForTest(8)->var()->raw_name()->IsOneByteEqualTo(
7599 : "nonexport"));
7600 5 : CHECK(!declarations->AtForTest(8)->var()->binding_needs_init());
7601 10 : CHECK(declarations->AtForTest(8)->var()->location() ==
7602 : i::VariableLocation::LOCAL);
7603 :
7604 5 : CHECK(declarations->AtForTest(9)->var()->raw_name()->IsOneByteEqualTo("mm"));
7605 10 : CHECK(declarations->AtForTest(9)->var()->mode() == i::VariableMode::kConst);
7606 5 : CHECK(declarations->AtForTest(9)->var()->binding_needs_init());
7607 10 : CHECK(declarations->AtForTest(9)->var()->location() ==
7608 : i::VariableLocation::MODULE);
7609 :
7610 5 : CHECK(declarations->AtForTest(10)->var()->raw_name()->IsOneByteEqualTo("aa"));
7611 10 : CHECK(declarations->AtForTest(10)->var()->mode() == i::VariableMode::kConst);
7612 5 : CHECK(declarations->AtForTest(10)->var()->binding_needs_init());
7613 10 : CHECK(declarations->AtForTest(10)->var()->location() ==
7614 : i::VariableLocation::MODULE);
7615 :
7616 5 : CHECK(
7617 : declarations->AtForTest(11)->var()->raw_name()->IsOneByteEqualTo("loo"));
7618 10 : CHECK(declarations->AtForTest(11)->var()->mode() == i::VariableMode::kConst);
7619 5 : CHECK(!declarations->AtForTest(11)->var()->binding_needs_init());
7620 10 : CHECK(declarations->AtForTest(11)->var()->location() !=
7621 : i::VariableLocation::MODULE);
7622 :
7623 5 : CHECK(
7624 : declarations->AtForTest(12)->var()->raw_name()->IsOneByteEqualTo("foob"));
7625 10 : CHECK(declarations->AtForTest(12)->var()->mode() == i::VariableMode::kConst);
7626 5 : CHECK(!declarations->AtForTest(12)->var()->binding_needs_init());
7627 10 : CHECK(declarations->AtForTest(12)->var()->location() ==
7628 : i::VariableLocation::MODULE);
7629 :
7630 : i::ModuleDescriptor* descriptor = module_scope->module();
7631 5 : CHECK_NOT_NULL(descriptor);
7632 :
7633 5 : CHECK_EQ(5u, descriptor->module_requests().size());
7634 35 : for (const auto& elem : descriptor->module_requests()) {
7635 25 : if (elem.first->IsOneByteEqualTo("m.js")) {
7636 5 : CHECK_EQ(0, elem.second.index);
7637 5 : CHECK_EQ(51, elem.second.position);
7638 20 : } else if (elem.first->IsOneByteEqualTo("n.js")) {
7639 5 : CHECK_EQ(1, elem.second.index);
7640 5 : CHECK_EQ(72, elem.second.position);
7641 15 : } else if (elem.first->IsOneByteEqualTo("p.js")) {
7642 5 : CHECK_EQ(2, elem.second.index);
7643 5 : CHECK_EQ(123, elem.second.position);
7644 10 : } else if (elem.first->IsOneByteEqualTo("q.js")) {
7645 5 : CHECK_EQ(3, elem.second.index);
7646 5 : CHECK_EQ(249, elem.second.position);
7647 5 : } else if (elem.first->IsOneByteEqualTo("bar.js")) {
7648 5 : CHECK_EQ(4, elem.second.index);
7649 5 : CHECK_EQ(370, elem.second.position);
7650 : } else {
7651 0 : UNREACHABLE();
7652 : }
7653 : }
7654 :
7655 10 : CHECK_EQ(3, descriptor->special_exports().size());
7656 5 : CheckEntry(descriptor->special_exports().at(0), "b", nullptr, "a", 0);
7657 5 : CheckEntry(descriptor->special_exports().at(1), nullptr, nullptr, nullptr, 2);
7658 : CheckEntry(descriptor->special_exports().at(2), "bb", nullptr, "aa",
7659 5 : 0); // !!!
7660 :
7661 5 : CHECK_EQ(8u, descriptor->regular_exports().size());
7662 : entry = descriptor->regular_exports()
7663 10 : .find(declarations->AtForTest(3)->var()->raw_name())
7664 5 : ->second;
7665 5 : CheckEntry(entry, "foo", "foo", nullptr, -1);
7666 : entry = descriptor->regular_exports()
7667 10 : .find(declarations->AtForTest(4)->var()->raw_name())
7668 5 : ->second;
7669 5 : CheckEntry(entry, "goo", "goo", nullptr, -1);
7670 : entry = descriptor->regular_exports()
7671 10 : .find(declarations->AtForTest(5)->var()->raw_name())
7672 5 : ->second;
7673 5 : CheckEntry(entry, "hoo", "hoo", nullptr, -1);
7674 : entry = descriptor->regular_exports()
7675 10 : .find(declarations->AtForTest(6)->var()->raw_name())
7676 5 : ->second;
7677 5 : CheckEntry(entry, "joo", "joo", nullptr, -1);
7678 : entry = descriptor->regular_exports()
7679 10 : .find(declarations->AtForTest(7)->var()->raw_name())
7680 5 : ->second;
7681 5 : CheckEntry(entry, "default", "*default*", nullptr, -1);
7682 : entry = descriptor->regular_exports()
7683 10 : .find(declarations->AtForTest(12)->var()->raw_name())
7684 5 : ->second;
7685 5 : CheckEntry(entry, "foob", "foob", nullptr, -1);
7686 : // TODO(neis): The next lines are terrible. Find a better way.
7687 5 : auto name_x = declarations->AtForTest(0)->var()->raw_name();
7688 5 : CHECK_EQ(2u, descriptor->regular_exports().count(name_x));
7689 : auto it = descriptor->regular_exports().equal_range(name_x).first;
7690 5 : entry = it->second;
7691 5 : if (entry->export_name->IsOneByteEqualTo("y")) {
7692 5 : CheckEntry(entry, "y", "x", nullptr, -1);
7693 5 : entry = (++it)->second;
7694 5 : CheckEntry(entry, "x", "x", nullptr, -1);
7695 : } else {
7696 0 : CheckEntry(entry, "x", "x", nullptr, -1);
7697 0 : entry = (++it)->second;
7698 0 : CheckEntry(entry, "y", "x", nullptr, -1);
7699 : }
7700 :
7701 10 : CHECK_EQ(2, descriptor->namespace_imports().size());
7702 5 : CheckEntry(descriptor->namespace_imports().at(0), nullptr, "loo", nullptr, 4);
7703 : CheckEntry(descriptor->namespace_imports().at(1), nullptr, "foob", nullptr,
7704 5 : 4);
7705 :
7706 5 : CHECK_EQ(4u, descriptor->regular_imports().size());
7707 : entry = descriptor->regular_imports()
7708 10 : .find(declarations->AtForTest(1)->var()->raw_name())
7709 5 : ->second;
7710 5 : CheckEntry(entry, nullptr, "z", "q", 0);
7711 : entry = descriptor->regular_imports()
7712 10 : .find(declarations->AtForTest(2)->var()->raw_name())
7713 5 : ->second;
7714 5 : CheckEntry(entry, nullptr, "n", "default", 1);
7715 : entry = descriptor->regular_imports()
7716 10 : .find(declarations->AtForTest(9)->var()->raw_name())
7717 5 : ->second;
7718 5 : CheckEntry(entry, nullptr, "mm", "m", 0);
7719 : entry = descriptor->regular_imports()
7720 10 : .find(declarations->AtForTest(10)->var()->raw_name())
7721 5 : ->second;
7722 10 : CheckEntry(entry, nullptr, "aa", "aa", 0);
7723 5 : }
7724 :
7725 :
7726 25880 : TEST(DuplicateProtoError) {
7727 : const char* context_data[][2] = {
7728 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7729 : const char* error_data[] = {"__proto__: {}, __proto__: {}",
7730 : "__proto__: {}, \"__proto__\": {}",
7731 : "__proto__: {}, \"__\x70roto__\": {}",
7732 5 : "__proto__: {}, a: 1, __proto__: {}", nullptr};
7733 :
7734 5 : RunParserSyncTest(context_data, error_data, kError);
7735 5 : }
7736 :
7737 :
7738 25880 : TEST(DuplicateProtoNoError) {
7739 : const char* context_data[][2] = {
7740 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7741 : const char* error_data[] = {
7742 : "__proto__: {}, ['__proto__']: {}", "__proto__: {}, __proto__() {}",
7743 : "__proto__: {}, get __proto__() {}", "__proto__: {}, set __proto__(v) {}",
7744 5 : "__proto__: {}, __proto__", nullptr};
7745 :
7746 5 : RunParserSyncTest(context_data, error_data, kSuccess);
7747 5 : }
7748 :
7749 :
7750 25880 : TEST(DeclarationsError) {
7751 : const char* context_data[][2] = {{"'use strict'; if (true)", ""},
7752 : {"'use strict'; if (false) {} else", ""},
7753 : {"'use strict'; while (false)", ""},
7754 : {"'use strict'; for (;;)", ""},
7755 : {"'use strict'; for (x in y)", ""},
7756 : {"'use strict'; do ", " while (false)"},
7757 5 : {nullptr, nullptr}};
7758 :
7759 : const char* statement_data[] = {"let x = 1;", "const x = 1;", "class C {}",
7760 5 : nullptr};
7761 :
7762 5 : RunParserSyncTest(context_data, statement_data, kError);
7763 5 : }
7764 :
7765 :
7766 20 : void TestLanguageMode(const char* source,
7767 : i::LanguageMode expected_language_mode) {
7768 : i::Isolate* isolate = CcTest::i_isolate();
7769 : i::Factory* factory = isolate->factory();
7770 20 : v8::HandleScope handles(CcTest::isolate());
7771 20 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7772 : v8::Context::Scope context_scope(context);
7773 20 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7774 20 : 128 * 1024);
7775 :
7776 : i::Handle<i::Script> script =
7777 20 : factory->NewScript(factory->NewStringFromAsciiChecked(source));
7778 40 : i::ParseInfo info(isolate, script);
7779 20 : i::parsing::ParseProgram(&info, isolate);
7780 20 : CHECK_NOT_NULL(info.literal());
7781 40 : CHECK_EQ(expected_language_mode, info.literal()->language_mode());
7782 20 : }
7783 :
7784 :
7785 25880 : TEST(LanguageModeDirectives) {
7786 5 : TestLanguageMode("\"use nothing\"", i::LanguageMode::kSloppy);
7787 5 : TestLanguageMode("\"use strict\"", i::LanguageMode::kStrict);
7788 :
7789 5 : TestLanguageMode("var x = 1; \"use strict\"", i::LanguageMode::kSloppy);
7790 :
7791 : TestLanguageMode("\"use some future directive\"; \"use strict\";",
7792 5 : i::LanguageMode::kStrict);
7793 5 : }
7794 :
7795 :
7796 25880 : TEST(PropertyNameEvalArguments) {
7797 5 : const char* context_data[][2] = {{"'use strict';", ""}, {nullptr, nullptr}};
7798 :
7799 : const char* statement_data[] = {"({eval: 1})",
7800 : "({arguments: 1})",
7801 : "({eval() {}})",
7802 : "({arguments() {}})",
7803 : "({*eval() {}})",
7804 : "({*arguments() {}})",
7805 : "({get eval() {}})",
7806 : "({get arguments() {}})",
7807 : "({set eval(_) {}})",
7808 : "({set arguments(_) {}})",
7809 :
7810 : "class C {eval() {}}",
7811 : "class C {arguments() {}}",
7812 : "class C {*eval() {}}",
7813 : "class C {*arguments() {}}",
7814 : "class C {get eval() {}}",
7815 : "class C {get arguments() {}}",
7816 : "class C {set eval(_) {}}",
7817 : "class C {set arguments(_) {}}",
7818 :
7819 : "class C {static eval() {}}",
7820 : "class C {static arguments() {}}",
7821 : "class C {static *eval() {}}",
7822 : "class C {static *arguments() {}}",
7823 : "class C {static get eval() {}}",
7824 : "class C {static get arguments() {}}",
7825 : "class C {static set eval(_) {}}",
7826 : "class C {static set arguments(_) {}}",
7827 :
7828 5 : nullptr};
7829 :
7830 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
7831 5 : }
7832 :
7833 :
7834 25880 : TEST(FunctionLiteralDuplicateParameters) {
7835 : const char* strict_context_data[][2] = {
7836 : {"'use strict';(function(", "){})();"},
7837 : {"(function(", ") { 'use strict'; })();"},
7838 : {"'use strict'; function fn(", ") {}; fn();"},
7839 : {"function fn(", ") { 'use strict'; }; fn();"},
7840 5 : {nullptr, nullptr}};
7841 :
7842 : const char* sloppy_context_data[][2] = {{"(function(", "){})();"},
7843 : {"(function(", ") {})();"},
7844 : {"function fn(", ") {}; fn();"},
7845 : {"function fn(", ") {}; fn();"},
7846 5 : {nullptr, nullptr}};
7847 :
7848 : const char* data[] = {
7849 : "a, a",
7850 : "a, a, a",
7851 : "b, a, a",
7852 : "a, b, c, c",
7853 : "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
7854 5 : nullptr};
7855 :
7856 5 : RunParserSyncTest(strict_context_data, data, kError);
7857 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
7858 5 : }
7859 :
7860 :
7861 25880 : TEST(ArrowFunctionASIErrors) {
7862 : const char* context_data[][2] = {
7863 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
7864 :
7865 : const char* data[] = {"(a\n=> a)(1)",
7866 : "(a/*\n*/=> a)(1)",
7867 : "((a)\n=> a)(1)",
7868 : "((a)/*\n*/=> a)(1)",
7869 : "((a, b)\n=> a + b)(1, 2)",
7870 : "((a, b)/*\n*/=> a + b)(1, 2)",
7871 5 : nullptr};
7872 5 : RunParserSyncTest(context_data, data, kError);
7873 5 : }
7874 :
7875 25880 : TEST(ObjectSpreadPositiveTests) {
7876 : // clang-format off
7877 : const char* context_data[][2] = {
7878 : {"x = ", ""},
7879 : {"'use strict'; x = ", ""},
7880 5 : {nullptr, nullptr}};
7881 :
7882 : // clang-format off
7883 : const char* data[] = {
7884 : "{ ...y }",
7885 : "{ a: 1, ...y }",
7886 : "{ b: 1, ...y }",
7887 : "{ y, ...y}",
7888 : "{ ...z = y}",
7889 : "{ ...y, y }",
7890 : "{ ...y, ...y}",
7891 : "{ a: 1, ...y, b: 1}",
7892 : "{ ...y, b: 1}",
7893 : "{ ...1}",
7894 : "{ ...null}",
7895 : "{ ...undefined}",
7896 : "{ ...1 in {}}",
7897 : "{ ...[]}",
7898 : "{ ...async function() { }}",
7899 : "{ ...async () => { }}",
7900 : "{ ...new Foo()}",
7901 5 : nullptr};
7902 : // clang-format on
7903 :
7904 5 : RunParserSyncTest(context_data, data, kSuccess);
7905 5 : }
7906 :
7907 25880 : TEST(ObjectSpreadNegativeTests) {
7908 : const char* context_data[][2] = {
7909 5 : {"x = ", ""}, {"'use strict'; x = ", ""}, {nullptr, nullptr}};
7910 :
7911 : // clang-format off
7912 : const char* data[] = {
7913 : "{ ...var z = y}",
7914 : "{ ...var}",
7915 : "{ ...foo bar}",
7916 : "{* ...foo}",
7917 : "{get ...foo}",
7918 : "{set ...foo}",
7919 : "{async ...foo}",
7920 5 : nullptr};
7921 :
7922 5 : RunParserSyncTest(context_data, data, kError);
7923 5 : }
7924 :
7925 25880 : TEST(TemplateEscapesPositiveTests) {
7926 : // clang-format off
7927 : const char* context_data[][2] = {
7928 : {"", ""},
7929 : {"'use strict';", ""},
7930 5 : {nullptr, nullptr}};
7931 :
7932 : // clang-format off
7933 : const char* data[] = {
7934 : "tag`\\08`",
7935 : "tag`\\01`",
7936 : "tag`\\01${0}right`",
7937 : "tag`left${0}\\01`",
7938 : "tag`left${0}\\01${1}right`",
7939 : "tag`\\1`",
7940 : "tag`\\1${0}right`",
7941 : "tag`left${0}\\1`",
7942 : "tag`left${0}\\1${1}right`",
7943 : "tag`\\xg`",
7944 : "tag`\\xg${0}right`",
7945 : "tag`left${0}\\xg`",
7946 : "tag`left${0}\\xg${1}right`",
7947 : "tag`\\xAg`",
7948 : "tag`\\xAg${0}right`",
7949 : "tag`left${0}\\xAg`",
7950 : "tag`left${0}\\xAg${1}right`",
7951 : "tag`\\u0`",
7952 : "tag`\\u0${0}right`",
7953 : "tag`left${0}\\u0`",
7954 : "tag`left${0}\\u0${1}right`",
7955 : "tag`\\u0g`",
7956 : "tag`\\u0g${0}right`",
7957 : "tag`left${0}\\u0g`",
7958 : "tag`left${0}\\u0g${1}right`",
7959 : "tag`\\u00g`",
7960 : "tag`\\u00g${0}right`",
7961 : "tag`left${0}\\u00g`",
7962 : "tag`left${0}\\u00g${1}right`",
7963 : "tag`\\u000g`",
7964 : "tag`\\u000g${0}right`",
7965 : "tag`left${0}\\u000g`",
7966 : "tag`left${0}\\u000g${1}right`",
7967 : "tag`\\u{}`",
7968 : "tag`\\u{}${0}right`",
7969 : "tag`left${0}\\u{}`",
7970 : "tag`left${0}\\u{}${1}right`",
7971 : "tag`\\u{-0}`",
7972 : "tag`\\u{-0}${0}right`",
7973 : "tag`left${0}\\u{-0}`",
7974 : "tag`left${0}\\u{-0}${1}right`",
7975 : "tag`\\u{g}`",
7976 : "tag`\\u{g}${0}right`",
7977 : "tag`left${0}\\u{g}`",
7978 : "tag`left${0}\\u{g}${1}right`",
7979 : "tag`\\u{0`",
7980 : "tag`\\u{0${0}right`",
7981 : "tag`left${0}\\u{0`",
7982 : "tag`left${0}\\u{0${1}right`",
7983 : "tag`\\u{\\u{0}`",
7984 : "tag`\\u{\\u{0}${0}right`",
7985 : "tag`left${0}\\u{\\u{0}`",
7986 : "tag`left${0}\\u{\\u{0}${1}right`",
7987 : "tag`\\u{110000}`",
7988 : "tag`\\u{110000}${0}right`",
7989 : "tag`left${0}\\u{110000}`",
7990 : "tag`left${0}\\u{110000}${1}right`",
7991 : "tag` ${tag`\\u`}`",
7992 : "tag` ``\\u`",
7993 : "tag`\\u`` `",
7994 : "tag`\\u``\\u`",
7995 : "` ${tag`\\u`}`",
7996 : "` ``\\u`",
7997 5 : nullptr};
7998 : // clang-format on
7999 :
8000 5 : RunParserSyncTest(context_data, data, kSuccess);
8001 5 : }
8002 :
8003 25880 : TEST(TemplateEscapesNegativeTests) {
8004 : // clang-format off
8005 : const char* context_data[][2] = {
8006 : {"", ""},
8007 : {"'use strict';", ""},
8008 5 : {nullptr, nullptr}};
8009 :
8010 : // clang-format off
8011 : const char* data[] = {
8012 : "`\\08`",
8013 : "`\\01`",
8014 : "`\\01${0}right`",
8015 : "`left${0}\\01`",
8016 : "`left${0}\\01${1}right`",
8017 : "`\\1`",
8018 : "`\\1${0}right`",
8019 : "`left${0}\\1`",
8020 : "`left${0}\\1${1}right`",
8021 : "`\\xg`",
8022 : "`\\xg${0}right`",
8023 : "`left${0}\\xg`",
8024 : "`left${0}\\xg${1}right`",
8025 : "`\\xAg`",
8026 : "`\\xAg${0}right`",
8027 : "`left${0}\\xAg`",
8028 : "`left${0}\\xAg${1}right`",
8029 : "`\\u0`",
8030 : "`\\u0${0}right`",
8031 : "`left${0}\\u0`",
8032 : "`left${0}\\u0${1}right`",
8033 : "`\\u0g`",
8034 : "`\\u0g${0}right`",
8035 : "`left${0}\\u0g`",
8036 : "`left${0}\\u0g${1}right`",
8037 : "`\\u00g`",
8038 : "`\\u00g${0}right`",
8039 : "`left${0}\\u00g`",
8040 : "`left${0}\\u00g${1}right`",
8041 : "`\\u000g`",
8042 : "`\\u000g${0}right`",
8043 : "`left${0}\\u000g`",
8044 : "`left${0}\\u000g${1}right`",
8045 : "`\\u{}`",
8046 : "`\\u{}${0}right`",
8047 : "`left${0}\\u{}`",
8048 : "`left${0}\\u{}${1}right`",
8049 : "`\\u{-0}`",
8050 : "`\\u{-0}${0}right`",
8051 : "`left${0}\\u{-0}`",
8052 : "`left${0}\\u{-0}${1}right`",
8053 : "`\\u{g}`",
8054 : "`\\u{g}${0}right`",
8055 : "`left${0}\\u{g}`",
8056 : "`left${0}\\u{g}${1}right`",
8057 : "`\\u{0`",
8058 : "`\\u{0${0}right`",
8059 : "`left${0}\\u{0`",
8060 : "`left${0}\\u{0${1}right`",
8061 : "`\\u{\\u{0}`",
8062 : "`\\u{\\u{0}${0}right`",
8063 : "`left${0}\\u{\\u{0}`",
8064 : "`left${0}\\u{\\u{0}${1}right`",
8065 : "`\\u{110000}`",
8066 : "`\\u{110000}${0}right`",
8067 : "`left${0}\\u{110000}`",
8068 : "`left${0}\\u{110000}${1}right`",
8069 : "`\\1``\\2`",
8070 : "tag` ${`\\u`}`",
8071 : "`\\u```",
8072 5 : nullptr};
8073 : // clang-format on
8074 :
8075 5 : RunParserSyncTest(context_data, data, kError);
8076 5 : }
8077 :
8078 25880 : TEST(DestructuringPositiveTests) {
8079 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8080 : {"var ", " = {};"},
8081 : {"'use strict'; const ", " = {};"},
8082 : {"function f(", ") {}"},
8083 : {"function f(argument1, ", ") {}"},
8084 : {"var f = (", ") => {};"},
8085 : {"var f = (argument1,", ") => {};"},
8086 : {"try {} catch(", ") {}"},
8087 5 : {nullptr, nullptr}};
8088 :
8089 : // clang-format off
8090 : const char* data[] = {
8091 : "a",
8092 : "{ x : y }",
8093 : "{ x : y = 1 }",
8094 : "{ get, set }",
8095 : "{ get = 1, set = 2 }",
8096 : "[a]",
8097 : "[a = 1]",
8098 : "[a,b,c]",
8099 : "[a, b = 42, c]",
8100 : "{ x : x, y : y }",
8101 : "{ x : x = 1, y : y }",
8102 : "{ x : x, y : y = 42 }",
8103 : "[]",
8104 : "{}",
8105 : "[{x:x, y:y}, [a,b,c]]",
8106 : "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
8107 : "{x}",
8108 : "{x, y}",
8109 : "{x = 42, y = 15}",
8110 : "[a,,b]",
8111 : "{42 : x}",
8112 : "{42 : x = 42}",
8113 : "{42e-2 : x}",
8114 : "{42e-2 : x = 42}",
8115 : "{x : y, x : z}",
8116 : "{'hi' : x}",
8117 : "{'hi' : x = 42}",
8118 : "{var: x}",
8119 : "{var: x = 42}",
8120 : "{[x] : z}",
8121 : "{[1+1] : z}",
8122 : "{[foo()] : z}",
8123 : "{}",
8124 : "[...rest]",
8125 : "[a,b,...rest]",
8126 : "[a,,...rest]",
8127 : "{ __proto__: x, __proto__: y}",
8128 : "{arguments: x}",
8129 : "{eval: x}",
8130 : "{ x : y, ...z }",
8131 : "{ x : y = 1, ...z }",
8132 : "{ x : x, y : y, ...z }",
8133 : "{ x : x = 1, y : y, ...z }",
8134 : "{ x : x, y : y = 42, ...z }",
8135 : "[{x:x, y:y, ...z}, [a,b,c]]",
8136 : "[{x:x = 1, y:y = 2, ...z}, [a = 3, b = 4, c = 5]]",
8137 : "{...x}",
8138 : "{x, ...y}",
8139 : "{x = 42, y = 15, ...z}",
8140 : "{42 : x = 42, ...y}",
8141 : "{'hi' : x, ...z}",
8142 : "{'hi' : x = 42, ...z}",
8143 : "{var: x = 42, ...z}",
8144 : "{[x] : z, ...y}",
8145 : "{[1+1] : z, ...x}",
8146 : "{arguments: x, ...z}",
8147 : "{ __proto__: x, __proto__: y, ...z}",
8148 : nullptr
8149 5 : };
8150 :
8151 : // clang-format on
8152 5 : RunParserSyncTest(context_data, data, kSuccess);
8153 :
8154 : // v8:5201
8155 : {
8156 : // clang-format off
8157 : const char* sloppy_context_data[][2] = {
8158 : {"var ", " = {};"},
8159 : {"function f(", ") {}"},
8160 : {"function f(argument1, ", ") {}"},
8161 : {"var f = (", ") => {};"},
8162 : {"var f = (argument1,", ") => {};"},
8163 : {"try {} catch(", ") {}"},
8164 : {nullptr, nullptr}
8165 5 : };
8166 :
8167 : const char* data[] = {
8168 : "{arguments}",
8169 : "{eval}",
8170 : "{x: arguments}",
8171 : "{x: eval}",
8172 : "{arguments = false}",
8173 : "{eval = false}",
8174 : "{...arguments}",
8175 : "{...eval}",
8176 : nullptr
8177 5 : };
8178 : // clang-format on
8179 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
8180 : }
8181 5 : }
8182 :
8183 :
8184 25880 : TEST(DestructuringNegativeTests) {
8185 : { // All modes.
8186 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8187 : {"var ", " = {};"},
8188 : {"'use strict'; const ", " = {};"},
8189 : {"function f(", ") {}"},
8190 : {"function f(argument1, ", ") {}"},
8191 : {"var f = (", ") => {};"},
8192 : {"var f = ", " => {};"},
8193 : {"var f = (argument1,", ") => {};"},
8194 : {"try {} catch(", ") {}"},
8195 5 : {nullptr, nullptr}};
8196 :
8197 : // clang-format off
8198 : const char* data[] = {
8199 : "a++",
8200 : "++a",
8201 : "delete a",
8202 : "void a",
8203 : "typeof a",
8204 : "--a",
8205 : "+a",
8206 : "-a",
8207 : "~a",
8208 : "!a",
8209 : "{ x : y++ }",
8210 : "[a++]",
8211 : "(x => y)",
8212 : "(async x => y)",
8213 : "((x, z) => y)",
8214 : "(async (x, z) => y)",
8215 : "a[i]", "a()",
8216 : "a.b",
8217 : "new a",
8218 : "a + a",
8219 : "a - a",
8220 : "a * a",
8221 : "a / a",
8222 : "a == a",
8223 : "a != a",
8224 : "a > a",
8225 : "a < a",
8226 : "a <<< a",
8227 : "a >>> a",
8228 : "function a() {}",
8229 : "function* a() {}",
8230 : "async function a() {}",
8231 : "a`bcd`",
8232 : "this",
8233 : "null",
8234 : "true",
8235 : "false",
8236 : "1",
8237 : "'abc'",
8238 : "/abc/",
8239 : "`abc`",
8240 : "class {}",
8241 : "{+2 : x}",
8242 : "{-2 : x}",
8243 : "var",
8244 : "[var]",
8245 : "{x : {y : var}}",
8246 : "{x : x = a+}",
8247 : "{x : x = (a+)}",
8248 : "{x : x += a}",
8249 : "{m() {} = 0}",
8250 : "{[1+1]}",
8251 : "[...rest, x]",
8252 : "[a,b,...rest, x]",
8253 : "[a,,...rest, x]",
8254 : "[...rest,]",
8255 : "[a,b,...rest,]",
8256 : "[a,,...rest,]",
8257 : "[...rest,...rest1]",
8258 : "[a,b,...rest,...rest1]",
8259 : "[a,,..rest,...rest1]",
8260 : "[x, y, ...z = 1]",
8261 : "[...z = 1]",
8262 : "[x, y, ...[z] = [1]]",
8263 : "[...[z] = [1]]",
8264 : "{ x : 3 }",
8265 : "{ x : 'foo' }",
8266 : "{ x : /foo/ }",
8267 : "{ x : `foo` }",
8268 : "{ get a() {} }",
8269 : "{ set a() {} }",
8270 : "{ method() {} }",
8271 : "{ *method() {} }",
8272 : "...a++",
8273 : "...++a",
8274 : "...typeof a",
8275 : "...[a++]",
8276 : "...(x => y)",
8277 : "{ ...x, }",
8278 : "{ ...x, y }",
8279 : "{ y, ...x, y }",
8280 : "{ ...x, ...y }",
8281 : "{ ...x, ...x }",
8282 : "{ ...x, ...x = {} }",
8283 : "{ ...x, ...x = ...x }",
8284 : "{ ...x, ...x = ...{ x } }",
8285 : "{ ,, ...x }",
8286 : "{ ...get a() {} }",
8287 : "{ ...set a() {} }",
8288 : "{ ...method() {} }",
8289 : "{ ...function() {} }",
8290 : "{ ...*method() {} }",
8291 : "{...{x} }",
8292 : "{...[x] }",
8293 : "{...{ x = 5 } }",
8294 : "{...[ x = 5 ] }",
8295 : "{...x.f }",
8296 : "{...x[0] }",
8297 : "async function* a() {}",
8298 : nullptr
8299 5 : };
8300 :
8301 : // clang-format on
8302 5 : RunParserSyncTest(context_data, data, kError);
8303 : }
8304 :
8305 : { // All modes.
8306 : const char* context_data[][2] = {
8307 : {"'use strict'; let ", " = {};"}, {"var ", " = {};"},
8308 : {"'use strict'; const ", " = {};"}, {"function f(", ") {}"},
8309 : {"function f(argument1, ", ") {}"}, {"var f = (", ") => {};"},
8310 5 : {"var f = (argument1,", ") => {};"}, {nullptr, nullptr}};
8311 :
8312 : // clang-format off
8313 : const char* data[] = {
8314 : "x => x",
8315 : "() => x",
8316 5 : nullptr};
8317 : // clang-format on
8318 5 : RunParserSyncTest(context_data, data, kError);
8319 : }
8320 :
8321 : { // Strict mode.
8322 : const char* context_data[][2] = {
8323 : {"'use strict'; var ", " = {};"},
8324 : {"'use strict'; let ", " = {};"},
8325 : {"'use strict'; const ", " = {};"},
8326 : {"'use strict'; function f(", ") {}"},
8327 : {"'use strict'; function f(argument1, ", ") {}"},
8328 5 : {nullptr, nullptr}};
8329 :
8330 : // clang-format off
8331 : const char* data[] = {
8332 : "[arguments]",
8333 : "[eval]",
8334 : "{ a : arguments }",
8335 : "{ a : eval }",
8336 : "[public]",
8337 : "{ x : private }",
8338 : "{ x : arguments }",
8339 : "{ x : eval }",
8340 : "{ arguments }",
8341 : "{ eval }",
8342 : "{ arguments = false }"
8343 : "{ eval = false }",
8344 : "{ ...eval }",
8345 : "{ ...arguments }",
8346 5 : nullptr};
8347 :
8348 : // clang-format on
8349 5 : RunParserSyncTest(context_data, data, kError);
8350 : }
8351 :
8352 : { // 'yield' in generators.
8353 : const char* context_data[][2] = {
8354 : {"function*() { var ", " = {};"},
8355 : {"function*() { 'use strict'; let ", " = {};"},
8356 : {"function*() { 'use strict'; const ", " = {};"},
8357 5 : {nullptr, nullptr}};
8358 :
8359 : // clang-format off
8360 : const char* data[] = {
8361 : "yield",
8362 : "[yield]",
8363 : "{ x : yield }",
8364 5 : nullptr};
8365 : // clang-format on
8366 5 : RunParserSyncTest(context_data, data, kError);
8367 : }
8368 :
8369 : { // Declaration-specific errors
8370 : const char* context_data[][2] = {{"'use strict'; var ", ""},
8371 : {"'use strict'; let ", ""},
8372 : {"'use strict'; const ", ""},
8373 : {"'use strict'; for (var ", ";;) {}"},
8374 : {"'use strict'; for (let ", ";;) {}"},
8375 : {"'use strict'; for (const ", ";;) {}"},
8376 : {"var ", ""},
8377 : {"let ", ""},
8378 : {"const ", ""},
8379 : {"for (var ", ";;) {}"},
8380 : {"for (let ", ";;) {}"},
8381 : {"for (const ", ";;) {}"},
8382 5 : {nullptr, nullptr}};
8383 :
8384 : // clang-format off
8385 : const char* data[] = {
8386 : "{ a }",
8387 : "[ a ]",
8388 : "{ ...a }",
8389 : nullptr
8390 5 : };
8391 : // clang-format on
8392 5 : RunParserSyncTest(context_data, data, kError);
8393 : }
8394 5 : }
8395 :
8396 25880 : TEST(ObjectRestNegativeTestSlow) {
8397 : // clang-format off
8398 : const char* context_data[][2] = {
8399 : {"var { ", " } = { a: 1};"},
8400 : { nullptr, nullptr }
8401 5 : };
8402 :
8403 : using v8::internal::Code;
8404 : std::string statement;
8405 327675 : for (int i = 0; i < Code::kMaxArguments; ++i) {
8406 983010 : statement += std::to_string(i) + " : " + "x, ";
8407 : }
8408 : statement += "...y";
8409 :
8410 : const char* statement_data[] = {
8411 : statement.c_str(),
8412 : nullptr
8413 10 : };
8414 :
8415 : // clang-format on
8416 : // The test is quite slow, so run it with a reduced set of flags.
8417 : static const ParserFlag flags[] = {kAllowLazy};
8418 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags,
8419 5 : arraysize(flags));
8420 5 : }
8421 :
8422 25880 : TEST(DestructuringAssignmentPositiveTests) {
8423 : const char* context_data[][2] = {
8424 : {"'use strict'; let x, y, z; (", " = {});"},
8425 : {"var x, y, z; (", " = {});"},
8426 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8427 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8428 : {"var x, y, z; for (x in ", " = {});"},
8429 : {"var x, y, z; for (x of ", " = {});"},
8430 : {"var x, y, z; for (", " in {});"},
8431 : {"var x, y, z; for (", " of {});"},
8432 : {"'use strict'; var x, y, z; for (", " in {});"},
8433 : {"'use strict'; var x, y, z; for (", " of {});"},
8434 : {"var x, y, z; m(['a']) ? ", " = {} : rhs"},
8435 : {"var x, y, z; m(['b']) ? lhs : ", " = {}"},
8436 : {"'use strict'; var x, y, z; m(['a']) ? ", " = {} : rhs"},
8437 : {"'use strict'; var x, y, z; m(['b']) ? lhs : ", " = {}"},
8438 5 : {nullptr, nullptr}};
8439 :
8440 : const char* mixed_assignments_context_data[][2] = {
8441 : {"'use strict'; let x, y, z; (", " = z = {});"},
8442 : {"var x, y, z; (", " = z = {});"},
8443 : {"'use strict'; let x, y, z; (x = ", " = z = {});"},
8444 : {"var x, y, z; (x = ", " = z = {});"},
8445 : {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
8446 : {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
8447 : {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
8448 : {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
8449 : {"var x, y, z; for (x in ", " = z = {});"},
8450 : {"var x, y, z; for (x in x = ", " = z = {});"},
8451 : {"var x, y, z; for (x of ", " = z = {});"},
8452 : {"var x, y, z; for (x of x = ", " = z = {});"},
8453 5 : {nullptr, nullptr}};
8454 :
8455 : // clang-format off
8456 : const char* data[] = {
8457 : "x",
8458 :
8459 : "{ x : y }",
8460 : "{ x : foo().y }",
8461 : "{ x : foo()[y] }",
8462 : "{ x : y.z }",
8463 : "{ x : y[z] }",
8464 : "{ x : { y } }",
8465 : "{ x : { foo: y } }",
8466 : "{ x : { foo: foo().y } }",
8467 : "{ x : { foo: foo()[y] } }",
8468 : "{ x : { foo: y.z } }",
8469 : "{ x : { foo: y[z] } }",
8470 : "{ x : [ y ] }",
8471 : "{ x : [ foo().y ] }",
8472 : "{ x : [ foo()[y] ] }",
8473 : "{ x : [ y.z ] }",
8474 : "{ x : [ y[z] ] }",
8475 :
8476 : "{ x : y = 10 }",
8477 : "{ x : foo().y = 10 }",
8478 : "{ x : foo()[y] = 10 }",
8479 : "{ x : y.z = 10 }",
8480 : "{ x : y[z] = 10 }",
8481 : "{ x : { y = 10 } = {} }",
8482 : "{ x : { foo: y = 10 } = {} }",
8483 : "{ x : { foo: foo().y = 10 } = {} }",
8484 : "{ x : { foo: foo()[y] = 10 } = {} }",
8485 : "{ x : { foo: y.z = 10 } = {} }",
8486 : "{ x : { foo: y[z] = 10 } = {} }",
8487 : "{ x : [ y = 10 ] = {} }",
8488 : "{ x : [ foo().y = 10 ] = {} }",
8489 : "{ x : [ foo()[y] = 10 ] = {} }",
8490 : "{ x : [ y.z = 10 ] = {} }",
8491 : "{ x : [ y[z] = 10 ] = {} }",
8492 : "{ z : { __proto__: x, __proto__: y } = z }"
8493 :
8494 : "[ x ]",
8495 : "[ foo().x ]",
8496 : "[ foo()[x] ]",
8497 : "[ x.y ]",
8498 : "[ x[y] ]",
8499 : "[ { x } ]",
8500 : "[ { x : y } ]",
8501 : "[ { x : foo().y } ]",
8502 : "[ { x : foo()[y] } ]",
8503 : "[ { x : x.y } ]",
8504 : "[ { x : x[y] } ]",
8505 : "[ [ x ] ]",
8506 : "[ [ foo().x ] ]",
8507 : "[ [ foo()[x] ] ]",
8508 : "[ [ x.y ] ]",
8509 : "[ [ x[y] ] ]",
8510 :
8511 : "[ x = 10 ]",
8512 : "[ foo().x = 10 ]",
8513 : "[ foo()[x] = 10 ]",
8514 : "[ x.y = 10 ]",
8515 : "[ x[y] = 10 ]",
8516 : "[ { x = 10 } = {} ]",
8517 : "[ { x : y = 10 } = {} ]",
8518 : "[ { x : foo().y = 10 } = {} ]",
8519 : "[ { x : foo()[y] = 10 } = {} ]",
8520 : "[ { x : x.y = 10 } = {} ]",
8521 : "[ { x : x[y] = 10 } = {} ]",
8522 : "[ [ x = 10 ] = {} ]",
8523 : "[ [ foo().x = 10 ] = {} ]",
8524 : "[ [ foo()[x] = 10 ] = {} ]",
8525 : "[ [ x.y = 10 ] = {} ]",
8526 : "[ [ x[y] = 10 ] = {} ]",
8527 : "{ x : y = 1 }",
8528 : "{ x }",
8529 : "{ x, y, z }",
8530 : "{ x = 1, y: z, z: y }",
8531 : "{x = 42, y = 15}",
8532 : "[x]",
8533 : "[x = 1]",
8534 : "[x,y,z]",
8535 : "[x, y = 42, z]",
8536 : "{ x : x, y : y }",
8537 : "{ x : x = 1, y : y }",
8538 : "{ x : x, y : y = 42 }",
8539 : "[]",
8540 : "{}",
8541 : "[{x:x, y:y}, [,x,z,]]",
8542 : "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
8543 : "[x,,y]",
8544 : "[(x),,(y)]",
8545 : "[(x)]",
8546 : "{42 : x}",
8547 : "{42 : x = 42}",
8548 : "{42e-2 : x}",
8549 : "{42e-2 : x = 42}",
8550 : "{'hi' : x}",
8551 : "{'hi' : x = 42}",
8552 : "{var: x}",
8553 : "{var: x = 42}",
8554 : "{var: (x) = 42}",
8555 : "{[x] : z}",
8556 : "{[1+1] : z}",
8557 : "{[1+1] : (z)}",
8558 : "{[foo()] : z}",
8559 : "{[foo()] : (z)}",
8560 : "{[foo()] : foo().bar}",
8561 : "{[foo()] : foo()['bar']}",
8562 : "{[foo()] : this.bar}",
8563 : "{[foo()] : this['bar']}",
8564 : "{[foo()] : 'foo'.bar}",
8565 : "{[foo()] : 'foo'['bar']}",
8566 : "[...x]",
8567 : "[x,y,...z]",
8568 : "[x,,...z]",
8569 : "{ x: y }",
8570 : "[x, y]",
8571 : "[((x, y) => z).x]",
8572 : "{x: ((y, z) => z).x}",
8573 : "[((x, y) => z)['x']]",
8574 : "{x: ((y, z) => z)['x']}",
8575 :
8576 : "{x: { y = 10 } }",
8577 : "[(({ x } = { x: 1 }) => x).a]",
8578 :
8579 : "{ ...d.x }",
8580 : "{ ...c[0]}",
8581 :
8582 : // v8:4662
8583 : "{ x: (y) }",
8584 : "{ x: (y) = [] }",
8585 : "{ x: (foo.bar) }",
8586 : "{ x: (foo['bar']) }",
8587 : "[ ...(a) ]",
8588 : "[ ...(foo['bar']) ]",
8589 : "[ ...(foo.bar) ]",
8590 : "[ (y) ]",
8591 : "[ (foo.bar) ]",
8592 : "[ (foo['bar']) ]",
8593 :
8594 5 : nullptr};
8595 : // clang-format on
8596 5 : RunParserSyncTest(context_data, data, kSuccess);
8597 :
8598 5 : RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
8599 :
8600 : const char* empty_context_data[][2] = {
8601 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8602 :
8603 : // CoverInitializedName ambiguity handling in various contexts
8604 : const char* ambiguity_data[] = {
8605 : "var foo = { x = 10 } = {};",
8606 : "var foo = { q } = { x = 10 } = {};",
8607 : "var foo; foo = { x = 10 } = {};",
8608 : "var foo; foo = { q } = { x = 10 } = {};",
8609 : "var x; ({ x = 10 } = {});",
8610 : "var q, x; ({ q } = { x = 10 } = {});",
8611 : "var x; [{ x = 10 } = {}]",
8612 : "var x; (true ? { x = true } = {} : { x = false } = {})",
8613 : "var q, x; (q, { x = 10 } = {});",
8614 : "var { x = 10 } = { x = 20 } = {};",
8615 : "var { __proto__: x, __proto__: y } = {}",
8616 : "({ __proto__: x, __proto__: y } = {})",
8617 : "var { x = 10 } = (o = { x = 20 } = {});",
8618 : "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
8619 : nullptr,
8620 5 : };
8621 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
8622 5 : }
8623 :
8624 :
8625 25880 : TEST(DestructuringAssignmentNegativeTests) {
8626 : const char* context_data[][2] = {
8627 : {"'use strict'; let x, y, z; (", " = {});"},
8628 : {"var x, y, z; (", " = {});"},
8629 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8630 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8631 : {"var x, y, z; for (x in ", " = {});"},
8632 : {"var x, y, z; for (x of ", " = {});"},
8633 5 : {nullptr, nullptr}};
8634 :
8635 : // clang-format off
8636 : const char* data[] = {
8637 : "{ x : ++y }",
8638 : "{ x : y * 2 }",
8639 : "{ get x() {} }",
8640 : "{ set x() {} }",
8641 : "{ x: y() }",
8642 : "{ this }",
8643 : "{ x: this }",
8644 : "{ x: this = 1 }",
8645 : "{ super }",
8646 : "{ x: super }",
8647 : "{ x: super = 1 }",
8648 : "{ new.target }",
8649 : "{ x: new.target }",
8650 : "{ x: new.target = 1 }",
8651 : "{ import.meta }",
8652 : "{ x: import.meta }",
8653 : "{ x: import.meta = 1 }",
8654 : "[x--]",
8655 : "[--x = 1]",
8656 : "[x()]",
8657 : "[this]",
8658 : "[this = 1]",
8659 : "[new.target]",
8660 : "[new.target = 1]",
8661 : "[import.meta]",
8662 : "[import.meta = 1]",
8663 : "[super]",
8664 : "[super = 1]",
8665 : "[function f() {}]",
8666 : "[async function f() {}]",
8667 : "[function* f() {}]",
8668 : "[50]",
8669 : "[(50)]",
8670 : "[(function() {})]",
8671 : "[(async function() {})]",
8672 : "[(function*() {})]",
8673 : "[(foo())]",
8674 : "{ x: 50 }",
8675 : "{ x: (50) }",
8676 : "['str']",
8677 : "{ x: 'str' }",
8678 : "{ x: ('str') }",
8679 : "{ x: (foo()) }",
8680 : "{ x: function() {} }",
8681 : "{ x: async function() {} }",
8682 : "{ x: function*() {} }",
8683 : "{ x: (function() {}) }",
8684 : "{ x: (async function() {}) }",
8685 : "{ x: (function*() {}) }",
8686 : "{ x: y } = 'str'",
8687 : "[x, y] = 'str'",
8688 : "[(x,y) => z]",
8689 : "[async(x,y) => z]",
8690 : "[async x => z]",
8691 : "{x: (y) => z}",
8692 : "{x: (y,w) => z}",
8693 : "{x: async (y) => z}",
8694 : "{x: async (y,w) => z}",
8695 : "[x, ...y, z]",
8696 : "[...x,]",
8697 : "[x, y, ...z = 1]",
8698 : "[...z = 1]",
8699 : "[x, y, ...[z] = [1]]",
8700 : "[...[z] = [1]]",
8701 :
8702 : "[...++x]",
8703 : "[...x--]",
8704 : "[...!x]",
8705 : "[...x + y]",
8706 :
8707 : // v8:4657
8708 : "({ x: x4, x: (x+=1e4) })",
8709 : "(({ x: x4, x: (x+=1e4) }))",
8710 : "({ x: x4, x: (x+=1e4) } = {})",
8711 : "(({ x: x4, x: (x+=1e4) } = {}))",
8712 : "(({ x: x4, x: (x+=1e4) }) = {})",
8713 : "({ x: y } = {})",
8714 : "(({ x: y } = {}))",
8715 : "(({ x: y }) = {})",
8716 : "([a])",
8717 : "(([a]))",
8718 : "([a] = [])",
8719 : "(([a] = []))",
8720 : "(([a]) = [])",
8721 :
8722 : // v8:4662
8723 : "{ x: ([y]) }",
8724 : "{ x: ([y] = []) }",
8725 : "{ x: ({y}) }",
8726 : "{ x: ({y} = {}) }",
8727 : "{ x: (++y) }",
8728 : "[ (...[a]) ]",
8729 : "[ ...([a]) ]",
8730 : "[ ...([a] = [])",
8731 : "[ ...[ ( [ a ] ) ] ]",
8732 : "[ ([a]) ]",
8733 : "[ (...[a]) ]",
8734 : "[ ([a] = []) ]",
8735 : "[ (++y) ]",
8736 : "[ ...(++y) ]",
8737 :
8738 : "[ x += x ]",
8739 : "{ foo: x += x }",
8740 :
8741 5 : nullptr};
8742 : // clang-format on
8743 5 : RunParserSyncTest(context_data, data, kError);
8744 :
8745 : const char* empty_context_data[][2] = {
8746 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8747 :
8748 : // CoverInitializedName ambiguity handling in various contexts
8749 : const char* ambiguity_data[] = {
8750 : "var foo = { x = 10 };", "var foo = { q } = { x = 10 };",
8751 : "var foo; foo = { x = 10 };", "var foo; foo = { q } = { x = 10 };",
8752 : "var x; ({ x = 10 });", "var q, x; ({ q } = { x = 10 });",
8753 : "var x; [{ x = 10 }]", "var x; (true ? { x = true } : { x = false })",
8754 : "var q, x; (q, { x = 10 });", "var { x = 10 } = { x = 20 };",
8755 : "var { x = 10 } = (o = { x = 20 });",
8756 : "var x; (({ x = 10 } = { x = 20 }) => x)({})",
8757 :
8758 : // Not ambiguous, but uses same context data
8759 : "switch([window %= []] = []) { default: }",
8760 :
8761 : nullptr,
8762 5 : };
8763 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kError);
8764 :
8765 : // Strict mode errors
8766 : const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
8767 : {"'use strict'; for (", " of {}) {}"},
8768 : {"'use strict'; for (", " in {}) {}"},
8769 5 : {nullptr, nullptr}};
8770 : const char* strict_data[] = {
8771 : "{ eval }", "{ arguments }", "{ foo: eval }", "{ foo: arguments }",
8772 : "{ eval = 0 }", "{ arguments = 0 }", "{ foo: eval = 0 }",
8773 : "{ foo: arguments = 0 }", "[ eval ]", "[ arguments ]", "[ eval = 0 ]",
8774 : "[ arguments = 0 ]",
8775 :
8776 : // v8:4662
8777 : "{ x: (eval) }", "{ x: (arguments) }", "{ x: (eval = 0) }",
8778 : "{ x: (arguments = 0) }", "{ x: (eval) = 0 }", "{ x: (arguments) = 0 }",
8779 : "[ (eval) ]", "[ (arguments) ]", "[ (eval = 0) ]", "[ (arguments = 0) ]",
8780 : "[ (eval) = 0 ]", "[ (arguments) = 0 ]", "[ ...(eval) ]",
8781 : "[ ...(arguments) ]", "[ ...(eval = 0) ]", "[ ...(arguments = 0) ]",
8782 : "[ ...(eval) = 0 ]", "[ ...(arguments) = 0 ]",
8783 :
8784 5 : nullptr};
8785 5 : RunParserSyncTest(strict_context_data, strict_data, kError);
8786 5 : }
8787 :
8788 :
8789 25880 : TEST(DestructuringDisallowPatternsInForVarIn) {
8790 : const char* context_data[][2] = {
8791 5 : {"", ""}, {"function f() {", "}"}, {nullptr, nullptr}};
8792 : // clang-format off
8793 : const char* error_data[] = {
8794 : "for (let x = {} in null);",
8795 : "for (let x = {} of null);",
8796 5 : nullptr};
8797 : // clang-format on
8798 5 : RunParserSyncTest(context_data, error_data, kError);
8799 :
8800 : // clang-format off
8801 : const char* success_data[] = {
8802 : "for (var x = {} in null);",
8803 5 : nullptr};
8804 : // clang-format on
8805 5 : RunParserSyncTest(context_data, success_data, kSuccess);
8806 5 : }
8807 :
8808 :
8809 25880 : TEST(DestructuringDuplicateParams) {
8810 : const char* context_data[][2] = {{"'use strict';", ""},
8811 : {"function outer() { 'use strict';", "}"},
8812 5 : {nullptr, nullptr}};
8813 :
8814 :
8815 : // clang-format off
8816 : const char* error_data[] = {
8817 : "function f(x,x){}",
8818 : "function f(x, {x : x}){}",
8819 : "function f(x, {x}){}",
8820 : "function f({x,x}) {}",
8821 : "function f([x,x]) {}",
8822 : "function f(x, [y,{z:x}]) {}",
8823 : "function f([x,{y:x}]) {}",
8824 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8825 : "function f(x, x, {a}) {}",
8826 5 : nullptr};
8827 : // clang-format on
8828 5 : RunParserSyncTest(context_data, error_data, kError);
8829 5 : }
8830 :
8831 :
8832 25880 : TEST(DestructuringDuplicateParamsSloppy) {
8833 : const char* context_data[][2] = {
8834 5 : {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
8835 :
8836 :
8837 : // clang-format off
8838 : const char* error_data[] = {
8839 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8840 : "function f(x, {x : x}){}",
8841 : "function f(x, {x}){}",
8842 : "function f({x,x}) {}",
8843 : "function f(x, x, {a}) {}",
8844 5 : nullptr};
8845 : // clang-format on
8846 5 : RunParserSyncTest(context_data, error_data, kError);
8847 5 : }
8848 :
8849 :
8850 25880 : TEST(DestructuringDisallowPatternsInSingleParamArrows) {
8851 : const char* context_data[][2] = {{"'use strict';", ""},
8852 : {"function outer() { 'use strict';", "}"},
8853 : {"", ""},
8854 : {"function outer() { ", "}"},
8855 5 : {nullptr, nullptr}};
8856 :
8857 : // clang-format off
8858 : const char* error_data[] = {
8859 : "var f = {x} => {};",
8860 : "var f = {x,y} => {};",
8861 5 : nullptr};
8862 : // clang-format on
8863 5 : RunParserSyncTest(context_data, error_data, kError);
8864 5 : }
8865 :
8866 :
8867 25880 : TEST(DefaultParametersYieldInInitializers) {
8868 : // clang-format off
8869 : const char* sloppy_function_context_data[][2] = {
8870 : {"(function f(", ") { });"},
8871 : {nullptr, nullptr}
8872 5 : };
8873 :
8874 : const char* strict_function_context_data[][2] = {
8875 : {"'use strict'; (function f(", ") { });"},
8876 : {nullptr, nullptr}
8877 5 : };
8878 :
8879 : const char* sloppy_arrow_context_data[][2] = {
8880 : {"((", ")=>{});"},
8881 : {nullptr, nullptr}
8882 5 : };
8883 :
8884 : const char* strict_arrow_context_data[][2] = {
8885 : {"'use strict'; ((", ")=>{});"},
8886 : {nullptr, nullptr}
8887 5 : };
8888 :
8889 : const char* generator_context_data[][2] = {
8890 : {"'use strict'; (function *g(", ") { });"},
8891 : {"(function *g(", ") { });"},
8892 : // Arrow function within generator has the same rules.
8893 : {"'use strict'; (function *g() { (", ") => {} });"},
8894 : {"(function *g() { (", ") => {} });"},
8895 : // And similarly for arrow functions in the parameter list.
8896 : {"'use strict'; (function *g(z = (", ") => {}) { });"},
8897 : {"(function *g(z = (", ") => {}) { });"},
8898 : {nullptr, nullptr}
8899 5 : };
8900 :
8901 : const char* parameter_data[] = {
8902 : "x=yield",
8903 : "x, y=yield",
8904 : "{x=yield}",
8905 : "[x=yield]",
8906 :
8907 : "x=(yield)",
8908 : "x, y=(yield)",
8909 : "{x=(yield)}",
8910 : "[x=(yield)]",
8911 :
8912 : "x=f(yield)",
8913 : "x, y=f(yield)",
8914 : "{x=f(yield)}",
8915 : "[x=f(yield)]",
8916 :
8917 : "{x}=yield",
8918 : "[x]=yield",
8919 :
8920 : "{x}=(yield)",
8921 : "[x]=(yield)",
8922 :
8923 : "{x}=f(yield)",
8924 : "[x]=f(yield)",
8925 : nullptr
8926 5 : };
8927 :
8928 : // Because classes are always in strict mode, these are always errors.
8929 : const char* always_error_param_data[] = {
8930 : "x = class extends (yield) { }",
8931 : "x = class extends f(yield) { }",
8932 : "x = class extends (null, yield) { }",
8933 : "x = class extends (a ? null : yield) { }",
8934 : "[x] = [class extends (a ? null : yield) { }]",
8935 : "[x = class extends (a ? null : yield) { }]",
8936 : "[x = class extends (a ? null : yield) { }] = [null]",
8937 : "x = class { [yield]() { } }",
8938 : "x = class { static [yield]() { } }",
8939 : "x = class { [(yield, 1)]() { } }",
8940 : "x = class { [y = (yield, 1)]() { } }",
8941 : nullptr
8942 5 : };
8943 : // clang-format on
8944 :
8945 5 : RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
8946 5 : RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
8947 :
8948 5 : RunParserSyncTest(strict_function_context_data, parameter_data, kError);
8949 5 : RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
8950 :
8951 5 : RunParserSyncTest(generator_context_data, parameter_data, kError);
8952 5 : RunParserSyncTest(generator_context_data, always_error_param_data, kError);
8953 5 : }
8954 :
8955 25880 : TEST(SpreadArray) {
8956 : const char* context_data[][2] = {
8957 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8958 :
8959 : // clang-format off
8960 : const char* data[] = {
8961 : "[...a]",
8962 : "[a, ...b]",
8963 : "[...a,]",
8964 : "[...a, ,]",
8965 : "[, ...a]",
8966 : "[...a, ...b]",
8967 : "[...a, , ...b]",
8968 : "[...[...a]]",
8969 : "[, ...a]",
8970 : "[, , ...a]",
8971 5 : nullptr};
8972 : // clang-format on
8973 5 : RunParserSyncTest(context_data, data, kSuccess);
8974 5 : }
8975 :
8976 :
8977 25880 : TEST(SpreadArrayError) {
8978 : const char* context_data[][2] = {
8979 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8980 :
8981 : // clang-format off
8982 : const char* data[] = {
8983 : "[...]",
8984 : "[a, ...]",
8985 : "[..., ]",
8986 : "[..., ...]",
8987 : "[ (...a)]",
8988 5 : nullptr};
8989 : // clang-format on
8990 5 : RunParserSyncTest(context_data, data, kError);
8991 5 : }
8992 :
8993 :
8994 25880 : TEST(NewTarget) {
8995 : // clang-format off
8996 : const char* good_context_data[][2] = {
8997 : {"function f() {", "}"},
8998 : {"'use strict'; function f() {", "}"},
8999 : {"var f = function() {", "}"},
9000 : {"'use strict'; var f = function() {", "}"},
9001 : {"({m: function() {", "}})"},
9002 : {"'use strict'; ({m: function() {", "}})"},
9003 : {"({m() {", "}})"},
9004 : {"'use strict'; ({m() {", "}})"},
9005 : {"({get x() {", "}})"},
9006 : {"'use strict'; ({get x() {", "}})"},
9007 : {"({set x(_) {", "}})"},
9008 : {"'use strict'; ({set x(_) {", "}})"},
9009 : {"class C {m() {", "}}"},
9010 : {"class C {get x() {", "}}"},
9011 : {"class C {set x(_) {", "}}"},
9012 : {nullptr}
9013 5 : };
9014 :
9015 : const char* bad_context_data[][2] = {
9016 : {"", ""},
9017 : {"'use strict';", ""},
9018 : {nullptr}
9019 5 : };
9020 :
9021 : const char* data[] = {
9022 : "new.target",
9023 : "{ new.target }",
9024 : "() => { new.target }",
9025 : "() => new.target",
9026 : "if (1) { new.target }",
9027 : "if (1) {} else { new.target }",
9028 : "while (0) { new.target }",
9029 : "do { new.target } while (0)",
9030 : nullptr
9031 5 : };
9032 :
9033 : // clang-format on
9034 :
9035 5 : RunParserSyncTest(good_context_data, data, kSuccess);
9036 5 : RunParserSyncTest(bad_context_data, data, kError);
9037 5 : }
9038 :
9039 25880 : TEST(ImportMetaSuccess) {
9040 : // clang-format off
9041 : const char* context_data[][2] = {
9042 : {"", ""},
9043 : {"'use strict';", ""},
9044 : {"function f() {", "}"},
9045 : {"'use strict'; function f() {", "}"},
9046 : {"var f = function() {", "}"},
9047 : {"'use strict'; var f = function() {", "}"},
9048 : {"({m: function() {", "}})"},
9049 : {"'use strict'; ({m: function() {", "}})"},
9050 : {"({m() {", "}})"},
9051 : {"'use strict'; ({m() {", "}})"},
9052 : {"({get x() {", "}})"},
9053 : {"'use strict'; ({get x() {", "}})"},
9054 : {"({set x(_) {", "}})"},
9055 : {"'use strict'; ({set x(_) {", "}})"},
9056 : {"class C {m() {", "}}"},
9057 : {"class C {get x() {", "}}"},
9058 : {"class C {set x(_) {", "}}"},
9059 : {nullptr}
9060 5 : };
9061 :
9062 : const char* data[] = {
9063 : "import.meta",
9064 : "() => { import.meta }",
9065 : "() => import.meta",
9066 : "if (1) { import.meta }",
9067 : "if (1) {} else { import.meta }",
9068 : "while (0) { import.meta }",
9069 : "do { import.meta } while (0)",
9070 : "import.meta.url",
9071 : "import.meta[0]",
9072 : "import.meta.couldBeMutable = true",
9073 : "import.meta()",
9074 : "new import.meta.MagicClass",
9075 : "new import.meta",
9076 : "t = [...import.meta]",
9077 : "f = {...import.meta}",
9078 : "delete import.meta",
9079 : nullptr
9080 5 : };
9081 :
9082 : // clang-format on
9083 :
9084 : // Making sure the same *wouldn't* parse without the flags
9085 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9086 : nullptr, 0, true, true);
9087 :
9088 : static const ParserFlag flags[] = {
9089 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9090 : };
9091 : // 2.1.1 Static Semantics: Early Errors
9092 : // ImportMeta
9093 : // * It is an early Syntax Error if Module is not the syntactic goal symbol.
9094 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9095 5 : arraysize(flags));
9096 : // Making sure the same wouldn't parse without the flags either
9097 5 : RunParserSyncTest(context_data, data, kError);
9098 :
9099 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
9100 : arraysize(flags));
9101 5 : }
9102 :
9103 25880 : TEST(ImportMetaFailure) {
9104 : // clang-format off
9105 : const char* context_data[][2] = {
9106 : {"var ", ""},
9107 : {"let ", ""},
9108 : {"const ", ""},
9109 : {"var [", "] = [1]"},
9110 : {"([", "] = [1])"},
9111 : {"({", "} = {1})"},
9112 : {"var {", " = 1} = 1"},
9113 : {"for (var ", " of [1]) {}"},
9114 : {"(", ") => {}"},
9115 : {"let f = ", " => {}"},
9116 : {nullptr}
9117 5 : };
9118 :
9119 : const char* data[] = {
9120 : "import.meta",
9121 : nullptr
9122 5 : };
9123 :
9124 : // clang-format on
9125 :
9126 : static const ParserFlag flags[] = {
9127 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9128 : };
9129 :
9130 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9131 5 : arraysize(flags));
9132 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9133 : arraysize(flags));
9134 :
9135 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9136 : nullptr, 0, true, true);
9137 5 : RunParserSyncTest(context_data, data, kError);
9138 5 : }
9139 :
9140 25880 : TEST(ConstSloppy) {
9141 : // clang-format off
9142 : const char* context_data[][2] = {
9143 : {"", ""},
9144 : {"{", "}"},
9145 : {nullptr, nullptr}
9146 5 : };
9147 :
9148 : const char* data[] = {
9149 : "const x = 1",
9150 : "for (const x = 1; x < 1; x++) {}",
9151 : "for (const x in {}) {}",
9152 : "for (const x of []) {}",
9153 : nullptr
9154 5 : };
9155 : // clang-format on
9156 5 : RunParserSyncTest(context_data, data, kSuccess);
9157 5 : }
9158 :
9159 :
9160 25880 : TEST(LetSloppy) {
9161 : // clang-format off
9162 : const char* context_data[][2] = {
9163 : {"", ""},
9164 : {"'use strict';", ""},
9165 : {"{", "}"},
9166 : {nullptr, nullptr}
9167 5 : };
9168 :
9169 : const char* data[] = {
9170 : "let x",
9171 : "let x = 1",
9172 : "for (let x = 1; x < 1; x++) {}",
9173 : "for (let x in {}) {}",
9174 : "for (let x of []) {}",
9175 : nullptr
9176 5 : };
9177 : // clang-format on
9178 :
9179 5 : RunParserSyncTest(context_data, data, kSuccess);
9180 5 : }
9181 :
9182 :
9183 25880 : TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
9184 : // TC39 deemed "use strict" directives to be an error when occurring in the
9185 : // body of a function with non-simple parameter list, on 29/7/2015.
9186 : // https://goo.gl/ueA7Ln
9187 : const char* context_data[][2] = {
9188 : {"function f(", ") { 'use strict'; }"},
9189 : {"function* g(", ") { 'use strict'; }"},
9190 : {"class c { foo(", ") { 'use strict' }"},
9191 : {"var a = (", ") => { 'use strict'; }"},
9192 : {"var o = { m(", ") { 'use strict'; }"},
9193 : {"var o = { *gm(", ") { 'use strict'; }"},
9194 : {"var c = { m(", ") { 'use strict'; }"},
9195 : {"var c = { *gm(", ") { 'use strict'; }"},
9196 :
9197 : {"'use strict'; function f(", ") { 'use strict'; }"},
9198 : {"'use strict'; function* g(", ") { 'use strict'; }"},
9199 : {"'use strict'; class c { foo(", ") { 'use strict' }"},
9200 : {"'use strict'; var a = (", ") => { 'use strict'; }"},
9201 : {"'use strict'; var o = { m(", ") { 'use strict'; }"},
9202 : {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
9203 : {"'use strict'; var c = { m(", ") { 'use strict'; }"},
9204 : {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
9205 :
9206 5 : {nullptr, nullptr}};
9207 :
9208 : const char* data[] = {
9209 : // TODO(@caitp): support formal parameter initializers
9210 : "{}",
9211 : "[]",
9212 : "[{}]",
9213 : "{a}",
9214 : "a, {b}",
9215 : "a, b, {c, d, e}",
9216 : "initializer = true",
9217 : "a, b, c = 1",
9218 : "...args",
9219 : "a, b, ...rest",
9220 : "[a, b, ...rest]",
9221 : "{ bindingPattern = {} }",
9222 : "{ initializedBindingPattern } = { initializedBindingPattern: true }",
9223 5 : nullptr};
9224 :
9225 5 : RunParserSyncTest(context_data, data, kError);
9226 5 : }
9227 :
9228 :
9229 25880 : TEST(LetSloppyOnly) {
9230 : // clang-format off
9231 : const char* context_data[][2] = {
9232 : {"", ""},
9233 : {"{", "}"},
9234 : {"(function() {", "})()"},
9235 : {nullptr, nullptr}
9236 5 : };
9237 :
9238 : const char* data[] = {
9239 : "let",
9240 : "let = 1",
9241 : "for (let = 1; let < 1; let++) {}",
9242 : "for (let in {}) {}",
9243 : "for (var let = 1; let < 1; let++) {}",
9244 : "for (var let in {}) {}",
9245 : "for (var [let] = 1; let < 1; let++) {}",
9246 : "for (var [let] in {}) {}",
9247 : "var let",
9248 : "var [let] = []",
9249 : nullptr
9250 5 : };
9251 : // clang-format on
9252 :
9253 5 : RunParserSyncTest(context_data, data, kSuccess);
9254 :
9255 : // Some things should be rejected even in sloppy mode
9256 : // This addresses BUG(v8:4403).
9257 :
9258 : // clang-format off
9259 : const char* fail_data[] = {
9260 : "let let = 1",
9261 : "for (let let = 1; let < 1; let++) {}",
9262 : "for (let let in {}) {}",
9263 : "for (let let of []) {}",
9264 : "const let = 1",
9265 : "for (const let = 1; let < 1; let++) {}",
9266 : "for (const let in {}) {}",
9267 : "for (const let of []) {}",
9268 : "let [let] = 1",
9269 : "for (let [let] = 1; let < 1; let++) {}",
9270 : "for (let [let] in {}) {}",
9271 : "for (let [let] of []) {}",
9272 : "const [let] = 1",
9273 : "for (const [let] = 1; let < 1; let++) {}",
9274 : "for (const [let] in {}) {}",
9275 : "for (const [let] of []) {}",
9276 :
9277 : // Sprinkle in the escaped version too.
9278 : "let l\\u0065t = 1",
9279 : "const l\\u0065t = 1",
9280 : "let [l\\u0065t] = 1",
9281 : "const [l\\u0065t] = 1",
9282 : "for (let l\\u0065t in {}) {}",
9283 : nullptr
9284 5 : };
9285 : // clang-format on
9286 :
9287 5 : RunParserSyncTest(context_data, fail_data, kError);
9288 5 : }
9289 :
9290 :
9291 25880 : TEST(EscapedKeywords) {
9292 : // clang-format off
9293 : const char* sloppy_context_data[][2] = {
9294 : {"", ""},
9295 : {nullptr, nullptr}
9296 5 : };
9297 :
9298 : const char* strict_context_data[][2] = {
9299 : {"'use strict';", ""},
9300 : {nullptr, nullptr}
9301 5 : };
9302 :
9303 : const char* fail_data[] = {
9304 : "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
9305 : "cl\\u0061ss Foo {}",
9306 : "var x = cl\\u0061ss {}",
9307 : "\\u0063onst foo = 1;",
9308 : "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
9309 : "d\\u0065bugger;",
9310 : "d\\u0065lete this.a;",
9311 : "\\u0063o { } while(0)",
9312 : "if (d\\u006f { true }) {}",
9313 : "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
9314 : "e\\u0078port var foo;",
9315 : "try { } catch (e) {} f\\u0069nally { }",
9316 : "f\\u006fr (var i = 0; i < 10; ++i);",
9317 : "f\\u0075nction fn() {}",
9318 : "var f = f\\u0075nction() {}",
9319 : "\\u0069f (true) { }",
9320 : "\\u0069mport blah from './foo.js';",
9321 : "n\\u0065w function f() {}",
9322 : "(function() { r\\u0065turn; })()",
9323 : "class C extends function() {} { constructor() { sup\\u0065r() } }",
9324 : "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
9325 : "sw\\u0069tch (this.a) {}",
9326 : "var x = th\\u0069s;",
9327 : "th\\u0069s.a = 1;",
9328 : "thr\\u006fw 'boo';",
9329 : "t\\u0072y { true } catch (e) {}",
9330 : "var x = typ\\u0065of 'blah'",
9331 : "v\\u0061r a = true",
9332 : "var v\\u0061r = true",
9333 : "(function() { return v\\u006fid 0; })()",
9334 : "wh\\u0069le (true) { }",
9335 : "w\\u0069th (this.scope) { }",
9336 : "(function*() { y\\u0069eld 1; })()",
9337 : "(function*() { var y\\u0069eld = 1; })()",
9338 :
9339 : "var \\u0065num = 1;",
9340 : "var { \\u0065num } = {}",
9341 : "(\\u0065num = 1);",
9342 :
9343 : // Null / Boolean literals
9344 : "(x === n\\u0075ll);",
9345 : "var x = n\\u0075ll;",
9346 : "var n\\u0075ll = 1;",
9347 : "var { n\\u0075ll } = { 1 };",
9348 : "n\\u0075ll = 1;",
9349 : "(x === tr\\u0075e);",
9350 : "var x = tr\\u0075e;",
9351 : "var tr\\u0075e = 1;",
9352 : "var { tr\\u0075e } = {};",
9353 : "tr\\u0075e = 1;",
9354 : "(x === f\\u0061lse);",
9355 : "var x = f\\u0061lse;",
9356 : "var f\\u0061lse = 1;",
9357 : "var { f\\u0061lse } = {};",
9358 : "f\\u0061lse = 1;",
9359 :
9360 : // TODO(caitp): consistent error messages for labeled statements and
9361 : // expressions
9362 : "switch (this.a) { c\\u0061se 6: break; }",
9363 : "try { } c\\u0061tch (e) {}",
9364 : "switch (this.a) { d\\u0065fault: break; }",
9365 : "class C \\u0065xtends function B() {} {}",
9366 : "for (var a i\\u006e this) {}",
9367 : "if ('foo' \\u0069n this) {}",
9368 : "if (this \\u0069nstanceof Array) {}",
9369 : "(n\\u0065w function f() {})",
9370 : "(typ\\u0065of 123)",
9371 : "(v\\u006fid 0)",
9372 : "do { ; } wh\\u0069le (true) { }",
9373 : "(function*() { return (n++, y\\u0069eld 1); })()",
9374 : "class C { st\\u0061tic bar() {} }",
9375 : "class C { st\\u0061tic *bar() {} }",
9376 : "class C { st\\u0061tic get bar() {} }",
9377 : "class C { st\\u0061tic set bar() {} }",
9378 : "(async ()=>{\\u0061wait 100})()",
9379 : "({\\u0067et get(){}})",
9380 : "({\\u0073et set(){}})",
9381 : "(async ()=>{var \\u0061wait = 100})()",
9382 : nullptr
9383 5 : };
9384 : // clang-format on
9385 :
9386 5 : RunParserSyncTest(sloppy_context_data, fail_data, kError);
9387 5 : RunParserSyncTest(strict_context_data, fail_data, kError);
9388 : RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
9389 :
9390 : // clang-format off
9391 : const char* let_data[] = {
9392 : "var l\\u0065t = 1;",
9393 : "l\\u0065t = 1;",
9394 : "(l\\u0065t === 1);",
9395 : "(y\\u0069eld);",
9396 : "var y\\u0069eld = 1;",
9397 : "var { y\\u0069eld } = {};",
9398 : nullptr
9399 5 : };
9400 : // clang-format on
9401 :
9402 5 : RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
9403 5 : RunParserSyncTest(strict_context_data, let_data, kError);
9404 :
9405 : // Non-errors in sloppy mode
9406 : const char* valid_data[] = {"(\\u0069mplements = 1);",
9407 : "var impl\\u0065ments = 1;",
9408 : "var { impl\\u0065ments } = {};",
9409 : "(\\u0069nterface = 1);",
9410 : "var int\\u0065rface = 1;",
9411 : "var { int\\u0065rface } = {};",
9412 : "(p\\u0061ckage = 1);",
9413 : "var packa\\u0067e = 1;",
9414 : "var { packa\\u0067e } = {};",
9415 : "(p\\u0072ivate = 1);",
9416 : "var p\\u0072ivate;",
9417 : "var { p\\u0072ivate } = {};",
9418 : "(prot\\u0065cted);",
9419 : "var prot\\u0065cted = 1;",
9420 : "var { prot\\u0065cted } = {};",
9421 : "(publ\\u0069c);",
9422 : "var publ\\u0069c = 1;",
9423 : "var { publ\\u0069c } = {};",
9424 : "(st\\u0061tic);",
9425 : "var st\\u0061tic = 1;",
9426 : "var { st\\u0061tic } = {};",
9427 5 : nullptr};
9428 5 : RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
9429 5 : RunParserSyncTest(strict_context_data, valid_data, kError);
9430 : RunModuleParserSyncTest(strict_context_data, valid_data, kError);
9431 5 : }
9432 :
9433 :
9434 25880 : TEST(MiscSyntaxErrors) {
9435 : // clang-format off
9436 : const char* context_data[][2] = {
9437 : { "'use strict'", "" },
9438 : { "", "" },
9439 : { nullptr, nullptr }
9440 5 : };
9441 : const char* error_data[] = {
9442 : "for (();;) {}",
9443 :
9444 : // crbug.com/582626
9445 : "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
9446 : nullptr
9447 5 : };
9448 : // clang-format on
9449 :
9450 5 : RunParserSyncTest(context_data, error_data, kError);
9451 5 : }
9452 :
9453 :
9454 25880 : TEST(EscapeSequenceErrors) {
9455 : // clang-format off
9456 : const char* context_data[][2] = {
9457 : { "'", "'" },
9458 : { "\"", "\"" },
9459 : { "`", "`" },
9460 : { "`${'", "'}`" },
9461 : { "`${\"", "\"}`" },
9462 : { "`${`", "`}`" },
9463 : { nullptr, nullptr }
9464 5 : };
9465 : const char* error_data[] = {
9466 : "\\uABCG",
9467 : "\\u{ZZ}",
9468 : "\\u{FFZ}",
9469 : "\\u{FFFFFFFFFF }",
9470 : "\\u{110000}",
9471 : "\\u{110000",
9472 : "\\u{FFFD }",
9473 : "\\xZF",
9474 : nullptr
9475 5 : };
9476 : // clang-format on
9477 :
9478 5 : RunParserSyncTest(context_data, error_data, kError);
9479 5 : }
9480 :
9481 25880 : TEST(NewTargetErrors) {
9482 : // clang-format off
9483 : const char* context_data[][2] = {
9484 : { "'use strict'", "" },
9485 : { "", "" },
9486 : { nullptr, nullptr }
9487 5 : };
9488 : const char* error_data[] = {
9489 : "var x = new.target",
9490 : "function f() { return new.t\\u0061rget; }",
9491 : nullptr
9492 5 : };
9493 : // clang-format on
9494 5 : RunParserSyncTest(context_data, error_data, kError);
9495 5 : }
9496 :
9497 25880 : TEST(FunctionDeclarationError) {
9498 : // clang-format off
9499 : const char* strict_context[][2] = {
9500 : { "'use strict';", "" },
9501 : { "'use strict'; { ", "}" },
9502 : {"(function() { 'use strict';", "})()"},
9503 : {"(function() { 'use strict'; {", "} })()"},
9504 : { nullptr, nullptr }
9505 5 : };
9506 : const char* sloppy_context[][2] = {
9507 : { "", "" },
9508 : { "{", "}" },
9509 : {"(function() {", "})()"},
9510 : {"(function() { {", "} })()"},
9511 : { nullptr, nullptr }
9512 5 : };
9513 : // Invalid in all contexts
9514 : const char* error_data[] = {
9515 : "try function foo() {} catch (e) {}",
9516 : "do function foo() {} while (0);",
9517 : "for (;false;) function foo() {}",
9518 : "for (var i = 0; i < 1; i++) function f() { };",
9519 : "for (var x in {a: 1}) function f() { };",
9520 : "for (var x in {}) function f() { };",
9521 : "for (var x in {}) function foo() {}",
9522 : "for (x in {a: 1}) function f() { };",
9523 : "for (x in {}) function f() { };",
9524 : "var x; for (x in {}) function foo() {}",
9525 : "with ({}) function f() { };",
9526 : "do label: function foo() {} while (0);",
9527 : "for (;false;) label: function foo() {}",
9528 : "for (var i = 0; i < 1; i++) label: function f() { };",
9529 : "for (var x in {a: 1}) label: function f() { };",
9530 : "for (var x in {}) label: function f() { };",
9531 : "for (var x in {}) label: function foo() {}",
9532 : "for (x in {a: 1}) label: function f() { };",
9533 : "for (x in {}) label: function f() { };",
9534 : "var x; for (x in {}) label: function foo() {}",
9535 : "with ({}) label: function f() { };",
9536 : "if (true) label: function f() {}",
9537 : "if (true) {} else label: function f() {}",
9538 : "if (true) function* f() { }",
9539 : "label: function* f() { }",
9540 : "if (true) async function f() { }",
9541 : "label: async function f() { }",
9542 : "if (true) async function* f() { }",
9543 : "label: async function* f() { }",
9544 : nullptr
9545 5 : };
9546 : // Valid only in sloppy mode.
9547 : const char* sloppy_data[] = {
9548 : "if (true) function foo() {}",
9549 : "if (false) {} else function f() { };",
9550 : "label: function f() { }",
9551 : "label: if (true) function f() { }",
9552 : "label: if (true) {} else function f() { }",
9553 : "label: label2: function f() { }",
9554 : nullptr
9555 5 : };
9556 : // clang-format on
9557 :
9558 : // Nothing parses in strict mode without a SyntaxError
9559 5 : RunParserSyncTest(strict_context, error_data, kError);
9560 5 : RunParserSyncTest(strict_context, sloppy_data, kError);
9561 :
9562 : // In sloppy mode, sloppy_data is successful
9563 5 : RunParserSyncTest(sloppy_context, error_data, kError);
9564 5 : RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
9565 5 : }
9566 :
9567 25880 : TEST(ExponentiationOperator) {
9568 : // clang-format off
9569 : const char* context_data[][2] = {
9570 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9571 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9572 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9573 : { nullptr, nullptr }
9574 5 : };
9575 : const char* data[] = {
9576 : "(delete O.p) ** 10",
9577 : "(delete x) ** 10",
9578 : "(~O.p) ** 10",
9579 : "(~x) ** 10",
9580 : "(!O.p) ** 10",
9581 : "(!x) ** 10",
9582 : "(+O.p) ** 10",
9583 : "(+x) ** 10",
9584 : "(-O.p) ** 10",
9585 : "(-x) ** 10",
9586 : "(typeof O.p) ** 10",
9587 : "(typeof x) ** 10",
9588 : "(void 0) ** 10",
9589 : "(void O.p) ** 10",
9590 : "(void x) ** 10",
9591 : "++O.p ** 10",
9592 : "++x ** 10",
9593 : "--O.p ** 10",
9594 : "--x ** 10",
9595 : "O.p++ ** 10",
9596 : "x++ ** 10",
9597 : "O.p-- ** 10",
9598 : "x-- ** 10",
9599 : nullptr
9600 5 : };
9601 : // clang-format on
9602 :
9603 5 : RunParserSyncTest(context_data, data, kSuccess);
9604 5 : }
9605 :
9606 25880 : TEST(ExponentiationOperatorErrors) {
9607 : // clang-format off
9608 : const char* context_data[][2] = {
9609 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9610 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9611 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9612 : { nullptr, nullptr }
9613 5 : };
9614 : const char* error_data[] = {
9615 : "delete O.p ** 10",
9616 : "delete x ** 10",
9617 : "~O.p ** 10",
9618 : "~x ** 10",
9619 : "!O.p ** 10",
9620 : "!x ** 10",
9621 : "+O.p ** 10",
9622 : "+x ** 10",
9623 : "-O.p ** 10",
9624 : "-x ** 10",
9625 : "typeof O.p ** 10",
9626 : "typeof x ** 10",
9627 : "void ** 10",
9628 : "void O.p ** 10",
9629 : "void x ** 10",
9630 : "++delete O.p ** 10",
9631 : "--delete O.p ** 10",
9632 : "++~O.p ** 10",
9633 : "++~x ** 10",
9634 : "--!O.p ** 10",
9635 : "--!x ** 10",
9636 : "++-O.p ** 10",
9637 : "++-x ** 10",
9638 : "--+O.p ** 10",
9639 : "--+x ** 10",
9640 : "[ x ] **= [ 2 ]",
9641 : "[ x **= 2 ] = [ 2 ]",
9642 : "{ x } **= { x: 2 }",
9643 : "{ x: x **= 2 ] = { x: 2 }",
9644 : // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
9645 : // "Array() **= 10",
9646 : nullptr
9647 5 : };
9648 : // clang-format on
9649 :
9650 5 : RunParserSyncTest(context_data, error_data, kError);
9651 5 : }
9652 :
9653 25880 : TEST(AsyncAwait) {
9654 : // clang-format off
9655 : const char* context_data[][2] = {
9656 : { "'use strict';", "" },
9657 : { "", "" },
9658 : { nullptr, nullptr }
9659 5 : };
9660 :
9661 : const char* data[] = {
9662 : "var asyncFn = async function() { await 1; };",
9663 : "var asyncFn = async function withName() { await 1; };",
9664 : "var asyncFn = async () => await 'test';",
9665 : "var asyncFn = async x => await x + 'test';",
9666 : "async function asyncFn() { await 1; }",
9667 : "var O = { async method() { await 1; } }",
9668 : "var O = { async ['meth' + 'od']() { await 1; } }",
9669 : "var O = { async 'method'() { await 1; } }",
9670 : "var O = { async 0() { await 1; } }",
9671 : "async function await() {}",
9672 :
9673 : "var asyncFn = async({ foo = 1 }) => foo;",
9674 : "var asyncFn = async({ foo = 1 } = {}) => foo;",
9675 :
9676 : "function* g() { var f = async(yield); }",
9677 : "function* g() { var f = async(x = yield); }",
9678 :
9679 : // v8:7817 assert that `await` is still allowed in the body of an arrow fn
9680 : // within formal parameters
9681 : "async(a = a => { var await = 1; return 1; }) => a()",
9682 : "async(a = await => 1); async(a) => 1",
9683 : "(async(a = await => 1), async(a) => 1)",
9684 : "async(a = await => 1, b = async() => 1);",
9685 :
9686 : nullptr
9687 5 : };
9688 : // clang-format on
9689 :
9690 5 : RunParserSyncTest(context_data, data, kSuccess);
9691 :
9692 : // clang-format off
9693 : const char* async_body_context_data[][2] = {
9694 : { "async function f() {", "}" },
9695 : { "var f = async function() {", "}" },
9696 : { "var f = async() => {", "}" },
9697 : { "var O = { async method() {", "} }" },
9698 : { "'use strict'; async function f() {", "}" },
9699 : { "'use strict'; var f = async function() {", "}" },
9700 : { "'use strict'; var f = async() => {", "}" },
9701 : { "'use strict'; var O = { async method() {", "} }" },
9702 : { nullptr, nullptr }
9703 5 : };
9704 :
9705 : const char* body_context_data[][2] = {
9706 : { "function f() {", "}" },
9707 : { "function* g() {", "}" },
9708 : { "var f = function() {", "}" },
9709 : { "var g = function*() {", "}" },
9710 : { "var O = { method() {", "} }" },
9711 : { "var O = { *method() {", "} }" },
9712 : { "var f = () => {", "}" },
9713 : { "'use strict'; function f() {", "}" },
9714 : { "'use strict'; function* g() {", "}" },
9715 : { "'use strict'; var f = function() {", "}" },
9716 : { "'use strict'; var g = function*() {", "}" },
9717 : { "'use strict'; var O = { method() {", "} }" },
9718 : { "'use strict'; var O = { *method() {", "} }" },
9719 : { "'use strict'; var f = () => {", "}" },
9720 : { nullptr, nullptr }
9721 5 : };
9722 :
9723 : const char* body_data[] = {
9724 : "var async = 1; return async;",
9725 : "let async = 1; return async;",
9726 : "const async = 1; return async;",
9727 : "function async() {} return async();",
9728 : "var async = async => async; return async();",
9729 : "function foo() { var await = 1; return await; }",
9730 : "function foo(await) { return await; }",
9731 : "function* foo() { var await = 1; return await; }",
9732 : "function* foo(await) { return await; }",
9733 : "var f = () => { var await = 1; return await; }",
9734 : "var O = { method() { var await = 1; return await; } };",
9735 : "var O = { method(await) { return await; } };",
9736 : "var O = { *method() { var await = 1; return await; } };",
9737 : "var O = { *method(await) { return await; } };",
9738 : "var asyncFn = async function*() {}",
9739 : "async function* f() {}",
9740 : "var O = { async *method() {} };",
9741 :
9742 : "(function await() {})",
9743 : nullptr
9744 5 : };
9745 : // clang-format on
9746 :
9747 5 : RunParserSyncTest(async_body_context_data, body_data, kSuccess);
9748 5 : RunParserSyncTest(body_context_data, body_data, kSuccess);
9749 5 : }
9750 :
9751 25880 : TEST(AsyncAwaitErrors) {
9752 : // clang-format off
9753 : const char* context_data[][2] = {
9754 : { "'use strict';", "" },
9755 : { "", "" },
9756 : { nullptr, nullptr }
9757 5 : };
9758 :
9759 : const char* strict_context_data[][2] = {
9760 : { "'use strict';", "" },
9761 : { nullptr, nullptr }
9762 5 : };
9763 :
9764 : const char* error_data[] = {
9765 : "var asyncFn = async function await() {};",
9766 : "var asyncFn = async () => var await = 'test';",
9767 : "var asyncFn = async await => await + 'test';",
9768 : "var asyncFn = async function(await) {};",
9769 : "var asyncFn = async (await) => 'test';",
9770 : "async function f(await) {}",
9771 :
9772 : "var O = { async method(a, a) {} }",
9773 : "var O = { async ['meth' + 'od'](a, a) {} }",
9774 : "var O = { async 'method'(a, a) {} }",
9775 : "var O = { async 0(a, a) {} }",
9776 :
9777 : "var f = async() => await;",
9778 :
9779 : "var O = { *async method() {} };",
9780 : "var O = { async method*() {} };",
9781 :
9782 : "var asyncFn = async function(x = await 1) { return x; }",
9783 : "async function f(x = await 1) { return x; }",
9784 : "var f = async(x = await 1) => x;",
9785 : "var O = { async method(x = await 1) { return x; } };",
9786 :
9787 : "function* g() { var f = async yield => 1; }",
9788 : "function* g() { var f = async(yield) => 1; }",
9789 : "function* g() { var f = async(x = yield) => 1; }",
9790 : "function* g() { var f = async({x = yield}) => 1; }",
9791 :
9792 : "class C { async constructor() {} }",
9793 : "class C {}; class C2 extends C { async constructor() {} }",
9794 : "class C { static async prototype() {} }",
9795 : "class C {}; class C2 extends C { static async prototype() {} }",
9796 :
9797 : "var f = async() => ((async(x = await 1) => x)();",
9798 :
9799 : // Henrique Ferreiro's bug (tm)
9800 : "(async function foo1() { } foo2 => 1)",
9801 : "(async function foo3() { } () => 1)",
9802 : "(async function foo4() { } => 1)",
9803 : "(async function() { } foo5 => 1)",
9804 : "(async function() { } () => 1)",
9805 : "(async function() { } => 1)",
9806 : "(async.foo6 => 1)",
9807 : "(async.foo7 foo8 => 1)",
9808 : "(async.foo9 () => 1)",
9809 : "(async().foo10 => 1)",
9810 : "(async().foo11 foo12 => 1)",
9811 : "(async().foo13 () => 1)",
9812 : "(async['foo14'] => 1)",
9813 : "(async['foo15'] foo16 => 1)",
9814 : "(async['foo17'] () => 1)",
9815 : "(async()['foo18'] => 1)",
9816 : "(async()['foo19'] foo20 => 1)",
9817 : "(async()['foo21'] () => 1)",
9818 : "(async`foo22` => 1)",
9819 : "(async`foo23` foo24 => 1)",
9820 : "(async`foo25` () => 1)",
9821 : "(async`foo26`.bar27 => 1)",
9822 : "(async`foo28`.bar29 foo30 => 1)",
9823 : "(async`foo31`.bar32 () => 1)",
9824 :
9825 : // v8:5148 assert that errors are still thrown for calls that may have been
9826 : // async functions
9827 : "async({ foo33 = 1 })",
9828 :
9829 : "async(...a = b) => b",
9830 : "async(...a,) => b",
9831 : "async(...a, b) => b",
9832 :
9833 : // v8:7817 assert that `await` is an invalid identifier in arrow formal
9834 : // parameters nested within an async arrow function
9835 : "async(a = await => 1) => a",
9836 : "async(a = (await) => 1) => a",
9837 : "async(a = (...await) => 1) => a",
9838 : nullptr
9839 5 : };
9840 :
9841 : const char* strict_error_data[] = {
9842 : "var O = { async method(eval) {} }",
9843 : "var O = { async ['meth' + 'od'](eval) {} }",
9844 : "var O = { async 'method'(eval) {} }",
9845 : "var O = { async 0(eval) {} }",
9846 :
9847 : "var O = { async method(arguments) {} }",
9848 : "var O = { async ['meth' + 'od'](arguments) {} }",
9849 : "var O = { async 'method'(arguments) {} }",
9850 : "var O = { async 0(arguments) {} }",
9851 :
9852 : "var O = { async method(dupe, dupe) {} }",
9853 :
9854 : // TODO(caitp): preparser needs to report duplicate parameter errors, too.
9855 : // "var f = async(dupe, dupe) => {}",
9856 :
9857 : nullptr
9858 5 : };
9859 :
9860 5 : RunParserSyncTest(context_data, error_data, kError);
9861 5 : RunParserSyncTest(strict_context_data, strict_error_data, kError);
9862 :
9863 : // clang-format off
9864 : const char* async_body_context_data[][2] = {
9865 : { "async function f() {", "}" },
9866 : { "var f = async function() {", "}" },
9867 : { "var f = async() => {", "}" },
9868 : { "var O = { async method() {", "} }" },
9869 : { "'use strict'; async function f() {", "}" },
9870 : { "'use strict'; var f = async function() {", "}" },
9871 : { "'use strict'; var f = async() => {", "}" },
9872 : { "'use strict'; var O = { async method() {", "} }" },
9873 : { nullptr, nullptr }
9874 5 : };
9875 :
9876 : const char* async_body_error_data[] = {
9877 : "var await = 1;",
9878 : "var { await } = 1;",
9879 : "var [ await ] = 1;",
9880 : "return async (await) => {};",
9881 : "var O = { async [await](a, a) {} }",
9882 : "await;",
9883 :
9884 : "function await() {}",
9885 :
9886 : "var f = await => 42;",
9887 : "var f = (await) => 42;",
9888 : "var f = (await, a) => 42;",
9889 : "var f = (...await) => 42;",
9890 :
9891 : "var e = (await);",
9892 : "var e = (await, f);",
9893 : "var e = (await = 42)",
9894 :
9895 : "var e = [await];",
9896 : "var e = {await};",
9897 :
9898 : nullptr
9899 5 : };
9900 : // clang-format on
9901 :
9902 5 : RunParserSyncTest(async_body_context_data, async_body_error_data, kError);
9903 5 : }
9904 :
9905 25880 : TEST(Regress7173) {
9906 : // Await expression is an invalid destructuring target, and should not crash
9907 :
9908 : // clang-format off
9909 : const char* error_context_data[][2] = {
9910 : { "'use strict'; async function f() {", "}" },
9911 : { "async function f() {", "}" },
9912 : { "'use strict'; function f() {", "}" },
9913 : { "function f() {", "}" },
9914 : { "let f = async() => {", "}" },
9915 : { "let f = () => {", "}" },
9916 : { "'use strict'; async function* f() {", "}" },
9917 : { "async function* f() {", "}" },
9918 : { "'use strict'; function* f() {", "}" },
9919 : { "function* f() {", "}" },
9920 : { nullptr, nullptr }
9921 5 : };
9922 :
9923 : const char* error_data[] = {
9924 : "var [await f] = [];",
9925 : "let [await f] = [];",
9926 : "const [await f] = [];",
9927 :
9928 : "var [...await f] = [];",
9929 : "let [...await f] = [];",
9930 : "const [...await f] = [];",
9931 :
9932 : "var { await f } = {};",
9933 : "let { await f } = {};",
9934 : "const { await f } = {};",
9935 :
9936 : "var { ...await f } = {};",
9937 : "let { ...await f } = {};",
9938 : "const { ...await f } = {};",
9939 :
9940 : "var { f: await f } = {};",
9941 : "let { f: await f } = {};",
9942 : "const { f: await f } = {};"
9943 :
9944 : "var { f: ...await f } = {};",
9945 : "let { f: ...await f } = {};",
9946 : "const { f: ...await f } = {};"
9947 :
9948 : "var { [f]: await f } = {};",
9949 : "let { [f]: await f } = {};",
9950 : "const { [f]: await f } = {};",
9951 :
9952 : "var { [f]: ...await f } = {};",
9953 : "let { [f]: ...await f } = {};",
9954 : "const { [f]: ...await f } = {};",
9955 :
9956 : nullptr
9957 5 : };
9958 : // clang-format on
9959 :
9960 5 : RunParserSyncTest(error_context_data, error_data, kError);
9961 5 : }
9962 :
9963 25880 : TEST(AsyncAwaitFormalParameters) {
9964 : // clang-format off
9965 : const char* context_for_formal_parameters[][2] = {
9966 : { "async function f(", ") {}" },
9967 : { "var f = async function f(", ") {}" },
9968 : { "var f = async(", ") => {}" },
9969 : { "'use strict'; async function f(", ") {}" },
9970 : { "'use strict'; var f = async function f(", ") {}" },
9971 : { "'use strict'; var f = async(", ") => {}" },
9972 : { nullptr, nullptr }
9973 5 : };
9974 :
9975 : const char* good_formal_parameters[] = {
9976 : "x = function await() {}",
9977 : "x = function *await() {}",
9978 : "x = function() { let await = 0; }",
9979 : "x = () => { let await = 0; }",
9980 : nullptr
9981 5 : };
9982 :
9983 : const char* bad_formal_parameters[] = {
9984 : "{ await }",
9985 : "{ await = 1 }",
9986 : "{ await } = {}",
9987 : "{ await = 1 } = {}",
9988 : "[await]",
9989 : "[await] = []",
9990 : "[await = 1]",
9991 : "[await = 1] = []",
9992 : "...await",
9993 : "await",
9994 : "await = 1",
9995 : "...[await]",
9996 : "x = await",
9997 :
9998 : // v8:5190
9999 : "1) => 1",
10000 : "'str') => 1",
10001 : "/foo/) => 1",
10002 : "{ foo = async(1) => 1 }) => 1",
10003 : "{ foo = async(a) => 1 })",
10004 :
10005 : "x = async(await)",
10006 : "x = { [await]: 1 }",
10007 : "x = class extends (await) { }",
10008 : "x = class { static [await]() {} }",
10009 : "{ x = await }",
10010 :
10011 : // v8:6714
10012 : "x = class await {}",
10013 : "x = 1 ? class await {} : 0",
10014 : "x = async function await() {}",
10015 :
10016 : "x = y[await]",
10017 : "x = `${await}`",
10018 : "x = y()[await]",
10019 :
10020 : nullptr
10021 5 : };
10022 : // clang-format on
10023 :
10024 : RunParserSyncTest(context_for_formal_parameters, good_formal_parameters,
10025 5 : kSuccess);
10026 :
10027 : RunParserSyncTest(context_for_formal_parameters, bad_formal_parameters,
10028 5 : kError);
10029 5 : }
10030 :
10031 25880 : TEST(AsyncAwaitModule) {
10032 : // clang-format off
10033 : const char* context_data[][2] = {
10034 : { "", "" },
10035 : { nullptr, nullptr }
10036 5 : };
10037 :
10038 : const char* data[] = {
10039 : "export default async function() { await 1; }",
10040 : "export default async function async() { await 1; }",
10041 : "export async function async() { await 1; }",
10042 : nullptr
10043 5 : };
10044 : // clang-format on
10045 :
10046 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
10047 : nullptr, 0, false);
10048 5 : }
10049 :
10050 25880 : TEST(AsyncAwaitModuleErrors) {
10051 : // clang-format off
10052 : const char* context_data[][2] = {
10053 : { "", "" },
10054 : { nullptr, nullptr }
10055 5 : };
10056 :
10057 : const char* error_data[] = {
10058 : "export default (async function await() {})",
10059 : "export default async function await() {}",
10060 : "export async function await() {}",
10061 : "export async function() {}",
10062 : "export async",
10063 : "export async\nfunction async() { await 1; }",
10064 : nullptr
10065 5 : };
10066 : // clang-format on
10067 :
10068 : RunModuleParserSyncTest(context_data, error_data, kError, nullptr, 0, nullptr,
10069 : 0, nullptr, 0, false);
10070 5 : }
10071 :
10072 25880 : TEST(RestrictiveForInErrors) {
10073 : // clang-format off
10074 : const char* strict_context_data[][2] = {
10075 : { "'use strict'", "" },
10076 : { nullptr, nullptr }
10077 5 : };
10078 : const char* sloppy_context_data[][2] = {
10079 : { "", "" },
10080 : { nullptr, nullptr }
10081 5 : };
10082 : const char* error_data[] = {
10083 : "for (const x = 0 in {});",
10084 : "for (let x = 0 in {});",
10085 : nullptr
10086 5 : };
10087 : const char* sloppy_data[] = {
10088 : "for (var x = 0 in {});",
10089 : nullptr
10090 5 : };
10091 : // clang-format on
10092 :
10093 5 : RunParserSyncTest(strict_context_data, error_data, kError);
10094 5 : RunParserSyncTest(strict_context_data, sloppy_data, kError);
10095 5 : RunParserSyncTest(sloppy_context_data, error_data, kError);
10096 5 : RunParserSyncTest(sloppy_context_data, sloppy_data, kSuccess);
10097 5 : }
10098 :
10099 25880 : TEST(NoDuplicateGeneratorsInBlock) {
10100 : const char* block_context_data[][2] = {
10101 : {"'use strict'; {", "}"},
10102 : {"{", "}"},
10103 : {"(function() { {", "} })()"},
10104 : {"(function() {'use strict'; {", "} })()"},
10105 5 : {nullptr, nullptr}};
10106 : const char* top_level_context_data[][2] = {
10107 : {"'use strict';", ""},
10108 : {"", ""},
10109 : {"(function() {", "})()"},
10110 : {"(function() {'use strict';", "})()"},
10111 5 : {nullptr, nullptr}};
10112 : const char* error_data[] = {"function* x() {} function* x() {}",
10113 : "function x() {} function* x() {}",
10114 5 : "function* x() {} function x() {}", nullptr};
10115 : // The preparser doesn't enforce the restriction, so turn it off.
10116 : bool test_preparser = false;
10117 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10118 5 : 0, nullptr, 0, false, test_preparser);
10119 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10120 5 : }
10121 :
10122 25880 : TEST(NoDuplicateAsyncFunctionInBlock) {
10123 : const char* block_context_data[][2] = {
10124 : {"'use strict'; {", "}"},
10125 : {"{", "}"},
10126 : {"(function() { {", "} })()"},
10127 : {"(function() {'use strict'; {", "} })()"},
10128 5 : {nullptr, nullptr}};
10129 : const char* top_level_context_data[][2] = {
10130 : {"'use strict';", ""},
10131 : {"", ""},
10132 : {"(function() {", "})()"},
10133 : {"(function() {'use strict';", "})()"},
10134 5 : {nullptr, nullptr}};
10135 : const char* error_data[] = {"async function x() {} async function x() {}",
10136 : "function x() {} async function x() {}",
10137 : "async function x() {} function x() {}",
10138 : "function* x() {} async function x() {}",
10139 : "function* x() {} async function x() {}",
10140 : "async function x() {} function* x() {}",
10141 : "function* x() {} async function x() {}",
10142 5 : nullptr};
10143 : // The preparser doesn't enforce the restriction, so turn it off.
10144 : bool test_preparser = false;
10145 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10146 5 : 0, nullptr, 0, false, test_preparser);
10147 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10148 5 : }
10149 :
10150 25880 : TEST(TrailingCommasInParameters) {
10151 : // clang-format off
10152 : const char* context_data[][2] = {
10153 : { "", "" },
10154 : { "'use strict';", "" },
10155 : { "function foo() {", "}" },
10156 : { "function foo() {'use strict';", "}" },
10157 : { nullptr, nullptr }
10158 5 : };
10159 :
10160 : const char* data[] = {
10161 : " function a(b,) {}",
10162 : " function* a(b,) {}",
10163 : "(function a(b,) {});",
10164 : "(function* a(b,) {});",
10165 : "(function (b,) {});",
10166 : "(function* (b,) {});",
10167 : " function a(b,c,d,) {}",
10168 : " function* a(b,c,d,) {}",
10169 : "(function a(b,c,d,) {});",
10170 : "(function* a(b,c,d,) {});",
10171 : "(function (b,c,d,) {});",
10172 : "(function* (b,c,d,) {});",
10173 : "(b,) => {};",
10174 : "(b,c,d,) => {};",
10175 : "a(1,);",
10176 : "a(1,2,3,);",
10177 : "a(...[],);",
10178 : "a(1, 2, ...[],);",
10179 : "a(...[], 2, ...[],);",
10180 : nullptr
10181 5 : };
10182 : // clang-format on
10183 :
10184 5 : RunParserSyncTest(context_data, data, kSuccess);
10185 5 : }
10186 :
10187 25880 : TEST(TrailingCommasInParametersErrors) {
10188 : // clang-format off
10189 : const char* context_data[][2] = {
10190 : { "", "" },
10191 : { "'use strict';", "" },
10192 : { "function foo() {", "}" },
10193 : { "function foo() {'use strict';", "}" },
10194 : { nullptr, nullptr }
10195 5 : };
10196 :
10197 : const char* data[] = {
10198 : // too many trailing commas
10199 : " function a(b,,) {}",
10200 : " function* a(b,,) {}",
10201 : "(function a(b,,) {});",
10202 : "(function* a(b,,) {});",
10203 : "(function (b,,) {});",
10204 : "(function* (b,,) {});",
10205 : " function a(b,c,d,,) {}",
10206 : " function* a(b,c,d,,) {}",
10207 : "(function a(b,c,d,,) {});",
10208 : "(function* a(b,c,d,,) {});",
10209 : "(function (b,c,d,,) {});",
10210 : "(function* (b,c,d,,) {});",
10211 : "(b,,) => {};",
10212 : "(b,c,d,,) => {};",
10213 : "a(1,,);",
10214 : "a(1,2,3,,);",
10215 : // only a trailing comma and no parameters
10216 : " function a1(,) {}",
10217 : " function* a2(,) {}",
10218 : "(function a3(,) {});",
10219 : "(function* a4(,) {});",
10220 : "(function (,) {});",
10221 : "(function* (,) {});",
10222 : "(,) => {};",
10223 : "a1(,);",
10224 : // no trailing commas after rest parameter declaration
10225 : " function a(...b,) {}",
10226 : " function* a(...b,) {}",
10227 : "(function a(...b,) {});",
10228 : "(function* a(...b,) {});",
10229 : "(function (...b,) {});",
10230 : "(function* (...b,) {});",
10231 : " function a(b, c, ...d,) {}",
10232 : " function* a(b, c, ...d,) {}",
10233 : "(function a(b, c, ...d,) {});",
10234 : "(function* a(b, c, ...d,) {});",
10235 : "(function (b, c, ...d,) {});",
10236 : "(function* (b, c, ...d,) {});",
10237 : "(...b,) => {};",
10238 : "(b, c, ...d,) => {};",
10239 : // parenthesized trailing comma without arrow is still an error
10240 : "(,);",
10241 : "(a,);",
10242 : "(a,b,c,);",
10243 : nullptr
10244 5 : };
10245 : // clang-format on
10246 :
10247 5 : RunParserSyncTest(context_data, data, kError);
10248 5 : }
10249 :
10250 25880 : TEST(ArgumentsRedeclaration) {
10251 : {
10252 : // clang-format off
10253 : const char* context_data[][2] = {
10254 : { "function f(", ") {}" },
10255 : { nullptr, nullptr }
10256 5 : };
10257 : const char* success_data[] = {
10258 : "{arguments}",
10259 : "{arguments = false}",
10260 : "arg1, arguments",
10261 : "arg1, ...arguments",
10262 : nullptr
10263 5 : };
10264 : // clang-format on
10265 5 : RunParserSyncTest(context_data, success_data, kSuccess);
10266 : }
10267 :
10268 : {
10269 : // clang-format off
10270 : const char* context_data[][2] = {
10271 : { "function f() {", "}" },
10272 : { nullptr, nullptr }
10273 5 : };
10274 : const char* data[] = {
10275 : "const arguments = 1",
10276 : "let arguments",
10277 : "var arguments",
10278 : nullptr
10279 5 : };
10280 : // clang-format on
10281 5 : RunParserSyncTest(context_data, data, kSuccess);
10282 : }
10283 5 : }
10284 :
10285 :
10286 : // Test that lazily parsed inner functions don't result in overly pessimistic
10287 : // context allocations.
10288 25880 : TEST(NoPessimisticContextAllocation) {
10289 : i::Isolate* isolate = CcTest::i_isolate();
10290 : i::Factory* factory = isolate->factory();
10291 : i::HandleScope scope(isolate);
10292 10 : LocalContext env;
10293 :
10294 : const char* prefix = "(function outer() { var my_var; ";
10295 : const char* suffix = " })();";
10296 5 : int prefix_len = Utf8LengthHelper(prefix);
10297 5 : int suffix_len = Utf8LengthHelper(suffix);
10298 :
10299 : // Test both normal inner functions and inner arrow functions.
10300 : const char* inner_functions[] = {"function inner(%s) { %s }",
10301 5 : "(%s) => { %s }"};
10302 :
10303 : struct {
10304 : const char* params;
10305 : const char* source;
10306 : bool ctxt_allocate;
10307 : } inners[] = {
10308 : // Context allocating because we need to:
10309 : {"", "my_var;", true},
10310 : {"", "if (true) { let my_var; } my_var;", true},
10311 : {"", "eval('foo');", true},
10312 : {"", "function inner2() { my_var; }", true},
10313 : {"", "function inner2() { eval('foo'); }", true},
10314 : {"", "var {my_var : a} = {my_var};", true},
10315 : {"", "let {my_var : a} = {my_var};", true},
10316 : {"", "const {my_var : a} = {my_var};", true},
10317 : {"", "var [a, b = my_var] = [1, 2];", true},
10318 : {"", "var [a, b = my_var] = [1, 2]; my_var;", true},
10319 : {"", "let [a, b = my_var] = [1, 2];", true},
10320 : {"", "let [a, b = my_var] = [1, 2]; my_var;", true},
10321 : {"", "const [a, b = my_var] = [1, 2];", true},
10322 : {"", "const [a, b = my_var] = [1, 2]; my_var;", true},
10323 : {"", "var {a = my_var} = {}", true},
10324 : {"", "var {a: b = my_var} = {}", true},
10325 : {"", "let {a = my_var} = {}", true},
10326 : {"", "let {a: b = my_var} = {}", true},
10327 : {"", "const {a = my_var} = {}", true},
10328 : {"", "const {a: b = my_var} = {}", true},
10329 : {"a = my_var", "", true},
10330 : {"a = my_var", "let my_var;", true},
10331 : {"", "function inner2(a = my_var) { }", true},
10332 : {"", "(a = my_var) => { }", true},
10333 : {"{a} = {a: my_var}", "", true},
10334 : {"", "function inner2({a} = {a: my_var}) { }", true},
10335 : {"", "({a} = {a: my_var}) => { }", true},
10336 : {"[a] = [my_var]", "", true},
10337 : {"", "function inner2([a] = [my_var]) { }", true},
10338 : {"", "([a] = [my_var]) => { }", true},
10339 : {"", "function inner2(a = eval('')) { }", true},
10340 : {"", "(a = eval('')) => { }", true},
10341 : {"", "try { } catch (my_var) { } my_var;", true},
10342 : {"", "for (my_var in {}) { my_var; }", true},
10343 : {"", "for (my_var in {}) { }", true},
10344 : {"", "for (my_var of []) { my_var; }", true},
10345 : {"", "for (my_var of []) { }", true},
10346 : {"", "for ([a, my_var, b] in {}) { my_var; }", true},
10347 : {"", "for ([a, my_var, b] of []) { my_var; }", true},
10348 : {"", "for ({x: my_var} in {}) { my_var; }", true},
10349 : {"", "for ({x: my_var} of []) { my_var; }", true},
10350 : {"", "for ({my_var} in {}) { my_var; }", true},
10351 : {"", "for ({my_var} of []) { my_var; }", true},
10352 : {"", "for ({y, x: my_var} in {}) { my_var; }", true},
10353 : {"", "for ({y, x: my_var} of []) { my_var; }", true},
10354 : {"", "for ({a, my_var} in {}) { my_var; }", true},
10355 : {"", "for ({a, my_var} of []) { my_var; }", true},
10356 : {"", "for (let my_var in {}) { } my_var;", true},
10357 : {"", "for (let my_var of []) { } my_var;", true},
10358 : {"", "for (let [a, my_var, b] in {}) { } my_var;", true},
10359 : {"", "for (let [a, my_var, b] of []) { } my_var;", true},
10360 : {"", "for (let {x: my_var} in {}) { } my_var;", true},
10361 : {"", "for (let {x: my_var} of []) { } my_var;", true},
10362 : {"", "for (let {my_var} in {}) { } my_var;", true},
10363 : {"", "for (let {my_var} of []) { } my_var;", true},
10364 : {"", "for (let {y, x: my_var} in {}) { } my_var;", true},
10365 : {"", "for (let {y, x: my_var} of []) { } my_var;", true},
10366 : {"", "for (let {a, my_var} in {}) { } my_var;", true},
10367 : {"", "for (let {a, my_var} of []) { } my_var;", true},
10368 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { } my_var;", true},
10369 : {"", "'use strict'; if (true) { function my_var() {} } my_var;", true},
10370 : {"",
10371 : "'use strict'; function inner2() { if (true) { function my_var() {} } "
10372 : "my_var; }",
10373 : true},
10374 : {"",
10375 : "function inner2() { 'use strict'; if (true) { function my_var() {} } "
10376 : "my_var; }",
10377 : true},
10378 : {"",
10379 : "() => { 'use strict'; if (true) { function my_var() {} } my_var; }",
10380 : true},
10381 : {"",
10382 : "if (true) { let my_var; if (true) { function my_var() {} } } my_var;",
10383 : true},
10384 : {"", "function inner2(a = my_var) {}", true},
10385 : {"", "function inner2(a = my_var) { let my_var; }", true},
10386 : {"", "(a = my_var) => {}", true},
10387 : {"", "(a = my_var) => { let my_var; }", true},
10388 : // No pessimistic context allocation:
10389 : {"", "var my_var; my_var;", false},
10390 : {"", "var my_var;", false},
10391 : {"", "var my_var = 0;", false},
10392 : {"", "if (true) { var my_var; } my_var;", false},
10393 : {"", "let my_var; my_var;", false},
10394 : {"", "let my_var;", false},
10395 : {"", "let my_var = 0;", false},
10396 : {"", "const my_var = 0; my_var;", false},
10397 : {"", "const my_var = 0;", false},
10398 : {"", "var [a, my_var] = [1, 2]; my_var;", false},
10399 : {"", "let [a, my_var] = [1, 2]; my_var;", false},
10400 : {"", "const [a, my_var] = [1, 2]; my_var;", false},
10401 : {"", "var {a: my_var} = {a: 3}; my_var;", false},
10402 : {"", "let {a: my_var} = {a: 3}; my_var;", false},
10403 : {"", "const {a: my_var} = {a: 3}; my_var;", false},
10404 : {"", "var {my_var} = {my_var: 3}; my_var;", false},
10405 : {"", "let {my_var} = {my_var: 3}; my_var;", false},
10406 : {"", "const {my_var} = {my_var: 3}; my_var;", false},
10407 : {"my_var", "my_var;", false},
10408 : {"my_var", "", false},
10409 : {"my_var = 5", "my_var;", false},
10410 : {"my_var = 5", "", false},
10411 : {"...my_var", "my_var;", false},
10412 : {"...my_var", "", false},
10413 : {"[a, my_var, b]", "my_var;", false},
10414 : {"[a, my_var, b]", "", false},
10415 : {"[a, my_var, b] = [1, 2, 3]", "my_var;", false},
10416 : {"[a, my_var, b] = [1, 2, 3]", "", false},
10417 : {"{x: my_var}", "my_var;", false},
10418 : {"{x: my_var}", "", false},
10419 : {"{x: my_var} = {x: 0}", "my_var;", false},
10420 : {"{x: my_var} = {x: 0}", "", false},
10421 : {"{my_var}", "my_var;", false},
10422 : {"{my_var}", "", false},
10423 : {"{my_var} = {my_var: 0}", "my_var;", false},
10424 : {"{my_var} = {my_var: 0}", "", false},
10425 : {"", "function inner2(my_var) { my_var; }", false},
10426 : {"", "function inner2(my_var) { }", false},
10427 : {"", "function inner2(my_var = 5) { my_var; }", false},
10428 : {"", "function inner2(my_var = 5) { }", false},
10429 : {"", "function inner2(...my_var) { my_var; }", false},
10430 : {"", "function inner2(...my_var) { }", false},
10431 : {"", "function inner2([a, my_var, b]) { my_var; }", false},
10432 : {"", "function inner2([a, my_var, b]) { }", false},
10433 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { my_var; }", false},
10434 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { }", false},
10435 : {"", "function inner2({x: my_var}) { my_var; }", false},
10436 : {"", "function inner2({x: my_var}) { }", false},
10437 : {"", "function inner2({x: my_var} = {x: 0}) { my_var; }", false},
10438 : {"", "function inner2({x: my_var} = {x: 0}) { }", false},
10439 : {"", "function inner2({my_var}) { my_var; }", false},
10440 : {"", "function inner2({my_var}) { }", false},
10441 : {"", "function inner2({my_var} = {my_var: 8}) { my_var; } ", false},
10442 : {"", "function inner2({my_var} = {my_var: 8}) { }", false},
10443 : {"", "my_var => my_var;", false},
10444 : {"", "my_var => { }", false},
10445 : {"", "(my_var = 5) => my_var;", false},
10446 : {"", "(my_var = 5) => { }", false},
10447 : {"", "(...my_var) => my_var;", false},
10448 : {"", "(...my_var) => { }", false},
10449 : {"", "([a, my_var, b]) => my_var;", false},
10450 : {"", "([a, my_var, b]) => { }", false},
10451 : {"", "([a, my_var, b] = [1, 2, 3]) => my_var;", false},
10452 : {"", "([a, my_var, b] = [1, 2, 3]) => { }", false},
10453 : {"", "({x: my_var}) => my_var;", false},
10454 : {"", "({x: my_var}) => { }", false},
10455 : {"", "({x: my_var} = {x: 0}) => my_var;", false},
10456 : {"", "({x: my_var} = {x: 0}) => { }", false},
10457 : {"", "({my_var}) => my_var;", false},
10458 : {"", "({my_var}) => { }", false},
10459 : {"", "({my_var} = {my_var: 5}) => my_var;", false},
10460 : {"", "({my_var} = {my_var: 5}) => { }", false},
10461 : {"", "({a, my_var}) => my_var;", false},
10462 : {"", "({a, my_var}) => { }", false},
10463 : {"", "({a, my_var} = {a: 0, my_var: 5}) => my_var;", false},
10464 : {"", "({a, my_var} = {a: 0, my_var: 5}) => { }", false},
10465 : {"", "({y, x: my_var}) => my_var;", false},
10466 : {"", "({y, x: my_var}) => { }", false},
10467 : {"", "({y, x: my_var} = {y: 0, x: 0}) => my_var;", false},
10468 : {"", "({y, x: my_var} = {y: 0, x: 0}) => { }", false},
10469 : {"", "try { } catch (my_var) { my_var; }", false},
10470 : {"", "try { } catch ([a, my_var, b]) { my_var; }", false},
10471 : {"", "try { } catch ({x: my_var}) { my_var; }", false},
10472 : {"", "try { } catch ({y, x: my_var}) { my_var; }", false},
10473 : {"", "try { } catch ({my_var}) { my_var; }", false},
10474 : {"", "for (let my_var in {}) { my_var; }", false},
10475 : {"", "for (let my_var in {}) { }", false},
10476 : {"", "for (let my_var of []) { my_var; }", false},
10477 : {"", "for (let my_var of []) { }", false},
10478 : {"", "for (let [a, my_var, b] in {}) { my_var; }", false},
10479 : {"", "for (let [a, my_var, b] of []) { my_var; }", false},
10480 : {"", "for (let {x: my_var} in {}) { my_var; }", false},
10481 : {"", "for (let {x: my_var} of []) { my_var; }", false},
10482 : {"", "for (let {my_var} in {}) { my_var; }", false},
10483 : {"", "for (let {my_var} of []) { my_var; }", false},
10484 : {"", "for (let {y, x: my_var} in {}) { my_var; }", false},
10485 : {"", "for (let {y, x: my_var} of []) { my_var; }", false},
10486 : {"", "for (let {a, my_var} in {}) { my_var; }", false},
10487 : {"", "for (let {a, my_var} of []) { my_var; }", false},
10488 : {"", "for (var my_var in {}) { my_var; }", false},
10489 : {"", "for (var my_var in {}) { }", false},
10490 : {"", "for (var my_var of []) { my_var; }", false},
10491 : {"", "for (var my_var of []) { }", false},
10492 : {"", "for (var [a, my_var, b] in {}) { my_var; }", false},
10493 : {"", "for (var [a, my_var, b] of []) { my_var; }", false},
10494 : {"", "for (var {x: my_var} in {}) { my_var; }", false},
10495 : {"", "for (var {x: my_var} of []) { my_var; }", false},
10496 : {"", "for (var {my_var} in {}) { my_var; }", false},
10497 : {"", "for (var {my_var} of []) { my_var; }", false},
10498 : {"", "for (var {y, x: my_var} in {}) { my_var; }", false},
10499 : {"", "for (var {y, x: my_var} of []) { my_var; }", false},
10500 : {"", "for (var {a, my_var} in {}) { my_var; }", false},
10501 : {"", "for (var {a, my_var} of []) { my_var; }", false},
10502 : {"", "for (var my_var in {}) { } my_var;", false},
10503 : {"", "for (var my_var of []) { } my_var;", false},
10504 : {"", "for (var [a, my_var, b] in {}) { } my_var;", false},
10505 : {"", "for (var [a, my_var, b] of []) { } my_var;", false},
10506 : {"", "for (var {x: my_var} in {}) { } my_var;", false},
10507 : {"", "for (var {x: my_var} of []) { } my_var;", false},
10508 : {"", "for (var {my_var} in {}) { } my_var;", false},
10509 : {"", "for (var {my_var} of []) { } my_var;", false},
10510 : {"", "for (var {y, x: my_var} in {}) { } my_var;", false},
10511 : {"", "for (var {y, x: my_var} of []) { } my_var;", false},
10512 : {"", "for (var {a, my_var} in {}) { } my_var;", false},
10513 : {"", "for (var {a, my_var} of []) { } my_var;", false},
10514 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10515 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10516 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { } my_var; ", false},
10517 : {"", "for (let a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10518 : false},
10519 : {"", "for (var a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10520 : false},
10521 : {"", "class my_var {}; my_var; ", false},
10522 : {"", "function my_var() {} my_var;", false},
10523 : {"", "if (true) { function my_var() {} } my_var;", false},
10524 : {"", "function inner2() { if (true) { function my_var() {} } my_var; }",
10525 : false},
10526 : {"", "() => { if (true) { function my_var() {} } my_var; }", false},
10527 : {"",
10528 : "if (true) { var my_var; if (true) { function my_var() {} } } my_var;",
10529 : false},
10530 5 : };
10531 :
10532 15 : for (unsigned inner_ix = 0; inner_ix < arraysize(inner_functions);
10533 : ++inner_ix) {
10534 10 : const char* inner_function = inner_functions[inner_ix];
10535 10 : int inner_function_len = Utf8LengthHelper(inner_function) - 4;
10536 :
10537 2060 : for (unsigned i = 0; i < arraysize(inners); ++i) {
10538 2050 : int params_len = Utf8LengthHelper(inners[i].params);
10539 2050 : int source_len = Utf8LengthHelper(inners[i].source);
10540 2050 : int len = prefix_len + inner_function_len + params_len + source_len +
10541 2050 : suffix_len;
10542 :
10543 2050 : i::ScopedVector<char> program(len + 1);
10544 2050 : i::SNPrintF(program, "%s", prefix);
10545 : i::SNPrintF(program + prefix_len, inner_function, inners[i].params,
10546 4100 : inners[i].source);
10547 : i::SNPrintF(
10548 2050 : program + prefix_len + inner_function_len + params_len + source_len,
10549 4100 : "%s", suffix);
10550 :
10551 : i::Handle<i::String> source =
10552 2050 : factory->InternalizeUtf8String(program.start());
10553 4100 : source->PrintOn(stdout);
10554 : printf("\n");
10555 :
10556 2050 : i::Handle<i::Script> script = factory->NewScript(source);
10557 4100 : i::ParseInfo info(isolate, script);
10558 :
10559 2050 : CHECK(i::parsing::ParseProgram(&info, isolate));
10560 2050 : CHECK(i::Compiler::Analyze(&info));
10561 2050 : CHECK_NOT_NULL(info.literal());
10562 :
10563 2050 : i::Scope* scope = info.literal()->scope()->inner_scope();
10564 : DCHECK_NOT_NULL(scope);
10565 : DCHECK_NULL(scope->sibling());
10566 : DCHECK(scope->is_function_scope());
10567 : const i::AstRawString* var_name =
10568 2050 : info.ast_value_factory()->GetOneByteString("my_var");
10569 : i::Variable* var = scope->LookupForTesting(var_name);
10570 2050 : CHECK_EQ(inners[i].ctxt_allocate,
10571 : i::ScopeTestHelper::MustAllocateInContext(var));
10572 : }
10573 : }
10574 5 : }
10575 :
10576 25880 : TEST(EscapedStrictReservedWord) {
10577 : // Test that identifiers which are both escaped and only reserved in the
10578 : // strict mode are accepted in non-strict mode.
10579 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
10580 :
10581 : const char* statement_data[] = {"if (true) l\\u0065t: ;",
10582 : "function l\\u0065t() { }",
10583 : "(function l\\u0065t() { })",
10584 : "async function l\\u0065t() { }",
10585 : "(async function l\\u0065t() { })",
10586 : "l\\u0065t => 42",
10587 : "async l\\u0065t => 42",
10588 : "function packag\\u0065() {}",
10589 : "function impl\\u0065ments() {}",
10590 : "function privat\\u0065() {}",
10591 5 : nullptr};
10592 :
10593 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
10594 5 : }
10595 :
10596 25880 : TEST(ForAwaitOf) {
10597 : // clang-format off
10598 : const char* context_data[][2] = {
10599 : { "async function f() { for await ", " ; }" },
10600 : { "async function f() { for await ", " { } }" },
10601 : { "async function * f() { for await ", " { } }" },
10602 : { "async function f() { 'use strict'; for await ", " ; }" },
10603 : { "async function f() { 'use strict'; for await ", " { } }" },
10604 : { "async function * f() { 'use strict'; for await ", " { } }" },
10605 : { "async function f() { for\nawait ", " ; }" },
10606 : { "async function f() { for\nawait ", " { } }" },
10607 : { "async function * f() { for\nawait ", " { } }" },
10608 : { "async function f() { 'use strict'; for\nawait ", " ; }" },
10609 : { "async function f() { 'use strict'; for\nawait ", " { } }" },
10610 : { "async function * f() { 'use strict'; for\nawait ", " { } }" },
10611 : { "async function f() { for await\n", " ; }" },
10612 : { "async function f() { for await\n", " { } }" },
10613 : { "async function * f() { for await\n", " { } }" },
10614 : { "async function f() { 'use strict'; for await\n", " ; }" },
10615 : { "async function f() { 'use strict'; for await\n", " { } }" },
10616 : { "async function * f() { 'use strict'; for await\n", " { } }" },
10617 : { nullptr, nullptr }
10618 5 : };
10619 :
10620 : const char* context_data2[][2] = {
10621 : { "async function f() { let a; for await ", " ; }" },
10622 : { "async function f() { let a; for await ", " { } }" },
10623 : { "async function * f() { let a; for await ", " { } }" },
10624 : { "async function f() { 'use strict'; let a; for await ", " ; }" },
10625 : { "async function f() { 'use strict'; let a; for await ", " { } }" },
10626 : { "async function * f() { 'use strict'; let a; for await ", " { } }" },
10627 : { "async function f() { let a; for\nawait ", " ; }" },
10628 : { "async function f() { let a; for\nawait ", " { } }" },
10629 : { "async function * f() { let a; for\nawait ", " { } }" },
10630 : { "async function f() { 'use strict'; let a; for\nawait ", " ; }" },
10631 : { "async function f() { 'use strict'; let a; for\nawait ", " { } }" },
10632 : { "async function * f() { 'use strict'; let a; for\nawait ", " { } }" },
10633 : { "async function f() { let a; for await\n", " ; }" },
10634 : { "async function f() { let a; for await\n", " { } }" },
10635 : { "async function * f() { let a; for await\n", " { } }" },
10636 : { "async function f() { 'use strict'; let a; for await\n", " ; }" },
10637 : { "async function f() { 'use strict'; let a; for await\n", " { } }" },
10638 : { "async function * f() { 'use strict'; let a; for await\n", " { } }" },
10639 : { nullptr, nullptr }
10640 5 : };
10641 :
10642 : const char* expr_data[] = {
10643 : // Primary Expressions
10644 : "(a of [])",
10645 : "(a.b of [])",
10646 : "([a] of [])",
10647 : "([a = 1] of [])",
10648 : "([a = 1, ...b] of [])",
10649 : "({a} of [])",
10650 : "({a: a} of [])",
10651 : "({'a': a} of [])",
10652 : "({\"a\": a} of [])",
10653 : "({[Symbol.iterator]: a} of [])",
10654 : "({0: a} of [])",
10655 : "({a = 1} of [])",
10656 : "({a: a = 1} of [])",
10657 : "({'a': a = 1} of [])",
10658 : "({\"a\": a = 1} of [])",
10659 : "({[Symbol.iterator]: a = 1} of [])",
10660 : "({0: a = 1} of [])",
10661 : nullptr
10662 5 : };
10663 :
10664 : const char* var_data[] = {
10665 : // VarDeclarations
10666 : "(var a of [])",
10667 : "(var [a] of [])",
10668 : "(var [a = 1] of [])",
10669 : "(var [a = 1, ...b] of [])",
10670 : "(var {a} of [])",
10671 : "(var {a: a} of [])",
10672 : "(var {'a': a} of [])",
10673 : "(var {\"a\": a} of [])",
10674 : "(var {[Symbol.iterator]: a} of [])",
10675 : "(var {0: a} of [])",
10676 : "(var {a = 1} of [])",
10677 : "(var {a: a = 1} of [])",
10678 : "(var {'a': a = 1} of [])",
10679 : "(var {\"a\": a = 1} of [])",
10680 : "(var {[Symbol.iterator]: a = 1} of [])",
10681 : "(var {0: a = 1} of [])",
10682 : nullptr
10683 5 : };
10684 :
10685 : const char* lexical_data[] = {
10686 : // LexicalDeclartions
10687 : "(let a of [])",
10688 : "(let [a] of [])",
10689 : "(let [a = 1] of [])",
10690 : "(let [a = 1, ...b] of [])",
10691 : "(let {a} of [])",
10692 : "(let {a: a} of [])",
10693 : "(let {'a': a} of [])",
10694 : "(let {\"a\": a} of [])",
10695 : "(let {[Symbol.iterator]: a} of [])",
10696 : "(let {0: a} of [])",
10697 : "(let {a = 1} of [])",
10698 : "(let {a: a = 1} of [])",
10699 : "(let {'a': a = 1} of [])",
10700 : "(let {\"a\": a = 1} of [])",
10701 : "(let {[Symbol.iterator]: a = 1} of [])",
10702 : "(let {0: a = 1} of [])",
10703 :
10704 : "(const a of [])",
10705 : "(const [a] of [])",
10706 : "(const [a = 1] of [])",
10707 : "(const [a = 1, ...b] of [])",
10708 : "(const {a} of [])",
10709 : "(const {a: a} of [])",
10710 : "(const {'a': a} of [])",
10711 : "(const {\"a\": a} of [])",
10712 : "(const {[Symbol.iterator]: a} of [])",
10713 : "(const {0: a} of [])",
10714 : "(const {a = 1} of [])",
10715 : "(const {a: a = 1} of [])",
10716 : "(const {'a': a = 1} of [])",
10717 : "(const {\"a\": a = 1} of [])",
10718 : "(const {[Symbol.iterator]: a = 1} of [])",
10719 : "(const {0: a = 1} of [])",
10720 : nullptr
10721 5 : };
10722 : // clang-format on
10723 5 : RunParserSyncTest(context_data, expr_data, kSuccess);
10724 5 : RunParserSyncTest(context_data2, expr_data, kSuccess);
10725 :
10726 5 : RunParserSyncTest(context_data, var_data, kSuccess);
10727 : // TODO(marja): PreParser doesn't report early errors.
10728 : // (https://bugs.chromium.org/p/v8/issues/detail?id=2728)
10729 : // RunParserSyncTest(context_data2, var_data, kError, nullptr, 0,
10730 : // always_flags,
10731 : // arraysize(always_flags));
10732 :
10733 5 : RunParserSyncTest(context_data, lexical_data, kSuccess);
10734 5 : RunParserSyncTest(context_data2, lexical_data, kSuccess);
10735 5 : }
10736 :
10737 25880 : TEST(ForAwaitOfErrors) {
10738 : // clang-format off
10739 : const char* context_data[][2] = {
10740 : { "async function f() { for await ", " ; }" },
10741 : { "async function f() { for await ", " { } }" },
10742 : { "async function f() { 'use strict'; for await ", " ; }" },
10743 : { "async function f() { 'use strict'; for await ", " { } }" },
10744 : { "async function * f() { for await ", " ; }" },
10745 : { "async function * f() { for await ", " { } }" },
10746 : { "async function * f() { 'use strict'; for await ", " ; }" },
10747 : { "async function * f() { 'use strict'; for await ", " { } }" },
10748 : { nullptr, nullptr }
10749 5 : };
10750 :
10751 : const char* data[] = {
10752 : // Primary Expressions
10753 : "(a = 1 of [])",
10754 : "(a = 1) of [])",
10755 : "(a.b = 1 of [])",
10756 : "((a.b = 1) of [])",
10757 : "([a] = 1 of [])",
10758 : "(([a] = 1) of [])",
10759 : "([a = 1] = 1 of [])",
10760 : "(([a = 1] = 1) of [])",
10761 : "([a = 1 = 1, ...b] = 1 of [])",
10762 : "(([a = 1 = 1, ...b] = 1) of [])",
10763 : "({a} = 1 of [])",
10764 : "(({a} = 1) of [])",
10765 : "({a: a} = 1 of [])",
10766 : "(({a: a} = 1) of [])",
10767 : "({'a': a} = 1 of [])",
10768 : "(({'a': a} = 1) of [])",
10769 : "({\"a\": a} = 1 of [])",
10770 : "(({\"a\": a} = 1) of [])",
10771 : "({[Symbol.iterator]: a} = 1 of [])",
10772 : "(({[Symbol.iterator]: a} = 1) of [])",
10773 : "({0: a} = 1 of [])",
10774 : "(({0: a} = 1) of [])",
10775 : "({a = 1} = 1 of [])",
10776 : "(({a = 1} = 1) of [])",
10777 : "({a: a = 1} = 1 of [])",
10778 : "(({a: a = 1} = 1) of [])",
10779 : "({'a': a = 1} = 1 of [])",
10780 : "(({'a': a = 1} = 1) of [])",
10781 : "({\"a\": a = 1} = 1 of [])",
10782 : "(({\"a\": a = 1} = 1) of [])",
10783 : "({[Symbol.iterator]: a = 1} = 1 of [])",
10784 : "(({[Symbol.iterator]: a = 1} = 1) of [])",
10785 : "({0: a = 1} = 1 of [])",
10786 : "(({0: a = 1} = 1) of [])",
10787 : "(function a() {} of [])",
10788 : "([1] of [])",
10789 : "({a: 1} of [])"
10790 :
10791 : // VarDeclarations
10792 : "(var a = 1 of [])",
10793 : "(var a, b of [])",
10794 : "(var [a] = 1 of [])",
10795 : "(var [a], b of [])",
10796 : "(var [a = 1] = 1 of [])",
10797 : "(var [a = 1], b of [])",
10798 : "(var [a = 1 = 1, ...b] of [])",
10799 : "(var [a = 1, ...b], c of [])",
10800 : "(var {a} = 1 of [])",
10801 : "(var {a}, b of [])",
10802 : "(var {a: a} = 1 of [])",
10803 : "(var {a: a}, b of [])",
10804 : "(var {'a': a} = 1 of [])",
10805 : "(var {'a': a}, b of [])",
10806 : "(var {\"a\": a} = 1 of [])",
10807 : "(var {\"a\": a}, b of [])",
10808 : "(var {[Symbol.iterator]: a} = 1 of [])",
10809 : "(var {[Symbol.iterator]: a}, b of [])",
10810 : "(var {0: a} = 1 of [])",
10811 : "(var {0: a}, b of [])",
10812 : "(var {a = 1} = 1 of [])",
10813 : "(var {a = 1}, b of [])",
10814 : "(var {a: a = 1} = 1 of [])",
10815 : "(var {a: a = 1}, b of [])",
10816 : "(var {'a': a = 1} = 1 of [])",
10817 : "(var {'a': a = 1}, b of [])",
10818 : "(var {\"a\": a = 1} = 1 of [])",
10819 : "(var {\"a\": a = 1}, b of [])",
10820 : "(var {[Symbol.iterator]: a = 1} = 1 of [])",
10821 : "(var {[Symbol.iterator]: a = 1}, b of [])",
10822 : "(var {0: a = 1} = 1 of [])",
10823 : "(var {0: a = 1}, b of [])",
10824 :
10825 : // LexicalDeclartions
10826 : "(let a = 1 of [])",
10827 : "(let a, b of [])",
10828 : "(let [a] = 1 of [])",
10829 : "(let [a], b of [])",
10830 : "(let [a = 1] = 1 of [])",
10831 : "(let [a = 1], b of [])",
10832 : "(let [a = 1, ...b] = 1 of [])",
10833 : "(let [a = 1, ...b], c of [])",
10834 : "(let {a} = 1 of [])",
10835 : "(let {a}, b of [])",
10836 : "(let {a: a} = 1 of [])",
10837 : "(let {a: a}, b of [])",
10838 : "(let {'a': a} = 1 of [])",
10839 : "(let {'a': a}, b of [])",
10840 : "(let {\"a\": a} = 1 of [])",
10841 : "(let {\"a\": a}, b of [])",
10842 : "(let {[Symbol.iterator]: a} = 1 of [])",
10843 : "(let {[Symbol.iterator]: a}, b of [])",
10844 : "(let {0: a} = 1 of [])",
10845 : "(let {0: a}, b of [])",
10846 : "(let {a = 1} = 1 of [])",
10847 : "(let {a = 1}, b of [])",
10848 : "(let {a: a = 1} = 1 of [])",
10849 : "(let {a: a = 1}, b of [])",
10850 : "(let {'a': a = 1} = 1 of [])",
10851 : "(let {'a': a = 1}, b of [])",
10852 : "(let {\"a\": a = 1} = 1 of [])",
10853 : "(let {\"a\": a = 1}, b of [])",
10854 : "(let {[Symbol.iterator]: a = 1} = 1 of [])",
10855 : "(let {[Symbol.iterator]: a = 1}, b of [])",
10856 : "(let {0: a = 1} = 1 of [])",
10857 : "(let {0: a = 1}, b of [])",
10858 :
10859 : "(const a = 1 of [])",
10860 : "(const a, b of [])",
10861 : "(const [a] = 1 of [])",
10862 : "(const [a], b of [])",
10863 : "(const [a = 1] = 1 of [])",
10864 : "(const [a = 1], b of [])",
10865 : "(const [a = 1, ...b] = 1 of [])",
10866 : "(const [a = 1, ...b], b of [])",
10867 : "(const {a} = 1 of [])",
10868 : "(const {a}, b of [])",
10869 : "(const {a: a} = 1 of [])",
10870 : "(const {a: a}, b of [])",
10871 : "(const {'a': a} = 1 of [])",
10872 : "(const {'a': a}, b of [])",
10873 : "(const {\"a\": a} = 1 of [])",
10874 : "(const {\"a\": a}, b of [])",
10875 : "(const {[Symbol.iterator]: a} = 1 of [])",
10876 : "(const {[Symbol.iterator]: a}, b of [])",
10877 : "(const {0: a} = 1 of [])",
10878 : "(const {0: a}, b of [])",
10879 : "(const {a = 1} = 1 of [])",
10880 : "(const {a = 1}, b of [])",
10881 : "(const {a: a = 1} = 1 of [])",
10882 : "(const {a: a = 1}, b of [])",
10883 : "(const {'a': a = 1} = 1 of [])",
10884 : "(const {'a': a = 1}, b of [])",
10885 : "(const {\"a\": a = 1} = 1 of [])",
10886 : "(const {\"a\": a = 1}, b of [])",
10887 : "(const {[Symbol.iterator]: a = 1} = 1 of [])",
10888 : "(const {[Symbol.iterator]: a = 1}, b of [])",
10889 : "(const {0: a = 1} = 1 of [])",
10890 : "(const {0: a = 1}, b of [])",
10891 :
10892 : nullptr
10893 5 : };
10894 : // clang-format on
10895 5 : RunParserSyncTest(context_data, data, kError);
10896 5 : }
10897 :
10898 25880 : TEST(ForAwaitOfFunctionDeclaration) {
10899 : // clang-format off
10900 : const char* context_data[][2] = {
10901 : { "async function f() {", "}" },
10902 : { "async function f() { 'use strict'; ", "}" },
10903 : { nullptr, nullptr }
10904 5 : };
10905 :
10906 : const char* data[] = {
10907 : "for await (x of []) function d() {};",
10908 : "for await (x of []) function d() {}; return d;",
10909 : "for await (x of []) function* g() {};",
10910 : "for await (x of []) function* g() {}; return g;",
10911 : // TODO(caitp): handle async function declarations in ParseScopedStatement.
10912 : // "for await (x of []) async function a() {};",
10913 : // "for await (x of []) async function a() {}; return a;",
10914 : nullptr
10915 5 : };
10916 :
10917 : // clang-format on
10918 5 : RunParserSyncTest(context_data, data, kError);
10919 5 : }
10920 :
10921 25880 : TEST(AsyncGenerator) {
10922 : // clang-format off
10923 : const char* context_data[][2] = {
10924 : { "async function * gen() {", "}" },
10925 : { "(async function * gen() {", "})" },
10926 : { "(async function * () {", "})" },
10927 : { "({ async * gen () {", "} })" },
10928 : { nullptr, nullptr }
10929 5 : };
10930 :
10931 : const char* statement_data[] = {
10932 : // An async generator without a body is valid.
10933 : ""
10934 : // Valid yield expressions inside generators.
10935 : "yield 2;",
10936 : "yield * 2;",
10937 : "yield * \n 2;",
10938 : "yield yield 1;",
10939 : "yield * yield * 1;",
10940 : "yield 3 + (yield 4);",
10941 : "yield * 3 + (yield * 4);",
10942 : "(yield * 3) + (yield * 4);",
10943 : "yield 3; yield 4;",
10944 : "yield * 3; yield * 4;",
10945 : "(function (yield) { })",
10946 : "(function yield() { })",
10947 : "(function (await) { })",
10948 : "(function await() { })",
10949 : "yield { yield: 12 }",
10950 : "yield /* comment */ { yield: 12 }",
10951 : "yield * \n { yield: 12 }",
10952 : "yield /* comment */ * \n { yield: 12 }",
10953 : // You can return in an async generator.
10954 : "yield 1; return",
10955 : "yield * 1; return",
10956 : "yield 1; return 37",
10957 : "yield * 1; return 37",
10958 : "yield 1; return 37; yield 'dead';",
10959 : "yield * 1; return 37; yield * 'dead';",
10960 : // Yield/Await are still a valid key in object literals.
10961 : "({ yield: 1 })",
10962 : "({ get yield() { } })",
10963 : "({ await: 1 })",
10964 : "({ get await() { } })",
10965 : // And in assignment pattern computed properties
10966 : "({ [yield]: x } = { })",
10967 : "({ [await 1]: x } = { })",
10968 : // Yield without RHS.
10969 : "yield;",
10970 : "yield",
10971 : "yield\n",
10972 : "yield /* comment */"
10973 : "yield // comment\n"
10974 : "(yield)",
10975 : "[yield]",
10976 : "{yield}",
10977 : "yield, yield",
10978 : "yield; yield",
10979 : "(yield) ? yield : yield",
10980 : "(yield) \n ? yield : yield",
10981 : // If there is a newline before the next token, we don't look for RHS.
10982 : "yield\nfor (;;) {}",
10983 : "x = class extends (yield) {}",
10984 : "x = class extends f(yield) {}",
10985 : "x = class extends (null, yield) { }",
10986 : "x = class extends (a ? null : yield) { }",
10987 : "x = class extends (await 10) {}",
10988 : "x = class extends f(await 10) {}",
10989 : "x = class extends (null, await 10) { }",
10990 : "x = class extends (a ? null : await 10) { }",
10991 :
10992 : // More tests featuring AwaitExpressions
10993 : "await 10",
10994 : "await 10; return",
10995 : "await 10; return 20",
10996 : "await 10; return 20; yield 'dead'",
10997 : "await (yield 10)",
10998 : "await (yield 10); return",
10999 : "await (yield 10); return 20",
11000 : "await (yield 10); return 20; yield 'dead'",
11001 : "yield await 10",
11002 : "yield await 10; return",
11003 : "yield await 10; return 20",
11004 : "yield await 10; return 20; yield 'dead'",
11005 : "await /* comment */ 10",
11006 : "await // comment\n 10",
11007 : "yield await /* comment\n */ 10",
11008 : "yield await // comment\n 10",
11009 : "await (yield /* comment */)",
11010 : "await (yield // comment\n)",
11011 : nullptr
11012 5 : };
11013 : // clang-format on
11014 :
11015 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
11016 5 : }
11017 :
11018 25880 : TEST(AsyncGeneratorErrors) {
11019 : // clang-format off
11020 : const char* context_data[][2] = {
11021 : { "async function * gen() {", "}" },
11022 : { "\"use strict\"; async function * gen() {", "}" },
11023 : { nullptr, nullptr }
11024 5 : };
11025 :
11026 : const char* statement_data[] = {
11027 : // Invalid yield expressions inside generators.
11028 : "var yield;",
11029 : "var await;",
11030 : "var foo, yield;",
11031 : "var foo, await;",
11032 : "try { } catch (yield) { }",
11033 : "try { } catch (await) { }",
11034 : "function yield() { }",
11035 : "function await() { }",
11036 : // The name of the NFE is bound in the generator, which does not permit
11037 : // yield or await to be identifiers.
11038 : "(async function * yield() { })",
11039 : "(async function * await() { })",
11040 : // Yield and Await aren't valid as a formal parameter for generators.
11041 : "async function * foo(yield) { }",
11042 : "(async function * foo(yield) { })",
11043 : "async function * foo(await) { }",
11044 : "(async function * foo(await) { })",
11045 : "yield = 1;",
11046 : "await = 1;",
11047 : "var foo = yield = 1;",
11048 : "var foo = await = 1;",
11049 : "++yield;",
11050 : "++await;",
11051 : "yield++;",
11052 : "await++;",
11053 : "yield *",
11054 : "(yield *)",
11055 : // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
11056 : // is invalid.
11057 : "yield 3 + yield 4;",
11058 : "yield: 34",
11059 : "yield ? 1 : 2",
11060 : // Parses as yield (/ yield): invalid.
11061 : "yield / yield",
11062 : "+ yield",
11063 : "+ yield 3",
11064 : // Invalid (no newline allowed between yield and *).
11065 : "yield\n*3",
11066 : // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
11067 : // object literal, and yield is not a valid label).
11068 : "yield\n{yield: 42}",
11069 : "yield /* comment */\n {yield: 42}",
11070 : "yield //comment\n {yield: 42}",
11071 : // Destructuring binding and assignment are both disallowed
11072 : "var [yield] = [42];",
11073 : "var [await] = [42];",
11074 : "var {foo: yield} = {a: 42};",
11075 : "var {foo: await} = {a: 42};",
11076 : "[yield] = [42];",
11077 : "[await] = [42];",
11078 : "({a: yield} = {a: 42});",
11079 : "({a: await} = {a: 42});",
11080 : // Also disallow full yield/await expressions on LHS
11081 : "var [yield 24] = [42];",
11082 : "var [await 24] = [42];",
11083 : "var {foo: yield 24} = {a: 42};",
11084 : "var {foo: await 24} = {a: 42};",
11085 : "[yield 24] = [42];",
11086 : "[await 24] = [42];",
11087 : "({a: yield 24} = {a: 42});",
11088 : "({a: await 24} = {a: 42});",
11089 : "for (yield 'x' in {});",
11090 : "for (await 'x' in {});",
11091 : "for (yield 'x' of {});",
11092 : "for (await 'x' of {});",
11093 : "for (yield 'x' in {} in {});",
11094 : "for (await 'x' in {} in {});",
11095 : "for (yield 'x' in {} of {});",
11096 : "for (await 'x' in {} of {});",
11097 : "class C extends yield { }",
11098 : "class C extends await { }",
11099 : nullptr
11100 5 : };
11101 : // clang-format on
11102 :
11103 5 : RunParserSyncTest(context_data, statement_data, kError);
11104 5 : }
11105 :
11106 25880 : TEST(LexicalLoopVariable) {
11107 : i::Isolate* isolate = CcTest::i_isolate();
11108 : i::HandleScope scope(isolate);
11109 10 : LocalContext env;
11110 : typedef std::function<void(const i::ParseInfo& info, i::DeclarationScope*)>
11111 : TestCB;
11112 50 : auto TestProgram = [isolate](const char* program, TestCB test) {
11113 50 : i::Factory* const factory = isolate->factory();
11114 : i::Handle<i::String> source =
11115 100 : factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
11116 50 : i::Handle<i::Script> script = factory->NewScript(source);
11117 50 : i::ParseInfo info(isolate, script);
11118 :
11119 : info.set_allow_lazy_parsing(false);
11120 50 : CHECK(i::parsing::ParseProgram(&info, isolate));
11121 50 : CHECK(i::Rewriter::Rewrite(&info));
11122 50 : CHECK(i::DeclarationScope::Analyze(&info));
11123 50 : i::DeclarationScope::AllocateScopeInfos(&info, isolate);
11124 50 : CHECK_NOT_NULL(info.literal());
11125 :
11126 50 : i::DeclarationScope* script_scope = info.literal()->scope();
11127 50 : CHECK(script_scope->is_script_scope());
11128 :
11129 50 : test(info, script_scope);
11130 55 : };
11131 :
11132 : // Check `let` loop variables is a stack local when not captured by
11133 : // an eval or closure within the area of the loop body.
11134 : const char* local_bindings[] = {
11135 : "function loop() {"
11136 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11137 : " }"
11138 : " eval('0');"
11139 : "}",
11140 :
11141 : "function loop() {"
11142 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11143 : " }"
11144 : " function foo() {}"
11145 : " foo();"
11146 : "}",
11147 5 : };
11148 15 : for (const char* source : local_bindings) {
11149 10 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11150 20 : i::Scope* fn = s->inner_scope();
11151 10 : CHECK(fn->is_function_scope());
11152 :
11153 25 : i::Scope* loop_block = fn->inner_scope();
11154 10 : if (loop_block->is_function_scope()) loop_block = loop_block->sibling();
11155 10 : CHECK(loop_block->is_block_scope());
11156 :
11157 : const i::AstRawString* var_name =
11158 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11159 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11160 10 : CHECK_NOT_NULL(loop_var);
11161 10 : CHECK(loop_var->IsStackLocal());
11162 10 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11163 10 : CHECK_NULL(loop_block->inner_scope());
11164 30 : });
11165 : }
11166 :
11167 : // Check `let` loop variable is not a stack local, and is duplicated in the
11168 : // loop body to ensure capturing can work correctly.
11169 : // In this version of the test, the inner loop block's duplicate `loop_var`
11170 : // binding is not captured, and is a local.
11171 : const char* context_bindings1[] = {
11172 : "function loop() {"
11173 : " for (let loop_var = eval('0'); loop_var < 10; ++loop_var) {"
11174 : " }"
11175 : "}",
11176 :
11177 : "function loop() {"
11178 : " for (let loop_var = (() => (loop_var, 0))(); loop_var < 10;"
11179 : " ++loop_var) {"
11180 : " }"
11181 5 : "}"};
11182 15 : for (const char* source : context_bindings1) {
11183 10 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11184 20 : i::Scope* fn = s->inner_scope();
11185 10 : CHECK(fn->is_function_scope());
11186 :
11187 30 : i::Scope* loop_block = fn->inner_scope();
11188 10 : CHECK(loop_block->is_block_scope());
11189 :
11190 : const i::AstRawString* var_name =
11191 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11192 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11193 10 : CHECK_NOT_NULL(loop_var);
11194 10 : CHECK(loop_var->IsContextSlot());
11195 10 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11196 :
11197 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11198 10 : CHECK_NE(loop_var, loop_var2);
11199 10 : CHECK(loop_var2->IsStackLocal());
11200 10 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
11201 30 : });
11202 : }
11203 :
11204 : // Check `let` loop variable is not a stack local, and is duplicated in the
11205 : // loop body to ensure capturing can work correctly.
11206 : // In this version of the test, the inner loop block's duplicate `loop_var`
11207 : // binding is captured, and must be context allocated.
11208 : const char* context_bindings2[] = {
11209 : "function loop() {"
11210 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11211 : " eval('0');"
11212 : " }"
11213 : "}",
11214 :
11215 : "function loop() {"
11216 : " for (let loop_var = 0; loop_var < eval('10'); ++loop_var) {"
11217 : " }"
11218 : "}",
11219 :
11220 : "function loop() {"
11221 : " for (let loop_var = 0; loop_var < 10; eval('++loop_var')) {"
11222 : " }"
11223 : "}",
11224 5 : };
11225 :
11226 20 : for (const char* source : context_bindings2) {
11227 15 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11228 30 : i::Scope* fn = s->inner_scope();
11229 15 : CHECK(fn->is_function_scope());
11230 :
11231 45 : i::Scope* loop_block = fn->inner_scope();
11232 15 : CHECK(loop_block->is_block_scope());
11233 :
11234 : const i::AstRawString* var_name =
11235 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11236 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11237 15 : CHECK_NOT_NULL(loop_var);
11238 15 : CHECK(loop_var->IsContextSlot());
11239 15 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11240 :
11241 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11242 15 : CHECK_NE(loop_var, loop_var2);
11243 15 : CHECK(loop_var2->IsContextSlot());
11244 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11245 45 : });
11246 : }
11247 :
11248 : // Similar to the above, but the first block scope's variables are not
11249 : // captured due to the closure occurring in a nested scope.
11250 : const char* context_bindings3[] = {
11251 : "function loop() {"
11252 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11253 : " (() => loop_var)();"
11254 : " }"
11255 : "}",
11256 :
11257 : "function loop() {"
11258 : " for (let loop_var = 0; loop_var < (() => (loop_var, 10))();"
11259 : " ++loop_var) {"
11260 : " }"
11261 : "}",
11262 :
11263 : "function loop() {"
11264 : " for (let loop_var = 0; loop_var < 10; (() => ++loop_var)()) {"
11265 : " }"
11266 : "}",
11267 5 : };
11268 :
11269 20 : for (const char* source : context_bindings3) {
11270 15 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11271 30 : i::Scope* fn = s->inner_scope();
11272 15 : CHECK(fn->is_function_scope());
11273 :
11274 45 : i::Scope* loop_block = fn->inner_scope();
11275 15 : CHECK(loop_block->is_block_scope());
11276 :
11277 : const i::AstRawString* var_name =
11278 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11279 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11280 15 : CHECK_NOT_NULL(loop_var);
11281 15 : CHECK(loop_var->IsStackLocal());
11282 15 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11283 :
11284 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11285 15 : CHECK_NE(loop_var, loop_var2);
11286 15 : CHECK(loop_var2->IsContextSlot());
11287 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11288 45 : });
11289 : }
11290 5 : }
11291 :
11292 25880 : TEST(PrivateNamesSyntaxError) {
11293 : i::Isolate* isolate = CcTest::i_isolate();
11294 : i::HandleScope scope(isolate);
11295 10 : LocalContext env;
11296 :
11297 155 : auto test = [isolate](const char* program, bool is_lazy) {
11298 155 : i::FLAG_harmony_private_fields = true;
11299 155 : i::Factory* const factory = isolate->factory();
11300 : i::Handle<i::String> source =
11301 310 : factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
11302 155 : i::Handle<i::Script> script = factory->NewScript(source);
11303 155 : i::ParseInfo info(isolate, script);
11304 :
11305 : info.set_allow_lazy_parsing(is_lazy);
11306 155 : CHECK(i::parsing::ParseProgram(&info, isolate));
11307 155 : CHECK(i::Rewriter::Rewrite(&info));
11308 155 : CHECK(!i::DeclarationScope::Analyze(&info));
11309 310 : return info.pending_error_handler()->has_pending_error();
11310 160 : };
11311 :
11312 : const char* data[] = {
11313 : "class A {"
11314 : " foo() { return this.#bar; }"
11315 : "}",
11316 :
11317 : "let A = class {"
11318 : " foo() { return this.#bar; }"
11319 : "}",
11320 :
11321 : "class A {"
11322 : " #foo; "
11323 : " bar() { return this.#baz; }"
11324 : "}",
11325 :
11326 : "let A = class {"
11327 : " #foo; "
11328 : " bar() { return this.#baz; }"
11329 : "}",
11330 :
11331 : "class A {"
11332 : " bar() {"
11333 : " class D { #baz = 1; };"
11334 : " return this.#baz;"
11335 : " }"
11336 : "}",
11337 :
11338 : "let A = class {"
11339 : " bar() {"
11340 : " class D { #baz = 1; };"
11341 : " return this.#baz;"
11342 : " }"
11343 : "}",
11344 :
11345 : "a.#bar",
11346 :
11347 : "class Foo {};"
11348 : "Foo.#bar;",
11349 :
11350 : "let Foo = class {};"
11351 : "Foo.#bar;",
11352 :
11353 : "class Foo {};"
11354 : "(new Foo).#bar;",
11355 :
11356 : "let Foo = class {};"
11357 : "(new Foo).#bar;",
11358 :
11359 : "class Foo { #bar; };"
11360 : "(new Foo).#bar;",
11361 :
11362 : "let Foo = class { #bar; };"
11363 : "(new Foo).#bar;",
11364 :
11365 : "function t(){"
11366 : " class Foo { getA() { return this.#foo; } }"
11367 : "}",
11368 :
11369 : "function t(){"
11370 : " return class { getA() { return this.#foo; } }"
11371 : "}",
11372 5 : };
11373 :
11374 : // TODO(gsathya): The preparser does not track unresolved
11375 : // variables in top level function which fails this test.
11376 : // https://bugs.chromium.org/p/v8/issues/detail?id=7468
11377 : const char* parser_data[] = {
11378 : "function t() {"
11379 : " return this.#foo;"
11380 : "}",
11381 5 : };
11382 :
11383 80 : for (const char* source : data) {
11384 75 : CHECK(test(source, true));
11385 75 : CHECK(test(source, false));
11386 : }
11387 :
11388 10 : for (const char* source : parser_data) {
11389 5 : CHECK(test(source, false));
11390 : }
11391 5 : }
11392 :
11393 25880 : TEST(HashbangSyntax) {
11394 : const char* context_data[][2] = {
11395 : {"#!\n", ""},
11396 : {"#!---IGNORED---\n", ""},
11397 : {"#!---IGNORED---\r", ""},
11398 : {"#!---IGNORED---\xE2\x80\xA8", ""}, // <U+2028>
11399 : {"#!---IGNORED---\xE2\x80\xA9", ""}, // <U+2029>
11400 5 : {nullptr, nullptr}};
11401 :
11402 5 : const char* data[] = {"function\nFN\n(\n)\n {\n}\nFN();", nullptr};
11403 :
11404 5 : i::FLAG_harmony_hashbang = true;
11405 5 : RunParserSyncTest(context_data, data, kSuccess);
11406 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
11407 5 : nullptr, 0, true);
11408 :
11409 5 : i::FLAG_harmony_hashbang = false;
11410 5 : RunParserSyncTest(context_data, data, kError);
11411 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0, nullptr,
11412 5 : 0, true);
11413 5 : }
11414 :
11415 25880 : TEST(HashbangSyntaxErrors) {
11416 5 : const char* file_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
11417 : const char* other_context_data[][2] = {{"/**/", ""},
11418 : {"//---\n", ""},
11419 : {";", ""},
11420 : {"function fn() {", "}"},
11421 : {"function* fn() {", "}"},
11422 : {"async function fn() {", "}"},
11423 : {"async function* fn() {", "}"},
11424 : {"() => {", "}"},
11425 : {"() => ", ""},
11426 : {"function fn(a = ", ") {}"},
11427 : {"function* fn(a = ", ") {}"},
11428 : {"async function fn(a = ", ") {}"},
11429 : {"async function* fn(a = ", ") {}"},
11430 : {"(a = ", ") => {}"},
11431 : {"(a = ", ") => a"},
11432 : {"class k {", "}"},
11433 : {"[", "]"},
11434 : {"{", "}"},
11435 : {"({", "})"},
11436 5 : {nullptr, nullptr}};
11437 :
11438 : const char* invalid_hashbang_data[] = {// Encoded characters are not allowed
11439 : "#\\u0021\n"
11440 : "#\\u{21}\n",
11441 : "#\\x21\n",
11442 : "#\\041\n",
11443 : "\\u0023!\n",
11444 : "\\u{23}!\n",
11445 : "\\x23!\n",
11446 : "\\043!\n",
11447 : "\\u0023\\u0021\n",
11448 :
11449 : "\n#!---IGNORED---\n",
11450 : " #!---IGNORED---\n",
11451 5 : nullptr};
11452 5 : const char* hashbang_data[] = {"#!\n", "#!---IGNORED---\n", nullptr};
11453 :
11454 15 : auto SyntaxErrorTest = [](const char* context_data[][2], const char* data[]) {
11455 15 : i::FLAG_harmony_hashbang = true;
11456 15 : RunParserSyncTest(context_data, data, kError);
11457 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11458 15 : nullptr, 0, true);
11459 :
11460 15 : i::FLAG_harmony_hashbang = false;
11461 15 : RunParserSyncTest(context_data, data, kError);
11462 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11463 15 : nullptr, 0, true);
11464 15 : };
11465 :
11466 5 : SyntaxErrorTest(file_context_data, invalid_hashbang_data);
11467 5 : SyntaxErrorTest(other_context_data, invalid_hashbang_data);
11468 5 : SyntaxErrorTest(other_context_data, hashbang_data);
11469 5 : }
11470 :
11471 : } // namespace test_parsing
11472 : } // namespace internal
11473 77625 : } // namespace v8
|