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 26644 : TEST(AutoSemicolonToken) {
86 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
87 : Token::Value token = static_cast<Token::Value>(i);
88 560 : 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 26644 : TEST(AnyIdentifierToken) {
111 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
112 : Token::Value token = static_cast<Token::Value>(i);
113 560 : 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 26644 : TEST(CallableToken) {
137 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
138 : Token::Value token = static_cast<Token::Value>(i);
139 560 : 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 26644 : TEST(IsValidIdentifierToken) {
167 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
168 : Token::Value token = static_cast<Token::Value>(i);
169 2800 : 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 5600 : for (int is_generator = 0; is_generator < 2; is_generator++) {
173 11200 : for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
174 4480 : 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 26644 : TEST(IsStrictReservedWord) {
199 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
200 : Token::Value token = static_cast<Token::Value>(i);
201 560 : 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 26644 : TEST(IsLiteralToken) {
223 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
224 : Token::Value token = static_cast<Token::Value>(i);
225 560 : 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 26644 : TEST(AssignmentOp) {
243 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
244 : Token::Value token = static_cast<Token::Value>(i);
245 560 : 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 26644 : TEST(ArrowOrAssignmentOp) {
254 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
255 : Token::Value token = static_cast<Token::Value>(i);
256 560 : 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 26644 : TEST(BinaryOp) {
276 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
277 : Token::Value token = static_cast<Token::Value>(i);
278 560 : 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 26644 : TEST(CompareOp) {
301 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
302 : Token::Value token = static_cast<Token::Value>(i);
303 560 : 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 26644 : TEST(IsOrderedRelationalCompareOp) {
320 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
321 : Token::Value token = static_cast<Token::Value>(i);
322 560 : 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 26644 : TEST(IsEqualityOp) {
338 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
339 : Token::Value token = static_cast<Token::Value>(i);
340 560 : 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 26644 : TEST(IsBitOp) {
360 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
361 : Token::Value token = static_cast<Token::Value>(i);
362 560 : 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 26644 : TEST(IsUnaryOp) {
382 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
383 : Token::Value token = static_cast<Token::Value>(i);
384 560 : 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 26644 : TEST(IsPropertyOrCall) {
402 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
403 : Token::Value token = static_cast<Token::Value>(i);
404 560 : 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 26644 : TEST(IsMember) {
441 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
442 : Token::Value token = static_cast<Token::Value>(i);
443 560 : CHECK_EQ(TokenIsMember(token), Token::IsMember(token));
444 : }
445 5 : }
446 :
447 26644 : TEST(IsTemplate) {
448 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
449 : Token::Value token = static_cast<Token::Value>(i);
450 560 : CHECK_EQ(TokenIsTemplate(token), Token::IsTemplate(token));
451 : }
452 5 : }
453 :
454 26644 : TEST(IsProperty) {
455 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
456 : Token::Value token = static_cast<Token::Value>(i);
457 560 : 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 26644 : TEST(IsCountOp) {
472 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
473 : Token::Value token = static_cast<Token::Value>(i);
474 560 : CHECK_EQ(TokenIsCountOp(token), Token::IsCountOp(token));
475 : }
476 5 : }
477 :
478 26644 : TEST(IsUnaryOrCountOp) {
479 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
480 : Token::Value token = static_cast<Token::Value>(i);
481 1085 : 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 26644 : TEST(IsShiftOp) {
498 1125 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
499 : Token::Value token = static_cast<Token::Value>(i);
500 560 : CHECK_EQ(TokenIsShiftOp(token), Token::IsShiftOp(token));
501 : }
502 5 : }
503 :
504 26644 : 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 435 : 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 1505 : 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 26644 : TEST(ScanHTMLEndComments) {
563 5 : v8::V8::Initialize();
564 5 : v8::Isolate* isolate = CcTest::isolate();
565 : i::Isolate* i_isolate = CcTest::i_isolate();
566 10 : 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 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
617 205 : 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 100 : &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 45 : 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 20 : &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 : }
654 5 : }
655 :
656 26644 : 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 : class ScriptResource : public v8::String::ExternalOneByteStringResource {
678 : public:
679 : ScriptResource(const char* data, size_t length)
680 : : data_(data), length_(length) { }
681 :
682 : const char* data() const override { return data_; }
683 : size_t length() const override { return length_; }
684 :
685 : private:
686 : const char* data_;
687 : size_t length_;
688 : };
689 :
690 :
691 26644 : TEST(StandAlonePreParser) {
692 5 : v8::V8::Initialize();
693 : 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 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
707 65 : 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 30 : &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 26644 : TEST(StandAlonePreParserNoNatives) {
729 5 : v8::V8::Initialize();
730 :
731 : 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 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
739 25 : 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 10 : 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 26644 : TEST(RegressChromium62639) {
762 5 : v8::V8::Initialize();
763 : 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 5 : 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 26644 : TEST(PreParseOverflow) {
795 5 : v8::V8::Initialize();
796 : 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 : 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 5 : 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 70 : i::Scanner scanner(stream, false);
828 35 : scanner.Initialize();
829 :
830 : int i = 0;
831 : 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 190 : } while (expected_tokens[i] != i::Token::ILLEGAL);
840 35 : }
841 :
842 :
843 26644 : 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 55 : 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 110 : HashSeed(CcTest::i_isolate()));
906 : 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 : i::Vector<const uint8_t> actual = content.ToOneByteVector();
914 910 : 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 26644 : 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 26644 : 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 10 : 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 35 : for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1041 1155 : 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 780 : factory->NewStringFromUtf8(i::CStrVector(program.start()))
1055 390 : .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 : i::DeclarationScope* script_scope = info.literal()->scope();
1068 390 : CHECK(script_scope->is_script_scope());
1069 :
1070 : 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 : }
1103 5 : }
1104 :
1105 75 : static void CheckParsesToNumber(const char* source) {
1106 75 : v8::V8::Initialize();
1107 150 : 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 150 : factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1118 75 : .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 75 : i::FunctionLiteral* fun = decl->AsFunctionDeclaration()->fun();
1131 75 : CHECK_EQ(fun->body()->length(), 1);
1132 150 : CHECK(fun->body()->at(0)->IsReturnStatement());
1133 75 : i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1134 75 : i::Literal* lit = ret->expression()->AsLiteral();
1135 75 : CHECK(lit->IsNumberLiteral());
1136 75 : }
1137 :
1138 :
1139 26644 : 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 26644 : 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 10 : 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 515 : 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 510 : i::Handle<i::String> source = factory->NewStringFromUtf8(
1428 : 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 : 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 : i::Scope* inner_scope = scope->inner_scope();
1443 : DCHECK_NOT_NULL(inner_scope);
1444 : DCHECK_NULL(inner_scope->sibling());
1445 255 : 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 : }
1451 5 : }
1452 :
1453 :
1454 26644 : 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 10 : v8::HandleScope handles(CcTest::isolate());
1470 : i::FunctionLiteral* function;
1471 :
1472 25 : 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 20 : i::ParseInfo info(isolate, script);
1478 10 : i::parsing::ParseProgram(&info, isolate);
1479 : function = info.literal();
1480 10 : CHECK_NOT_NULL(function);
1481 10 : CHECK_EQ(1, function->body()->length());
1482 : i::FunctionLiteral* inner =
1483 10 : 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 10 : ->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 : }
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 525089 : void SetGlobalFlags(base::EnumSet<ParserFlag> flags) {
1544 525089 : i::FLAG_allow_natives_syntax = flags.contains(kAllowNatives);
1545 525089 : i::FLAG_harmony_public_fields = flags.contains(kAllowHarmonyPublicFields);
1546 525089 : i::FLAG_harmony_private_fields = flags.contains(kAllowHarmonyPrivateFields);
1547 525089 : i::FLAG_harmony_private_methods = flags.contains(kAllowHarmonyPrivateMethods);
1548 525089 : i::FLAG_harmony_static_fields = flags.contains(kAllowHarmonyStaticFields);
1549 525089 : i::FLAG_harmony_dynamic_import = flags.contains(kAllowHarmonyDynamicImport);
1550 525089 : i::FLAG_harmony_import_meta = flags.contains(kAllowHarmonyImportMeta);
1551 : i::FLAG_harmony_numeric_separator =
1552 525089 : flags.contains(kAllowHarmonyNumericSeparator);
1553 525089 : }
1554 :
1555 524109 : 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 524109 : }
1572 :
1573 525089 : 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 : i::Isolate* isolate = CcTest::i_isolate();
1579 : i::Factory* factory = isolate->factory();
1580 :
1581 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1582 :
1583 : // Preparse the data.
1584 : i::PendingCompilationErrorHandler pending_error_handler;
1585 525089 : if (test_preparser) {
1586 : std::unique_ptr<i::Utf16CharacterStream> stream(
1587 524109 : i::ScannerStream::For(isolate, source));
1588 1048218 : i::Scanner scanner(stream.get(), is_module);
1589 1048218 : i::Zone zone(isolate->allocator(), ZONE_NAME);
1590 : i::AstValueFactory ast_value_factory(&zone, isolate->ast_string_constants(),
1591 524109 : HashSeed(isolate));
1592 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
1593 : &pending_error_handler,
1594 : isolate->counters()->runtime_call_stats(),
1595 1048218 : isolate->logger(), -1, is_module);
1596 524109 : SetParserFlags(&preparser, flags);
1597 524109 : scanner.Initialize();
1598 524109 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
1599 524109 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1600 : }
1601 :
1602 : // Parse the data
1603 : i::FunctionLiteral* function;
1604 : {
1605 525089 : SetGlobalFlags(flags);
1606 525089 : i::Handle<i::Script> script = factory->NewScript(source);
1607 1050178 : i::ParseInfo info(isolate, script);
1608 : info.set_allow_lazy_parsing(flags.contains(kAllowLazy));
1609 525089 : if (is_module) info.set_module();
1610 525089 : i::parsing::ParseProgram(&info, isolate);
1611 : function = info.literal();
1612 : }
1613 :
1614 : // Check that preparsing fails iff parsing fails.
1615 525089 : if (function == nullptr) {
1616 : // Extract exception from the parser.
1617 277550 : 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 555100 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1622 : .ToHandleChecked());
1623 : isolate->clear_pending_exception();
1624 :
1625 277550 : 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 277550 : if (test_preparser && !pending_error_handler.has_pending_error() &&
1636 : !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 277550 : if (test_preparser && !ignore_error_msg &&
1648 : !pending_error_handler.has_error_unidentifiable_by_preparser()) {
1649 : i::Handle<i::String> preparser_message =
1650 3042 : pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate());
1651 3042 : 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 247539 : } 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 247539 : } 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 525089 : }
1681 :
1682 134163 : 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 402489 : ->NewStringFromUtf8(Vector<const char>(source, strlen(source)))
1695 134163 : .ToHandleChecked();
1696 1184341 : for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1697 : base::EnumSet<ParserFlag> flags;
1698 2606873 : for (size_t flag_index = 0; flag_index < varying_flags_length;
1699 : ++flag_index) {
1700 1040892 : if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1701 : }
1702 823549 : for (size_t flag_index = 0; flag_index < always_true_flags_length;
1703 : ++flag_index) {
1704 149230 : flags.Add(always_true_flags[flag_index]);
1705 : }
1706 525089 : 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 525089 : TestParserSyncWithFlags(str, flags, result, is_module, test_preparser,
1711 525089 : ignore_error_msg);
1712 : }
1713 134163 : }
1714 :
1715 :
1716 26640 : 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 2 : 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 1 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1754 2 : i::GetCurrentStackPosition() - 128 * 1024);
1755 :
1756 27 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1757 923 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1758 5005 : 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 1 : TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1788 1 : }
1789 :
1790 :
1791 26644 : 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 10 : 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 : *exception));
1813 5 : }
1814 :
1815 1580 : 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 3160 : v8::HandleScope handles(CcTest::isolate());
1823 1580 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1824 : v8::Context::Scope context_scope(context);
1825 :
1826 1580 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1827 3160 : 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 1580 : if (flags == nullptr) {
1837 : flags = default_flags;
1838 : flags_len = arraysize(default_flags);
1839 1560 : if (always_true_flags != nullptr || always_false_flags != nullptr) {
1840 : // Remove always_true/false_flags from default_flags (if present).
1841 190 : CHECK((always_true_flags != nullptr) == (always_true_len > 0));
1842 190 : CHECK((always_false_flags != nullptr) == (always_false_len > 0));
1843 190 : generated_flags = new ParserFlag[flags_len + always_true_len];
1844 : int flag_index = 0;
1845 950 : for (int i = 0; i < flags_len; ++i) {
1846 : bool use_flag = true;
1847 1520 : for (int j = 0; use_flag && j < always_true_len; ++j) {
1848 570 : if (flags[i] == always_true_flags[j]) use_flag = false;
1849 : }
1850 380 : 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 380 : if (use_flag) generated_flags[flag_index++] = flags[i];
1854 : }
1855 : flags_len = flag_index;
1856 : flags = generated_flags;
1857 : }
1858 : }
1859 15270 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1860 270615 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1861 131885 : int kPrefixLen = i::StrLength(context_data[i][0]);
1862 : int kStatementLen = i::StrLength(statement_data[j]);
1863 131885 : int kSuffixLen = i::StrLength(context_data[i][1]);
1864 131885 : int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1865 :
1866 : // Plug the source code pieces together.
1867 131885 : i::ScopedVector<char> program(kProgramSize + 1);
1868 131885 : int length = i::SNPrintF(program,
1869 : "%s%s%s",
1870 : context_data[i][0],
1871 : statement_data[j],
1872 131885 : context_data[i][1]);
1873 131885 : PrintF("%s\n", program.start());
1874 131885 : CHECK_EQ(length, kProgramSize);
1875 131885 : 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 131885 : ignore_error_msg);
1879 : }
1880 : }
1881 1580 : delete[] generated_flags;
1882 1580 : }
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 0 : 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 26644 : TEST(NumericSeparator) {
1897 10 : 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 5 : RunParserSyncTest(context_data, statement_data, kError);
1912 5 : }
1913 :
1914 26644 : TEST(NumericSeparatorErrors) {
1915 10 : 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 5 : RunParserSyncTest(context_data, statement_data, kError);
1932 5 : }
1933 :
1934 26644 : TEST(NumericSeparatorImplicitOctalsErrors) {
1935 10 : 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 5 : RunParserSyncTest(context_data, statement_data, kError);
1950 5 : }
1951 :
1952 26644 : TEST(NumericSeparatorUnicodeEscapeSequencesErrors) {
1953 10 : 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 5 : RunParserSyncTest(context_data, statement_data, kError);
1966 5 : }
1967 :
1968 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 655345 : 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 26644 : 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 26644 : 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 26644 : 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 26644 : 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 10 : v8::HandleScope scope(isolate);
3083 5 : 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 5 : ExpectString("%FunctionGetInferredName(obj3[1])", "obj3.<computed>");
3111 5 : ExpectString("%FunctionGetInferredName(obj4[1])", "");
3112 5 : ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3113 5 : ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3114 5 : }
3115 :
3116 :
3117 26644 : TEST(FuncNameInferrerTwoByte) {
3118 : // Tests function name inferring in cases where some parts of the inferred
3119 : // function name are two-byte strings.
3120 5 : i::FLAG_allow_natives_syntax = true;
3121 5 : v8::Isolate* isolate = CcTest::isolate();
3122 10 : v8::HandleScope scope(isolate);
3123 5 : LocalContext env;
3124 : uint16_t* two_byte_source = AsciiToTwoByteString(
3125 : "var obj1 = { oXj2 : { foo1: function() {} } }; "
3126 5 : "%FunctionGetInferredName(obj1.oXj2.foo1)");
3127 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3128 : // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3129 5 : two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010D;
3130 : v8::Local<v8::String> source =
3131 5 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3132 : v8::NewStringType::kNormal)
3133 5 : .ToLocalChecked();
3134 5 : v8::Local<v8::Value> result = CompileRun(source);
3135 5 : CHECK(result->IsString());
3136 : v8::Local<v8::String> expected_name =
3137 5 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3138 : v8::NewStringType::kNormal)
3139 : .ToLocalChecked();
3140 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3141 : i::DeleteArray(two_byte_source);
3142 : i::DeleteArray(two_byte_name);
3143 5 : }
3144 :
3145 :
3146 26644 : TEST(FuncNameInferrerEscaped) {
3147 : // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3148 : // character as a Unicode escape.
3149 5 : i::FLAG_allow_natives_syntax = true;
3150 5 : v8::Isolate* isolate = CcTest::isolate();
3151 10 : v8::HandleScope scope(isolate);
3152 5 : LocalContext env;
3153 : uint16_t* two_byte_source = AsciiToTwoByteString(
3154 : "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3155 5 : "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3156 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3157 : // Fix to correspond to the non-ASCII name in two_byte_source.
3158 5 : two_byte_name[6] = 0x010D;
3159 : v8::Local<v8::String> source =
3160 5 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3161 : v8::NewStringType::kNormal)
3162 5 : .ToLocalChecked();
3163 5 : v8::Local<v8::Value> result = CompileRun(source);
3164 5 : CHECK(result->IsString());
3165 : v8::Local<v8::String> expected_name =
3166 5 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3167 : v8::NewStringType::kNormal)
3168 : .ToLocalChecked();
3169 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3170 : i::DeleteArray(two_byte_source);
3171 : i::DeleteArray(two_byte_name);
3172 5 : }
3173 :
3174 :
3175 26644 : TEST(RegressionLazyFunctionWithErrorWithArg) {
3176 : // Test only applies when lazy parsing.
3177 5 : if (!i::FLAG_lazy) return;
3178 :
3179 : // The bug occurred when a lazy function had an error which requires a
3180 : // parameter (such as "unknown label" here). The error message was processed
3181 : // before the AstValueFactory containing the error message string was
3182 : // internalized.
3183 5 : v8::Isolate* isolate = CcTest::isolate();
3184 10 : v8::HandleScope scope(isolate);
3185 5 : LocalContext env;
3186 5 : i::FLAG_lazy = true;
3187 : CompileRun("function this_is_lazy() {\n"
3188 : " break p;\n"
3189 : "}\n"
3190 : "this_is_lazy();\n");
3191 : }
3192 :
3193 :
3194 26644 : TEST(SerializationOfMaybeAssignmentFlag) {
3195 : i::Isolate* isolate = CcTest::i_isolate();
3196 : i::Factory* factory = isolate->factory();
3197 : i::HandleScope scope(isolate);
3198 5 : LocalContext env;
3199 :
3200 : const char* src =
3201 : "function h() {"
3202 : " var result = [];"
3203 : " function f() {"
3204 : " result.push(2);"
3205 : " }"
3206 : " function assertResult(r) {"
3207 : " f();"
3208 : " result = [];"
3209 : " }"
3210 : " assertResult([2]);"
3211 : " assertResult([2]);"
3212 : " return f;"
3213 : "};"
3214 : "h();";
3215 :
3216 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3217 5 : i::SNPrintF(program, "%s", src);
3218 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3219 10 : source->PrintOn(stdout);
3220 : printf("\n");
3221 10 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
3222 : v8::Local<v8::Value> v = CompileRun(src);
3223 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3224 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3225 5 : i::Context context = f->context();
3226 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3227 5 : HashSeed(isolate));
3228 5 : const i::AstRawString* name = avf.GetOneByteString("result");
3229 5 : avf.Internalize(isolate);
3230 : i::Handle<i::String> str = name->string();
3231 5 : CHECK(str->IsInternalizedString());
3232 : i::DeclarationScope* script_scope =
3233 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3234 5 : i::Scope* s = i::Scope::DeserializeScopeChain(
3235 : isolate, &zone, context->scope_info(), script_scope, &avf,
3236 5 : i::Scope::DeserializationMode::kIncludingVariables);
3237 5 : CHECK(s != script_scope);
3238 5 : CHECK_NOT_NULL(name);
3239 :
3240 : // Get result from h's function context (that is f's context)
3241 : i::Variable* var = s->LookupForTesting(name);
3242 :
3243 5 : CHECK_NOT_NULL(var);
3244 : // Maybe assigned should survive deserialization
3245 5 : CHECK_EQ(var->maybe_assigned(), i::kMaybeAssigned);
3246 : // TODO(sigurds) Figure out if is_used should survive context serialization.
3247 5 : }
3248 :
3249 :
3250 26644 : TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3251 : i::Isolate* isolate = CcTest::i_isolate();
3252 : i::Factory* factory = isolate->factory();
3253 : i::HandleScope scope(isolate);
3254 5 : LocalContext env;
3255 :
3256 : const char* src =
3257 : "function f(x) {"
3258 : " var a = arguments;"
3259 : " function g(i) {"
3260 : " ++a[0];"
3261 : " };"
3262 : " return g;"
3263 : " }"
3264 : "f(0);";
3265 :
3266 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3267 5 : i::SNPrintF(program, "%s", src);
3268 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3269 10 : source->PrintOn(stdout);
3270 : printf("\n");
3271 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
3272 : v8::Local<v8::Value> v = CompileRun(src);
3273 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3274 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3275 5 : i::Context context = f->context();
3276 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3277 5 : HashSeed(isolate));
3278 5 : const i::AstRawString* name_x = avf.GetOneByteString("x");
3279 5 : avf.Internalize(isolate);
3280 :
3281 : i::DeclarationScope* script_scope =
3282 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3283 5 : i::Scope* s = i::Scope::DeserializeScopeChain(
3284 : isolate, &zone, context->scope_info(), script_scope, &avf,
3285 5 : i::Scope::DeserializationMode::kIncludingVariables);
3286 5 : CHECK(s != script_scope);
3287 :
3288 : // Get result from f's function context (that is g's outer context)
3289 : i::Variable* var_x = s->LookupForTesting(name_x);
3290 5 : CHECK_NOT_NULL(var_x);
3291 5 : CHECK_EQ(var_x->maybe_assigned(), i::kMaybeAssigned);
3292 5 : }
3293 :
3294 :
3295 26644 : TEST(InnerAssignment) {
3296 : i::Isolate* isolate = CcTest::i_isolate();
3297 : i::Factory* factory = isolate->factory();
3298 : i::HandleScope scope(isolate);
3299 5 : LocalContext env;
3300 :
3301 : const char* prefix = "function f() {";
3302 : const char* midfix = " function g() {";
3303 : const char* suffix = "}}; f";
3304 : struct {
3305 : const char* source;
3306 : bool assigned;
3307 : bool strict;
3308 : } outers[] = {
3309 : // Actual assignments.
3310 : {"var x; var x = 5;", true, false},
3311 : {"var x; { var x = 5; }", true, false},
3312 : {"'use strict'; let x; x = 6;", true, true},
3313 : {"var x = 5; function x() {}", true, false},
3314 : {"var x = 4; var x = 5;", true, false},
3315 : {"var [x, x] = [4, 5];", true, false},
3316 : {"var x; [x, x] = [4, 5];", true, false},
3317 : {"var {a: x, b: x} = {a: 4, b: 5};", true, false},
3318 : {"var x = {a: 4, b: (x = 5)};", true, false},
3319 : {"var {x=1} = {a: 4, b: (x = 5)};", true, false},
3320 : {"var {x} = {x: 4, b: (x = 5)};", true, false},
3321 : // Actual non-assignments.
3322 : {"var x;", false, false},
3323 : {"var x = 5;", false, false},
3324 : {"'use strict'; let x;", false, true},
3325 : {"'use strict'; let x = 6;", false, true},
3326 : {"'use strict'; var x = 0; { let x = 6; }", false, true},
3327 : {"'use strict'; var x = 0; { let x; x = 6; }", false, true},
3328 : {"'use strict'; let x = 0; { let x = 6; }", false, true},
3329 : {"'use strict'; let x = 0; { let x; x = 6; }", false, true},
3330 : {"var x; try {} catch (x) { x = 5; }", false, false},
3331 : {"function x() {}", false, false},
3332 : // Eval approximation.
3333 : {"var x; eval('');", true, false},
3334 : {"eval(''); var x;", true, false},
3335 : {"'use strict'; let x; eval('');", true, true},
3336 : {"'use strict'; eval(''); let x;", true, true},
3337 : // Non-assignments not recognized, because the analysis is approximative.
3338 : {"var x; var x;", true, false},
3339 : {"var x = 5; var x;", true, false},
3340 : {"var x; { var x; }", true, false},
3341 : {"var x; function x() {}", true, false},
3342 : {"function x() {}; var x;", true, false},
3343 : {"var x; try {} catch (x) { var x = 5; }", true, false},
3344 5 : };
3345 :
3346 : // We set allow_error_in_inner_function to true in cases where our handling of
3347 : // assigned variables in lazy inner functions is currently overly pessimistic.
3348 : // FIXME(marja): remove it when no longer needed.
3349 : struct {
3350 : const char* source;
3351 : bool assigned;
3352 : bool with;
3353 : bool allow_error_in_inner_function;
3354 : } inners[] = {
3355 : // Actual assignments.
3356 : {"x = 1;", true, false, false},
3357 : {"x++;", true, false, false},
3358 : {"++x;", true, false, false},
3359 : {"x--;", true, false, false},
3360 : {"--x;", true, false, false},
3361 : {"{ x = 1; }", true, false, false},
3362 : {"'use strict'; { let x; }; x = 0;", true, false, false},
3363 : {"'use strict'; { const x = 1; }; x = 0;", true, false, false},
3364 : {"'use strict'; { function x() {} }; x = 0;", true, false, false},
3365 : {"with ({}) { x = 1; }", true, true, false},
3366 : {"eval('');", true, false, false},
3367 : {"'use strict'; { let y; eval('') }", true, false, false},
3368 : {"function h() { x = 0; }", true, false, false},
3369 : {"(function() { x = 0; })", true, false, false},
3370 : {"(function() { x = 0; })", true, false, false},
3371 : {"with ({}) (function() { x = 0; })", true, true, false},
3372 : {"for (x of [1,2,3]) {}", true, false, false},
3373 : {"for (x in {a: 1}) {}", true, false, false},
3374 : {"for ([x] of [[1],[2],[3]]) {}", true, false, false},
3375 : {"for ([x] in {ab: 1}) {}", true, false, false},
3376 : {"for ([...x] in {ab: 1}) {}", true, false, false},
3377 : {"[x] = [1]", true, false, false},
3378 : // Actual non-assignments.
3379 : {"", false, false, false},
3380 : {"x;", false, false, false},
3381 : {"var x;", false, false, false},
3382 : {"var x = 8;", false, false, false},
3383 : {"var x; x = 8;", false, false, false},
3384 : {"'use strict'; let x;", false, false, false},
3385 : {"'use strict'; let x = 8;", false, false, false},
3386 : {"'use strict'; let x; x = 8;", false, false, false},
3387 : {"'use strict'; const x = 8;", false, false, false},
3388 : {"function x() {}", false, false, false},
3389 : {"function x() { x = 0; }", false, false, true},
3390 : {"function h(x) { x = 0; }", false, false, false},
3391 : {"'use strict'; { let x; x = 0; }", false, false, false},
3392 : {"{ var x; }; x = 0;", false, false, false},
3393 : {"with ({}) {}", false, true, false},
3394 : {"var x; { with ({}) { x = 1; } }", false, true, false},
3395 : {"try {} catch(x) { x = 0; }", false, false, true},
3396 : {"try {} catch(x) { with ({}) { x = 1; } }", false, true, true},
3397 : // Eval approximation.
3398 : {"eval('');", true, false, false},
3399 : {"function h() { eval(''); }", true, false, false},
3400 : {"(function() { eval(''); })", true, false, false},
3401 : // Shadowing not recognized because of eval approximation.
3402 : {"var x; eval('');", true, false, false},
3403 : {"'use strict'; let x; eval('');", true, false, false},
3404 : {"try {} catch(x) { eval(''); }", true, false, false},
3405 : {"function x() { eval(''); }", true, false, false},
3406 : {"(function(x) { eval(''); })", true, false, false},
3407 5 : };
3408 :
3409 5 : int prefix_len = Utf8LengthHelper(prefix);
3410 5 : int midfix_len = Utf8LengthHelper(midfix);
3411 5 : int suffix_len = Utf8LengthHelper(suffix);
3412 315 : for (unsigned i = 0; i < arraysize(outers); ++i) {
3413 155 : const char* outer = outers[i].source;
3414 155 : int outer_len = Utf8LengthHelper(outer);
3415 15035 : for (unsigned j = 0; j < arraysize(inners); ++j) {
3416 37200 : for (unsigned lazy = 0; lazy < 2; ++lazy) {
3417 15330 : if (outers[i].strict && inners[j].with) continue;
3418 14430 : const char* inner = inners[j].source;
3419 14430 : int inner_len = Utf8LengthHelper(inner);
3420 :
3421 14430 : int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len;
3422 14430 : i::ScopedVector<char> program(len + 1);
3423 :
3424 : i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner,
3425 14430 : suffix);
3426 :
3427 28860 : std::unique_ptr<i::ParseInfo> info;
3428 14430 : if (lazy) {
3429 : printf("%s\n", program.start());
3430 : v8::Local<v8::Value> v = CompileRun(program.start());
3431 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3432 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3433 : i::Handle<i::SharedFunctionInfo> shared =
3434 : i::handle(f->shared(), isolate);
3435 14430 : info =
3436 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3437 7215 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3438 : } else {
3439 : i::Handle<i::String> source =
3440 7215 : factory->InternalizeUtf8String(program.start());
3441 14430 : source->PrintOn(stdout);
3442 : printf("\n");
3443 7215 : i::Handle<i::Script> script = factory->NewScript(source);
3444 14430 : info =
3445 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3446 : info->set_allow_lazy_parsing(false);
3447 7215 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3448 : }
3449 14430 : CHECK(i::Compiler::Analyze(info.get()));
3450 14430 : CHECK_NOT_NULL(info->literal());
3451 :
3452 : i::Scope* scope = info->literal()->scope();
3453 14430 : if (!lazy) {
3454 : scope = scope->inner_scope();
3455 : }
3456 : DCHECK_NOT_NULL(scope);
3457 : DCHECK_NULL(scope->sibling());
3458 : DCHECK(scope->is_function_scope());
3459 : const i::AstRawString* var_name =
3460 14430 : info->ast_value_factory()->GetOneByteString("x");
3461 : i::Variable* var = scope->LookupForTesting(var_name);
3462 14430 : bool expected = outers[i].assigned || inners[j].assigned;
3463 14430 : CHECK_NOT_NULL(var);
3464 14430 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3465 14430 : CHECK(is_maybe_assigned == expected ||
3466 : (is_maybe_assigned && inners[j].allow_error_in_inner_function));
3467 : }
3468 : }
3469 : }
3470 5 : }
3471 :
3472 26644 : TEST(MaybeAssignedParameters) {
3473 : i::Isolate* isolate = CcTest::i_isolate();
3474 : i::HandleScope scope(isolate);
3475 5 : LocalContext env;
3476 :
3477 : struct {
3478 : bool arg_assigned;
3479 : const char* source;
3480 : } tests[] = {
3481 : {false, "function f(arg) {}"},
3482 : {false, "function f(arg) {g(arg)}"},
3483 : {false, "function f(arg) {function h() { g(arg) }; h()}"},
3484 : {false, "function f(arg) {function h() { g(arg) }; return h}"},
3485 : {false, "function f(arg=1) {}"},
3486 : {false, "function f(arg=1) {g(arg)}"},
3487 : {false, "function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3488 : {false,
3489 : "function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3490 : {false,
3491 : "function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)}"},
3492 : {false, "function f(...arg) {g(arg); arguments[0] = 42; g(arg)}"},
3493 : {false,
3494 : "function f(arg) {g(arg); g(function() {arguments[0] = 42}); g(arg)}"},
3495 :
3496 : // strict arguments object
3497 : {false, "function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)}"},
3498 : {false, "function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)}"},
3499 : {false, "function f(arg=1) {g(arg); arguments[0] = 42; g(arg)}"},
3500 : {false,
3501 : "function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)}"},
3502 : {false, "function f(arg) {g(arg); f.arguments[0] = 42; g(arg)}"},
3503 : {false, "function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)}"},
3504 :
3505 : {true, "function f(arg) {g(arg); arg = 42; g(arg)}"},
3506 : {true, "function f(arg) {g(arg); eval('arg = 42'); g(arg)}"},
3507 : {true, "function f(arg) {g(arg); var arg = 42; g(arg)}"},
3508 : {true, "function f(arg, x=1) {g(arg); arg = 42; g(arg)}"},
3509 : {true, "function f(arg, ...x) {g(arg); arg = 42; g(arg)}"},
3510 : {true, "function f(arg=1) {g(arg); arg = 42; g(arg)}"},
3511 : {true, "function f(arg) {'use strict'; g(arg); arg = 42; g(arg)}"},
3512 : {true, "function f(arg, {a=(g(arg), arg=42)}) {g(arg)}"},
3513 : {true, "function f(arg) {g(arg); g(function() {arg = 42}); g(arg)}"},
3514 : {true,
3515 : "function f(arg) {g(arg); g(function() {eval('arg = 42')}); g(arg)}"},
3516 : {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"},
3517 : {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"},
3518 : {true, "function f(...arg) {g(arg); eval('arg = 42'); g(arg)}"},
3519 :
3520 : // sloppy arguments object
3521 : {true, "function f(arg) {g(arg); arguments[0] = 42; g(arg)}"},
3522 : {true, "function f(arg) {g(arg); h(arguments); g(arg)}"},
3523 : {true,
3524 : "function f(arg) {((args) => {arguments[0] = 42})(arguments); "
3525 : "g(arg)}"},
3526 : {true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"},
3527 : {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
3528 5 : };
3529 :
3530 : const char* suffix = "; f";
3531 :
3532 355 : for (unsigned i = 0; i < arraysize(tests); ++i) {
3533 175 : bool assigned = tests[i].arg_assigned;
3534 175 : const char* source = tests[i].source;
3535 875 : for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) {
3536 700 : i::ScopedVector<char> program(Utf8LengthHelper(source) +
3537 700 : Utf8LengthHelper(suffix) + 1);
3538 350 : i::SNPrintF(program, "%s%s", source, suffix);
3539 700 : std::unique_ptr<i::ParseInfo> info;
3540 : printf("%s\n", program.start());
3541 : v8::Local<v8::Value> v = CompileRun(program.start());
3542 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3543 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3544 : i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
3545 700 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3546 : info->set_allow_lazy_parsing(allow_lazy);
3547 350 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3548 350 : CHECK(i::Compiler::Analyze(info.get()));
3549 350 : CHECK_NOT_NULL(info->literal());
3550 :
3551 : i::Scope* scope = info->literal()->scope();
3552 700 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3553 350 : CHECK_NULL(scope->sibling());
3554 350 : CHECK(scope->is_function_scope());
3555 : const i::AstRawString* var_name =
3556 350 : info->ast_value_factory()->GetOneByteString("arg");
3557 : i::Variable* var = scope->LookupForTesting(var_name);
3558 350 : CHECK(var->is_used() || !assigned);
3559 350 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3560 350 : CHECK_EQ(is_maybe_assigned, assigned);
3561 : }
3562 : }
3563 5 : }
3564 :
3565 82960 : struct Input {
3566 : bool assigned;
3567 : std::string source;
3568 : std::vector<unsigned> location; // "Directions" to the relevant scope.
3569 : };
3570 :
3571 15000 : static void TestMaybeAssigned(Input input, const char* variable, bool module,
3572 : bool allow_lazy_parsing) {
3573 : i::Isolate* isolate = CcTest::i_isolate();
3574 : i::Factory* factory = isolate->factory();
3575 : i::Handle<i::String> string =
3576 15000 : factory->InternalizeUtf8String(input.source.c_str());
3577 30000 : string->PrintOn(stdout);
3578 : printf("\n");
3579 15000 : i::Handle<i::Script> script = factory->NewScript(string);
3580 :
3581 30000 : std::unique_ptr<i::ParseInfo> info;
3582 30000 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3583 : info->set_module(module);
3584 : info->set_allow_lazy_parsing(allow_lazy_parsing);
3585 :
3586 15000 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3587 15000 : CHECK(i::Compiler::Analyze(info.get()));
3588 :
3589 15000 : CHECK_NOT_NULL(info->literal());
3590 : i::Scope* scope = info->literal()->scope();
3591 30000 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3592 15000 : CHECK_NULL(scope->sibling());
3593 15000 : CHECK(module ? scope->is_module_scope() : scope->is_script_scope());
3594 :
3595 : i::Variable* var;
3596 : {
3597 : // Find the variable.
3598 15000 : scope = i::ScopeTestHelper::FindScope(scope, input.location);
3599 : const i::AstRawString* var_name =
3600 15000 : info->ast_value_factory()->GetOneByteString(variable);
3601 : var = scope->LookupForTesting(var_name);
3602 : }
3603 :
3604 15000 : CHECK_NOT_NULL(var);
3605 26400 : CHECK_IMPLIES(input.assigned, var->is_used());
3606 : STATIC_ASSERT(true == i::kMaybeAssigned);
3607 15000 : CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
3608 15000 : }
3609 :
3610 4200 : static Input wrap(Input input) {
3611 : Input result;
3612 4200 : result.assigned = input.assigned;
3613 12600 : result.source = "function WRAPPED() { " + input.source + " }";
3614 8400 : result.location.push_back(0);
3615 7580 : for (auto n : input.location) {
3616 3380 : result.location.push_back(n);
3617 : }
3618 4200 : return result;
3619 : }
3620 :
3621 26644 : TEST(MaybeAssignedInsideLoop) {
3622 : i::Isolate* isolate = CcTest::i_isolate();
3623 : i::HandleScope scope(isolate);
3624 5 : LocalContext env;
3625 :
3626 : std::vector<unsigned> top; // Can't use {} in initializers below.
3627 :
3628 : Input module_and_script_tests[] = {
3629 : {true, "for (j=x; j<10; ++j) { foo = j }", top},
3630 : {true, "for (j=x; j<10; ++j) { [foo] = [j] }", top},
3631 : {true, "for (j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3632 : {true, "for (j=x; j<10; ++j) { var foo = j }", top},
3633 : {true, "for (j=x; j<10; ++j) { var [foo] = [j] }", top},
3634 : {true, "for (j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3635 : {true, "for (j=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3638 : {true, "for (j=x; j<10; ++j) { let foo; foo = j }", {0}},
3639 : {true, "for (j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3640 : {true, "for (j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3641 : {false, "for (j=x; j<10; ++j) { let foo = j }", {0}},
3642 : {false, "for (j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3643 : {false, "for (j=x; j<10; ++j) { const foo = j }", {0}},
3644 : {false, "for (j=x; j<10; ++j) { const [foo] = [j] }", {0}},
3645 : {false, "for (j=x; j<10; ++j) { function foo() {return j} }", {0}},
3646 :
3647 : {true, "for ({j}=x; j<10; ++j) { foo = j }", top},
3648 : {true, "for ({j}=x; j<10; ++j) { [foo] = [j] }", top},
3649 : {true, "for ({j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3650 : {true, "for ({j}=x; j<10; ++j) { var foo = j }", top},
3651 : {true, "for ({j}=x; j<10; ++j) { var [foo] = [j] }", top},
3652 : {true, "for ({j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3653 : {true, "for ({j}=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3656 : {true, "for ({j}=x; j<10; ++j) { let foo; foo = j }", {0}},
3657 : {true, "for ({j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3658 : {true, "for ({j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3659 : {false, "for ({j}=x; j<10; ++j) { let foo = j }", {0}},
3660 : {false, "for ({j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3661 : {false, "for ({j}=x; j<10; ++j) { const foo = j }", {0}},
3662 : {false, "for ({j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
3663 : {false, "for ({j}=x; j<10; ++j) { function foo() {return j} }", {0}},
3664 :
3665 : {true, "for (var j=x; j<10; ++j) { foo = j }", top},
3666 : {true, "for (var j=x; j<10; ++j) { [foo] = [j] }", top},
3667 : {true, "for (var j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3668 : {true, "for (var j=x; j<10; ++j) { var foo = j }", 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]=[42]] = [] }", top},
3671 : {true, "for (var j=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3674 : {true, "for (var j=x; j<10; ++j) { let foo; foo = j }", {0}},
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]=[42]] = [] }", {0}},
3677 : {false, "for (var j=x; j<10; ++j) { let foo = j }", {0}},
3678 : {false, "for (var j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3679 : {false, "for (var j=x; j<10; ++j) { const 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) { function foo() {return j} }", {0}},
3682 :
3683 : {true, "for (var {j}=x; j<10; ++j) { foo = j }", top},
3684 : {true, "for (var {j}=x; j<10; ++j) { [foo] = [j] }", top},
3685 : {true, "for (var {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3686 : {true, "for (var {j}=x; j<10; ++j) { var foo = j }", 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]=[42]] = [] }", top},
3689 : {true, "for (var {j}=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3692 : {true, "for (var {j}=x; j<10; ++j) { let foo; foo = j }", {0}},
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]=[42]] = [] }", {0}},
3695 : {false, "for (var {j}=x; j<10; ++j) { let foo = j }", {0}},
3696 : {false, "for (var {j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3697 : {false, "for (var {j}=x; j<10; ++j) { const 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) { function foo() {return j} }", {0}},
3700 :
3701 : {true, "for (let j=x; j<10; ++j) { foo = j }", top},
3702 : {true, "for (let j=x; j<10; ++j) { [foo] = [j] }", top},
3703 : {true, "for (let j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3704 : {true, "for (let j=x; j<10; ++j) { var foo = j }", 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]=[42]] = [] }", top},
3707 : {true, "for (let j=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3710 : {true, "for (let j=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
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]=[42]] = [] }", {0, 0}},
3713 : {false, "for (let j=x; j<10; ++j) { let foo = j }", {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) { const foo = j }", {0, 0}},
3716 : {false, "for (let j=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3717 : {false,
3718 : "for (let j=x; j<10; ++j) { function foo() {return j} }",
3719 : {0, 0, 0}},
3720 :
3721 : {true, "for (let {j}=x; j<10; ++j) { foo = j }", top},
3722 : {true, "for (let {j}=x; j<10; ++j) { [foo] = [j] }", top},
3723 : {true, "for (let {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3724 : {true, "for (let {j}=x; j<10; ++j) { var foo = j }", 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]=[42]] = [] }", top},
3727 : {true, "for (let {j}=x; j<10; ++j) { var foo; foo = j }", 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]=[42]] = [] }", top},
3730 : {true, "for (let {j}=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
3731 : {true, "for (let {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
3732 : {true,
3733 : "for (let {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }",
3734 : {0, 0}},
3735 : {false, "for (let {j}=x; j<10; ++j) { let foo = j }", {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) { const foo = j }", {0, 0}},
3738 : {false, "for (let {j}=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3739 : {false,
3740 : "for (let {j}=x; j<10; ++j) { function foo(){return j} }",
3741 : {0, 0, 0}},
3742 :
3743 : {true, "for (j of x) { foo = j }", top},
3744 : {true, "for (j of x) { [foo] = [j] }", top},
3745 : {true, "for (j of x) { [[foo]=[42]] = [] }", top},
3746 : {true, "for (j of x) { var foo = j }", top},
3747 : {true, "for (j of x) { var [foo] = [j] }", top},
3748 : {true, "for (j of x) { var [[foo]=[42]] = [] }", top},
3749 : {true, "for (j of x) { var foo; foo = j }", top},
3750 : {true, "for (j of x) { var foo; [foo] = [j] }", top},
3751 : {true, "for (j of x) { var foo; [[foo]=[42]] = [] }", top},
3752 : {true, "for (j of x) { let foo; foo = j }", {0}},
3753 : {true, "for (j of x) { let foo; [foo] = [j] }", {0}},
3754 : {true, "for (j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3755 : {false, "for (j of x) { let foo = j }", {0}},
3756 : {false, "for (j of x) { let [foo] = [j] }", {0}},
3757 : {false, "for (j of x) { const foo = j }", {0}},
3758 : {false, "for (j of x) { const [foo] = [j] }", {0}},
3759 : {false, "for (j of x) { function foo() {return j} }", {0}},
3760 :
3761 : {true, "for ({j} of x) { foo = j }", top},
3762 : {true, "for ({j} of x) { [foo] = [j] }", top},
3763 : {true, "for ({j} of x) { [[foo]=[42]] = [] }", top},
3764 : {true, "for ({j} of x) { var foo = j }", top},
3765 : {true, "for ({j} of x) { var [foo] = [j] }", top},
3766 : {true, "for ({j} of x) { var [[foo]=[42]] = [] }", top},
3767 : {true, "for ({j} of x) { var foo; foo = j }", top},
3768 : {true, "for ({j} of x) { var foo; [foo] = [j] }", top},
3769 : {true, "for ({j} of x) { var foo; [[foo]=[42]] = [] }", top},
3770 : {true, "for ({j} of x) { let foo; foo = j }", {0}},
3771 : {true, "for ({j} of x) { let foo; [foo] = [j] }", {0}},
3772 : {true, "for ({j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3773 : {false, "for ({j} of x) { let foo = j }", {0}},
3774 : {false, "for ({j} of x) { let [foo] = [j] }", {0}},
3775 : {false, "for ({j} of x) { const foo = j }", {0}},
3776 : {false, "for ({j} of x) { const [foo] = [j] }", {0}},
3777 : {false, "for ({j} of x) { function foo() {return j} }", {0}},
3778 :
3779 : {true, "for (var j of x) { foo = j }", top},
3780 : {true, "for (var j of x) { [foo] = [j] }", top},
3781 : {true, "for (var j of x) { [[foo]=[42]] = [] }", top},
3782 : {true, "for (var j of x) { var foo = j }", top},
3783 : {true, "for (var j of x) { var [foo] = [j] }", top},
3784 : {true, "for (var j of x) { var [[foo]=[42]] = [] }", top},
3785 : {true, "for (var j of x) { var foo; foo = j }", top},
3786 : {true, "for (var j of x) { var foo; [foo] = [j] }", top},
3787 : {true, "for (var j of x) { var foo; [[foo]=[42]] = [] }", top},
3788 : {true, "for (var j of x) { let foo; foo = j }", {0}},
3789 : {true, "for (var j of x) { let foo; [foo] = [j] }", {0}},
3790 : {true, "for (var j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3791 : {false, "for (var j of x) { let foo = j }", {0}},
3792 : {false, "for (var j of x) { let [foo] = [j] }", {0}},
3793 : {false, "for (var j of x) { const foo = j }", {0}},
3794 : {false, "for (var j of x) { const [foo] = [j] }", {0}},
3795 : {false, "for (var j of x) { function foo() {return j} }", {0}},
3796 :
3797 : {true, "for (var {j} of x) { foo = j }", top},
3798 : {true, "for (var {j} of x) { [foo] = [j] }", top},
3799 : {true, "for (var {j} of x) { [[foo]=[42]] = [] }", top},
3800 : {true, "for (var {j} of x) { var foo = j }", top},
3801 : {true, "for (var {j} of x) { var [foo] = [j] }", top},
3802 : {true, "for (var {j} of x) { var [[foo]=[42]] = [] }", top},
3803 : {true, "for (var {j} of x) { var foo; foo = j }", top},
3804 : {true, "for (var {j} of x) { var foo; [foo] = [j] }", top},
3805 : {true, "for (var {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3806 : {true, "for (var {j} of x) { let foo; foo = j }", {0}},
3807 : {true, "for (var {j} of x) { let foo; [foo] = [j] }", {0}},
3808 : {true, "for (var {j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3809 : {false, "for (var {j} of x) { let foo = j }", {0}},
3810 : {false, "for (var {j} of x) { let [foo] = [j] }", {0}},
3811 : {false, "for (var {j} of x) { const foo = j }", {0}},
3812 : {false, "for (var {j} of x) { const [foo] = [j] }", {0}},
3813 : {false, "for (var {j} of x) { function foo() {return j} }", {0}},
3814 :
3815 : {true, "for (let j of x) { foo = j }", top},
3816 : {true, "for (let j of x) { [foo] = [j] }", top},
3817 : {true, "for (let j of x) { [[foo]=[42]] = [] }", top},
3818 : {true, "for (let j of x) { var foo = j }", top},
3819 : {true, "for (let j of x) { var [foo] = [j] }", top},
3820 : {true, "for (let j of x) { var [[foo]=[42]] = [] }", top},
3821 : {true, "for (let j of x) { var foo; foo = j }", top},
3822 : {true, "for (let j of x) { var foo; [foo] = [j] }", top},
3823 : {true, "for (let j of x) { var foo; [[foo]=[42]] = [] }", top},
3824 : {true, "for (let j of x) { let foo; foo = j }", {0, 0, 0}},
3825 : {true, "for (let j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3826 : {true, "for (let j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3827 : {false, "for (let j of x) { let foo = j }", {0, 0, 0}},
3828 : {false, "for (let j of x) { let [foo] = [j] }", {0, 0, 0}},
3829 : {false, "for (let j of x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3832 :
3833 : {true, "for (let {j} of x) { foo = j }", top},
3834 : {true, "for (let {j} of x) { [foo] = [j] }", top},
3835 : {true, "for (let {j} of x) { [[foo]=[42]] = [] }", top},
3836 : {true, "for (let {j} of x) { var foo = j }", top},
3837 : {true, "for (let {j} of x) { var [foo] = [j] }", top},
3838 : {true, "for (let {j} of x) { var [[foo]=[42]] = [] }", top},
3839 : {true, "for (let {j} of x) { var foo; foo = j }", top},
3840 : {true, "for (let {j} of x) { var foo; [foo] = [j] }", top},
3841 : {true, "for (let {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3842 : {true, "for (let {j} of x) { let foo; foo = j }", {0, 0, 0}},
3843 : {true, "for (let {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3844 : {true, "for (let {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3845 : {false, "for (let {j} of x) { let foo = j }", {0, 0, 0}},
3846 : {false, "for (let {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3847 : {false, "for (let {j} of x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3850 :
3851 : {true, "for (const j of x) { foo = j }", top},
3852 : {true, "for (const j of x) { [foo] = [j] }", top},
3853 : {true, "for (const j of x) { [[foo]=[42]] = [] }", top},
3854 : {true, "for (const j of x) { var foo = j }", top},
3855 : {true, "for (const j of x) { var [foo] = [j] }", top},
3856 : {true, "for (const j of x) { var [[foo]=[42]] = [] }", top},
3857 : {true, "for (const j of x) { var foo; foo = j }", top},
3858 : {true, "for (const j of x) { var foo; [foo] = [j] }", top},
3859 : {true, "for (const j of x) { var foo; [[foo]=[42]] = [] }", top},
3860 : {true, "for (const j of x) { let foo; foo = j }", {0, 0, 0}},
3861 : {true, "for (const j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3862 : {true, "for (const j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3863 : {false, "for (const j of x) { let foo = j }", {0, 0, 0}},
3864 : {false, "for (const j of x) { let [foo] = [j] }", {0, 0, 0}},
3865 : {false, "for (const j of x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3868 :
3869 : {true, "for (const {j} of x) { foo = j }", top},
3870 : {true, "for (const {j} of x) { [foo] = [j] }", top},
3871 : {true, "for (const {j} of x) { [[foo]=[42]] = [] }", top},
3872 : {true, "for (const {j} of x) { var foo = j }", top},
3873 : {true, "for (const {j} of x) { var [foo] = [j] }", top},
3874 : {true, "for (const {j} of x) { var [[foo]=[42]] = [] }", top},
3875 : {true, "for (const {j} of x) { var foo; foo = j }", top},
3876 : {true, "for (const {j} of x) { var foo; [foo] = [j] }", top},
3877 : {true, "for (const {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3878 : {true, "for (const {j} of x) { let foo; foo = j }", {0, 0, 0}},
3879 : {true, "for (const {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3880 : {true, "for (const {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3881 : {false, "for (const {j} of x) { let foo = j }", {0, 0, 0}},
3882 : {false, "for (const {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3883 : {false, "for (const {j} of x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3886 :
3887 : {true, "for (j in x) { foo = j }", top},
3888 : {true, "for (j in x) { [foo] = [j] }", top},
3889 : {true, "for (j in x) { [[foo]=[42]] = [] }", top},
3890 : {true, "for (j in x) { var foo = j }", top},
3891 : {true, "for (j in x) { var [foo] = [j] }", top},
3892 : {true, "for (j in x) { var [[foo]=[42]] = [] }", top},
3893 : {true, "for (j in x) { var foo; foo = j }", top},
3894 : {true, "for (j in x) { var foo; [foo] = [j] }", top},
3895 : {true, "for (j in x) { var foo; [[foo]=[42]] = [] }", top},
3896 : {true, "for (j in x) { let foo; foo = j }", {0}},
3897 : {true, "for (j in x) { let foo; [foo] = [j] }", {0}},
3898 : {true, "for (j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3899 : {false, "for (j in x) { let foo = j }", {0}},
3900 : {false, "for (j in x) { let [foo] = [j] }", {0}},
3901 : {false, "for (j in x) { const foo = j }", {0}},
3902 : {false, "for (j in x) { const [foo] = [j] }", {0}},
3903 : {false, "for (j in x) { function foo() {return j} }", {0}},
3904 :
3905 : {true, "for ({j} in x) { foo = j }", top},
3906 : {true, "for ({j} in x) { [foo] = [j] }", top},
3907 : {true, "for ({j} in x) { [[foo]=[42]] = [] }", top},
3908 : {true, "for ({j} in x) { var foo = j }", top},
3909 : {true, "for ({j} in x) { var [foo] = [j] }", top},
3910 : {true, "for ({j} in x) { var [[foo]=[42]] = [] }", top},
3911 : {true, "for ({j} in x) { var foo; foo = j }", top},
3912 : {true, "for ({j} in x) { var foo; [foo] = [j] }", top},
3913 : {true, "for ({j} in x) { var foo; [[foo]=[42]] = [] }", top},
3914 : {true, "for ({j} in x) { let foo; foo = j }", {0}},
3915 : {true, "for ({j} in x) { let foo; [foo] = [j] }", {0}},
3916 : {true, "for ({j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3917 : {false, "for ({j} in x) { let foo = j }", {0}},
3918 : {false, "for ({j} in x) { let [foo] = [j] }", {0}},
3919 : {false, "for ({j} in x) { const foo = j }", {0}},
3920 : {false, "for ({j} in x) { const [foo] = [j] }", {0}},
3921 : {false, "for ({j} in x) { function foo() {return j} }", {0}},
3922 :
3923 : {true, "for (var j in x) { foo = j }", top},
3924 : {true, "for (var j in x) { [foo] = [j] }", top},
3925 : {true, "for (var j in x) { [[foo]=[42]] = [] }", top},
3926 : {true, "for (var j in x) { var foo = j }", top},
3927 : {true, "for (var j in x) { var [foo] = [j] }", top},
3928 : {true, "for (var j in x) { var [[foo]=[42]] = [] }", top},
3929 : {true, "for (var j in x) { var foo; foo = j }", top},
3930 : {true, "for (var j in x) { var foo; [foo] = [j] }", top},
3931 : {true, "for (var j in x) { var foo; [[foo]=[42]] = [] }", top},
3932 : {true, "for (var j in x) { let foo; foo = j }", {0}},
3933 : {true, "for (var j in x) { let foo; [foo] = [j] }", {0}},
3934 : {true, "for (var j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3935 : {false, "for (var j in x) { let foo = j }", {0}},
3936 : {false, "for (var j in x) { let [foo] = [j] }", {0}},
3937 : {false, "for (var j in x) { const foo = j }", {0}},
3938 : {false, "for (var j in x) { const [foo] = [j] }", {0}},
3939 : {false, "for (var j in x) { function foo() {return j} }", {0}},
3940 :
3941 : {true, "for (var {j} in x) { foo = j }", top},
3942 : {true, "for (var {j} in x) { [foo] = [j] }", top},
3943 : {true, "for (var {j} in x) { [[foo]=[42]] = [] }", top},
3944 : {true, "for (var {j} in x) { var foo = j }", top},
3945 : {true, "for (var {j} in x) { var [foo] = [j] }", top},
3946 : {true, "for (var {j} in x) { var [[foo]=[42]] = [] }", top},
3947 : {true, "for (var {j} in x) { var foo; foo = j }", top},
3948 : {true, "for (var {j} in x) { var foo; [foo] = [j] }", top},
3949 : {true, "for (var {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3950 : {true, "for (var {j} in x) { let foo; foo = j }", {0}},
3951 : {true, "for (var {j} in x) { let foo; [foo] = [j] }", {0}},
3952 : {true, "for (var {j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3953 : {false, "for (var {j} in x) { let foo = j }", {0}},
3954 : {false, "for (var {j} in x) { let [foo] = [j] }", {0}},
3955 : {false, "for (var {j} in x) { const foo = j }", {0}},
3956 : {false, "for (var {j} in x) { const [foo] = [j] }", {0}},
3957 : {false, "for (var {j} in x) { function foo() {return j} }", {0}},
3958 :
3959 : {true, "for (let j in x) { foo = j }", top},
3960 : {true, "for (let j in x) { [foo] = [j] }", top},
3961 : {true, "for (let j in x) { [[foo]=[42]] = [] }", top},
3962 : {true, "for (let j in x) { var foo = j }", top},
3963 : {true, "for (let j in x) { var [foo] = [j] }", top},
3964 : {true, "for (let j in x) { var [[foo]=[42]] = [] }", top},
3965 : {true, "for (let j in x) { var foo; foo = j }", top},
3966 : {true, "for (let j in x) { var foo; [foo] = [j] }", top},
3967 : {true, "for (let j in x) { var foo; [[foo]=[42]] = [] }", top},
3968 : {true, "for (let j in x) { let foo; foo = j }", {0, 0, 0}},
3969 : {true, "for (let j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
3970 : {true, "for (let j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3971 : {false, "for (let j in x) { let foo = j }", {0, 0, 0}},
3972 : {false, "for (let j in x) { let [foo] = [j] }", {0, 0, 0}},
3973 : {false, "for (let j in x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3976 :
3977 : {true, "for (let {j} in x) { foo = j }", top},
3978 : {true, "for (let {j} in x) { [foo] = [j] }", top},
3979 : {true, "for (let {j} in x) { [[foo]=[42]] = [] }", top},
3980 : {true, "for (let {j} in x) { var foo = j }", top},
3981 : {true, "for (let {j} in x) { var [foo] = [j] }", top},
3982 : {true, "for (let {j} in x) { var [[foo]=[42]] = [] }", top},
3983 : {true, "for (let {j} in x) { var foo; foo = j }", top},
3984 : {true, "for (let {j} in x) { var foo; [foo] = [j] }", top},
3985 : {true, "for (let {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3986 : {true, "for (let {j} in x) { let foo; foo = j }", {0, 0, 0}},
3987 : {true, "for (let {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
3988 : {true, "for (let {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3989 : {false, "for (let {j} in x) { let foo = j }", {0, 0, 0}},
3990 : {false, "for (let {j} in x) { let [foo] = [j] }", {0, 0, 0}},
3991 : {false, "for (let {j} in x) { const 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) { function foo() {return j} }", {0, 0, 0}},
3994 :
3995 : {true, "for (const j in x) { foo = j }", top},
3996 : {true, "for (const j in x) { [foo] = [j] }", top},
3997 : {true, "for (const j in x) { [[foo]=[42]] = [] }", top},
3998 : {true, "for (const j in x) { var foo = j }", top},
3999 : {true, "for (const j in x) { var [foo] = [j] }", top},
4000 : {true, "for (const j in x) { var [[foo]=[42]] = [] }", top},
4001 : {true, "for (const j in x) { var foo; foo = j }", top},
4002 : {true, "for (const j in x) { var foo; [foo] = [j] }", top},
4003 : {true, "for (const j in x) { var foo; [[foo]=[42]] = [] }", top},
4004 : {true, "for (const j in x) { let foo; foo = j }", {0, 0, 0}},
4005 : {true, "for (const j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4006 : {true, "for (const j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4007 : {false, "for (const j in x) { let foo = j }", {0, 0, 0}},
4008 : {false, "for (const j in x) { let [foo] = [j] }", {0, 0, 0}},
4009 : {false, "for (const j in x) { const 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) { function foo() {return j} }", {0, 0, 0}},
4012 :
4013 : {true, "for (const {j} in x) { foo = j }", top},
4014 : {true, "for (const {j} in x) { [foo] = [j] }", top},
4015 : {true, "for (const {j} in x) { [[foo]=[42]] = [] }", top},
4016 : {true, "for (const {j} in x) { var foo = j }", top},
4017 : {true, "for (const {j} in x) { var [foo] = [j] }", top},
4018 : {true, "for (const {j} in x) { var [[foo]=[42]] = [] }", top},
4019 : {true, "for (const {j} in x) { var foo; foo = j }", top},
4020 : {true, "for (const {j} in x) { var foo; [foo] = [j] }", top},
4021 : {true, "for (const {j} in x) { var foo; [[foo]=[42]] = [] }", top},
4022 : {true, "for (const {j} in x) { let foo; foo = j }", {0, 0, 0}},
4023 : {true, "for (const {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4024 : {true, "for (const {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4025 : {false, "for (const {j} in x) { let foo = j }", {0, 0, 0}},
4026 : {false, "for (const {j} in x) { let [foo] = [j] }", {0, 0, 0}},
4027 : {false, "for (const {j} in x) { const 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) { function foo() {return j} }", {0, 0, 0}},
4030 :
4031 : {true, "while (j) { foo = j }", top},
4032 : {true, "while (j) { [foo] = [j] }", top},
4033 : {true, "while (j) { [[foo]=[42]] = [] }", top},
4034 : {true, "while (j) { var foo = j }", top},
4035 : {true, "while (j) { var [foo] = [j] }", top},
4036 : {true, "while (j) { var [[foo]=[42]] = [] }", top},
4037 : {true, "while (j) { var foo; foo = j }", top},
4038 : {true, "while (j) { var foo; [foo] = [j] }", top},
4039 : {true, "while (j) { var foo; [[foo]=[42]] = [] }", top},
4040 : {true, "while (j) { let foo; foo = j }", {0}},
4041 : {true, "while (j) { let foo; [foo] = [j] }", {0}},
4042 : {true, "while (j) { let foo; [[foo]=[42]] = [] }", {0}},
4043 : {false, "while (j) { let foo = j }", {0}},
4044 : {false, "while (j) { let [foo] = [j] }", {0}},
4045 : {false, "while (j) { const foo = j }", {0}},
4046 : {false, "while (j) { const [foo] = [j] }", {0}},
4047 : {false, "while (j) { function foo() {return j} }", {0}},
4048 :
4049 : {true, "do { foo = j } while (j)", top},
4050 : {true, "do { [foo] = [j] } while (j)", top},
4051 : {true, "do { [[foo]=[42]] = [] } while (j)", top},
4052 : {true, "do { var foo = j } while (j)", top},
4053 : {true, "do { var [foo] = [j] } while (j)", top},
4054 : {true, "do { var [[foo]=[42]] = [] } while (j)", top},
4055 : {true, "do { var foo; foo = j } while (j)", top},
4056 : {true, "do { var foo; [foo] = [j] } while (j)", top},
4057 : {true, "do { var foo; [[foo]=[42]] = [] } while (j)", top},
4058 : {true, "do { let foo; foo = j } while (j)", {0}},
4059 : {true, "do { let foo; [foo] = [j] } while (j)", {0}},
4060 : {true, "do { let foo; [[foo]=[42]] = [] } while (j)", {0}},
4061 : {false, "do { let foo = j } while (j)", {0}},
4062 : {false, "do { let [foo] = [j] } while (j)", {0}},
4063 : {false, "do { const foo = j } while (j)", {0}},
4064 : {false, "do { const [foo] = [j] } while (j)", {0}},
4065 : {false, "do { function foo() {return j} } while (j)", {0}},
4066 3005 : };
4067 :
4068 : Input script_only_tests[] = {
4069 : {true, "for (j=x; j<10; ++j) { function foo() {return j} }", top},
4070 : {true, "for ({j}=x; j<10; ++j) { function foo() {return j} }", top},
4071 : {true, "for (var 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 (let 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 (j of x) { function foo() {return j} }", top},
4076 : {true, "for ({j} of x) { function foo() {return j} }", top},
4077 : {true, "for (var j of x) { function foo() {return j} }", top},
4078 : {true, "for (var {j} of x) { function foo() {return j} }", top},
4079 : {true, "for (let j of x) { function foo() {return j} }", top},
4080 : {true, "for (let {j} of x) { function foo() {return j} }", top},
4081 : {true, "for (const j of x) { function foo() {return j} }", top},
4082 : {true, "for (const {j} of x) { function foo() {return j} }", top},
4083 : {true, "for (j in x) { function foo() {return j} }", top},
4084 : {true, "for ({j} in x) { function foo() {return j} }", top},
4085 : {true, "for (var j in x) { function foo() {return j} }", top},
4086 : {true, "for (var {j} in x) { function foo() {return j} }", top},
4087 : {true, "for (let j in x) { function foo() {return j} }", top},
4088 : {true, "for (let {j} in x) { function foo() {return j} }", top},
4089 : {true, "for (const j in x) { function foo() {return j} }", top},
4090 : {true, "for (const {j} in x) { function foo() {return j} }", top},
4091 : {true, "while (j) { function foo() {return j} }", top},
4092 : {true, "do { function foo() {return j} } while (j)", top},
4093 130 : };
4094 :
4095 4085 : for (unsigned i = 0; i < arraysize(module_and_script_tests); ++i) {
4096 4080 : Input input = module_and_script_tests[i];
4097 10200 : for (unsigned module = 0; module <= 1; ++module) {
4098 20400 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4099 : ++allow_lazy_parsing) {
4100 8160 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4101 : }
4102 4080 : TestMaybeAssigned(wrap(input), "foo", module, false);
4103 : }
4104 : }
4105 :
4106 245 : for (unsigned i = 0; i < arraysize(script_only_tests); ++i) {
4107 240 : Input input = script_only_tests[i];
4108 600 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4109 : ++allow_lazy_parsing) {
4110 240 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4111 : }
4112 120 : TestMaybeAssigned(wrap(input), "foo", false, false);
4113 : }
4114 5 : }
4115 :
4116 26644 : TEST(MaybeAssignedTopLevel) {
4117 : i::Isolate* isolate = CcTest::i_isolate();
4118 : i::HandleScope scope(isolate);
4119 5 : LocalContext env;
4120 :
4121 : const char* prefixes[] = {
4122 : "let foo; ",
4123 : "let foo = 0; ",
4124 : "let [foo] = [1]; ",
4125 : "let {foo} = {foo: 2}; ",
4126 : "let {foo=3} = {}; ",
4127 : "var foo; ",
4128 : "var foo = 0; ",
4129 : "var [foo] = [1]; ",
4130 : "var {foo} = {foo: 2}; ",
4131 : "var {foo=3} = {}; ",
4132 : "{ var foo; }; ",
4133 : "{ var foo = 0; }; ",
4134 : "{ var [foo] = [1]; }; ",
4135 : "{ var {foo} = {foo: 2}; }; ",
4136 : "{ var {foo=3} = {}; }; ",
4137 : "function foo() {}; ",
4138 : "function* foo() {}; ",
4139 : "async function foo() {}; ",
4140 : "class foo {}; ",
4141 : "class foo extends null {}; ",
4142 5 : };
4143 :
4144 : const char* module_and_script_tests[] = {
4145 : "function bar() {foo = 42}; ext(bar); ext(foo)",
4146 : "ext(function() {foo++}); ext(foo)",
4147 : "bar = () => --foo; ext(bar); ext(foo)",
4148 : "function* bar() {eval(ext)}; ext(bar); ext(foo)",
4149 5 : };
4150 :
4151 : const char* script_only_tests[] = {
4152 : "",
4153 : "{ function foo() {}; }; ",
4154 : "{ function* foo() {}; }; ",
4155 : "{ async function foo() {}; }; ",
4156 5 : };
4157 :
4158 205 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4159 900 : for (unsigned j = 0; j < arraysize(module_and_script_tests); ++j) {
4160 400 : std::string source(prefixes[i]);
4161 400 : source += module_and_script_tests[j];
4162 : std::vector<unsigned> top;
4163 1200 : Input input({true, source, top});
4164 2000 : for (unsigned module = 0; module <= 1; ++module) {
4165 4000 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4166 : ++allow_lazy_parsing) {
4167 1600 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4168 : }
4169 : }
4170 : }
4171 : }
4172 :
4173 205 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4174 900 : for (unsigned j = 0; j < arraysize(script_only_tests); ++j) {
4175 400 : std::string source(prefixes[i]);
4176 400 : source += script_only_tests[j];
4177 : std::vector<unsigned> top;
4178 1200 : Input input({true, source, top});
4179 2000 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4180 : ++allow_lazy_parsing) {
4181 800 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4182 : }
4183 : }
4184 : }
4185 5 : }
4186 :
4187 : namespace {
4188 :
4189 5 : i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone,
4190 : i::Handle<i::JSObject> m, const char* name) {
4191 : i::AstValueFactory avf(zone, isolate->ast_string_constants(),
4192 5 : HashSeed(isolate));
4193 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(
4194 10 : i::JSReceiver::GetProperty(isolate, m, name).ToHandleChecked());
4195 : i::DeclarationScope* script_scope =
4196 5 : new (zone) i::DeclarationScope(zone, &avf);
4197 5 : i::Scope* s = i::Scope::DeserializeScopeChain(
4198 10 : isolate, zone, f->context()->scope_info(), script_scope, &avf,
4199 5 : i::Scope::DeserializationMode::kIncludingVariables);
4200 5 : return s;
4201 : }
4202 :
4203 : } // namespace
4204 :
4205 26644 : TEST(AsmModuleFlag) {
4206 5 : i::FLAG_validate_asm = false;
4207 : i::Isolate* isolate = CcTest::i_isolate();
4208 : i::HandleScope scope(isolate);
4209 5 : LocalContext env;
4210 :
4211 : const char* src =
4212 : "function m() {"
4213 : " 'use asm';"
4214 : " function f() { return 0 };"
4215 : " return { f:f };"
4216 : "}"
4217 : "m();";
4218 :
4219 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
4220 : v8::Local<v8::Value> v = CompileRun(src);
4221 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
4222 5 : i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o);
4223 :
4224 : // The asm.js module should be marked as such.
4225 5 : i::Scope* s = DeserializeFunctionScope(isolate, &zone, m, "f");
4226 10 : CHECK(s->IsAsmModule() && s->AsDeclarationScope()->is_asm_module());
4227 5 : }
4228 :
4229 :
4230 26644 : TEST(UseAsmUseCount) {
4231 : i::Isolate* isolate = CcTest::i_isolate();
4232 : i::HandleScope scope(isolate);
4233 5 : LocalContext env;
4234 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4235 5 : global_use_counts = use_counts;
4236 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4237 : CompileRun("\"use asm\";\n"
4238 : "var foo = 1;\n"
4239 : "function bar() { \"use asm\"; var baz = 1; }");
4240 5 : CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
4241 5 : }
4242 :
4243 :
4244 26644 : TEST(StrictModeUseCount) {
4245 : i::Isolate* isolate = CcTest::i_isolate();
4246 : i::HandleScope scope(isolate);
4247 5 : LocalContext env;
4248 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4249 5 : global_use_counts = use_counts;
4250 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4251 : CompileRun(
4252 : "\"use strict\";\n"
4253 : "function bar() { var baz = 1; }"); // strict mode inherits
4254 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4255 5 : CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
4256 5 : }
4257 :
4258 :
4259 26644 : TEST(SloppyModeUseCount) {
4260 : i::Isolate* isolate = CcTest::i_isolate();
4261 : i::HandleScope scope(isolate);
4262 5 : LocalContext env;
4263 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4264 5 : global_use_counts = use_counts;
4265 : // Force eager parsing (preparser doesn't update use counts).
4266 5 : i::FLAG_lazy = false;
4267 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4268 : CompileRun("function bar() { var baz = 1; }");
4269 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4270 5 : CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
4271 5 : }
4272 :
4273 :
4274 26644 : TEST(BothModesUseCount) {
4275 : i::Isolate* isolate = CcTest::i_isolate();
4276 : i::HandleScope scope(isolate);
4277 5 : LocalContext env;
4278 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4279 5 : global_use_counts = use_counts;
4280 : // Force eager parsing (preparser doesn't update use counts).
4281 5 : i::FLAG_lazy = false;
4282 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4283 : CompileRun("function bar() { 'use strict'; var baz = 1; }");
4284 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4285 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4286 5 : }
4287 :
4288 26644 : TEST(LineOrParagraphSeparatorAsLineTerminator) {
4289 : // Tests that both preparsing and parsing accept U+2028 LINE SEPARATOR and
4290 : // U+2029 PARAGRAPH SEPARATOR as LineTerminator symbols outside of string
4291 : // literals.
4292 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
4293 : const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // 1<U+2028>2
4294 : "\x31\xE2\x80\xA9\x32", // 1<U+2029>2
4295 5 : nullptr};
4296 :
4297 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4298 5 : }
4299 :
4300 26644 : TEST(LineOrParagraphSeparatorInStringLiteral) {
4301 : // Tests that both preparsing and parsing don't treat U+2028 LINE SEPARATOR
4302 : // and U+2029 PARAGRAPH SEPARATOR as line terminators within string literals.
4303 : // https://github.com/tc39/proposal-json-superset
4304 : const char* context_data[][2] = {
4305 5 : {"\"", "\""}, {"'", "'"}, {nullptr, nullptr}};
4306 : const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // 1<U+2028>2
4307 : "\x31\xE2\x80\xA9\x32", // 1<U+2029>2
4308 5 : nullptr};
4309 :
4310 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4311 5 : }
4312 :
4313 26644 : TEST(ErrorsArrowFormalParameters) {
4314 : const char* context_data[][2] = {
4315 : { "()", "=>{}" },
4316 : { "()", "=>{};" },
4317 : { "var x = ()", "=>{}" },
4318 : { "var x = ()", "=>{};" },
4319 :
4320 : { "a", "=>{}" },
4321 : { "a", "=>{};" },
4322 : { "var x = a", "=>{}" },
4323 : { "var x = a", "=>{};" },
4324 :
4325 : { "(a)", "=>{}" },
4326 : { "(a)", "=>{};" },
4327 : { "var x = (a)", "=>{}" },
4328 : { "var x = (a)", "=>{};" },
4329 :
4330 : { "(...a)", "=>{}" },
4331 : { "(...a)", "=>{};" },
4332 : { "var x = (...a)", "=>{}" },
4333 : { "var x = (...a)", "=>{};" },
4334 :
4335 : { "(a,b)", "=>{}" },
4336 : { "(a,b)", "=>{};" },
4337 : { "var x = (a,b)", "=>{}" },
4338 : { "var x = (a,b)", "=>{};" },
4339 :
4340 : { "(a,...b)", "=>{}" },
4341 : { "(a,...b)", "=>{};" },
4342 : { "var x = (a,...b)", "=>{}" },
4343 : { "var x = (a,...b)", "=>{};" },
4344 :
4345 : { nullptr, nullptr }
4346 5 : };
4347 : const char* assignment_expression_suffix_data[] = {
4348 : "?c:d=>{}",
4349 : "=c=>{}",
4350 : "()",
4351 : "(c)",
4352 : "[1]",
4353 : "[c]",
4354 : ".c",
4355 : "-c",
4356 : "+c",
4357 : "c++",
4358 : "`c`",
4359 : "`${c}`",
4360 : "`template-head${c}`",
4361 : "`${c}template-tail`",
4362 : "`template-head${c}template-tail`",
4363 : "`${c}template-tail`",
4364 : nullptr
4365 5 : };
4366 :
4367 5 : RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
4368 5 : }
4369 :
4370 :
4371 26644 : TEST(ErrorsArrowFunctions) {
4372 : // Tests that parser and preparser generate the same kind of errors
4373 : // on invalid arrow function syntax.
4374 :
4375 : // clang-format off
4376 : const char* context_data[][2] = {
4377 : {"", ";"},
4378 : {"v = ", ";"},
4379 : {"bar ? (", ") : baz;"},
4380 : {"bar ? baz : (", ");"},
4381 : {"bar[", "];"},
4382 : {"bar, ", ";"},
4383 : {"", ", bar;"},
4384 : {nullptr, nullptr}
4385 5 : };
4386 :
4387 : const char* statement_data[] = {
4388 : "=> 0",
4389 : "=>",
4390 : "() =>",
4391 : "=> {}",
4392 : ") => {}",
4393 : ", => {}",
4394 : "(,) => {}",
4395 : "return => {}",
4396 : "() => {'value': 42}",
4397 :
4398 : // Check that the early return introduced in ParsePrimaryExpression
4399 : // does not accept stray closing parentheses.
4400 : ")",
4401 : ") => 0",
4402 : "foo[()]",
4403 : "()",
4404 :
4405 : // Parameter lists with extra parens should be recognized as errors.
4406 : "(()) => 0",
4407 : "((x)) => 0",
4408 : "((x, y)) => 0",
4409 : "(x, (y)) => 0",
4410 : "((x, y, z)) => 0",
4411 : "(x, (y, z)) => 0",
4412 : "((x, y), z) => 0",
4413 :
4414 : // Arrow function formal parameters are parsed as StrictFormalParameters,
4415 : // which confusingly only implies that there are no duplicates. Words
4416 : // reserved in strict mode, and eval or arguments, are indeed valid in
4417 : // sloppy mode.
4418 : "eval => { 'use strict'; 0 }",
4419 : "arguments => { 'use strict'; 0 }",
4420 : "yield => { 'use strict'; 0 }",
4421 : "interface => { 'use strict'; 0 }",
4422 : "(eval) => { 'use strict'; 0 }",
4423 : "(arguments) => { 'use strict'; 0 }",
4424 : "(yield) => { 'use strict'; 0 }",
4425 : "(interface) => { 'use strict'; 0 }",
4426 : "(eval, bar) => { 'use strict'; 0 }",
4427 : "(bar, eval) => { 'use strict'; 0 }",
4428 : "(bar, arguments) => { 'use strict'; 0 }",
4429 : "(bar, yield) => { 'use strict'; 0 }",
4430 : "(bar, interface) => { 'use strict'; 0 }",
4431 : // TODO(aperez): Detecting duplicates does not work in PreParser.
4432 : // "(bar, bar) => {}",
4433 :
4434 : // The parameter list is parsed as an expression, but only
4435 : // a comma-separated list of identifier is valid.
4436 : "32 => {}",
4437 : "(32) => {}",
4438 : "(a, 32) => {}",
4439 : "if => {}",
4440 : "(if) => {}",
4441 : "(a, if) => {}",
4442 : "a + b => {}",
4443 : "(a + b) => {}",
4444 : "(a + b, c) => {}",
4445 : "(a, b - c) => {}",
4446 : "\"a\" => {}",
4447 : "(\"a\") => {}",
4448 : "(\"a\", b) => {}",
4449 : "(a, \"b\") => {}",
4450 : "-a => {}",
4451 : "(-a) => {}",
4452 : "(-a, b) => {}",
4453 : "(a, -b) => {}",
4454 : "{} => {}",
4455 : "a++ => {}",
4456 : "(a++) => {}",
4457 : "(a++, b) => {}",
4458 : "(a, b++) => {}",
4459 : "[] => {}",
4460 : "(foo ? bar : baz) => {}",
4461 : "(a, foo ? bar : baz) => {}",
4462 : "(foo ? bar : baz, a) => {}",
4463 : "(a.b, c) => {}",
4464 : "(c, a.b) => {}",
4465 : "(a['b'], c) => {}",
4466 : "(c, a['b']) => {}",
4467 : "(...a = b) => b",
4468 :
4469 : // crbug.com/582626
4470 : "(...rest - a) => b",
4471 : "(a, ...b - 10) => b",
4472 :
4473 : nullptr
4474 5 : };
4475 : // clang-format on
4476 :
4477 : // The test is quite slow, so run it with a reduced set of flags.
4478 : static const ParserFlag flags[] = {kAllowLazy};
4479 : RunParserSyncTest(context_data, statement_data, kError, flags,
4480 5 : arraysize(flags));
4481 :
4482 : // In a context where a concise arrow body is parsed with [~In] variant,
4483 : // ensure that an error is reported in both full parser and preparser.
4484 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4485 5 : {nullptr, nullptr}};
4486 5 : const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
4487 : RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
4488 5 : arraysize(flags));
4489 5 : }
4490 :
4491 :
4492 26644 : TEST(NoErrorsArrowFunctions) {
4493 : // Tests that parser and preparser accept valid arrow functions syntax.
4494 : // clang-format off
4495 : const char* context_data[][2] = {
4496 : {"", ";"},
4497 : {"bar ? (", ") : baz;"},
4498 : {"bar ? baz : (", ");"},
4499 : {"bar, ", ";"},
4500 : {"", ", bar;"},
4501 : {nullptr, nullptr}
4502 5 : };
4503 :
4504 : const char* statement_data[] = {
4505 : "() => {}",
4506 : "() => { return 42 }",
4507 : "x => { return x; }",
4508 : "(x) => { return x; }",
4509 : "(x, y) => { return x + y; }",
4510 : "(x, y, z) => { return x + y + z; }",
4511 : "(x, y) => { x.a = y; }",
4512 : "() => 42",
4513 : "x => x",
4514 : "x => x * x",
4515 : "(x) => x",
4516 : "(x) => x * x",
4517 : "(x, y) => x + y",
4518 : "(x, y, z) => x, y, z",
4519 : "(x, y) => x.a = y",
4520 : "() => ({'value': 42})",
4521 : "x => y => x + y",
4522 : "(x, y) => (u, v) => x*u + y*v",
4523 : "(x, y) => z => z * (x + y)",
4524 : "x => (y, z) => z * (x + y)",
4525 :
4526 : // Those are comma-separated expressions, with arrow functions as items.
4527 : // They stress the code for validating arrow function parameter lists.
4528 : "a, b => 0",
4529 : "a, b, (c, d) => 0",
4530 : "(a, b, (c, d) => 0)",
4531 : "(a, b) => 0, (c, d) => 1",
4532 : "(a, b => {}, a => a + 1)",
4533 : "((a, b) => {}, (a => a + 1))",
4534 : "(a, (a, (b, c) => 0))",
4535 :
4536 : // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
4537 : "foo ? bar : baz => {}",
4538 :
4539 : // Arrows with non-simple parameters.
4540 : "({}) => {}",
4541 : "(a, {}) => {}",
4542 : "({}, a) => {}",
4543 : "([]) => {}",
4544 : "(a, []) => {}",
4545 : "([], a) => {}",
4546 : "(a = b) => {}",
4547 : "(a = b, c) => {}",
4548 : "(a, b = c) => {}",
4549 : "({a}) => {}",
4550 : "(x = 9) => {}",
4551 : "(x, y = 9) => {}",
4552 : "(x = 9, y) => {}",
4553 : "(x, y = 9, z) => {}",
4554 : "(x, y = 9, z = 8) => {}",
4555 : "(...a) => {}",
4556 : "(x, ...a) => {}",
4557 : "(x = 9, ...a) => {}",
4558 : "(x, y = 9, ...a) => {}",
4559 : "(x, y = 9, {b}, z = 8, ...a) => {}",
4560 : "({a} = {}) => {}",
4561 : "([x] = []) => {}",
4562 : "({a = 42}) => {}",
4563 : "([x = 0]) => {}",
4564 : nullptr
4565 5 : };
4566 : // clang-format on
4567 :
4568 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4569 :
4570 : static const ParserFlag flags[] = {kAllowLazy};
4571 : // In a context where a concise arrow body is parsed with [~In] variant,
4572 : // ensure that nested expressions can still use the 'in' operator,
4573 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4574 5 : {nullptr, nullptr}};
4575 5 : const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
4576 : RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
4577 5 : arraysize(flags));
4578 5 : }
4579 :
4580 :
4581 26644 : TEST(ArrowFunctionsSloppyParameterNames) {
4582 : const char* strict_context_data[][2] = {{"'use strict'; ", ";"},
4583 : {"'use strict'; bar ? (", ") : baz;"},
4584 : {"'use strict'; bar ? baz : (", ");"},
4585 : {"'use strict'; bar, ", ";"},
4586 : {"'use strict'; ", ", bar;"},
4587 5 : {nullptr, nullptr}};
4588 :
4589 : const char* sloppy_context_data[][2] = {
4590 : {"", ";"}, {"bar ? (", ") : baz;"}, {"bar ? baz : (", ");"},
4591 5 : {"bar, ", ";"}, {"", ", bar;"}, {nullptr, nullptr}};
4592 :
4593 : const char* statement_data[] = {"eval => {}",
4594 : "arguments => {}",
4595 : "yield => {}",
4596 : "interface => {}",
4597 : "(eval) => {}",
4598 : "(arguments) => {}",
4599 : "(yield) => {}",
4600 : "(interface) => {}",
4601 : "(eval, bar) => {}",
4602 : "(bar, eval) => {}",
4603 : "(bar, arguments) => {}",
4604 : "(bar, yield) => {}",
4605 : "(bar, interface) => {}",
4606 : "(interface, eval) => {}",
4607 : "(interface, arguments) => {}",
4608 : "(eval, interface) => {}",
4609 : "(arguments, interface) => {}",
4610 5 : nullptr};
4611 :
4612 5 : RunParserSyncTest(strict_context_data, statement_data, kError);
4613 5 : RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
4614 5 : }
4615 :
4616 :
4617 26644 : TEST(ArrowFunctionsYieldParameterNameInGenerator) {
4618 : const char* sloppy_function_context_data[][2] = {
4619 5 : {"(function f() { (", "); });"}, {nullptr, nullptr}};
4620 :
4621 : const char* strict_function_context_data[][2] = {
4622 5 : {"(function f() {'use strict'; (", "); });"}, {nullptr, nullptr}};
4623 :
4624 : const char* generator_context_data[][2] = {
4625 : {"(function *g() {'use strict'; (", "); });"},
4626 : {"(function *g() { (", "); });"},
4627 5 : {nullptr, nullptr}};
4628 :
4629 : const char* arrow_data[] = {
4630 : "yield => {}", "(yield) => {}", "(a, yield) => {}",
4631 : "(yield, a) => {}", "(yield, ...a) => {}", "(a, ...yield) => {}",
4632 5 : "({yield}) => {}", "([yield]) => {}", nullptr};
4633 :
4634 5 : RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
4635 5 : RunParserSyncTest(strict_function_context_data, arrow_data, kError);
4636 5 : RunParserSyncTest(generator_context_data, arrow_data, kError);
4637 5 : }
4638 :
4639 :
4640 26644 : TEST(SuperNoErrors) {
4641 : // Tests that parser and preparser accept 'super' keyword in right places.
4642 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4643 : {"class C { m() { k = ", "; } }"},
4644 : {"class C { m() { foo(", "); } }"},
4645 : {"class C { m() { () => ", "; } }"},
4646 5 : {nullptr, nullptr}};
4647 :
4648 : const char* statement_data[] = {"super.x", "super[27]",
4649 : "new super.x", "new super.x()",
4650 : "new super[27]", "new super[27]()",
4651 : "z.super", // Ok, property lookup.
4652 5 : nullptr};
4653 :
4654 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4655 5 : }
4656 :
4657 :
4658 26644 : TEST(SuperErrors) {
4659 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4660 : {"class C { m() { k = ", "; } }"},
4661 : {"class C { m() { foo(", "); } }"},
4662 : {"class C { m() { () => ", "; } }"},
4663 5 : {nullptr, nullptr}};
4664 :
4665 : const char* expression_data[] = {"super",
4666 : "super = x",
4667 : "y = super",
4668 : "f(super)",
4669 : "new super",
4670 : "new super()",
4671 : "new super(12, 45)",
4672 : "new new super",
4673 : "new new super()",
4674 : "new new super()()",
4675 5 : nullptr};
4676 :
4677 5 : RunParserSyncTest(context_data, expression_data, kError);
4678 5 : }
4679 :
4680 26644 : TEST(ImportExpressionSuccess) {
4681 : // clang-format off
4682 : const char* context_data[][2] = {
4683 : {"", ""},
4684 : {nullptr, nullptr}
4685 5 : };
4686 :
4687 : const char* data[] = {
4688 : "import(1)",
4689 : "import(y=x)",
4690 : "f(...[import(y=x)])",
4691 : "x = {[import(y=x)]: 1}",
4692 : "var {[import(y=x)]: x} = {}",
4693 : "({[import(y=x)]: x} = {})",
4694 : "async () => { await import(x) }",
4695 : "() => { import(x) }",
4696 : "(import(y=x))",
4697 : "{import(y=x)}",
4698 : "import(import(x))",
4699 : "x = import(x)",
4700 : "var x = import(x)",
4701 : "let x = import(x)",
4702 : "for(x of import(x)) {}",
4703 : "import(x).then()",
4704 : nullptr
4705 5 : };
4706 :
4707 : // clang-format on
4708 :
4709 : // We ignore test error messages because the error message from the
4710 : // parser/preparser is different for the same data depending on the
4711 : // context.
4712 : // For example, a top level "import(" is parsed as an
4713 : // import declaration. The parser parses the import token correctly
4714 : // and then shows an "Unexpected token (" error message. The
4715 : // preparser does not understand the import keyword (this test is
4716 : // run without kAllowHarmonyDynamicImport flag), so this results in
4717 : // an "Unexpected token import" error.
4718 5 : RunParserSyncTest(context_data, data, kError);
4719 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4720 : nullptr, 0, true, true);
4721 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4722 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4723 5 : arraysize(flags));
4724 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4725 : arraysize(flags));
4726 5 : }
4727 :
4728 26644 : TEST(ImportExpressionErrors) {
4729 : {
4730 : // clang-format off
4731 : const char* context_data[][2] = {
4732 : {"", ""},
4733 : {"var ", ""},
4734 : {"let ", ""},
4735 : {"new ", ""},
4736 : {nullptr, nullptr}
4737 5 : };
4738 :
4739 : const char* data[] = {
4740 : "import(",
4741 : "import)",
4742 : "import()",
4743 : "import('x",
4744 : "import('x']",
4745 : "import['x')",
4746 : "import = x",
4747 : "import[",
4748 : "import[]",
4749 : "import]",
4750 : "import[x]",
4751 : "import{",
4752 : "import{x",
4753 : "import{x}",
4754 : "import(x, y)",
4755 : "import(...y)",
4756 : "import(x,)",
4757 : "import(,)",
4758 : "import(,y)",
4759 : "import(;)",
4760 : "[import]",
4761 : "{import}",
4762 : "import+",
4763 : "import = 1",
4764 : "import.wat",
4765 : "new import(x)",
4766 : nullptr
4767 5 : };
4768 :
4769 : // clang-format on
4770 5 : RunParserSyncTest(context_data, data, kError);
4771 : // We ignore the error messages for the reason explained in the
4772 : // ImportExpressionSuccess test.
4773 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4774 : nullptr, 0, true, true);
4775 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4776 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4777 5 : arraysize(flags));
4778 :
4779 : // We ignore test error messages because the error message from
4780 : // the parser/preparser is different for the same data depending
4781 : // on the context. For example, a top level "import{" is parsed
4782 : // as an import declaration. The parser parses the import token
4783 : // correctly and then shows an "Unexpected end of input" error
4784 : // message because of the '{'. The preparser shows an "Unexpected
4785 : // token {" because it's not a valid token in a CallExpression.
4786 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4787 : arraysize(flags), nullptr, 0, true, true);
4788 : }
4789 :
4790 : {
4791 : // clang-format off
4792 : const char* context_data[][2] = {
4793 : {"var ", ""},
4794 : {"let ", ""},
4795 : {nullptr, nullptr}
4796 5 : };
4797 :
4798 : const char* data[] = {
4799 : "import('x')",
4800 : nullptr
4801 5 : };
4802 :
4803 : // clang-format on
4804 5 : RunParserSyncTest(context_data, data, kError);
4805 : RunModuleParserSyncTest(context_data, data, kError);
4806 :
4807 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4808 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4809 5 : arraysize(flags));
4810 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4811 : arraysize(flags));
4812 : }
4813 :
4814 : // Import statements as arrow function params and destructuring targets.
4815 : {
4816 : // clang-format off
4817 : const char* context_data[][2] = {
4818 : {"(", ") => {}"},
4819 : {"(a, ", ") => {}"},
4820 : {"(1, ", ") => {}"},
4821 : {"let f = ", " => {}"},
4822 : {"[", "] = [1];"},
4823 : {"{", "} = {'a': 1};"},
4824 : {nullptr, nullptr}
4825 5 : };
4826 :
4827 : const char* data[] = {
4828 : "import(foo)",
4829 : "import(1)",
4830 : "import(y=x)",
4831 : "import(import(x))",
4832 : "import(x).then()",
4833 : nullptr
4834 5 : };
4835 :
4836 : // clang-format on
4837 5 : RunParserSyncTest(context_data, data, kError);
4838 : RunModuleParserSyncTest(context_data, data, kError);
4839 :
4840 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4841 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4842 5 : arraysize(flags));
4843 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4844 : arraysize(flags));
4845 : }
4846 5 : }
4847 :
4848 26644 : TEST(SuperCall) {
4849 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
4850 :
4851 : const char* success_data[] = {
4852 : "class C extends B { constructor() { super(); } }",
4853 5 : "class C extends B { constructor() { () => super(); } }", nullptr};
4854 :
4855 5 : RunParserSyncTest(context_data, success_data, kSuccess);
4856 :
4857 : const char* error_data[] = {"class C { constructor() { super(); } }",
4858 : "class C { method() { super(); } }",
4859 : "class C { method() { () => super(); } }",
4860 : "class C { *method() { super(); } }",
4861 : "class C { get x() { super(); } }",
4862 : "class C { set x(_) { super(); } }",
4863 : "({ method() { super(); } })",
4864 : "({ *method() { super(); } })",
4865 : "({ get x() { super(); } })",
4866 : "({ set x(_) { super(); } })",
4867 : "({ f: function() { super(); } })",
4868 : "(function() { super(); })",
4869 : "var f = function() { super(); }",
4870 : "({ f: function*() { super(); } })",
4871 : "(function*() { super(); })",
4872 : "var f = function*() { super(); }",
4873 5 : nullptr};
4874 :
4875 5 : RunParserSyncTest(context_data, error_data, kError);
4876 5 : }
4877 :
4878 :
4879 26644 : TEST(SuperNewNoErrors) {
4880 : const char* context_data[][2] = {{"class C { constructor() { ", " } }"},
4881 : {"class C { *method() { ", " } }"},
4882 : {"class C { get x() { ", " } }"},
4883 : {"class C { set x(_) { ", " } }"},
4884 : {"({ method() { ", " } })"},
4885 : {"({ *method() { ", " } })"},
4886 : {"({ get x() { ", " } })"},
4887 : {"({ set x(_) { ", " } })"},
4888 5 : {nullptr, nullptr}};
4889 :
4890 : const char* expression_data[] = {"new super.x;", "new super.x();",
4891 : "() => new super.x;", "() => new super.x();",
4892 5 : nullptr};
4893 :
4894 5 : RunParserSyncTest(context_data, expression_data, kSuccess);
4895 5 : }
4896 :
4897 :
4898 26644 : TEST(SuperNewErrors) {
4899 : const char* context_data[][2] = {{"class C { method() { ", " } }"},
4900 : {"class C { *method() { ", " } }"},
4901 : {"class C { get x() { ", " } }"},
4902 : {"class C { set x(_) { ", " } }"},
4903 : {"({ method() { ", " } })"},
4904 : {"({ *method() { ", " } })"},
4905 : {"({ get x() { ", " } })"},
4906 : {"({ set x(_) { ", " } })"},
4907 : {"({ f: function() { ", " } })"},
4908 : {"(function() { ", " })"},
4909 : {"var f = function() { ", " }"},
4910 : {"({ f: function*() { ", " } })"},
4911 : {"(function*() { ", " })"},
4912 : {"var f = function*() { ", " }"},
4913 5 : {nullptr, nullptr}};
4914 :
4915 : const char* statement_data[] = {"new super;", "new super();",
4916 : "() => new super;", "() => new super();",
4917 5 : nullptr};
4918 :
4919 5 : RunParserSyncTest(context_data, statement_data, kError);
4920 5 : }
4921 :
4922 :
4923 26644 : TEST(SuperErrorsNonMethods) {
4924 : // super is only allowed in methods, accessors and constructors.
4925 : const char* context_data[][2] = {{"", ";"},
4926 : {"k = ", ";"},
4927 : {"foo(", ");"},
4928 : {"if (", ") {}"},
4929 : {"if (true) {", "}"},
4930 : {"if (false) {} else {", "}"},
4931 : {"while (true) {", "}"},
4932 : {"function f() {", "}"},
4933 : {"class C extends (", ") {}"},
4934 : {"class C { m() { function f() {", "} } }"},
4935 : {"({ m() { function f() {", "} } })"},
4936 5 : {nullptr, nullptr}};
4937 :
4938 : const char* statement_data[] = {
4939 : "super", "super = x", "y = super", "f(super)",
4940 : "super.x", "super[27]", "super.x()", "super[27]()",
4941 : "super()", "new super.x", "new super.x()", "new super[27]",
4942 5 : "new super[27]()", nullptr};
4943 :
4944 5 : RunParserSyncTest(context_data, statement_data, kError);
4945 5 : }
4946 :
4947 :
4948 26644 : TEST(NoErrorsMethodDefinition) {
4949 : const char* context_data[][2] = {{"({", "});"},
4950 : {"'use strict'; ({", "});"},
4951 : {"({*", "});"},
4952 : {"'use strict'; ({*", "});"},
4953 5 : {nullptr, nullptr}};
4954 :
4955 : const char* object_literal_body_data[] = {
4956 : "m() {}", "m(x) { return x; }", "m(x, y) {}, n() {}",
4957 5 : "set(x, y) {}", "get(x, y) {}", nullptr};
4958 :
4959 5 : RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
4960 5 : }
4961 :
4962 :
4963 26644 : TEST(MethodDefinitionNames) {
4964 : const char* context_data[][2] = {{"({", "(x, y) {}});"},
4965 : {"'use strict'; ({", "(x, y) {}});"},
4966 : {"({*", "(x, y) {}});"},
4967 : {"'use strict'; ({*", "(x, y) {}});"},
4968 5 : {nullptr, nullptr}};
4969 :
4970 : const char* name_data[] = {
4971 : "m", "'m'", "\"m\"", "\"m n\"", "true", "false", "null", "0", "1.2",
4972 : "1e1", "1E1", "1e+1", "1e-1",
4973 :
4974 : // Keywords
4975 : "async", "await", "break", "case", "catch", "class", "const", "continue",
4976 : "debugger", "default", "delete", "do", "else", "enum", "export",
4977 : "extends", "finally", "for", "function", "if", "implements", "import",
4978 : "in", "instanceof", "interface", "let", "new", "package", "private",
4979 : "protected", "public", "return", "static", "super", "switch", "this",
4980 : "throw", "try", "typeof", "var", "void", "while", "with", "yield",
4981 5 : nullptr};
4982 :
4983 5 : RunParserSyncTest(context_data, name_data, kSuccess);
4984 5 : }
4985 :
4986 :
4987 26644 : TEST(MethodDefinitionStrictFormalParamereters) {
4988 : const char* context_data[][2] = {{"({method(", "){}});"},
4989 : {"'use strict'; ({method(", "){}});"},
4990 : {"({*method(", "){}});"},
4991 : {"'use strict'; ({*method(", "){}});"},
4992 5 : {nullptr, nullptr}};
4993 :
4994 5 : const char* params_data[] = {"x, x", "x, y, x", "var", "const", nullptr};
4995 :
4996 5 : RunParserSyncTest(context_data, params_data, kError);
4997 5 : }
4998 :
4999 :
5000 26644 : TEST(MethodDefinitionEvalArguments) {
5001 : const char* strict_context_data[][2] = {
5002 : {"'use strict'; ({method(", "){}});"},
5003 : {"'use strict'; ({*method(", "){}});"},
5004 5 : {nullptr, nullptr}};
5005 : const char* sloppy_context_data[][2] = {
5006 5 : {"({method(", "){}});"}, {"({*method(", "){}});"}, {nullptr, nullptr}};
5007 :
5008 5 : const char* data[] = {"eval", "arguments", nullptr};
5009 :
5010 : // Fail in strict mode
5011 5 : RunParserSyncTest(strict_context_data, data, kError);
5012 :
5013 : // OK in sloppy mode
5014 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
5015 5 : }
5016 :
5017 :
5018 26644 : TEST(MethodDefinitionDuplicateEvalArguments) {
5019 : const char* context_data[][2] = {{"'use strict'; ({method(", "){}});"},
5020 : {"'use strict'; ({*method(", "){}});"},
5021 : {"({method(", "){}});"},
5022 : {"({*method(", "){}});"},
5023 5 : {nullptr, nullptr}};
5024 :
5025 : const char* data[] = {"eval, eval", "eval, a, eval", "arguments, arguments",
5026 5 : "arguments, a, arguments", nullptr};
5027 :
5028 : // In strict mode, the error is using "eval" or "arguments" as parameter names
5029 : // In sloppy mode, the error is that eval / arguments are duplicated
5030 5 : RunParserSyncTest(context_data, data, kError);
5031 5 : }
5032 :
5033 :
5034 26644 : TEST(MethodDefinitionDuplicateProperty) {
5035 : const char* context_data[][2] = {{"'use strict'; ({", "});"},
5036 5 : {nullptr, nullptr}};
5037 :
5038 : const char* params_data[] = {"x: 1, x() {}",
5039 : "x() {}, x: 1",
5040 : "x() {}, get x() {}",
5041 : "x() {}, set x(_) {}",
5042 : "x() {}, x() {}",
5043 : "x() {}, y() {}, x() {}",
5044 : "x() {}, \"x\"() {}",
5045 : "x() {}, 'x'() {}",
5046 : "0() {}, '0'() {}",
5047 : "1.0() {}, 1: 1",
5048 :
5049 : "x: 1, *x() {}",
5050 : "*x() {}, x: 1",
5051 : "*x() {}, get x() {}",
5052 : "*x() {}, set x(_) {}",
5053 : "*x() {}, *x() {}",
5054 : "*x() {}, y() {}, *x() {}",
5055 : "*x() {}, *\"x\"() {}",
5056 : "*x() {}, *'x'() {}",
5057 : "*0() {}, *'0'() {}",
5058 : "*1.0() {}, 1: 1",
5059 :
5060 5 : nullptr};
5061 :
5062 5 : RunParserSyncTest(context_data, params_data, kSuccess);
5063 5 : }
5064 :
5065 :
5066 26644 : TEST(ClassExpressionNoErrors) {
5067 : const char* context_data[][2] = {
5068 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
5069 : const char* class_data[] = {"class {}",
5070 : "class name {}",
5071 : "class extends F {}",
5072 : "class name extends F {}",
5073 : "class extends (F, G) {}",
5074 : "class name extends (F, G) {}",
5075 : "class extends class {} {}",
5076 : "class name extends class {} {}",
5077 : "class extends class base {} {}",
5078 : "class name extends class base {} {}",
5079 5 : nullptr};
5080 :
5081 5 : RunParserSyncTest(context_data, class_data, kSuccess);
5082 5 : }
5083 :
5084 :
5085 26644 : TEST(ClassDeclarationNoErrors) {
5086 : const char* context_data[][2] = {{"'use strict'; ", ""},
5087 : {"'use strict'; {", "}"},
5088 : {"'use strict'; if (true) {", "}"},
5089 5 : {nullptr, nullptr}};
5090 : const char* statement_data[] = {"class name {}",
5091 : "class name extends F {}",
5092 : "class name extends (F, G) {}",
5093 : "class name extends class {} {}",
5094 : "class name extends class base {} {}",
5095 5 : nullptr};
5096 :
5097 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
5098 5 : }
5099 :
5100 :
5101 26644 : TEST(ClassBodyNoErrors) {
5102 : // clang-format off
5103 : // Tests that parser and preparser accept valid class syntax.
5104 : const char* context_data[][2] = {{"(class {", "});"},
5105 : {"(class extends Base {", "});"},
5106 : {"class C {", "}"},
5107 : {"class C extends Base {", "}"},
5108 5 : {nullptr, nullptr}};
5109 : const char* class_body_data[] = {
5110 : ";",
5111 : ";;",
5112 : "m() {}",
5113 : "m() {};",
5114 : "; m() {}",
5115 : "m() {}; n(x) {}",
5116 : "get x() {}",
5117 : "set x(v) {}",
5118 : "get() {}",
5119 : "set() {}",
5120 : "*g() {}",
5121 : "*g() {};",
5122 : "; *g() {}",
5123 : "*g() {}; *h(x) {}",
5124 : "async *x(){}",
5125 : "static() {}",
5126 : "get static() {}",
5127 : "set static(v) {}",
5128 : "static m() {}",
5129 : "static get x() {}",
5130 : "static set x(v) {}",
5131 : "static get() {}",
5132 : "static set() {}",
5133 : "static static() {}",
5134 : "static get static() {}",
5135 : "static set static(v) {}",
5136 : "*static() {}",
5137 : "static *static() {}",
5138 : "*get() {}",
5139 : "*set() {}",
5140 : "static *g() {}",
5141 : "async(){}",
5142 : "*async(){}",
5143 : "static async(){}",
5144 : "static *async(){}",
5145 : "static async *x(){}",
5146 :
5147 : // Escaped 'static' should be allowed anywhere
5148 : // static-as-PropertyName is.
5149 : "st\\u0061tic() {}",
5150 : "get st\\u0061tic() {}",
5151 : "set st\\u0061tic(v) {}",
5152 : "static st\\u0061tic() {}",
5153 : "static get st\\u0061tic() {}",
5154 : "static set st\\u0061tic(v) {}",
5155 : "*st\\u0061tic() {}",
5156 : "static *st\\u0061tic() {}",
5157 :
5158 : "static async x(){}",
5159 : "static async(){}",
5160 : "static *async(){}",
5161 : "async x(){}",
5162 : "async 0(){}",
5163 : "async get(){}",
5164 : "async set(){}",
5165 : "async static(){}",
5166 : "async async(){}",
5167 : "async(){}",
5168 : "*async(){}",
5169 5 : nullptr};
5170 : // clang-format on
5171 :
5172 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
5173 5 : }
5174 :
5175 :
5176 26644 : TEST(ClassPropertyNameNoErrors) {
5177 : const char* context_data[][2] = {{"(class {", "() {}});"},
5178 : {"(class { get ", "() {}});"},
5179 : {"(class { set ", "(v) {}});"},
5180 : {"(class { static ", "() {}});"},
5181 : {"(class { static get ", "() {}});"},
5182 : {"(class { static set ", "(v) {}});"},
5183 : {"(class { *", "() {}});"},
5184 : {"(class { static *", "() {}});"},
5185 : {"class C {", "() {}}"},
5186 : {"class C { get ", "() {}}"},
5187 : {"class C { set ", "(v) {}}"},
5188 : {"class C { static ", "() {}}"},
5189 : {"class C { static get ", "() {}}"},
5190 : {"class C { static set ", "(v) {}}"},
5191 : {"class C { *", "() {}}"},
5192 : {"class C { static *", "() {}}"},
5193 5 : {nullptr, nullptr}};
5194 : const char* name_data[] = {
5195 : "42", "42.5", "42e2", "42e+2", "42e-2", "null",
5196 : "false", "true", "'str'", "\"str\"", "static", "get",
5197 : "set", "var", "const", "let", "this", "class",
5198 : "function", "yield", "if", "else", "for", "while",
5199 5 : "do", "try", "catch", "finally", nullptr};
5200 :
5201 5 : RunParserSyncTest(context_data, name_data, kSuccess);
5202 5 : }
5203 :
5204 26644 : TEST(StaticClassFieldsNoErrors) {
5205 : // clang-format off
5206 : // Tests proposed class fields syntax.
5207 : const char* context_data[][2] = {{"(class {", "});"},
5208 : {"(class extends Base {", "});"},
5209 : {"class C {", "}"},
5210 : {"class C extends Base {", "}"},
5211 5 : {nullptr, nullptr}};
5212 : const char* class_body_data[] = {
5213 : // Basic syntax
5214 : "static a = 0;",
5215 : "static a = 0; b",
5216 : "static a = 0; b(){}",
5217 : "static a = 0; *b(){}",
5218 : "static a = 0; ['b'](){}",
5219 : "static a;",
5220 : "static a; b;",
5221 : "static a; b(){}",
5222 : "static a; *b(){}",
5223 : "static a; ['b'](){}",
5224 : "static ['a'] = 0;",
5225 : "static ['a'] = 0; b",
5226 : "static ['a'] = 0; b(){}",
5227 : "static ['a'] = 0; *b(){}",
5228 : "static ['a'] = 0; ['b'](){}",
5229 : "static ['a'];",
5230 : "static ['a']; b;",
5231 : "static ['a']; b(){}",
5232 : "static ['a']; *b(){}",
5233 : "static ['a']; ['b'](){}",
5234 :
5235 : "static 0 = 0;",
5236 : "static 0;",
5237 : "static 'a' = 0;",
5238 : "static 'a';",
5239 :
5240 : "static c = [c] = c",
5241 :
5242 : // ASI
5243 : "static a = 0\n",
5244 : "static a = 0\n b",
5245 : "static a = 0\n b(){}",
5246 : "static a\n",
5247 : "static a\n b\n",
5248 : "static a\n b(){}",
5249 : "static a\n *b(){}",
5250 : "static a\n ['b'](){}",
5251 : "static ['a'] = 0\n",
5252 : "static ['a'] = 0\n b",
5253 : "static ['a'] = 0\n b(){}",
5254 : "static ['a']\n",
5255 : "static ['a']\n b\n",
5256 : "static ['a']\n b(){}",
5257 : "static ['a']\n *b(){}",
5258 : "static ['a']\n ['b'](){}",
5259 :
5260 : "static a = function t() { arguments; }",
5261 : "static a = () => function t() { arguments; }",
5262 :
5263 : // ASI edge cases
5264 : "static a\n get",
5265 : "static get\n *a(){}",
5266 : "static a\n static",
5267 :
5268 : // Misc edge cases
5269 : "static yield",
5270 : "static yield = 0",
5271 : "static yield\n a",
5272 : "static async;",
5273 : "static async = 0;",
5274 : "static async",
5275 : "static async = 0",
5276 : "static async\n a(){}", // a field named async, and a method named a.
5277 : "static async\n a",
5278 : "static await;",
5279 : "static await = 0;",
5280 : "static await\n a",
5281 : nullptr
5282 5 : };
5283 : // clang-format on
5284 :
5285 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5286 : kAllowHarmonyStaticFields};
5287 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5288 5 : always_flags, arraysize(always_flags));
5289 :
5290 : // Without the static flag, all of these are errors
5291 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5292 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5293 5 : no_static_flags, arraysize(no_static_flags));
5294 5 : }
5295 :
5296 26644 : TEST(ClassFieldsNoErrors) {
5297 : // clang-format off
5298 : // Tests proposed class fields syntax.
5299 : const char* context_data[][2] = {{"(class {", "});"},
5300 : {"(class extends Base {", "});"},
5301 : {"class C {", "}"},
5302 : {"class C extends Base {", "}"},
5303 5 : {nullptr, nullptr}};
5304 : const char* class_body_data[] = {
5305 : // Basic syntax
5306 : "a = 0;",
5307 : "a = 0; b",
5308 : "a = 0; b(){}",
5309 : "a = 0; *b(){}",
5310 : "a = 0; ['b'](){}",
5311 : "a;",
5312 : "a; b;",
5313 : "a; b(){}",
5314 : "a; *b(){}",
5315 : "a; ['b'](){}",
5316 : "['a'] = 0;",
5317 : "['a'] = 0; b",
5318 : "['a'] = 0; b(){}",
5319 : "['a'] = 0; *b(){}",
5320 : "['a'] = 0; ['b'](){}",
5321 : "['a'];",
5322 : "['a']; b;",
5323 : "['a']; b(){}",
5324 : "['a']; *b(){}",
5325 : "['a']; ['b'](){}",
5326 :
5327 : "0 = 0;",
5328 : "0;",
5329 : "'a' = 0;",
5330 : "'a';",
5331 :
5332 : "c = [c] = c",
5333 :
5334 : // ASI
5335 : "a = 0\n",
5336 : "a = 0\n b",
5337 : "a = 0\n b(){}",
5338 : "a\n",
5339 : "a\n b\n",
5340 : "a\n b(){}",
5341 : "a\n *b(){}",
5342 : "a\n ['b'](){}",
5343 : "['a'] = 0\n",
5344 : "['a'] = 0\n b",
5345 : "['a'] = 0\n b(){}",
5346 : "['a']\n",
5347 : "['a']\n b\n",
5348 : "['a']\n b(){}",
5349 : "['a']\n *b(){}",
5350 : "['a']\n ['b'](){}",
5351 :
5352 : // ASI edge cases
5353 : "a\n get",
5354 : "get\n *a(){}",
5355 : "a\n static",
5356 :
5357 : "a = function t() { arguments; }",
5358 : "a = () => function() { arguments; }",
5359 :
5360 : // Misc edge cases
5361 : "yield",
5362 : "yield = 0",
5363 : "yield\n a",
5364 : "async;",
5365 : "async = 0;",
5366 : "async",
5367 : "async = 0",
5368 : "async\n a(){}", // a field named async, and a method named a.
5369 : "async\n a",
5370 : "await;",
5371 : "await = 0;",
5372 : "await\n a",
5373 : nullptr
5374 5 : };
5375 : // clang-format on
5376 :
5377 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5378 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5379 5 : always_flags, arraysize(always_flags));
5380 :
5381 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5382 : kAllowHarmonyStaticFields};
5383 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5384 5 : static_flags, arraysize(static_flags));
5385 5 : }
5386 :
5387 26644 : TEST(PrivateMethodsNoErrors) {
5388 : // clang-format off
5389 : // Tests proposed class methods syntax.
5390 : const char* context_data[][2] = {{"(class {", "});"},
5391 : {"(class extends Base {", "});"},
5392 : {"class C {", "}"},
5393 : {"class C extends Base {", "}"},
5394 5 : {nullptr, nullptr}};
5395 : const char* class_body_data[] = {
5396 : // Basic syntax
5397 : "#a() { }",
5398 : "get #a() { }",
5399 : "set #a(foo) { }",
5400 : "*#a() { }",
5401 : "async #a() { }",
5402 : "async *#a() { }",
5403 :
5404 : "#a() { } #b() {}",
5405 : "get #a() { } set #a(foo) {}",
5406 : "get #a() { } get #b() {} set #a(foo) {}",
5407 : "get #a() { } get #b() {} set #a(foo) {} set #b(foo) {}",
5408 : "set #a(foo) { } set #b(foo) {}",
5409 : "get #a() { } get #b() {}",
5410 :
5411 : "#a() { } static a() {}",
5412 : "#a() { } a() {}",
5413 : "#a() { } a() {} static a() {}",
5414 : "get #a() { } get a() {} static get a() {}",
5415 : "set #a(foo) { } set a(foo) {} static set a(foo) {}",
5416 :
5417 : "#a() { } get #b() {}",
5418 : "#a() { } async #b() {}",
5419 : "#a() { } async *#b() {}",
5420 :
5421 : // With arguments
5422 : "#a(...args) { }",
5423 : "#a(a = 1) { }",
5424 : "get #a() { }",
5425 : "set #a(a = (...args) => {}) { }",
5426 :
5427 : // Misc edge cases
5428 : "#get() {}",
5429 : "#set() {}",
5430 : "#yield() {}",
5431 : "#await() {}",
5432 : "#async() {}",
5433 : "#static() {}",
5434 : "#arguments() {}",
5435 : "get #yield() {}",
5436 : "get #await() {}",
5437 : "get #async() {}",
5438 : "get #get() {}",
5439 : "get #static() {}",
5440 : "get #arguments() {}",
5441 : "set #yield(test) {}",
5442 : "set #async(test) {}",
5443 : "set #await(test) {}",
5444 : "set #set(test) {}",
5445 : "set #static(test) {}",
5446 : "set #arguments(test) {}",
5447 : "async #yield() {}",
5448 : "async #async() {}",
5449 : "async #await() {}",
5450 : "async #get() {}",
5451 : "async #set() {}",
5452 : "async #static() {}",
5453 : "async #arguments() {}",
5454 : "*#async() {}",
5455 : "*#await() {}",
5456 : "*#yield() {}",
5457 : "*#get() {}",
5458 : "*#set() {}",
5459 : "*#static() {}",
5460 : "*#arguments() {}",
5461 : "async *#yield() {}",
5462 : "async *#async() {}",
5463 : "async *#await() {}",
5464 : "async *#get() {}",
5465 : "async *#set() {}",
5466 : "async *#static() {}",
5467 : "async *#arguments() {}",
5468 : nullptr
5469 5 : };
5470 : // clang-format on
5471 :
5472 5 : RunParserSyncTest(context_data, class_body_data, kError);
5473 :
5474 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5475 : kAllowHarmonyPrivateMethods};
5476 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5477 5 : private_methods, arraysize(private_methods));
5478 5 : }
5479 :
5480 26644 : TEST(PrivateMethodsAndFieldsNoErrors) {
5481 : // clang-format off
5482 : // Tests proposed class methods syntax in combination with fields
5483 : const char* context_data[][2] = {{"(class {", "});"},
5484 : {"(class extends Base {", "});"},
5485 : {"class C {", "}"},
5486 : {"class C extends Base {", "}"},
5487 5 : {nullptr, nullptr}};
5488 : const char* class_body_data[] = {
5489 : // Basic syntax
5490 : "#b;#a() { }",
5491 : "#b;get #a() { }",
5492 : "#b;set #a(foo) { }",
5493 : "#b;*#a() { }",
5494 : "#b;async #a() { }",
5495 : "#b;async *#a() { }",
5496 : "#b = 1;#a() { }",
5497 : "#b = 1;get #a() { }",
5498 : "#b = 1;set #a(foo) { }",
5499 : "#b = 1;*#a() { }",
5500 : "#b = 1;async #a() { }",
5501 : "#b = 1;async *#a() { }",
5502 :
5503 : // With public fields
5504 : "a;#a() { }",
5505 : "a;get #a() { }",
5506 : "a;set #a(foo) { }",
5507 : "a;*#a() { }",
5508 : "a;async #a() { }",
5509 : "a;async *#a() { }",
5510 : "a = 1;#a() { }",
5511 : "a = 1;get #a() { }",
5512 : "a = 1;set #a(foo) { }",
5513 : "a = 1;*#a() { }",
5514 : "a = 1;async #a() { }",
5515 : "a = 1;async *#a() { }",
5516 :
5517 : // ASI
5518 : "#a = 0\n #b(){}",
5519 : "#a\n *#b(){}",
5520 : "#a = 0\n get #b(){}",
5521 : "#a\n *#b(){}",
5522 :
5523 : "b = 0\n #b(){}",
5524 : "b\n *#b(){}",
5525 : "b = 0\n get #b(){}",
5526 : "b\n *#b(){}",
5527 : nullptr
5528 5 : };
5529 : // clang-format on
5530 :
5531 5 : RunParserSyncTest(context_data, class_body_data, kError);
5532 :
5533 : static const ParserFlag private_methods_and_fields[] = {
5534 : kAllowHarmonyPrivateFields, kAllowHarmonyPublicFields,
5535 : kAllowHarmonyPrivateMethods};
5536 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5537 : private_methods_and_fields,
5538 5 : arraysize(private_methods_and_fields));
5539 5 : }
5540 :
5541 26644 : TEST(PrivateMethodsErrors) {
5542 : // clang-format off
5543 : // Tests proposed class methods syntax in combination with fields
5544 : const char* context_data[][2] = {{"(class {", "});"},
5545 : {"(class extends Base {", "});"},
5546 : {"class C {", "}"},
5547 : {"class C extends Base {", "}"},
5548 5 : {nullptr, nullptr}};
5549 : const char* class_body_data[] = {
5550 : "#a() : 0",
5551 : "#a() =",
5552 : "#a() => {}",
5553 : "#a => {}",
5554 : "*#a() = 0",
5555 : "*#a() => 0",
5556 : "*#a() => {}",
5557 : "get #a()[]",
5558 : "yield #a()[]",
5559 : "yield #a => {}",
5560 : "async #a() = 0",
5561 : "async #a => {}",
5562 : "#a(arguments) {}",
5563 : "set #a(arguments) {}",
5564 :
5565 : "#['a']() { }",
5566 : "get #['a']() { }",
5567 : "set #['a'](foo) { }",
5568 : "*#['a']() { }",
5569 : "async #['a']() { }",
5570 : "async *#['a]() { }",
5571 :
5572 : // TODO(joyee): check duplicate accessors
5573 :
5574 : "#a\n#",
5575 : "#a() c",
5576 : "#a() #",
5577 : "#a(arg) c",
5578 : "#a(arg) #",
5579 : "#a(arg) #c",
5580 : "#a#",
5581 : "#a#b",
5582 : "#a#b(){}",
5583 : "#[test](){}",
5584 :
5585 : "async *#constructor() {}",
5586 : "*#constructor() {}",
5587 : "async #constructor() {}",
5588 : "set #constructor(test) {}",
5589 : "#constructor() {}",
5590 : "get #constructor() {}",
5591 : nullptr
5592 5 : };
5593 : // clang-format on
5594 :
5595 5 : RunParserSyncTest(context_data, class_body_data, kError);
5596 :
5597 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5598 : kAllowHarmonyPrivateMethods};
5599 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5600 5 : private_methods, arraysize(private_methods));
5601 5 : }
5602 :
5603 : // Test that private members do not parse outside class bodies
5604 26644 : TEST(PrivateMembersInNonClassNoErrors) {
5605 : // clang-format off
5606 : const char* context_data[][2] = {{"", ""},
5607 : {"({", "})"},
5608 : {"'use strict'; ({", "});"},
5609 : {"function() {", "}"},
5610 : {"() => {", "}"},
5611 : {"class C { test() {", "} }"},
5612 : {"const {", "} = {}"},
5613 : {"({", "} = {})"},
5614 5 : {nullptr, nullptr}};
5615 : const char* class_body_data[] = {
5616 : "#a = 1",
5617 : "#a = () => {}",
5618 : "#a",
5619 : "#a() { }",
5620 : "get #a() { }",
5621 : "set #a(foo) { }",
5622 : "*#a() { }",
5623 : "async #a() { }",
5624 : "async *#a() { }",
5625 : nullptr
5626 5 : };
5627 : // clang-format on
5628 :
5629 5 : RunParserSyncTest(context_data, class_body_data, kError);
5630 :
5631 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5632 : kAllowHarmonyPrivateMethods};
5633 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5634 5 : private_methods, arraysize(private_methods));
5635 5 : }
5636 :
5637 26644 : TEST(PrivateClassFieldsNoErrors) {
5638 : // clang-format off
5639 : // Tests proposed class fields syntax.
5640 : const char* context_data[][2] = {{"(class {", "});"},
5641 : {"(class extends Base {", "});"},
5642 : {"class C {", "}"},
5643 : {"class C extends Base {", "}"},
5644 5 : {nullptr, nullptr}};
5645 : const char* class_body_data[] = {
5646 : // Basic syntax
5647 : "#a = 0;",
5648 : "#a = 0; #b",
5649 : "#a = 0; b",
5650 : "#a = 0; b(){}",
5651 : "#a = 0; *b(){}",
5652 : "#a = 0; ['b'](){}",
5653 : "#a;",
5654 : "#a; #b;",
5655 : "#a; b;",
5656 : "#a; b(){}",
5657 : "#a; *b(){}",
5658 : "#a; ['b'](){}",
5659 :
5660 : // ASI
5661 : "#a = 0\n",
5662 : "#a = 0\n #b",
5663 : "#a = 0\n b",
5664 : "#a = 0\n b(){}",
5665 : "#a\n",
5666 : "#a\n #b\n",
5667 : "#a\n b\n",
5668 : "#a\n b(){}",
5669 : "#a\n *b(){}",
5670 : "#a\n ['b'](){}",
5671 :
5672 : // ASI edge cases
5673 : "#a\n get",
5674 : "#get\n *a(){}",
5675 : "#a\n static",
5676 :
5677 : "#a = function t() { arguments; }",
5678 : "#a = () => function() { arguments; }",
5679 :
5680 : // Misc edge cases
5681 : "#yield",
5682 : "#yield = 0",
5683 : "#yield\n a",
5684 : "#async;",
5685 : "#async = 0;",
5686 : "#async",
5687 : "#async = 0",
5688 : "#async\n a(){}", // a field named async, and a method named a.
5689 : "#async\n a",
5690 : "#await;",
5691 : "#await = 0;",
5692 : "#await\n a",
5693 : nullptr
5694 5 : };
5695 : // clang-format on
5696 :
5697 5 : RunParserSyncTest(context_data, class_body_data, kError);
5698 :
5699 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5700 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5701 5 : private_fields, arraysize(private_fields));
5702 5 : }
5703 :
5704 26644 : TEST(StaticClassFieldsErrors) {
5705 : // clang-format off
5706 : // Tests proposed class fields syntax.
5707 : const char* context_data[][2] = {{"(class {", "});"},
5708 : {"(class extends Base {", "});"},
5709 : {"class C {", "}"},
5710 : {"class C extends Base {", "}"},
5711 5 : {nullptr, nullptr}};
5712 : const char* class_body_data[] = {
5713 : "static a : 0",
5714 : "static a =",
5715 : "static constructor",
5716 : "static prototype",
5717 : "static *a = 0",
5718 : "static *a",
5719 : "static get a",
5720 : "static get\n a",
5721 : "static yield a",
5722 : "static async a = 0",
5723 : "static async a",
5724 :
5725 : "static a = arguments",
5726 : "static a = () => arguments",
5727 : "static a = () => { arguments }",
5728 : "static a = arguments[0]",
5729 : "static a = delete arguments[0]",
5730 : "static a = f(arguments)",
5731 : "static a = () => () => arguments",
5732 :
5733 : // ASI requires a linebreak
5734 : "static a b",
5735 : "static a = 0 b",
5736 :
5737 : "static c = [1] = [c]",
5738 :
5739 : // ASI requires that the next token is not part of any legal production
5740 : "static a = 0\n *b(){}",
5741 : "static a = 0\n ['b'](){}",
5742 : nullptr
5743 5 : };
5744 : // clang-format on
5745 :
5746 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5747 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5748 5 : no_static_flags, arraysize(no_static_flags));
5749 :
5750 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5751 : kAllowHarmonyStaticFields};
5752 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5753 5 : always_flags, arraysize(always_flags));
5754 5 : }
5755 :
5756 26644 : TEST(ClassFieldsErrors) {
5757 : // clang-format off
5758 : // Tests proposed class fields syntax.
5759 : const char* context_data[][2] = {{"(class {", "});"},
5760 : {"(class extends Base {", "});"},
5761 : {"class C {", "}"},
5762 : {"class C extends Base {", "}"},
5763 5 : {nullptr, nullptr}};
5764 : const char* class_body_data[] = {
5765 : "a : 0",
5766 : "a =",
5767 : "constructor",
5768 : "*a = 0",
5769 : "*a",
5770 : "get a",
5771 : "yield a",
5772 : "async a = 0",
5773 : "async a",
5774 :
5775 : "a = arguments",
5776 : "a = () => arguments",
5777 : "a = () => { arguments }",
5778 : "a = arguments[0]",
5779 : "a = delete arguments[0]",
5780 : "a = f(arguments)",
5781 : "a = () => () => arguments",
5782 :
5783 : // ASI requires a linebreak
5784 : "a b",
5785 : "a = 0 b",
5786 :
5787 : "c = [1] = [c]",
5788 :
5789 : // ASI requires that the next token is not part of any legal production
5790 : "a = 0\n *b(){}",
5791 : "a = 0\n ['b'](){}",
5792 : "get\n a",
5793 : nullptr
5794 5 : };
5795 : // clang-format on
5796 :
5797 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5798 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5799 5 : always_flags, arraysize(always_flags));
5800 :
5801 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5802 : kAllowHarmonyStaticFields};
5803 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5804 5 : static_flags, arraysize(static_flags));
5805 5 : }
5806 :
5807 26644 : TEST(PrivateClassFieldsErrors) {
5808 : // clang-format off
5809 : // Tests proposed class fields syntax.
5810 : const char* context_data[][2] = {{"(class {", "});"},
5811 : {"(class extends Base {", "});"},
5812 : {"class C {", "}"},
5813 : {"class C extends Base {", "}"},
5814 5 : {nullptr, nullptr}};
5815 : const char* class_body_data[] = {
5816 : "#a : 0",
5817 : "#a =",
5818 : "#*a = 0",
5819 : "#*a",
5820 : "#get a",
5821 : "#yield a",
5822 : "#async a = 0",
5823 : "#async a",
5824 :
5825 : "#a; #a",
5826 : "#a = 1; #a",
5827 : "#a; #a = 1;",
5828 :
5829 : "#constructor",
5830 : "#constructor = function() {}",
5831 :
5832 : "# a = 0",
5833 : "#a() { }",
5834 : "get #a() { }",
5835 : "#get a() { }",
5836 : "set #a() { }",
5837 : "#set a() { }",
5838 : "*#a() { }",
5839 : "#*a() { }",
5840 : "async #a() { }",
5841 : "async *#a() { }",
5842 : "async #*a() { }",
5843 :
5844 : "#0 = 0;",
5845 : "#0;",
5846 : "#'a' = 0;",
5847 : "#'a';",
5848 :
5849 : "#['a']",
5850 : "#['a'] = 1",
5851 : "#[a]",
5852 : "#[a] = 1",
5853 :
5854 : "#a = arguments",
5855 : "#a = () => arguments",
5856 : "#a = () => { arguments }",
5857 : "#a = arguments[0]",
5858 : "#a = delete arguments[0]",
5859 : "#a = f(arguments)",
5860 : "#a = () => () => arguments",
5861 :
5862 : "foo() { delete this.#a }",
5863 : "foo() { delete this.x.#a }",
5864 : "foo() { delete this.x().#a }",
5865 :
5866 : "foo() { delete f.#a }",
5867 : "foo() { delete f.x.#a }",
5868 : "foo() { delete f.x().#a }",
5869 :
5870 : // ASI requires a linebreak
5871 : "#a b",
5872 : "#a = 0 b",
5873 :
5874 : // ASI requires that the next token is not part of any legal production
5875 : "#a = 0\n *b(){}",
5876 : "#a = 0\n ['b'](){}",
5877 : nullptr
5878 5 : };
5879 : // clang-format on
5880 :
5881 5 : RunParserSyncTest(context_data, class_body_data, kError);
5882 :
5883 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5884 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5885 5 : private_fields, arraysize(private_fields));
5886 5 : }
5887 :
5888 26644 : TEST(PrivateStaticClassFieldsNoErrors) {
5889 : // clang-format off
5890 : // Tests proposed class fields syntax.
5891 : const char* context_data[][2] = {{"(class {", "});"},
5892 : {"(class extends Base {", "});"},
5893 : {"class C {", "}"},
5894 : {"class C extends Base {", "}"},
5895 5 : {nullptr, nullptr}};
5896 : const char* class_body_data[] = {
5897 : // Basic syntax
5898 : "static #a = 0;",
5899 : "static #a = 0; b",
5900 : "static #a = 0; #b",
5901 : "static #a = 0; b(){}",
5902 : "static #a = 0; *b(){}",
5903 : "static #a = 0; ['b'](){}",
5904 : "static #a;",
5905 : "static #a; b;",
5906 : "static #a; b(){}",
5907 : "static #a; *b(){}",
5908 : "static #a; ['b'](){}",
5909 :
5910 : "#prototype",
5911 : "#prototype = function() {}",
5912 :
5913 : // ASI
5914 : "static #a = 0\n",
5915 : "static #a = 0\n b",
5916 : "static #a = 0\n #b",
5917 : "static #a = 0\n b(){}",
5918 : "static #a\n",
5919 : "static #a\n b\n",
5920 : "static #a\n #b\n",
5921 : "static #a\n b(){}",
5922 : "static #a\n *b(){}",
5923 : "static #a\n ['b'](){}",
5924 :
5925 : "static #a = function t() { arguments; }",
5926 : "static #a = () => function t() { arguments; }",
5927 :
5928 : // ASI edge cases
5929 : "static #a\n get",
5930 : "static #get\n *a(){}",
5931 : "static #a\n static",
5932 :
5933 : // Misc edge cases
5934 : "static #yield",
5935 : "static #yield = 0",
5936 : "static #yield\n a",
5937 : "static #async;",
5938 : "static #async = 0;",
5939 : "static #async",
5940 : "static #async = 0",
5941 : "static #async\n a(){}", // a field named async, and a method named a.
5942 : "static #async\n a",
5943 : "static #await;",
5944 : "static #await = 0;",
5945 : "static #await\n a",
5946 : nullptr
5947 5 : };
5948 : // clang-format on
5949 :
5950 5 : RunParserSyncTest(context_data, class_body_data, kError);
5951 :
5952 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
5953 : kAllowHarmonyStaticFields};
5954 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5955 5 : public_static_fields, arraysize(public_static_fields));
5956 :
5957 : static const ParserFlag private_static_fields[] = {
5958 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
5959 : kAllowHarmonyPrivateFields};
5960 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5961 5 : private_static_fields, arraysize(private_static_fields));
5962 5 : }
5963 :
5964 26644 : TEST(PrivateStaticClassFieldsErrors) {
5965 : // clang-format off
5966 : // Tests proposed class fields syntax.
5967 : const char* context_data[][2] = {{"(class {", "});"},
5968 : {"(class extends Base {", "});"},
5969 : {"class C {", "}"},
5970 : {"class C extends Base {", "}"},
5971 5 : {nullptr, nullptr}};
5972 : const char* class_body_data[] = {
5973 : // Basic syntax
5974 : "static #['a'] = 0;",
5975 : "static #['a'] = 0; b",
5976 : "static #['a'] = 0; #b",
5977 : "static #['a'] = 0; b(){}",
5978 : "static #['a'] = 0; *b(){}",
5979 : "static #['a'] = 0; ['b'](){}",
5980 : "static #['a'];",
5981 : "static #['a']; b;",
5982 : "static #['a']; #b;",
5983 : "static #['a']; b(){}",
5984 : "static #['a']; *b(){}",
5985 : "static #['a']; ['b'](){}",
5986 :
5987 : "static #0 = 0;",
5988 : "static #0;",
5989 : "static #'a' = 0;",
5990 : "static #'a';",
5991 :
5992 : "static # a = 0",
5993 : "static #get a() { }",
5994 : "static #set a() { }",
5995 : "static #*a() { }",
5996 : "static async #*a() { }",
5997 :
5998 : "#a = arguments",
5999 : "#a = () => arguments",
6000 : "#a = () => { arguments }",
6001 : "#a = arguments[0]",
6002 : "#a = delete arguments[0]",
6003 : "#a = f(arguments)",
6004 : "#a = () => () => arguments",
6005 :
6006 : "#a; static #a",
6007 : "static #a; #a",
6008 :
6009 : // TODO(joyee): support static private methods
6010 : "static #a() { }",
6011 : "static get #a() { }",
6012 : "static set #a() { }",
6013 : "static *#a() { }",
6014 : "static async #a() { }",
6015 : "static async *#a() { }",
6016 :
6017 : // ASI
6018 : "static #['a'] = 0\n",
6019 : "static #['a'] = 0\n b",
6020 : "static #['a'] = 0\n #b",
6021 : "static #['a'] = 0\n b(){}",
6022 : "static #['a']\n",
6023 : "static #['a']\n b\n",
6024 : "static #['a']\n #b\n",
6025 : "static #['a']\n b(){}",
6026 : "static #['a']\n *b(){}",
6027 : "static #['a']\n ['b'](){}",
6028 :
6029 : // ASI requires a linebreak
6030 : "static #a b",
6031 : "static #a = 0 b",
6032 :
6033 : // ASI requires that the next token is not part of any legal production
6034 : "static #a = 0\n *b(){}",
6035 : "static #a = 0\n ['b'](){}",
6036 :
6037 : "static #a : 0",
6038 : "static #a =",
6039 : "static #*a = 0",
6040 : "static #*a",
6041 : "static #get a",
6042 : "static #yield a",
6043 : "static #async a = 0",
6044 : "static #async a",
6045 : "static # a = 0",
6046 :
6047 : "#constructor",
6048 : "#constructor = function() {}",
6049 :
6050 : "foo() { delete this.#a }",
6051 : "foo() { delete this.x.#a }",
6052 : "foo() { delete this.x().#a }",
6053 :
6054 : "foo() { delete f.#a }",
6055 : "foo() { delete f.x.#a }",
6056 : "foo() { delete f.x().#a }",
6057 : nullptr
6058 5 : };
6059 : // clang-format on
6060 :
6061 5 : RunParserSyncTest(context_data, class_body_data, kError);
6062 :
6063 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
6064 : kAllowHarmonyStaticFields};
6065 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6066 5 : public_static_fields, arraysize(public_static_fields));
6067 :
6068 : static const ParserFlag private_static_fields[] = {
6069 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
6070 : kAllowHarmonyPrivateFields};
6071 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6072 5 : private_static_fields, arraysize(private_static_fields));
6073 5 : }
6074 :
6075 26644 : TEST(PrivateNameResolutionErrors) {
6076 : // clang-format off
6077 : const char* context_data[][2] = {
6078 : {"class X { bar() { ", " } }"},
6079 : {"\"use strict\";", ""},
6080 : {nullptr, nullptr}
6081 5 : };
6082 :
6083 : const char* statement_data[] = {
6084 : "this.#a",
6085 : "this.#a()",
6086 : "this.#b.#a",
6087 : "this.#b.#a()",
6088 :
6089 : "foo.#a",
6090 : "foo.#a()",
6091 : "foo.#b.#a",
6092 : "foo.#b.#a()",
6093 :
6094 : "foo().#a",
6095 : "foo().b.#a",
6096 : "foo().b().#a",
6097 : "foo().b().#a()",
6098 : "foo().b().#a.bar",
6099 : "foo().b().#a.bar()",
6100 :
6101 : "foo(this.#a)",
6102 : "foo(bar().#a)",
6103 :
6104 : "new foo.#a",
6105 : "new foo.#b.#a",
6106 : "new foo.#b.#a()",
6107 :
6108 : "foo.#if;",
6109 : "foo.#yield;",
6110 : "foo.#super;",
6111 : "foo.#interface;",
6112 : "foo.#eval;",
6113 : "foo.#arguments;",
6114 :
6115 : nullptr
6116 5 : };
6117 :
6118 : // clang-format on
6119 5 : RunParserSyncTest(context_data, statement_data, kError);
6120 :
6121 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6122 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0,
6123 5 : private_fields, arraysize(private_fields));
6124 5 : }
6125 :
6126 26644 : TEST(PrivateNameErrors) {
6127 : // clang-format off
6128 : const char* context_data[][2] = {
6129 : {"", ""},
6130 : {"function t() { ", " }"},
6131 : {"var t => { ", " }"},
6132 : {"var t = { [ ", " ] }"},
6133 : {"\"use strict\";", ""},
6134 : {nullptr, nullptr}
6135 5 : };
6136 :
6137 : const char* statement_data[] = {
6138 : "#foo",
6139 : "#foo = 1",
6140 :
6141 : "# a;",
6142 : "#\n a;",
6143 : "a, # b",
6144 : "a, #, b;",
6145 :
6146 : "foo.#[a];",
6147 : "foo.#['a'];",
6148 :
6149 : "foo()#a",
6150 : "foo()#[a]",
6151 : "foo()#['a']",
6152 :
6153 : "super.#a;",
6154 : "super.#a = 1;",
6155 : "super.#['a']",
6156 : "super.#[a]",
6157 :
6158 : "new.#a",
6159 : "new.#[a]",
6160 :
6161 : "foo.#{;",
6162 : "foo.#};",
6163 : "foo.#=;",
6164 : "foo.#888;",
6165 : "foo.#-;",
6166 : "foo.#--;",
6167 : nullptr
6168 5 : };
6169 :
6170 : // clang-format on
6171 5 : RunParserSyncTest(context_data, statement_data, kError);
6172 :
6173 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6174 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0,
6175 5 : private_fields, arraysize(private_fields));
6176 5 : }
6177 :
6178 26644 : TEST(ClassExpressionErrors) {
6179 : const char* context_data[][2] = {
6180 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
6181 : const char* class_data[] = {
6182 : "class",
6183 : "class name",
6184 : "class name extends",
6185 : "class extends",
6186 : "class {",
6187 : "class { m }",
6188 : "class { m; n }",
6189 : "class { m: 1 }",
6190 : "class { m(); n() }",
6191 : "class { get m }",
6192 : "class { get m() }",
6193 : "class { get m() { }",
6194 : "class { set m() {} }", // Missing required parameter.
6195 : "class { m() {}, n() {} }", // No commas allowed.
6196 5 : nullptr};
6197 :
6198 5 : RunParserSyncTest(context_data, class_data, kError);
6199 5 : }
6200 :
6201 :
6202 26644 : TEST(ClassDeclarationErrors) {
6203 : const char* context_data[][2] = {
6204 5 : {"", ""}, {"{", "}"}, {"if (true) {", "}"}, {nullptr, nullptr}};
6205 : const char* class_data[] = {
6206 : "class",
6207 : "class name",
6208 : "class name extends",
6209 : "class extends",
6210 : "class name {",
6211 : "class name { m }",
6212 : "class name { m; n }",
6213 : "class name { m: 1 }",
6214 : "class name { m(); n() }",
6215 : "class name { get x }",
6216 : "class name { get x() }",
6217 : "class name { set x() {) }", // missing required param
6218 : "class {}", // Name is required for declaration
6219 : "class extends base {}",
6220 : "class name { *",
6221 : "class name { * }",
6222 : "class name { *; }",
6223 : "class name { *get x() {} }",
6224 : "class name { *set x(_) {} }",
6225 : "class name { *static m() {} }",
6226 5 : nullptr};
6227 :
6228 5 : RunParserSyncTest(context_data, class_data, kError);
6229 5 : }
6230 :
6231 26644 : TEST(ClassAsyncErrors) {
6232 : // clang-format off
6233 : const char* context_data[][2] = {{"(class {", "});"},
6234 : {"(class extends Base {", "});"},
6235 : {"class C {", "}"},
6236 : {"class C extends Base {", "}"},
6237 5 : {nullptr, nullptr}};
6238 : const char* async_data[] = {
6239 : "*async x(){}",
6240 : "async *(){}",
6241 : "async get x(){}",
6242 : "async set x(y){}",
6243 : "async x : 0",
6244 : "async : 0",
6245 :
6246 : "async static x(){}",
6247 :
6248 : "static *async x(){}",
6249 : "static async *(){}",
6250 : "static async get x(){}",
6251 : "static async set x(y){}",
6252 : "static async x : 0",
6253 : "static async : 0",
6254 : nullptr
6255 5 : };
6256 : // clang-format on
6257 :
6258 5 : RunParserSyncTest(context_data, async_data, kError);
6259 5 : }
6260 :
6261 26644 : TEST(ClassNameErrors) {
6262 : const char* context_data[][2] = {{"class ", "{}"},
6263 : {"(class ", "{});"},
6264 : {"'use strict'; class ", "{}"},
6265 : {"'use strict'; (class ", "{});"},
6266 5 : {nullptr, nullptr}};
6267 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6268 : "let", "package", "private", "protected",
6269 : "public", "static", "var", "yield",
6270 5 : nullptr};
6271 :
6272 5 : RunParserSyncTest(context_data, class_name, kError);
6273 5 : }
6274 :
6275 :
6276 26644 : TEST(ClassGetterParamNameErrors) {
6277 : const char* context_data[][2] = {
6278 : {"class C { get name(", ") {} }"},
6279 : {"(class { get name(", ") {} });"},
6280 : {"'use strict'; class C { get name(", ") {} }"},
6281 : {"'use strict'; (class { get name(", ") {} })"},
6282 5 : {nullptr, nullptr}};
6283 :
6284 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6285 : "let", "package", "private", "protected",
6286 : "public", "static", "var", "yield",
6287 5 : nullptr};
6288 :
6289 5 : RunParserSyncTest(context_data, class_name, kError);
6290 5 : }
6291 :
6292 :
6293 26644 : TEST(ClassStaticPrototypeErrors) {
6294 : const char* context_data[][2] = {
6295 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6296 :
6297 : const char* class_body_data[] = {"static prototype() {}",
6298 : "static get prototype() {}",
6299 : "static set prototype(_) {}",
6300 : "static *prototype() {}",
6301 : "static 'prototype'() {}",
6302 : "static *'prototype'() {}",
6303 : "static prot\\u006ftype() {}",
6304 : "static 'prot\\u006ftype'() {}",
6305 : "static get 'prot\\u006ftype'() {}",
6306 : "static set 'prot\\u006ftype'(_) {}",
6307 : "static *'prot\\u006ftype'() {}",
6308 5 : nullptr};
6309 :
6310 5 : RunParserSyncTest(context_data, class_body_data, kError);
6311 5 : }
6312 :
6313 :
6314 26644 : TEST(ClassSpecialConstructorErrors) {
6315 : const char* context_data[][2] = {
6316 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6317 :
6318 : const char* class_body_data[] = {"get constructor() {}",
6319 : "get constructor(_) {}",
6320 : "*constructor() {}",
6321 : "get 'constructor'() {}",
6322 : "*'constructor'() {}",
6323 : "get c\\u006fnstructor() {}",
6324 : "*c\\u006fnstructor() {}",
6325 : "get 'c\\u006fnstructor'() {}",
6326 : "get 'c\\u006fnstructor'(_) {}",
6327 : "*'c\\u006fnstructor'() {}",
6328 5 : nullptr};
6329 :
6330 5 : RunParserSyncTest(context_data, class_body_data, kError);
6331 5 : }
6332 :
6333 :
6334 26644 : TEST(ClassConstructorNoErrors) {
6335 : const char* context_data[][2] = {
6336 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6337 :
6338 : const char* class_body_data[] = {"constructor() {}",
6339 : "static constructor() {}",
6340 : "static get constructor() {}",
6341 : "static set constructor(_) {}",
6342 : "static *constructor() {}",
6343 5 : nullptr};
6344 :
6345 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6346 5 : }
6347 :
6348 :
6349 26644 : TEST(ClassMultipleConstructorErrors) {
6350 : const char* context_data[][2] = {
6351 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6352 :
6353 : const char* class_body_data[] = {"constructor() {}; constructor() {}",
6354 5 : nullptr};
6355 :
6356 5 : RunParserSyncTest(context_data, class_body_data, kError);
6357 5 : }
6358 :
6359 :
6360 26644 : TEST(ClassMultiplePropertyNamesNoErrors) {
6361 : const char* context_data[][2] = {
6362 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6363 :
6364 : const char* class_body_data[] = {
6365 : "constructor() {}; static constructor() {}",
6366 : "m() {}; static m() {}",
6367 : "m() {}; m() {}",
6368 : "static m() {}; static m() {}",
6369 : "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
6370 5 : nullptr};
6371 :
6372 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6373 5 : }
6374 :
6375 :
6376 26644 : TEST(ClassesAreStrictErrors) {
6377 5 : const char* context_data[][2] = {{"", ""}, {"(", ");"}, {nullptr, nullptr}};
6378 :
6379 : const char* class_body_data[] = {
6380 : "class C { method() { with ({}) {} } }",
6381 : "class C extends function() { with ({}) {} } {}",
6382 5 : "class C { *method() { with ({}) {} } }", nullptr};
6383 :
6384 5 : RunParserSyncTest(context_data, class_body_data, kError);
6385 5 : }
6386 :
6387 :
6388 26644 : TEST(ObjectLiteralPropertyShorthandKeywordsError) {
6389 : const char* context_data[][2] = {
6390 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6391 :
6392 : const char* name_data[] = {
6393 : "break", "case", "catch", "class", "const", "continue",
6394 : "debugger", "default", "delete", "do", "else", "enum",
6395 : "export", "extends", "false", "finally", "for", "function",
6396 : "if", "import", "in", "instanceof", "new", "null",
6397 : "return", "super", "switch", "this", "throw", "true",
6398 : "try", "typeof", "var", "void", "while", "with",
6399 5 : nullptr};
6400 :
6401 5 : RunParserSyncTest(context_data, name_data, kError);
6402 5 : }
6403 :
6404 :
6405 26644 : TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
6406 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
6407 :
6408 : const char* name_data[] = {"implements", "interface", "let", "package",
6409 : "private", "protected", "public", "static",
6410 5 : "yield", nullptr};
6411 :
6412 5 : RunParserSyncTest(context_data, name_data, kSuccess);
6413 :
6414 : const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
6415 5 : {nullptr, nullptr}};
6416 5 : RunParserSyncTest(context_strict_data, name_data, kError);
6417 5 : }
6418 :
6419 :
6420 26644 : TEST(ObjectLiteralPropertyShorthandError) {
6421 : const char* context_data[][2] = {
6422 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6423 :
6424 : const char* name_data[] = {"1", "1.2", "0", "0.1", "1.0",
6425 5 : "1e1", "0x1", "\"s\"", "'s'", nullptr};
6426 :
6427 5 : RunParserSyncTest(context_data, name_data, kError);
6428 5 : }
6429 :
6430 :
6431 26644 : TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
6432 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6433 :
6434 5 : const char* name_data[] = {"function* g() { ({yield}); }", nullptr};
6435 :
6436 5 : RunParserSyncTest(context_data, name_data, kError);
6437 5 : }
6438 :
6439 :
6440 26644 : TEST(ConstParsingInForIn) {
6441 : const char* context_data[][2] = {{"'use strict';", ""},
6442 : {"function foo(){ 'use strict';", "}"},
6443 5 : {nullptr, nullptr}};
6444 :
6445 : const char* data[] = {
6446 : "for(const x = 1; ; ) {}", "for(const x = 1, y = 2;;){}",
6447 5 : "for(const x in [1,2,3]) {}", "for(const x of [1,2,3]) {}", nullptr};
6448 5 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
6449 5 : }
6450 :
6451 :
6452 26644 : TEST(StatementParsingInForIn) {
6453 : const char* context_data[][2] = {{"", ""},
6454 : {"'use strict';", ""},
6455 : {"function foo(){ 'use strict';", "}"},
6456 5 : {nullptr, nullptr}};
6457 :
6458 : const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
6459 : "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
6460 5 : nullptr};
6461 :
6462 5 : RunParserSyncTest(context_data, data, kSuccess);
6463 5 : }
6464 :
6465 :
6466 26644 : TEST(ConstParsingInForInError) {
6467 : const char* context_data[][2] = {{"'use strict';", ""},
6468 : {"function foo(){ 'use strict';", "}"},
6469 5 : {nullptr, nullptr}};
6470 :
6471 : const char* data[] = {
6472 : "for(const x,y = 1; ; ) {}", "for(const x = 4 in [1,2,3]) {}",
6473 : "for(const x = 4, y in [1,2,3]) {}", "for(const x = 4 of [1,2,3]) {}",
6474 : "for(const x = 4, y of [1,2,3]) {}", "for(const x = 1, y = 2 in []) {}",
6475 : "for(const x,y in []) {}", "for(const x = 1, y = 2 of []) {}",
6476 5 : "for(const x,y of []) {}", nullptr};
6477 5 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
6478 5 : }
6479 :
6480 26644 : TEST(InitializedDeclarationsInForInOf) {
6481 : // https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads
6482 :
6483 : // Initialized declarations only allowed for
6484 : // - sloppy mode (not strict mode)
6485 : // - for-in (not for-of)
6486 : // - var (not let / const)
6487 :
6488 : // clang-format off
6489 : const char* strict_context[][2] = {{"'use strict';", ""},
6490 : {"function foo(){ 'use strict';", "}"},
6491 : {"function* foo(){ 'use strict';", "}"},
6492 5 : {nullptr, nullptr}};
6493 :
6494 : const char* sloppy_context[][2] = {{"", ""},
6495 : {"function foo(){ ", "}"},
6496 : {"function* foo(){ ", "}"},
6497 : {"function foo(){ var yield = 0; ", "}"},
6498 5 : {nullptr, nullptr}};
6499 :
6500 : const char* let_const_var_for_of[] = {
6501 : "for (let i = 1 of {}) {}",
6502 : "for (let i = void 0 of [1, 2, 3]) {}",
6503 : "for (const i = 1 of {}) {}",
6504 : "for (const i = void 0 of [1, 2, 3]) {}",
6505 : "for (var i = 1 of {}) {}",
6506 : "for (var i = void 0 of [1, 2, 3]) {}",
6507 5 : nullptr};
6508 :
6509 : const char* let_const_for_in[] = {
6510 : "for (let i = 1 in {}) {}",
6511 : "for (let i = void 0 in [1, 2, 3]) {}",
6512 : "for (const i = 1 in {}) {}",
6513 : "for (const i = void 0 in [1, 2, 3]) {}",
6514 5 : nullptr};
6515 :
6516 : const char* var_for_in[] = {
6517 : "for (var i = 1 in {}) {}",
6518 : "for (var i = void 0 in [1, 2, 3]) {}",
6519 : "for (var i = yield in [1, 2, 3]) {}",
6520 5 : nullptr};
6521 : // clang-format on
6522 :
6523 : // The only allowed case is sloppy + var + for-in.
6524 5 : RunParserSyncTest(sloppy_context, var_for_in, kSuccess);
6525 :
6526 : // Everything else is disallowed.
6527 5 : RunParserSyncTest(sloppy_context, let_const_var_for_of, kError);
6528 5 : RunParserSyncTest(sloppy_context, let_const_for_in, kError);
6529 :
6530 5 : RunParserSyncTest(strict_context, let_const_var_for_of, kError);
6531 5 : RunParserSyncTest(strict_context, let_const_for_in, kError);
6532 5 : RunParserSyncTest(strict_context, var_for_in, kError);
6533 5 : }
6534 :
6535 26644 : TEST(ForInMultipleDeclarationsError) {
6536 : const char* context_data[][2] = {{"", ""},
6537 : {"function foo(){", "}"},
6538 : {"'use strict';", ""},
6539 : {"function foo(){ 'use strict';", "}"},
6540 5 : {nullptr, nullptr}};
6541 :
6542 : const char* data[] = {"for (var i, j in {}) {}",
6543 : "for (var i, j in [1, 2, 3]) {}",
6544 : "for (var i, j = 1 in {}) {}",
6545 : "for (var i, j = void 0 in [1, 2, 3]) {}",
6546 :
6547 : "for (let i, j in {}) {}",
6548 : "for (let i, j in [1, 2, 3]) {}",
6549 : "for (let i, j = 1 in {}) {}",
6550 : "for (let i, j = void 0 in [1, 2, 3]) {}",
6551 :
6552 : "for (const i, j in {}) {}",
6553 : "for (const i, j in [1, 2, 3]) {}",
6554 : "for (const i, j = 1 in {}) {}",
6555 : "for (const i, j = void 0 in [1, 2, 3]) {}",
6556 5 : nullptr};
6557 5 : RunParserSyncTest(context_data, data, kError);
6558 5 : }
6559 :
6560 :
6561 26644 : TEST(ForOfMultipleDeclarationsError) {
6562 : const char* context_data[][2] = {{"", ""},
6563 : {"function foo(){", "}"},
6564 : {"'use strict';", ""},
6565 : {"function foo(){ 'use strict';", "}"},
6566 5 : {nullptr, nullptr}};
6567 :
6568 : const char* data[] = {"for (var i, j of {}) {}",
6569 : "for (var i, j of [1, 2, 3]) {}",
6570 : "for (var i, j = 1 of {}) {}",
6571 : "for (var i, j = void 0 of [1, 2, 3]) {}",
6572 :
6573 : "for (let i, j of {}) {}",
6574 : "for (let i, j of [1, 2, 3]) {}",
6575 : "for (let i, j = 1 of {}) {}",
6576 : "for (let i, j = void 0 of [1, 2, 3]) {}",
6577 :
6578 : "for (const i, j of {}) {}",
6579 : "for (const i, j of [1, 2, 3]) {}",
6580 : "for (const i, j = 1 of {}) {}",
6581 : "for (const i, j = void 0 of [1, 2, 3]) {}",
6582 5 : nullptr};
6583 5 : RunParserSyncTest(context_data, data, kError);
6584 5 : }
6585 :
6586 :
6587 26644 : TEST(ForInNoDeclarationsError) {
6588 : const char* context_data[][2] = {{"", ""},
6589 : {"function foo(){", "}"},
6590 : {"'use strict';", ""},
6591 : {"function foo(){ 'use strict';", "}"},
6592 5 : {nullptr, nullptr}};
6593 :
6594 5 : const char* data[] = {"for (var in {}) {}", "for (const in {}) {}", nullptr};
6595 5 : RunParserSyncTest(context_data, data, kError);
6596 5 : }
6597 :
6598 :
6599 26644 : TEST(ForOfNoDeclarationsError) {
6600 : const char* context_data[][2] = {{"", ""},
6601 : {"function foo(){", "}"},
6602 : {"'use strict';", ""},
6603 : {"function foo(){ 'use strict';", "}"},
6604 5 : {nullptr, nullptr}};
6605 :
6606 : const char* data[] = {"for (var of [1, 2, 3]) {}",
6607 5 : "for (const of [1, 2, 3]) {}", nullptr};
6608 5 : RunParserSyncTest(context_data, data, kError);
6609 5 : }
6610 :
6611 :
6612 26644 : TEST(ForOfInOperator) {
6613 : const char* context_data[][2] = {{"", ""},
6614 : {"'use strict';", ""},
6615 : {"function foo(){ 'use strict';", "}"},
6616 5 : {nullptr, nullptr}};
6617 :
6618 : const char* data[] = {"for(x of 'foo' in {}) {}",
6619 : "for(var x of 'foo' in {}) {}",
6620 : "for(let x of 'foo' in {}) {}",
6621 5 : "for(const x of 'foo' in {}) {}", nullptr};
6622 :
6623 5 : RunParserSyncTest(context_data, data, kSuccess);
6624 5 : }
6625 :
6626 :
6627 26644 : TEST(ForOfYieldIdentifier) {
6628 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6629 :
6630 : const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
6631 : "for(let x of yield) {}", "for(const x of yield) {}",
6632 5 : nullptr};
6633 :
6634 5 : RunParserSyncTest(context_data, data, kSuccess);
6635 5 : }
6636 :
6637 :
6638 26644 : TEST(ForOfYieldExpression) {
6639 : const char* context_data[][2] = {{"", ""},
6640 : {"'use strict';", ""},
6641 : {"function foo(){ 'use strict';", "}"},
6642 5 : {nullptr, nullptr}};
6643 :
6644 : const char* data[] = {"function* g() { for(x of yield) {} }",
6645 : "function* g() { for(var x of yield) {} }",
6646 : "function* g() { for(let x of yield) {} }",
6647 5 : "function* g() { for(const x of yield) {} }", nullptr};
6648 :
6649 5 : RunParserSyncTest(context_data, data, kSuccess);
6650 5 : }
6651 :
6652 :
6653 26644 : TEST(ForOfExpressionError) {
6654 : const char* context_data[][2] = {{"", ""},
6655 : {"'use strict';", ""},
6656 : {"function foo(){ 'use strict';", "}"},
6657 5 : {nullptr, nullptr}};
6658 :
6659 : const char* data[] = {
6660 : "for(x of [], []) {}", "for(var x of [], []) {}",
6661 : "for(let x of [], []) {}", "for(const x of [], []) {}",
6662 :
6663 : // AssignmentExpression should be validated statically:
6664 : "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
6665 5 : "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", nullptr};
6666 :
6667 5 : RunParserSyncTest(context_data, data, kError);
6668 5 : }
6669 :
6670 :
6671 26644 : TEST(InvalidUnicodeEscapes) {
6672 : const char* context_data[][2] = {
6673 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6674 : const char* data[] = {
6675 : "var foob\\u123r = 0;", "var \\u123roo = 0;", "\"foob\\u123rr\"",
6676 : // No escapes allowed in regexp flags
6677 : "/regex/\\u0069g", "/regex/\\u006g",
6678 : // Braces gone wrong
6679 : "var foob\\u{c481r = 0;", "var foob\\uc481}r = 0;", "var \\u{0052oo = 0;",
6680 : "var \\u0052}oo = 0;", "\"foob\\u{c481r\"", "var foob\\u{}ar = 0;",
6681 : // Too high value for the Unicode code point escape
6682 : "\"\\u{110000}\"",
6683 : // Not a Unicode code point escape
6684 : "var foob\\v1234r = 0;", "var foob\\U1234r = 0;",
6685 5 : "var foob\\v{1234}r = 0;", "var foob\\U{1234}r = 0;", nullptr};
6686 5 : RunParserSyncTest(context_data, data, kError);
6687 5 : }
6688 :
6689 :
6690 26644 : TEST(UnicodeEscapes) {
6691 : const char* context_data[][2] = {
6692 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6693 : const char* data[] = {
6694 : // Identifier starting with escape
6695 : "var \\u0052oo = 0;", "var \\u{0052}oo = 0;", "var \\u{52}oo = 0;",
6696 : "var \\u{00000000052}oo = 0;",
6697 : // Identifier with an escape but not starting with an escape
6698 : "var foob\\uc481r = 0;", "var foob\\u{c481}r = 0;",
6699 : // String with an escape
6700 : "\"foob\\uc481r\"", "\"foob\\{uc481}r\"",
6701 : // This character is a valid Unicode character, representable as a
6702 : // surrogate pair, not representable as 4 hex digits.
6703 : "\"foo\\u{10e6d}\"",
6704 : // Max value for the Unicode code point escape
6705 5 : "\"\\u{10ffff}\"", nullptr};
6706 5 : RunParserSyncTest(context_data, data, kSuccess);
6707 5 : }
6708 :
6709 26644 : TEST(OctalEscapes) {
6710 : const char* sloppy_context_data[][2] = {{"", ""}, // as a directive
6711 : {"0;", ""}, // as a string literal
6712 5 : {nullptr, nullptr}};
6713 :
6714 : const char* strict_context_data[][2] = {
6715 : {"'use strict';", ""}, // as a directive before 'use strict'
6716 : {"", ";'use strict';"}, // as a directive after 'use strict'
6717 : {"'use strict'; 0;", ""}, // as a string literal
6718 5 : {nullptr, nullptr}};
6719 :
6720 : // clang-format off
6721 : const char* data[] = {
6722 : "'\\1'",
6723 : "'\\01'",
6724 : "'\\001'",
6725 : "'\\08'",
6726 : "'\\09'",
6727 5 : nullptr};
6728 : // clang-format on
6729 :
6730 : // Permitted in sloppy mode
6731 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6732 :
6733 : // Error in strict mode
6734 5 : RunParserSyncTest(strict_context_data, data, kError);
6735 5 : }
6736 :
6737 26644 : TEST(ScanTemplateLiterals) {
6738 : const char* context_data[][2] = {{"'use strict';", ""},
6739 : {"function foo(){ 'use strict';"
6740 : " var a, b, c; return ",
6741 : "}"},
6742 5 : {nullptr, nullptr}};
6743 :
6744 : const char* data[] = {"``",
6745 : "`no-subst-template`",
6746 : "`template-head${a}`",
6747 : "`${a}`",
6748 : "`${a}template-tail`",
6749 : "`template-head${a}template-tail`",
6750 : "`${a}${b}${c}`",
6751 : "`a${a}b${b}c${c}`",
6752 : "`${a}a${b}b${c}c`",
6753 : "`foo\n\nbar\r\nbaz`",
6754 : "`foo\n\n${ bar }\r\nbaz`",
6755 : "`foo${a /* comment */}`",
6756 : "`foo${a // comment\n}`",
6757 : "`foo${a \n}`",
6758 : "`foo${a \r\n}`",
6759 : "`foo${a \r}`",
6760 : "`foo${/* comment */ a}`",
6761 : "`foo${// comment\na}`",
6762 : "`foo${\n a}`",
6763 : "`foo${\r\n a}`",
6764 : "`foo${\r a}`",
6765 : "`foo${'a' in a}`",
6766 5 : nullptr};
6767 5 : RunParserSyncTest(context_data, data, kSuccess);
6768 5 : }
6769 :
6770 :
6771 26644 : TEST(ScanTaggedTemplateLiterals) {
6772 : const char* context_data[][2] = {{"'use strict';", ""},
6773 : {"function foo(){ 'use strict';"
6774 : " function tag() {}"
6775 : " var a, b, c; return ",
6776 : "}"},
6777 5 : {nullptr, nullptr}};
6778 :
6779 : const char* data[] = {"tag ``",
6780 : "tag `no-subst-template`",
6781 : "tag`template-head${a}`",
6782 : "tag `${a}`",
6783 : "tag `${a}template-tail`",
6784 : "tag `template-head${a}template-tail`",
6785 : "tag\n`${a}${b}${c}`",
6786 : "tag\r\n`a${a}b${b}c${c}`",
6787 : "tag `${a}a${b}b${c}c`",
6788 : "tag\t`foo\n\nbar\r\nbaz`",
6789 : "tag\r`foo\n\n${ bar }\r\nbaz`",
6790 : "tag`foo${a /* comment */}`",
6791 : "tag`foo${a // comment\n}`",
6792 : "tag`foo${a \n}`",
6793 : "tag`foo${a \r\n}`",
6794 : "tag`foo${a \r}`",
6795 : "tag`foo${/* comment */ a}`",
6796 : "tag`foo${// comment\na}`",
6797 : "tag`foo${\n a}`",
6798 : "tag`foo${\r\n a}`",
6799 : "tag`foo${\r a}`",
6800 : "tag`foo${'a' in a}`",
6801 5 : nullptr};
6802 5 : RunParserSyncTest(context_data, data, kSuccess);
6803 5 : }
6804 :
6805 :
6806 26644 : TEST(TemplateMaterializedLiterals) {
6807 : const char* context_data[][2] = {{"'use strict';\n"
6808 : "function tag() {}\n"
6809 : "var a, b, c;\n"
6810 : "(",
6811 : ")"},
6812 5 : {nullptr, nullptr}};
6813 :
6814 : const char* data[] = {"tag``", "tag`a`", "tag`a${1}b`", "tag`a${1}b${2}c`",
6815 : "``", "`a`", "`a${1}b`", "`a${1}b${2}c`",
6816 5 : nullptr};
6817 :
6818 5 : RunParserSyncTest(context_data, data, kSuccess);
6819 5 : }
6820 :
6821 :
6822 26644 : TEST(ScanUnterminatedTemplateLiterals) {
6823 : const char* context_data[][2] = {{"'use strict';", ""},
6824 : {"function foo(){ 'use strict';"
6825 : " var a, b, c; return ",
6826 : "}"},
6827 5 : {nullptr, nullptr}};
6828 :
6829 : const char* data[] = {"`no-subst-template",
6830 : "`template-head${a}",
6831 : "`${a}template-tail",
6832 : "`template-head${a}template-tail",
6833 : "`${a}${b}${c}",
6834 : "`a${a}b${b}c${c}",
6835 : "`${a}a${b}b${c}c",
6836 : "`foo\n\nbar\r\nbaz",
6837 : "`foo\n\n${ bar }\r\nbaz",
6838 : "`foo${a /* comment } */`",
6839 : "`foo${a /* comment } `*/",
6840 : "`foo${a // comment}`",
6841 : "`foo${a \n`",
6842 : "`foo${a \r\n`",
6843 : "`foo${a \r`",
6844 : "`foo${/* comment */ a`",
6845 : "`foo${// commenta}`",
6846 : "`foo${\n a`",
6847 : "`foo${\r\n a`",
6848 : "`foo${\r a`",
6849 : "`foo${fn(}`",
6850 : "`foo${1 if}`",
6851 5 : nullptr};
6852 5 : RunParserSyncTest(context_data, data, kError);
6853 5 : }
6854 :
6855 :
6856 26644 : TEST(TemplateLiteralsIllegalTokens) {
6857 : const char* context_data[][2] = {{"'use strict';", ""},
6858 : {"function foo(){ 'use strict';"
6859 : " var a, b, c; return ",
6860 : "}"},
6861 5 : {nullptr, nullptr}};
6862 : const char* data[] = {
6863 : "`hello\\x`", "`hello\\x${1}`", "`hello${1}\\x`",
6864 : "`hello${1}\\x${2}`", "`hello\\x\n`", "`hello\\x\n${1}`",
6865 5 : "`hello${1}\\x\n`", "`hello${1}\\x\n${2}`", nullptr};
6866 :
6867 5 : RunParserSyncTest(context_data, data, kError);
6868 5 : }
6869 :
6870 :
6871 26644 : TEST(ParseRestParameters) {
6872 : const char* context_data[][2] = {{"'use strict';(function(",
6873 : "){ return args;})(1, [], /regexp/, 'str',"
6874 : "function(){});"},
6875 : {"(function(",
6876 : "){ return args;})(1, [],"
6877 : "/regexp/, 'str', function(){});"},
6878 5 : {nullptr, nullptr}};
6879 :
6880 : const char* data[] = {"...args",
6881 : "a, ...args",
6882 : "... args",
6883 : "a, ... args",
6884 : "...\targs",
6885 : "a, ...\targs",
6886 : "...\r\nargs",
6887 : "a, ...\r\nargs",
6888 : "...\rargs",
6889 : "a, ...\rargs",
6890 : "...\t\n\t\t\n args",
6891 : "a, ... \n \n args",
6892 : "...{ length, 0: a, 1: b}",
6893 : "...{}",
6894 : "...[a, b]",
6895 : "...[]",
6896 : "...[...[a, b, ...c]]",
6897 5 : nullptr};
6898 5 : RunParserSyncTest(context_data, data, kSuccess);
6899 5 : }
6900 :
6901 :
6902 26644 : TEST(ParseRestParametersErrors) {
6903 : const char* context_data[][2] = {{"'use strict';(function(",
6904 : "){ return args;}(1, [], /regexp/, 'str',"
6905 : "function(){});"},
6906 : {"(function(",
6907 : "){ return args;}(1, [],"
6908 : "/regexp/, 'str', function(){});"},
6909 5 : {nullptr, nullptr}};
6910 :
6911 : const char* data[] = {"...args, b",
6912 : "a, ...args, b",
6913 : "...args, b",
6914 : "a, ...args, b",
6915 : "...args,\tb",
6916 : "a,...args\t,b",
6917 : "...args\r\n, b",
6918 : "a, ... args,\r\nb",
6919 : "...args\r,b",
6920 : "a, ... args,\rb",
6921 : "...args\t\n\t\t\n, b",
6922 : "a, ... args, \n \n b",
6923 : "a, a, ...args",
6924 : "a,\ta, ...args",
6925 : "a,\ra, ...args",
6926 : "a,\na, ...args",
6927 5 : nullptr};
6928 5 : RunParserSyncTest(context_data, data, kError);
6929 5 : }
6930 :
6931 :
6932 26644 : TEST(RestParameterInSetterMethodError) {
6933 : const char* context_data[][2] = {
6934 : {"'use strict';({ set prop(", ") {} }).prop = 1;"},
6935 : {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
6936 : {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
6937 : {"({ set prop(", ") {} }).prop = 1;"},
6938 : {"(class { static set prop(", ") {} }).prop = 1;"},
6939 : {"(new (class { set prop(", ") {} })).prop = 1;"},
6940 5 : {nullptr, nullptr}};
6941 5 : const char* data[] = {"...a", "...arguments", "...eval", nullptr};
6942 :
6943 5 : RunParserSyncTest(context_data, data, kError);
6944 5 : }
6945 :
6946 :
6947 26644 : TEST(RestParametersEvalArguments) {
6948 : // clang-format off
6949 : const char* strict_context_data[][2] =
6950 : {{"'use strict';(function(",
6951 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6952 5 : {nullptr, nullptr}};
6953 : const char* sloppy_context_data[][2] =
6954 : {{"(function(",
6955 : "){ return;})(1, [],/regexp/, 'str', function(){});"},
6956 5 : {nullptr, nullptr}};
6957 :
6958 : const char* data[] = {
6959 : "...eval",
6960 : "eval, ...args",
6961 : "...arguments",
6962 : // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
6963 : // "arguments, ...args",
6964 5 : nullptr};
6965 : // clang-format on
6966 :
6967 : // Fail in strict mode
6968 5 : RunParserSyncTest(strict_context_data, data, kError);
6969 :
6970 : // OK in sloppy mode
6971 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6972 5 : }
6973 :
6974 :
6975 26644 : TEST(RestParametersDuplicateEvalArguments) {
6976 : const char* context_data[][2] = {
6977 : {"'use strict';(function(",
6978 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6979 : {"(function(", "){ return;})(1, [],/regexp/, 'str', function(){});"},
6980 5 : {nullptr, nullptr}};
6981 :
6982 : const char* data[] = {"eval, ...eval", "eval, eval, ...args",
6983 : "arguments, ...arguments",
6984 5 : "arguments, arguments, ...args", nullptr};
6985 :
6986 : // In strict mode, the error is using "eval" or "arguments" as parameter names
6987 : // In sloppy mode, the error is that eval / arguments are duplicated
6988 5 : RunParserSyncTest(context_data, data, kError);
6989 5 : }
6990 :
6991 :
6992 26644 : TEST(SpreadCall) {
6993 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
6994 : {"function fn() {} fn(", ");"},
6995 5 : {nullptr, nullptr}};
6996 :
6997 : const char* data[] = {"...([1, 2, 3])",
6998 : "...'123', ...'456'",
6999 : "...new Set([1, 2, 3]), 4",
7000 : "1, ...[2, 3], 4",
7001 : "...Array(...[1,2,3,4])",
7002 : "...NaN",
7003 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
7004 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
7005 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
7006 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]",
7007 5 : nullptr};
7008 :
7009 5 : RunParserSyncTest(context_data, data, kSuccess);
7010 5 : }
7011 :
7012 :
7013 26644 : TEST(SpreadCallErrors) {
7014 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
7015 : {"function fn() {} fn(", ");"},
7016 5 : {nullptr, nullptr}};
7017 :
7018 5 : const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", nullptr};
7019 :
7020 5 : RunParserSyncTest(context_data, data, kError);
7021 5 : }
7022 :
7023 :
7024 26644 : TEST(BadRestSpread) {
7025 : const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
7026 : {"function fn() { ", "} fn();"},
7027 5 : {nullptr, nullptr}};
7028 : const char* data[] = {"return ...[1,2,3];",
7029 : "var ...x = [1,2,3];",
7030 : "var [...x,] = [1,2,3];",
7031 : "var [...x, y] = [1,2,3];",
7032 : "var { x } = {x: ...[1,2,3]}",
7033 5 : nullptr};
7034 5 : RunParserSyncTest(context_data, data, kError);
7035 5 : }
7036 :
7037 :
7038 26644 : TEST(LexicalScopingSloppyMode) {
7039 : const char* context_data[][2] = {
7040 5 : {"", ""}, {"function f() {", "}"}, {"{", "}"}, {nullptr, nullptr}};
7041 :
7042 5 : const char* good_data[] = {"let = 1;", "for(let = 1;;){}", nullptr};
7043 5 : RunParserSyncTest(context_data, good_data, kSuccess);
7044 5 : }
7045 :
7046 :
7047 26644 : TEST(ComputedPropertyName) {
7048 : const char* context_data[][2] = {{"({[", "]: 1});"},
7049 : {"({get [", "]() {}});"},
7050 : {"({set [", "](_) {}});"},
7051 : {"({[", "]() {}});"},
7052 : {"({*[", "]() {}});"},
7053 : {"(class {get [", "]() {}});"},
7054 : {"(class {set [", "](_) {}});"},
7055 : {"(class {[", "]() {}});"},
7056 : {"(class {*[", "]() {}});"},
7057 5 : {nullptr, nullptr}};
7058 5 : const char* error_data[] = {"1, 2", "var name", nullptr};
7059 :
7060 5 : RunParserSyncTest(context_data, error_data, kError);
7061 :
7062 : const char* name_data[] = {"1", "1 + 2", "'name'", "\"name\"",
7063 5 : "[]", "{}", nullptr};
7064 :
7065 5 : RunParserSyncTest(context_data, name_data, kSuccess);
7066 5 : }
7067 :
7068 :
7069 26644 : TEST(ComputedPropertyNameShorthandError) {
7070 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
7071 5 : const char* error_data[] = {"a: 1, [2]", "[1], a: 1", nullptr};
7072 :
7073 5 : RunParserSyncTest(context_data, error_data, kError);
7074 5 : }
7075 :
7076 :
7077 26644 : TEST(BasicImportExportParsing) {
7078 : // clang-format off
7079 : const char* kSources[] = {
7080 : "export let x = 0;",
7081 : "export var y = 0;",
7082 : "export const z = 0;",
7083 : "export function func() { };",
7084 : "export class C { };",
7085 : "export { };",
7086 : "function f() {}; f(); export { f };",
7087 : "var a, b, c; export { a, b as baz, c };",
7088 : "var d, e; export { d as dreary, e, };",
7089 : "export default function f() {}",
7090 : "export default function() {}",
7091 : "export default function*() {}",
7092 : "export default class C {}",
7093 : "export default class {}",
7094 : "export default class extends C {}",
7095 : "export default 42",
7096 : "var x; export default x = 7",
7097 : "export { Q } from 'somemodule.js';",
7098 : "export * from 'somemodule.js';",
7099 : "var foo; export { foo as for };",
7100 : "export { arguments } from 'm.js';",
7101 : "export { for } from 'm.js';",
7102 : "export { yield } from 'm.js'",
7103 : "export { static } from 'm.js'",
7104 : "export { let } from 'm.js'",
7105 : "var a; export { a as b, a as c };",
7106 : "var a; export { a as await };",
7107 : "var a; export { a as enum };",
7108 :
7109 : "import 'somemodule.js';",
7110 : "import { } from 'm.js';",
7111 : "import { a } from 'm.js';",
7112 : "import { a, b as d, c, } from 'm.js';",
7113 : "import * as thing from 'm.js';",
7114 : "import thing from 'm.js';",
7115 : "import thing, * as rest from 'm.js';",
7116 : "import thing, { a, b, c } from 'm.js';",
7117 : "import { arguments as a } from 'm.js';",
7118 : "import { for as f } from 'm.js';",
7119 : "import { yield as y } from 'm.js';",
7120 : "import { static as s } from 'm.js';",
7121 : "import { let as l } from 'm.js';",
7122 :
7123 : "import thing from 'a.js'; export {thing};",
7124 : "export {thing}; import thing from 'a.js';",
7125 : "import {thing} from 'a.js'; export {thing};",
7126 : "export {thing}; import {thing} from 'a.js';",
7127 : "import * as thing from 'a.js'; export {thing};",
7128 : "export {thing}; import * as thing from 'a.js';",
7129 5 : };
7130 : // clang-format on
7131 :
7132 : i::Isolate* isolate = CcTest::i_isolate();
7133 : i::Factory* factory = isolate->factory();
7134 :
7135 10 : v8::HandleScope handles(CcTest::isolate());
7136 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7137 : v8::Context::Scope context_scope(context);
7138 :
7139 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7140 5 : 128 * 1024);
7141 :
7142 475 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7143 : i::Handle<i::String> source =
7144 235 : factory->NewStringFromAsciiChecked(kSources[i]);
7145 :
7146 : // Show that parsing as a module works
7147 : {
7148 235 : i::Handle<i::Script> script = factory->NewScript(source);
7149 470 : i::ParseInfo info(isolate, script);
7150 : info.set_module();
7151 235 : if (!i::parsing::ParseProgram(&info, isolate)) {
7152 : i::Handle<i::JSObject> exception_handle(
7153 : i::JSObject::cast(isolate->pending_exception()), isolate);
7154 : i::Handle<i::String> message_string = i::Handle<i::String>::cast(
7155 0 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
7156 : .ToHandleChecked());
7157 : isolate->clear_pending_exception();
7158 :
7159 0 : FATAL(
7160 : "Parser failed on:\n"
7161 : "\t%s\n"
7162 : "with error:\n"
7163 : "\t%s\n"
7164 : "However, we expected no error.",
7165 0 : source->ToCString().get(), message_string->ToCString().get());
7166 : }
7167 : }
7168 :
7169 : // And that parsing a script does not.
7170 : {
7171 235 : i::Handle<i::Script> script = factory->NewScript(source);
7172 470 : i::ParseInfo info(isolate, script);
7173 235 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7174 : isolate->clear_pending_exception();
7175 : }
7176 : }
7177 5 : }
7178 :
7179 26644 : TEST(NamespaceExportParsing) {
7180 : // clang-format off
7181 : const char* kSources[] = {
7182 : "export * as arguments from 'bar'",
7183 : "export * as await from 'bar'",
7184 : "export * as default from 'bar'",
7185 : "export * as enum from 'bar'",
7186 : "export * as foo from 'bar'",
7187 : "export * as for from 'bar'",
7188 : "export * as let from 'bar'",
7189 : "export * as static from 'bar'",
7190 : "export * as yield from 'bar'",
7191 5 : };
7192 : // clang-format on
7193 :
7194 5 : i::FLAG_harmony_namespace_exports = true;
7195 : i::Isolate* isolate = CcTest::i_isolate();
7196 : i::Factory* factory = isolate->factory();
7197 :
7198 10 : v8::HandleScope handles(CcTest::isolate());
7199 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7200 : v8::Context::Scope context_scope(context);
7201 :
7202 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7203 5 : 128 * 1024);
7204 :
7205 95 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7206 : i::Handle<i::String> source =
7207 45 : factory->NewStringFromAsciiChecked(kSources[i]);
7208 45 : i::Handle<i::Script> script = factory->NewScript(source);
7209 90 : i::ParseInfo info(isolate, script);
7210 : info.set_module();
7211 45 : CHECK(i::parsing::ParseProgram(&info, isolate));
7212 : }
7213 5 : }
7214 :
7215 26644 : TEST(ImportExportParsingErrors) {
7216 : // clang-format off
7217 : const char* kErrorSources[] = {
7218 : "export {",
7219 : "var a; export { a",
7220 : "var a; export { a,",
7221 : "var a; export { a, ;",
7222 : "var a; export { a as };",
7223 : "var a, b; export { a as , b};",
7224 : "export }",
7225 : "var foo, bar; export { foo bar };",
7226 : "export { foo };",
7227 : "export { , };",
7228 : "export default;",
7229 : "export default var x = 7;",
7230 : "export default let x = 7;",
7231 : "export default const x = 7;",
7232 : "export *;",
7233 : "export * from;",
7234 : "export { Q } from;",
7235 : "export default from 'module.js';",
7236 : "export { for }",
7237 : "export { for as foo }",
7238 : "export { arguments }",
7239 : "export { arguments as foo }",
7240 : "var a; export { a, a };",
7241 : "var a, b; export { a as b, b };",
7242 : "var a, b; export { a as c, b as c };",
7243 : "export default function f(){}; export default class C {};",
7244 : "export default function f(){}; var a; export { a as default };",
7245 : "export function() {}",
7246 : "export function*() {}",
7247 : "export class {}",
7248 : "export class extends C {}",
7249 :
7250 : "import from;",
7251 : "import from 'm.js';",
7252 : "import { };",
7253 : "import {;",
7254 : "import };",
7255 : "import { , };",
7256 : "import { , } from 'm.js';",
7257 : "import { a } from;",
7258 : "import { a } 'm.js';",
7259 : "import , from 'm.js';",
7260 : "import a , from 'm.js';",
7261 : "import a { b, c } from 'm.js';",
7262 : "import arguments from 'm.js';",
7263 : "import eval from 'm.js';",
7264 : "import { arguments } from 'm.js';",
7265 : "import { eval } from 'm.js';",
7266 : "import { a as arguments } from 'm.js';",
7267 : "import { for } from 'm.js';",
7268 : "import { y as yield } from 'm.js'",
7269 : "import { s as static } from 'm.js'",
7270 : "import { l as let } from 'm.js'",
7271 : "import { a as await } from 'm.js';",
7272 : "import { a as enum } from 'm.js';",
7273 : "import { x }, def from 'm.js';",
7274 : "import def, def2 from 'm.js';",
7275 : "import * as x, def from 'm.js';",
7276 : "import * as x, * as y from 'm.js';",
7277 : "import {x}, {y} from 'm.js';",
7278 : "import * as x, {y} from 'm.js';",
7279 :
7280 : "export *;",
7281 : "export * as;",
7282 : "export * as foo;",
7283 : "export * as foo from;",
7284 : "export * as foo from ';",
7285 : "export * as ,foo from 'bar'",
7286 5 : };
7287 : // clang-format on
7288 :
7289 : i::Isolate* isolate = CcTest::i_isolate();
7290 : i::Factory* factory = isolate->factory();
7291 :
7292 10 : v8::HandleScope handles(CcTest::isolate());
7293 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7294 : v8::Context::Scope context_scope(context);
7295 :
7296 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7297 5 : 128 * 1024);
7298 :
7299 665 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7300 : i::Handle<i::String> source =
7301 330 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7302 :
7303 330 : i::Handle<i::Script> script = factory->NewScript(source);
7304 660 : i::ParseInfo info(isolate, script);
7305 : info.set_module();
7306 330 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7307 : isolate->clear_pending_exception();
7308 : }
7309 5 : }
7310 :
7311 26644 : TEST(ModuleTopLevelFunctionDecl) {
7312 : // clang-format off
7313 : const char* kErrorSources[] = {
7314 : "function f() {} function f() {}",
7315 : "var f; function f() {}",
7316 : "function f() {} var f;",
7317 : "function* f() {} function* f() {}",
7318 : "var f; function* f() {}",
7319 : "function* f() {} var f;",
7320 : "function f() {} function* f() {}",
7321 : "function* f() {} function f() {}",
7322 5 : };
7323 : // clang-format on
7324 :
7325 : i::Isolate* isolate = CcTest::i_isolate();
7326 : i::Factory* factory = isolate->factory();
7327 :
7328 10 : v8::HandleScope handles(CcTest::isolate());
7329 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7330 : v8::Context::Scope context_scope(context);
7331 :
7332 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7333 5 : 128 * 1024);
7334 :
7335 85 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7336 : i::Handle<i::String> source =
7337 40 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7338 :
7339 40 : i::Handle<i::Script> script = factory->NewScript(source);
7340 80 : i::ParseInfo info(isolate, script);
7341 : info.set_module();
7342 40 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7343 : isolate->clear_pending_exception();
7344 : }
7345 5 : }
7346 :
7347 26644 : TEST(ModuleAwaitReserved) {
7348 : // clang-format off
7349 : const char* kErrorSources[] = {
7350 : "await;",
7351 : "await: ;",
7352 : "var await;",
7353 : "var [await] = [];",
7354 : "var { await } = {};",
7355 : "var { x: await } = {};",
7356 : "{ var await; }",
7357 : "let await;",
7358 : "let [await] = [];",
7359 : "let { await } = {};",
7360 : "let { x: await } = {};",
7361 : "{ let await; }",
7362 : "const await = null;",
7363 : "const [await] = [];",
7364 : "const { await } = {};",
7365 : "const { x: await } = {};",
7366 : "{ const await = null; }",
7367 : "function await() {}",
7368 : "function f(await) {}",
7369 : "function* await() {}",
7370 : "function* g(await) {}",
7371 : "(function await() {});",
7372 : "(function (await) {});",
7373 : "(function* await() {});",
7374 : "(function* (await) {});",
7375 : "(await) => {};",
7376 : "await => {};",
7377 : "class await {}",
7378 : "class C { constructor(await) {} }",
7379 : "class C { m(await) {} }",
7380 : "class C { static m(await) {} }",
7381 : "class C { *m(await) {} }",
7382 : "class C { static *m(await) {} }",
7383 : "(class await {})",
7384 : "(class { constructor(await) {} });",
7385 : "(class { m(await) {} });",
7386 : "(class { static m(await) {} });",
7387 : "(class { *m(await) {} });",
7388 : "(class { static *m(await) {} });",
7389 : "({ m(await) {} });",
7390 : "({ *m(await) {} });",
7391 : "({ set p(await) {} });",
7392 : "try {} catch (await) {}",
7393 : "try {} catch (await) {} finally {}",
7394 : nullptr
7395 5 : };
7396 : // clang-format on
7397 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7398 :
7399 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7400 5 : }
7401 :
7402 26644 : TEST(ModuleAwaitReservedPreParse) {
7403 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7404 5 : const char* error_data[] = {"function f() { var await = 0; }", nullptr};
7405 :
7406 : RunModuleParserSyncTest(context_data, error_data, kError);
7407 5 : }
7408 :
7409 26644 : TEST(ModuleAwaitPermitted) {
7410 : // clang-format off
7411 : const char* kValidSources[] = {
7412 : "({}).await;",
7413 : "({ await: null });",
7414 : "({ await() {} });",
7415 : "({ get await() {} });",
7416 : "({ set await(x) {} });",
7417 : "(class { await() {} });",
7418 : "(class { static await() {} });",
7419 : "(class { *await() {} });",
7420 : "(class { static *await() {} });",
7421 : nullptr
7422 5 : };
7423 : // clang-format on
7424 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7425 :
7426 : RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
7427 5 : }
7428 :
7429 26644 : TEST(EnumReserved) {
7430 : // clang-format off
7431 : const char* kErrorSources[] = {
7432 : "enum;",
7433 : "enum: ;",
7434 : "var enum;",
7435 : "var [enum] = [];",
7436 : "var { enum } = {};",
7437 : "var { x: enum } = {};",
7438 : "{ var enum; }",
7439 : "let enum;",
7440 : "let [enum] = [];",
7441 : "let { enum } = {};",
7442 : "let { x: enum } = {};",
7443 : "{ let enum; }",
7444 : "const enum = null;",
7445 : "const [enum] = [];",
7446 : "const { enum } = {};",
7447 : "const { x: enum } = {};",
7448 : "{ const enum = null; }",
7449 : "function enum() {}",
7450 : "function f(enum) {}",
7451 : "function* enum() {}",
7452 : "function* g(enum) {}",
7453 : "(function enum() {});",
7454 : "(function (enum) {});",
7455 : "(function* enum() {});",
7456 : "(function* (enum) {});",
7457 : "(enum) => {};",
7458 : "enum => {};",
7459 : "class enum {}",
7460 : "class C { constructor(enum) {} }",
7461 : "class C { m(enum) {} }",
7462 : "class C { static m(enum) {} }",
7463 : "class C { *m(enum) {} }",
7464 : "class C { static *m(enum) {} }",
7465 : "(class enum {})",
7466 : "(class { constructor(enum) {} });",
7467 : "(class { m(enum) {} });",
7468 : "(class { static m(enum) {} });",
7469 : "(class { *m(enum) {} });",
7470 : "(class { static *m(enum) {} });",
7471 : "({ m(enum) {} });",
7472 : "({ *m(enum) {} });",
7473 : "({ set p(enum) {} });",
7474 : "try {} catch (enum) {}",
7475 : "try {} catch (enum) {} finally {}",
7476 : nullptr
7477 5 : };
7478 : // clang-format on
7479 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7480 :
7481 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7482 5 : }
7483 :
7484 85 : static void CheckEntry(const i::ModuleDescriptor::Entry* entry,
7485 : const char* export_name, const char* local_name,
7486 : const char* import_name, int module_request) {
7487 85 : CHECK_NOT_NULL(entry);
7488 85 : if (export_name == nullptr) {
7489 35 : CHECK_NULL(entry->export_name);
7490 : } else {
7491 50 : CHECK(entry->export_name->IsOneByteEqualTo(export_name));
7492 : }
7493 85 : if (local_name == nullptr) {
7494 15 : CHECK_NULL(entry->local_name);
7495 : } else {
7496 70 : CHECK(entry->local_name->IsOneByteEqualTo(local_name));
7497 : }
7498 85 : if (import_name == nullptr) {
7499 55 : CHECK_NULL(entry->import_name);
7500 : } else {
7501 30 : CHECK(entry->import_name->IsOneByteEqualTo(import_name));
7502 : }
7503 85 : CHECK_EQ(entry->module_request, module_request);
7504 85 : }
7505 :
7506 26644 : TEST(ModuleParsingInternals) {
7507 : i::Isolate* isolate = CcTest::i_isolate();
7508 : i::Factory* factory = isolate->factory();
7509 10 : v8::HandleScope handles(CcTest::isolate());
7510 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7511 : v8::Context::Scope context_scope(context);
7512 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7513 5 : 128 * 1024);
7514 :
7515 : static const char kSource[] =
7516 : "let x = 5;"
7517 : "export { x as y };"
7518 : "import { q as z } from 'm.js';"
7519 : "import n from 'n.js';"
7520 : "export { a as b } from 'm.js';"
7521 : "export * from 'p.js';"
7522 : "export var foo;"
7523 : "export function goo() {};"
7524 : "export let hoo;"
7525 : "export const joo = 42;"
7526 : "export default (function koo() {});"
7527 : "import 'q.js';"
7528 : "let nonexport = 42;"
7529 : "import {m as mm} from 'm.js';"
7530 : "import {aa} from 'm.js';"
7531 : "export {aa as bb, x};"
7532 : "import * as loo from 'bar.js';"
7533 : "import * as foob from 'bar.js';"
7534 : "export {foob};";
7535 5 : i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
7536 5 : i::Handle<i::Script> script = factory->NewScript(source);
7537 10 : i::ParseInfo info(isolate, script);
7538 : info.set_module();
7539 5 : CHECK(i::parsing::ParseProgram(&info, isolate));
7540 5 : CHECK(i::Compiler::Analyze(&info));
7541 : i::FunctionLiteral* func = info.literal();
7542 5 : i::ModuleScope* module_scope = func->scope()->AsModuleScope();
7543 : i::Scope* outer_scope = module_scope->outer_scope();
7544 5 : CHECK(outer_scope->is_script_scope());
7545 5 : CHECK_NULL(outer_scope->outer_scope());
7546 5 : CHECK(module_scope->is_module_scope());
7547 : const i::ModuleDescriptor::Entry* entry;
7548 : i::Declaration::List* declarations = module_scope->declarations();
7549 5 : CHECK_EQ(13, declarations->LengthForTest());
7550 :
7551 5 : CHECK(declarations->AtForTest(0)->var()->raw_name()->IsOneByteEqualTo("x"));
7552 5 : CHECK(declarations->AtForTest(0)->var()->mode() == i::VariableMode::kLet);
7553 5 : CHECK(declarations->AtForTest(0)->var()->binding_needs_init());
7554 5 : CHECK(declarations->AtForTest(0)->var()->location() ==
7555 : i::VariableLocation::MODULE);
7556 :
7557 5 : CHECK(declarations->AtForTest(1)->var()->raw_name()->IsOneByteEqualTo("z"));
7558 5 : CHECK(declarations->AtForTest(1)->var()->mode() == i::VariableMode::kConst);
7559 5 : CHECK(declarations->AtForTest(1)->var()->binding_needs_init());
7560 5 : CHECK(declarations->AtForTest(1)->var()->location() ==
7561 : i::VariableLocation::MODULE);
7562 :
7563 5 : CHECK(declarations->AtForTest(2)->var()->raw_name()->IsOneByteEqualTo("n"));
7564 5 : CHECK(declarations->AtForTest(2)->var()->mode() == i::VariableMode::kConst);
7565 5 : CHECK(declarations->AtForTest(2)->var()->binding_needs_init());
7566 5 : CHECK(declarations->AtForTest(2)->var()->location() ==
7567 : i::VariableLocation::MODULE);
7568 :
7569 5 : CHECK(declarations->AtForTest(3)->var()->raw_name()->IsOneByteEqualTo("foo"));
7570 5 : CHECK(declarations->AtForTest(3)->var()->mode() == i::VariableMode::kVar);
7571 5 : CHECK(!declarations->AtForTest(3)->var()->binding_needs_init());
7572 5 : CHECK(declarations->AtForTest(3)->var()->location() ==
7573 : i::VariableLocation::MODULE);
7574 :
7575 5 : CHECK(declarations->AtForTest(4)->var()->raw_name()->IsOneByteEqualTo("goo"));
7576 5 : CHECK(declarations->AtForTest(4)->var()->mode() == i::VariableMode::kLet);
7577 5 : CHECK(!declarations->AtForTest(4)->var()->binding_needs_init());
7578 5 : CHECK(declarations->AtForTest(4)->var()->location() ==
7579 : i::VariableLocation::MODULE);
7580 :
7581 5 : CHECK(declarations->AtForTest(5)->var()->raw_name()->IsOneByteEqualTo("hoo"));
7582 5 : CHECK(declarations->AtForTest(5)->var()->mode() == i::VariableMode::kLet);
7583 5 : CHECK(declarations->AtForTest(5)->var()->binding_needs_init());
7584 5 : CHECK(declarations->AtForTest(5)->var()->location() ==
7585 : i::VariableLocation::MODULE);
7586 :
7587 5 : CHECK(declarations->AtForTest(6)->var()->raw_name()->IsOneByteEqualTo("joo"));
7588 5 : CHECK(declarations->AtForTest(6)->var()->mode() == i::VariableMode::kConst);
7589 5 : CHECK(declarations->AtForTest(6)->var()->binding_needs_init());
7590 5 : CHECK(declarations->AtForTest(6)->var()->location() ==
7591 : i::VariableLocation::MODULE);
7592 :
7593 5 : CHECK(declarations->AtForTest(7)->var()->raw_name()->IsOneByteEqualTo(
7594 : ".default"));
7595 5 : CHECK(declarations->AtForTest(7)->var()->mode() == i::VariableMode::kConst);
7596 5 : CHECK(declarations->AtForTest(7)->var()->binding_needs_init());
7597 5 : CHECK(declarations->AtForTest(7)->var()->location() ==
7598 : i::VariableLocation::MODULE);
7599 :
7600 5 : CHECK(declarations->AtForTest(8)->var()->raw_name()->IsOneByteEqualTo(
7601 : "nonexport"));
7602 5 : CHECK(!declarations->AtForTest(8)->var()->binding_needs_init());
7603 5 : CHECK(declarations->AtForTest(8)->var()->location() ==
7604 : i::VariableLocation::LOCAL);
7605 :
7606 5 : CHECK(declarations->AtForTest(9)->var()->raw_name()->IsOneByteEqualTo("mm"));
7607 5 : CHECK(declarations->AtForTest(9)->var()->mode() == i::VariableMode::kConst);
7608 5 : CHECK(declarations->AtForTest(9)->var()->binding_needs_init());
7609 5 : CHECK(declarations->AtForTest(9)->var()->location() ==
7610 : i::VariableLocation::MODULE);
7611 :
7612 5 : CHECK(declarations->AtForTest(10)->var()->raw_name()->IsOneByteEqualTo("aa"));
7613 5 : CHECK(declarations->AtForTest(10)->var()->mode() == i::VariableMode::kConst);
7614 5 : CHECK(declarations->AtForTest(10)->var()->binding_needs_init());
7615 5 : CHECK(declarations->AtForTest(10)->var()->location() ==
7616 : i::VariableLocation::MODULE);
7617 :
7618 5 : CHECK(
7619 : declarations->AtForTest(11)->var()->raw_name()->IsOneByteEqualTo("loo"));
7620 5 : CHECK(declarations->AtForTest(11)->var()->mode() == i::VariableMode::kConst);
7621 5 : CHECK(!declarations->AtForTest(11)->var()->binding_needs_init());
7622 5 : CHECK(declarations->AtForTest(11)->var()->location() !=
7623 : i::VariableLocation::MODULE);
7624 :
7625 5 : CHECK(
7626 : declarations->AtForTest(12)->var()->raw_name()->IsOneByteEqualTo("foob"));
7627 5 : CHECK(declarations->AtForTest(12)->var()->mode() == i::VariableMode::kConst);
7628 5 : CHECK(!declarations->AtForTest(12)->var()->binding_needs_init());
7629 5 : CHECK(declarations->AtForTest(12)->var()->location() ==
7630 : i::VariableLocation::MODULE);
7631 :
7632 : i::ModuleDescriptor* descriptor = module_scope->module();
7633 5 : CHECK_NOT_NULL(descriptor);
7634 :
7635 5 : CHECK_EQ(5u, descriptor->module_requests().size());
7636 30 : for (const auto& elem : descriptor->module_requests()) {
7637 25 : if (elem.first->IsOneByteEqualTo("m.js")) {
7638 5 : CHECK_EQ(0, elem.second.index);
7639 5 : CHECK_EQ(51, elem.second.position);
7640 20 : } else if (elem.first->IsOneByteEqualTo("n.js")) {
7641 5 : CHECK_EQ(1, elem.second.index);
7642 5 : CHECK_EQ(72, elem.second.position);
7643 15 : } else if (elem.first->IsOneByteEqualTo("p.js")) {
7644 5 : CHECK_EQ(2, elem.second.index);
7645 5 : CHECK_EQ(123, elem.second.position);
7646 10 : } else if (elem.first->IsOneByteEqualTo("q.js")) {
7647 5 : CHECK_EQ(3, elem.second.index);
7648 5 : CHECK_EQ(249, elem.second.position);
7649 5 : } else if (elem.first->IsOneByteEqualTo("bar.js")) {
7650 5 : CHECK_EQ(4, elem.second.index);
7651 5 : CHECK_EQ(370, elem.second.position);
7652 : } else {
7653 0 : UNREACHABLE();
7654 : }
7655 : }
7656 :
7657 5 : CHECK_EQ(3, descriptor->special_exports().size());
7658 5 : CheckEntry(descriptor->special_exports().at(0), "b", nullptr, "a", 0);
7659 5 : CheckEntry(descriptor->special_exports().at(1), nullptr, nullptr, nullptr, 2);
7660 5 : CheckEntry(descriptor->special_exports().at(2), "bb", nullptr, "aa",
7661 5 : 0); // !!!
7662 :
7663 5 : CHECK_EQ(8u, descriptor->regular_exports().size());
7664 : entry = descriptor->regular_exports()
7665 10 : .find(declarations->AtForTest(3)->var()->raw_name())
7666 5 : ->second;
7667 5 : CheckEntry(entry, "foo", "foo", nullptr, -1);
7668 : entry = descriptor->regular_exports()
7669 10 : .find(declarations->AtForTest(4)->var()->raw_name())
7670 5 : ->second;
7671 5 : CheckEntry(entry, "goo", "goo", nullptr, -1);
7672 : entry = descriptor->regular_exports()
7673 10 : .find(declarations->AtForTest(5)->var()->raw_name())
7674 5 : ->second;
7675 5 : CheckEntry(entry, "hoo", "hoo", nullptr, -1);
7676 : entry = descriptor->regular_exports()
7677 10 : .find(declarations->AtForTest(6)->var()->raw_name())
7678 5 : ->second;
7679 5 : CheckEntry(entry, "joo", "joo", nullptr, -1);
7680 : entry = descriptor->regular_exports()
7681 10 : .find(declarations->AtForTest(7)->var()->raw_name())
7682 5 : ->second;
7683 5 : CheckEntry(entry, "default", ".default", nullptr, -1);
7684 : entry = descriptor->regular_exports()
7685 10 : .find(declarations->AtForTest(12)->var()->raw_name())
7686 5 : ->second;
7687 5 : CheckEntry(entry, "foob", "foob", nullptr, -1);
7688 : // TODO(neis): The next lines are terrible. Find a better way.
7689 5 : auto name_x = declarations->AtForTest(0)->var()->raw_name();
7690 5 : CHECK_EQ(2u, descriptor->regular_exports().count(name_x));
7691 : auto it = descriptor->regular_exports().equal_range(name_x).first;
7692 5 : entry = it->second;
7693 5 : if (entry->export_name->IsOneByteEqualTo("y")) {
7694 5 : CheckEntry(entry, "y", "x", nullptr, -1);
7695 5 : entry = (++it)->second;
7696 5 : CheckEntry(entry, "x", "x", nullptr, -1);
7697 : } else {
7698 0 : CheckEntry(entry, "x", "x", nullptr, -1);
7699 0 : entry = (++it)->second;
7700 0 : CheckEntry(entry, "y", "x", nullptr, -1);
7701 : }
7702 :
7703 5 : CHECK_EQ(2, descriptor->namespace_imports().size());
7704 5 : CheckEntry(descriptor->namespace_imports().at(0), nullptr, "loo", nullptr, 4);
7705 5 : CheckEntry(descriptor->namespace_imports().at(1), nullptr, "foob", nullptr,
7706 5 : 4);
7707 :
7708 5 : CHECK_EQ(4u, descriptor->regular_imports().size());
7709 : entry = descriptor->regular_imports()
7710 10 : .find(declarations->AtForTest(1)->var()->raw_name())
7711 5 : ->second;
7712 5 : CheckEntry(entry, nullptr, "z", "q", 0);
7713 : entry = descriptor->regular_imports()
7714 10 : .find(declarations->AtForTest(2)->var()->raw_name())
7715 5 : ->second;
7716 5 : CheckEntry(entry, nullptr, "n", "default", 1);
7717 : entry = descriptor->regular_imports()
7718 10 : .find(declarations->AtForTest(9)->var()->raw_name())
7719 5 : ->second;
7720 5 : CheckEntry(entry, nullptr, "mm", "m", 0);
7721 : entry = descriptor->regular_imports()
7722 10 : .find(declarations->AtForTest(10)->var()->raw_name())
7723 5 : ->second;
7724 5 : CheckEntry(entry, nullptr, "aa", "aa", 0);
7725 5 : }
7726 :
7727 :
7728 26644 : TEST(DuplicateProtoError) {
7729 : const char* context_data[][2] = {
7730 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7731 : const char* error_data[] = {"__proto__: {}, __proto__: {}",
7732 : "__proto__: {}, \"__proto__\": {}",
7733 : "__proto__: {}, \"__\x70roto__\": {}",
7734 5 : "__proto__: {}, a: 1, __proto__: {}", nullptr};
7735 :
7736 5 : RunParserSyncTest(context_data, error_data, kError);
7737 5 : }
7738 :
7739 :
7740 26644 : TEST(DuplicateProtoNoError) {
7741 : const char* context_data[][2] = {
7742 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7743 : const char* error_data[] = {
7744 : "__proto__: {}, ['__proto__']: {}", "__proto__: {}, __proto__() {}",
7745 : "__proto__: {}, get __proto__() {}", "__proto__: {}, set __proto__(v) {}",
7746 5 : "__proto__: {}, __proto__", nullptr};
7747 :
7748 5 : RunParserSyncTest(context_data, error_data, kSuccess);
7749 5 : }
7750 :
7751 :
7752 26644 : TEST(DeclarationsError) {
7753 : const char* context_data[][2] = {{"'use strict'; if (true)", ""},
7754 : {"'use strict'; if (false) {} else", ""},
7755 : {"'use strict'; while (false)", ""},
7756 : {"'use strict'; for (;;)", ""},
7757 : {"'use strict'; for (x in y)", ""},
7758 : {"'use strict'; do ", " while (false)"},
7759 5 : {nullptr, nullptr}};
7760 :
7761 : const char* statement_data[] = {"let x = 1;", "const x = 1;", "class C {}",
7762 5 : nullptr};
7763 :
7764 5 : RunParserSyncTest(context_data, statement_data, kError);
7765 5 : }
7766 :
7767 :
7768 20 : void TestLanguageMode(const char* source,
7769 : i::LanguageMode expected_language_mode) {
7770 : i::Isolate* isolate = CcTest::i_isolate();
7771 : i::Factory* factory = isolate->factory();
7772 40 : v8::HandleScope handles(CcTest::isolate());
7773 20 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7774 : v8::Context::Scope context_scope(context);
7775 20 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7776 20 : 128 * 1024);
7777 :
7778 : i::Handle<i::Script> script =
7779 20 : factory->NewScript(factory->NewStringFromAsciiChecked(source));
7780 40 : i::ParseInfo info(isolate, script);
7781 20 : i::parsing::ParseProgram(&info, isolate);
7782 20 : CHECK_NOT_NULL(info.literal());
7783 20 : CHECK_EQ(expected_language_mode, info.literal()->language_mode());
7784 20 : }
7785 :
7786 :
7787 26644 : TEST(LanguageModeDirectives) {
7788 5 : TestLanguageMode("\"use nothing\"", i::LanguageMode::kSloppy);
7789 5 : TestLanguageMode("\"use strict\"", i::LanguageMode::kStrict);
7790 :
7791 5 : TestLanguageMode("var x = 1; \"use strict\"", i::LanguageMode::kSloppy);
7792 :
7793 : TestLanguageMode("\"use some future directive\"; \"use strict\";",
7794 5 : i::LanguageMode::kStrict);
7795 5 : }
7796 :
7797 :
7798 26644 : TEST(PropertyNameEvalArguments) {
7799 5 : const char* context_data[][2] = {{"'use strict';", ""}, {nullptr, nullptr}};
7800 :
7801 : const char* statement_data[] = {"({eval: 1})",
7802 : "({arguments: 1})",
7803 : "({eval() {}})",
7804 : "({arguments() {}})",
7805 : "({*eval() {}})",
7806 : "({*arguments() {}})",
7807 : "({get eval() {}})",
7808 : "({get arguments() {}})",
7809 : "({set eval(_) {}})",
7810 : "({set arguments(_) {}})",
7811 :
7812 : "class C {eval() {}}",
7813 : "class C {arguments() {}}",
7814 : "class C {*eval() {}}",
7815 : "class C {*arguments() {}}",
7816 : "class C {get eval() {}}",
7817 : "class C {get arguments() {}}",
7818 : "class C {set eval(_) {}}",
7819 : "class C {set arguments(_) {}}",
7820 :
7821 : "class C {static eval() {}}",
7822 : "class C {static arguments() {}}",
7823 : "class C {static *eval() {}}",
7824 : "class C {static *arguments() {}}",
7825 : "class C {static get eval() {}}",
7826 : "class C {static get arguments() {}}",
7827 : "class C {static set eval(_) {}}",
7828 : "class C {static set arguments(_) {}}",
7829 :
7830 5 : nullptr};
7831 :
7832 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
7833 5 : }
7834 :
7835 :
7836 26644 : TEST(FunctionLiteralDuplicateParameters) {
7837 : const char* strict_context_data[][2] = {
7838 : {"'use strict';(function(", "){})();"},
7839 : {"(function(", ") { 'use strict'; })();"},
7840 : {"'use strict'; function fn(", ") {}; fn();"},
7841 : {"function fn(", ") { 'use strict'; }; fn();"},
7842 5 : {nullptr, nullptr}};
7843 :
7844 : const char* sloppy_context_data[][2] = {{"(function(", "){})();"},
7845 : {"(function(", ") {})();"},
7846 : {"function fn(", ") {}; fn();"},
7847 : {"function fn(", ") {}; fn();"},
7848 5 : {nullptr, nullptr}};
7849 :
7850 : const char* data[] = {
7851 : "a, a",
7852 : "a, a, a",
7853 : "b, a, a",
7854 : "a, b, c, c",
7855 : "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
7856 5 : nullptr};
7857 :
7858 5 : RunParserSyncTest(strict_context_data, data, kError);
7859 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
7860 5 : }
7861 :
7862 :
7863 26644 : TEST(ArrowFunctionASIErrors) {
7864 : const char* context_data[][2] = {
7865 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
7866 :
7867 : const char* data[] = {"(a\n=> a)(1)",
7868 : "(a/*\n*/=> a)(1)",
7869 : "((a)\n=> a)(1)",
7870 : "((a)/*\n*/=> a)(1)",
7871 : "((a, b)\n=> a + b)(1, 2)",
7872 : "((a, b)/*\n*/=> a + b)(1, 2)",
7873 5 : nullptr};
7874 5 : RunParserSyncTest(context_data, data, kError);
7875 5 : }
7876 :
7877 26644 : TEST(ObjectSpreadPositiveTests) {
7878 : // clang-format off
7879 : const char* context_data[][2] = {
7880 : {"x = ", ""},
7881 : {"'use strict'; x = ", ""},
7882 5 : {nullptr, nullptr}};
7883 :
7884 : // clang-format off
7885 : const char* data[] = {
7886 : "{ ...y }",
7887 : "{ a: 1, ...y }",
7888 : "{ b: 1, ...y }",
7889 : "{ y, ...y}",
7890 : "{ ...z = y}",
7891 : "{ ...y, y }",
7892 : "{ ...y, ...y}",
7893 : "{ a: 1, ...y, b: 1}",
7894 : "{ ...y, b: 1}",
7895 : "{ ...1}",
7896 : "{ ...null}",
7897 : "{ ...undefined}",
7898 : "{ ...1 in {}}",
7899 : "{ ...[]}",
7900 : "{ ...async function() { }}",
7901 : "{ ...async () => { }}",
7902 : "{ ...new Foo()}",
7903 5 : nullptr};
7904 : // clang-format on
7905 :
7906 5 : RunParserSyncTest(context_data, data, kSuccess);
7907 5 : }
7908 :
7909 26644 : TEST(ObjectSpreadNegativeTests) {
7910 : const char* context_data[][2] = {
7911 5 : {"x = ", ""}, {"'use strict'; x = ", ""}, {nullptr, nullptr}};
7912 :
7913 : // clang-format off
7914 : const char* data[] = {
7915 : "{ ...var z = y}",
7916 : "{ ...var}",
7917 : "{ ...foo bar}",
7918 : "{* ...foo}",
7919 : "{get ...foo}",
7920 : "{set ...foo}",
7921 : "{async ...foo}",
7922 5 : nullptr};
7923 :
7924 5 : RunParserSyncTest(context_data, data, kError);
7925 5 : }
7926 :
7927 26644 : TEST(TemplateEscapesPositiveTests) {
7928 : // clang-format off
7929 : const char* context_data[][2] = {
7930 : {"", ""},
7931 : {"'use strict';", ""},
7932 5 : {nullptr, nullptr}};
7933 :
7934 : // clang-format off
7935 : const char* data[] = {
7936 : "tag`\\08`",
7937 : "tag`\\01`",
7938 : "tag`\\01${0}right`",
7939 : "tag`left${0}\\01`",
7940 : "tag`left${0}\\01${1}right`",
7941 : "tag`\\1`",
7942 : "tag`\\1${0}right`",
7943 : "tag`left${0}\\1`",
7944 : "tag`left${0}\\1${1}right`",
7945 : "tag`\\xg`",
7946 : "tag`\\xg${0}right`",
7947 : "tag`left${0}\\xg`",
7948 : "tag`left${0}\\xg${1}right`",
7949 : "tag`\\xAg`",
7950 : "tag`\\xAg${0}right`",
7951 : "tag`left${0}\\xAg`",
7952 : "tag`left${0}\\xAg${1}right`",
7953 : "tag`\\u0`",
7954 : "tag`\\u0${0}right`",
7955 : "tag`left${0}\\u0`",
7956 : "tag`left${0}\\u0${1}right`",
7957 : "tag`\\u0g`",
7958 : "tag`\\u0g${0}right`",
7959 : "tag`left${0}\\u0g`",
7960 : "tag`left${0}\\u0g${1}right`",
7961 : "tag`\\u00g`",
7962 : "tag`\\u00g${0}right`",
7963 : "tag`left${0}\\u00g`",
7964 : "tag`left${0}\\u00g${1}right`",
7965 : "tag`\\u000g`",
7966 : "tag`\\u000g${0}right`",
7967 : "tag`left${0}\\u000g`",
7968 : "tag`left${0}\\u000g${1}right`",
7969 : "tag`\\u{}`",
7970 : "tag`\\u{}${0}right`",
7971 : "tag`left${0}\\u{}`",
7972 : "tag`left${0}\\u{}${1}right`",
7973 : "tag`\\u{-0}`",
7974 : "tag`\\u{-0}${0}right`",
7975 : "tag`left${0}\\u{-0}`",
7976 : "tag`left${0}\\u{-0}${1}right`",
7977 : "tag`\\u{g}`",
7978 : "tag`\\u{g}${0}right`",
7979 : "tag`left${0}\\u{g}`",
7980 : "tag`left${0}\\u{g}${1}right`",
7981 : "tag`\\u{0`",
7982 : "tag`\\u{0${0}right`",
7983 : "tag`left${0}\\u{0`",
7984 : "tag`left${0}\\u{0${1}right`",
7985 : "tag`\\u{\\u{0}`",
7986 : "tag`\\u{\\u{0}${0}right`",
7987 : "tag`left${0}\\u{\\u{0}`",
7988 : "tag`left${0}\\u{\\u{0}${1}right`",
7989 : "tag`\\u{110000}`",
7990 : "tag`\\u{110000}${0}right`",
7991 : "tag`left${0}\\u{110000}`",
7992 : "tag`left${0}\\u{110000}${1}right`",
7993 : "tag` ${tag`\\u`}`",
7994 : "tag` ``\\u`",
7995 : "tag`\\u`` `",
7996 : "tag`\\u``\\u`",
7997 : "` ${tag`\\u`}`",
7998 : "` ``\\u`",
7999 5 : nullptr};
8000 : // clang-format on
8001 :
8002 5 : RunParserSyncTest(context_data, data, kSuccess);
8003 5 : }
8004 :
8005 26644 : TEST(TemplateEscapesNegativeTests) {
8006 : // clang-format off
8007 : const char* context_data[][2] = {
8008 : {"", ""},
8009 : {"'use strict';", ""},
8010 5 : {nullptr, nullptr}};
8011 :
8012 : // clang-format off
8013 : const char* data[] = {
8014 : "`\\08`",
8015 : "`\\01`",
8016 : "`\\01${0}right`",
8017 : "`left${0}\\01`",
8018 : "`left${0}\\01${1}right`",
8019 : "`\\1`",
8020 : "`\\1${0}right`",
8021 : "`left${0}\\1`",
8022 : "`left${0}\\1${1}right`",
8023 : "`\\xg`",
8024 : "`\\xg${0}right`",
8025 : "`left${0}\\xg`",
8026 : "`left${0}\\xg${1}right`",
8027 : "`\\xAg`",
8028 : "`\\xAg${0}right`",
8029 : "`left${0}\\xAg`",
8030 : "`left${0}\\xAg${1}right`",
8031 : "`\\u0`",
8032 : "`\\u0${0}right`",
8033 : "`left${0}\\u0`",
8034 : "`left${0}\\u0${1}right`",
8035 : "`\\u0g`",
8036 : "`\\u0g${0}right`",
8037 : "`left${0}\\u0g`",
8038 : "`left${0}\\u0g${1}right`",
8039 : "`\\u00g`",
8040 : "`\\u00g${0}right`",
8041 : "`left${0}\\u00g`",
8042 : "`left${0}\\u00g${1}right`",
8043 : "`\\u000g`",
8044 : "`\\u000g${0}right`",
8045 : "`left${0}\\u000g`",
8046 : "`left${0}\\u000g${1}right`",
8047 : "`\\u{}`",
8048 : "`\\u{}${0}right`",
8049 : "`left${0}\\u{}`",
8050 : "`left${0}\\u{}${1}right`",
8051 : "`\\u{-0}`",
8052 : "`\\u{-0}${0}right`",
8053 : "`left${0}\\u{-0}`",
8054 : "`left${0}\\u{-0}${1}right`",
8055 : "`\\u{g}`",
8056 : "`\\u{g}${0}right`",
8057 : "`left${0}\\u{g}`",
8058 : "`left${0}\\u{g}${1}right`",
8059 : "`\\u{0`",
8060 : "`\\u{0${0}right`",
8061 : "`left${0}\\u{0`",
8062 : "`left${0}\\u{0${1}right`",
8063 : "`\\u{\\u{0}`",
8064 : "`\\u{\\u{0}${0}right`",
8065 : "`left${0}\\u{\\u{0}`",
8066 : "`left${0}\\u{\\u{0}${1}right`",
8067 : "`\\u{110000}`",
8068 : "`\\u{110000}${0}right`",
8069 : "`left${0}\\u{110000}`",
8070 : "`left${0}\\u{110000}${1}right`",
8071 : "`\\1``\\2`",
8072 : "tag` ${`\\u`}`",
8073 : "`\\u```",
8074 5 : nullptr};
8075 : // clang-format on
8076 :
8077 5 : RunParserSyncTest(context_data, data, kError);
8078 5 : }
8079 :
8080 26644 : TEST(DestructuringPositiveTests) {
8081 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8082 : {"var ", " = {};"},
8083 : {"'use strict'; const ", " = {};"},
8084 : {"function f(", ") {}"},
8085 : {"function f(argument1, ", ") {}"},
8086 : {"var f = (", ") => {};"},
8087 : {"var f = (argument1,", ") => {};"},
8088 : {"try {} catch(", ") {}"},
8089 5 : {nullptr, nullptr}};
8090 :
8091 : // clang-format off
8092 : const char* data[] = {
8093 : "a",
8094 : "{ x : y }",
8095 : "{ x : y = 1 }",
8096 : "{ get, set }",
8097 : "{ get = 1, set = 2 }",
8098 : "[a]",
8099 : "[a = 1]",
8100 : "[a,b,c]",
8101 : "[a, b = 42, c]",
8102 : "{ x : x, y : y }",
8103 : "{ x : x = 1, y : y }",
8104 : "{ x : x, y : y = 42 }",
8105 : "[]",
8106 : "{}",
8107 : "[{x:x, y:y}, [a,b,c]]",
8108 : "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
8109 : "{x}",
8110 : "{x, y}",
8111 : "{x = 42, y = 15}",
8112 : "[a,,b]",
8113 : "{42 : x}",
8114 : "{42 : x = 42}",
8115 : "{42e-2 : x}",
8116 : "{42e-2 : x = 42}",
8117 : "{x : y, x : z}",
8118 : "{'hi' : x}",
8119 : "{'hi' : x = 42}",
8120 : "{var: x}",
8121 : "{var: x = 42}",
8122 : "{[x] : z}",
8123 : "{[1+1] : z}",
8124 : "{[foo()] : z}",
8125 : "{}",
8126 : "[...rest]",
8127 : "[a,b,...rest]",
8128 : "[a,,...rest]",
8129 : "{ __proto__: x, __proto__: y}",
8130 : "{arguments: x}",
8131 : "{eval: x}",
8132 : "{ x : y, ...z }",
8133 : "{ x : y = 1, ...z }",
8134 : "{ x : x, y : y, ...z }",
8135 : "{ x : x = 1, y : y, ...z }",
8136 : "{ x : x, y : y = 42, ...z }",
8137 : "[{x:x, y:y, ...z}, [a,b,c]]",
8138 : "[{x:x = 1, y:y = 2, ...z}, [a = 3, b = 4, c = 5]]",
8139 : "{...x}",
8140 : "{x, ...y}",
8141 : "{x = 42, y = 15, ...z}",
8142 : "{42 : x = 42, ...y}",
8143 : "{'hi' : x, ...z}",
8144 : "{'hi' : x = 42, ...z}",
8145 : "{var: x = 42, ...z}",
8146 : "{[x] : z, ...y}",
8147 : "{[1+1] : z, ...x}",
8148 : "{arguments: x, ...z}",
8149 : "{ __proto__: x, __proto__: y, ...z}",
8150 : nullptr
8151 5 : };
8152 :
8153 : // clang-format on
8154 5 : RunParserSyncTest(context_data, data, kSuccess);
8155 :
8156 : // v8:5201
8157 : {
8158 : // clang-format off
8159 : const char* sloppy_context_data[][2] = {
8160 : {"var ", " = {};"},
8161 : {"function f(", ") {}"},
8162 : {"function f(argument1, ", ") {}"},
8163 : {"var f = (", ") => {};"},
8164 : {"var f = (argument1,", ") => {};"},
8165 : {"try {} catch(", ") {}"},
8166 : {nullptr, nullptr}
8167 5 : };
8168 :
8169 : const char* data[] = {
8170 : "{arguments}",
8171 : "{eval}",
8172 : "{x: arguments}",
8173 : "{x: eval}",
8174 : "{arguments = false}",
8175 : "{eval = false}",
8176 : "{...arguments}",
8177 : "{...eval}",
8178 : nullptr
8179 5 : };
8180 : // clang-format on
8181 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
8182 : }
8183 5 : }
8184 :
8185 :
8186 26644 : TEST(DestructuringNegativeTests) {
8187 : { // All modes.
8188 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8189 : {"var ", " = {};"},
8190 : {"'use strict'; const ", " = {};"},
8191 : {"function f(", ") {}"},
8192 : {"function f(argument1, ", ") {}"},
8193 : {"var f = (", ") => {};"},
8194 : {"var f = ", " => {};"},
8195 : {"var f = (argument1,", ") => {};"},
8196 : {"try {} catch(", ") {}"},
8197 5 : {nullptr, nullptr}};
8198 :
8199 : // clang-format off
8200 : const char* data[] = {
8201 : "a++",
8202 : "++a",
8203 : "delete a",
8204 : "void a",
8205 : "typeof a",
8206 : "--a",
8207 : "+a",
8208 : "-a",
8209 : "~a",
8210 : "!a",
8211 : "{ x : y++ }",
8212 : "[a++]",
8213 : "(x => y)",
8214 : "(async x => y)",
8215 : "((x, z) => y)",
8216 : "(async (x, z) => y)",
8217 : "a[i]", "a()",
8218 : "a.b",
8219 : "new 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 : "a <<< a",
8229 : "a >>> a",
8230 : "function a() {}",
8231 : "function* a() {}",
8232 : "async function a() {}",
8233 : "a`bcd`",
8234 : "this",
8235 : "null",
8236 : "true",
8237 : "false",
8238 : "1",
8239 : "'abc'",
8240 : "/abc/",
8241 : "`abc`",
8242 : "class {}",
8243 : "{+2 : x}",
8244 : "{-2 : x}",
8245 : "var",
8246 : "[var]",
8247 : "{x : {y : var}}",
8248 : "{x : x = a+}",
8249 : "{x : x = (a+)}",
8250 : "{x : x += a}",
8251 : "{m() {} = 0}",
8252 : "{[1+1]}",
8253 : "[...rest, x]",
8254 : "[a,b,...rest, x]",
8255 : "[a,,...rest, x]",
8256 : "[...rest,]",
8257 : "[a,b,...rest,]",
8258 : "[a,,...rest,]",
8259 : "[...rest,...rest1]",
8260 : "[a,b,...rest,...rest1]",
8261 : "[a,,..rest,...rest1]",
8262 : "[x, y, ...z = 1]",
8263 : "[...z = 1]",
8264 : "[x, y, ...[z] = [1]]",
8265 : "[...[z] = [1]]",
8266 : "{ x : 3 }",
8267 : "{ x : 'foo' }",
8268 : "{ x : /foo/ }",
8269 : "{ x : `foo` }",
8270 : "{ get a() {} }",
8271 : "{ set a() {} }",
8272 : "{ method() {} }",
8273 : "{ *method() {} }",
8274 : "...a++",
8275 : "...++a",
8276 : "...typeof a",
8277 : "...[a++]",
8278 : "...(x => y)",
8279 : "{ ...x, }",
8280 : "{ ...x, y }",
8281 : "{ y, ...x, y }",
8282 : "{ ...x, ...y }",
8283 : "{ ...x, ...x }",
8284 : "{ ...x, ...x = {} }",
8285 : "{ ...x, ...x = ...x }",
8286 : "{ ...x, ...x = ...{ x } }",
8287 : "{ ,, ...x }",
8288 : "{ ...get a() {} }",
8289 : "{ ...set a() {} }",
8290 : "{ ...method() {} }",
8291 : "{ ...function() {} }",
8292 : "{ ...*method() {} }",
8293 : "{...{x} }",
8294 : "{...[x] }",
8295 : "{...{ x = 5 } }",
8296 : "{...[ x = 5 ] }",
8297 : "{...x.f }",
8298 : "{...x[0] }",
8299 : "async function* a() {}",
8300 : nullptr
8301 5 : };
8302 :
8303 : // clang-format on
8304 5 : RunParserSyncTest(context_data, data, kError);
8305 : }
8306 :
8307 : { // All modes.
8308 : const char* context_data[][2] = {
8309 : {"'use strict'; let ", " = {};"}, {"var ", " = {};"},
8310 : {"'use strict'; const ", " = {};"}, {"function f(", ") {}"},
8311 : {"function f(argument1, ", ") {}"}, {"var f = (", ") => {};"},
8312 5 : {"var f = (argument1,", ") => {};"}, {nullptr, nullptr}};
8313 :
8314 : // clang-format off
8315 : const char* data[] = {
8316 : "x => x",
8317 : "() => x",
8318 5 : nullptr};
8319 : // clang-format on
8320 5 : RunParserSyncTest(context_data, data, kError);
8321 : }
8322 :
8323 : { // Strict mode.
8324 : const char* context_data[][2] = {
8325 : {"'use strict'; var ", " = {};"},
8326 : {"'use strict'; let ", " = {};"},
8327 : {"'use strict'; const ", " = {};"},
8328 : {"'use strict'; function f(", ") {}"},
8329 : {"'use strict'; function f(argument1, ", ") {}"},
8330 5 : {nullptr, nullptr}};
8331 :
8332 : // clang-format off
8333 : const char* data[] = {
8334 : "[arguments]",
8335 : "[eval]",
8336 : "{ a : arguments }",
8337 : "{ a : eval }",
8338 : "[public]",
8339 : "{ x : private }",
8340 : "{ x : arguments }",
8341 : "{ x : eval }",
8342 : "{ arguments }",
8343 : "{ eval }",
8344 : "{ arguments = false }"
8345 : "{ eval = false }",
8346 : "{ ...eval }",
8347 : "{ ...arguments }",
8348 5 : nullptr};
8349 :
8350 : // clang-format on
8351 5 : RunParserSyncTest(context_data, data, kError);
8352 : }
8353 :
8354 : { // 'yield' in generators.
8355 : const char* context_data[][2] = {
8356 : {"function*() { var ", " = {};"},
8357 : {"function*() { 'use strict'; let ", " = {};"},
8358 : {"function*() { 'use strict'; const ", " = {};"},
8359 5 : {nullptr, nullptr}};
8360 :
8361 : // clang-format off
8362 : const char* data[] = {
8363 : "yield",
8364 : "[yield]",
8365 : "{ x : yield }",
8366 5 : nullptr};
8367 : // clang-format on
8368 5 : RunParserSyncTest(context_data, data, kError);
8369 : }
8370 :
8371 : { // Declaration-specific errors
8372 : const char* context_data[][2] = {{"'use strict'; var ", ""},
8373 : {"'use strict'; let ", ""},
8374 : {"'use strict'; const ", ""},
8375 : {"'use strict'; for (var ", ";;) {}"},
8376 : {"'use strict'; for (let ", ";;) {}"},
8377 : {"'use strict'; for (const ", ";;) {}"},
8378 : {"var ", ""},
8379 : {"let ", ""},
8380 : {"const ", ""},
8381 : {"for (var ", ";;) {}"},
8382 : {"for (let ", ";;) {}"},
8383 : {"for (const ", ";;) {}"},
8384 5 : {nullptr, nullptr}};
8385 :
8386 : // clang-format off
8387 : const char* data[] = {
8388 : "{ a }",
8389 : "[ a ]",
8390 : "{ ...a }",
8391 : nullptr
8392 5 : };
8393 : // clang-format on
8394 5 : RunParserSyncTest(context_data, data, kError);
8395 : }
8396 5 : }
8397 :
8398 26644 : TEST(ObjectRestNegativeTestSlow) {
8399 : // clang-format off
8400 : const char* context_data[][2] = {
8401 : {"var { ", " } = { a: 1};"},
8402 : { nullptr, nullptr }
8403 5 : };
8404 :
8405 : using v8::internal::Code;
8406 : std::string statement;
8407 655345 : for (int i = 0; i < Code::kMaxArguments; ++i) {
8408 1310680 : statement += std::to_string(i) + " : " + "x, ";
8409 : }
8410 : statement += "...y";
8411 :
8412 : const char* statement_data[] = {
8413 : statement.c_str(),
8414 : nullptr
8415 5 : };
8416 :
8417 : // clang-format on
8418 : // The test is quite slow, so run it with a reduced set of flags.
8419 : static const ParserFlag flags[] = {kAllowLazy};
8420 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags,
8421 5 : arraysize(flags));
8422 5 : }
8423 :
8424 26644 : TEST(DestructuringAssignmentPositiveTests) {
8425 : const char* context_data[][2] = {
8426 : {"'use strict'; let x, y, z; (", " = {});"},
8427 : {"var x, y, z; (", " = {});"},
8428 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8429 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8430 : {"var x, y, z; for (x in ", " = {});"},
8431 : {"var x, y, z; for (x of ", " = {});"},
8432 : {"var x, y, z; for (", " in {});"},
8433 : {"var x, y, z; for (", " of {});"},
8434 : {"'use strict'; var x, y, z; for (", " in {});"},
8435 : {"'use strict'; var x, y, z; for (", " of {});"},
8436 : {"var x, y, z; m(['a']) ? ", " = {} : rhs"},
8437 : {"var x, y, z; m(['b']) ? lhs : ", " = {}"},
8438 : {"'use strict'; var x, y, z; m(['a']) ? ", " = {} : rhs"},
8439 : {"'use strict'; var x, y, z; m(['b']) ? lhs : ", " = {}"},
8440 5 : {nullptr, nullptr}};
8441 :
8442 : const char* mixed_assignments_context_data[][2] = {
8443 : {"'use strict'; let x, y, z; (", " = z = {});"},
8444 : {"var x, y, z; (", " = z = {});"},
8445 : {"'use strict'; let x, y, z; (x = ", " = z = {});"},
8446 : {"var x, y, z; (x = ", " = z = {});"},
8447 : {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
8448 : {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
8449 : {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
8450 : {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
8451 : {"var x, y, z; for (x in ", " = z = {});"},
8452 : {"var x, y, z; for (x in x = ", " = z = {});"},
8453 : {"var x, y, z; for (x of ", " = z = {});"},
8454 : {"var x, y, z; for (x of x = ", " = z = {});"},
8455 5 : {nullptr, nullptr}};
8456 :
8457 : // clang-format off
8458 : const char* data[] = {
8459 : "x",
8460 :
8461 : "{ x : y }",
8462 : "{ x : foo().y }",
8463 : "{ x : foo()[y] }",
8464 : "{ x : y.z }",
8465 : "{ x : y[z] }",
8466 : "{ x : { y } }",
8467 : "{ x : { foo: y } }",
8468 : "{ x : { foo: foo().y } }",
8469 : "{ x : { foo: foo()[y] } }",
8470 : "{ x : { foo: y.z } }",
8471 : "{ x : { foo: y[z] } }",
8472 : "{ x : [ y ] }",
8473 : "{ x : [ foo().y ] }",
8474 : "{ x : [ foo()[y] ] }",
8475 : "{ x : [ y.z ] }",
8476 : "{ x : [ y[z] ] }",
8477 :
8478 : "{ x : y = 10 }",
8479 : "{ x : foo().y = 10 }",
8480 : "{ x : foo()[y] = 10 }",
8481 : "{ x : y.z = 10 }",
8482 : "{ x : y[z] = 10 }",
8483 : "{ x : { y = 10 } = {} }",
8484 : "{ x : { foo: y = 10 } = {} }",
8485 : "{ x : { foo: foo().y = 10 } = {} }",
8486 : "{ x : { foo: foo()[y] = 10 } = {} }",
8487 : "{ x : { foo: y.z = 10 } = {} }",
8488 : "{ x : { foo: y[z] = 10 } = {} }",
8489 : "{ x : [ y = 10 ] = {} }",
8490 : "{ x : [ foo().y = 10 ] = {} }",
8491 : "{ x : [ foo()[y] = 10 ] = {} }",
8492 : "{ x : [ y.z = 10 ] = {} }",
8493 : "{ x : [ y[z] = 10 ] = {} }",
8494 : "{ z : { __proto__: x, __proto__: y } = z }"
8495 :
8496 : "[ x ]",
8497 : "[ foo().x ]",
8498 : "[ foo()[x] ]",
8499 : "[ x.y ]",
8500 : "[ x[y] ]",
8501 : "[ { x } ]",
8502 : "[ { x : y } ]",
8503 : "[ { x : foo().y } ]",
8504 : "[ { x : foo()[y] } ]",
8505 : "[ { x : x.y } ]",
8506 : "[ { x : x[y] } ]",
8507 : "[ [ x ] ]",
8508 : "[ [ foo().x ] ]",
8509 : "[ [ foo()[x] ] ]",
8510 : "[ [ x.y ] ]",
8511 : "[ [ x[y] ] ]",
8512 :
8513 : "[ x = 10 ]",
8514 : "[ foo().x = 10 ]",
8515 : "[ foo()[x] = 10 ]",
8516 : "[ x.y = 10 ]",
8517 : "[ x[y] = 10 ]",
8518 : "[ { x = 10 } = {} ]",
8519 : "[ { x : y = 10 } = {} ]",
8520 : "[ { x : foo().y = 10 } = {} ]",
8521 : "[ { x : foo()[y] = 10 } = {} ]",
8522 : "[ { x : x.y = 10 } = {} ]",
8523 : "[ { x : x[y] = 10 } = {} ]",
8524 : "[ [ x = 10 ] = {} ]",
8525 : "[ [ foo().x = 10 ] = {} ]",
8526 : "[ [ foo()[x] = 10 ] = {} ]",
8527 : "[ [ x.y = 10 ] = {} ]",
8528 : "[ [ x[y] = 10 ] = {} ]",
8529 : "{ x : y = 1 }",
8530 : "{ x }",
8531 : "{ x, y, z }",
8532 : "{ x = 1, y: z, z: y }",
8533 : "{x = 42, y = 15}",
8534 : "[x]",
8535 : "[x = 1]",
8536 : "[x,y,z]",
8537 : "[x, y = 42, z]",
8538 : "{ x : x, y : y }",
8539 : "{ x : x = 1, y : y }",
8540 : "{ x : x, y : y = 42 }",
8541 : "[]",
8542 : "{}",
8543 : "[{x:x, y:y}, [,x,z,]]",
8544 : "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
8545 : "[x,,y]",
8546 : "[(x),,(y)]",
8547 : "[(x)]",
8548 : "{42 : x}",
8549 : "{42 : x = 42}",
8550 : "{42e-2 : x}",
8551 : "{42e-2 : x = 42}",
8552 : "{'hi' : x}",
8553 : "{'hi' : x = 42}",
8554 : "{var: x}",
8555 : "{var: x = 42}",
8556 : "{var: (x) = 42}",
8557 : "{[x] : z}",
8558 : "{[1+1] : z}",
8559 : "{[1+1] : (z)}",
8560 : "{[foo()] : z}",
8561 : "{[foo()] : (z)}",
8562 : "{[foo()] : foo().bar}",
8563 : "{[foo()] : foo()['bar']}",
8564 : "{[foo()] : this.bar}",
8565 : "{[foo()] : this['bar']}",
8566 : "{[foo()] : 'foo'.bar}",
8567 : "{[foo()] : 'foo'['bar']}",
8568 : "[...x]",
8569 : "[x,y,...z]",
8570 : "[x,,...z]",
8571 : "{ x: y }",
8572 : "[x, y]",
8573 : "[((x, y) => z).x]",
8574 : "{x: ((y, z) => z).x}",
8575 : "[((x, y) => z)['x']]",
8576 : "{x: ((y, z) => z)['x']}",
8577 :
8578 : "{x: { y = 10 } }",
8579 : "[(({ x } = { x: 1 }) => x).a]",
8580 :
8581 : "{ ...d.x }",
8582 : "{ ...c[0]}",
8583 :
8584 : // v8:4662
8585 : "{ x: (y) }",
8586 : "{ x: (y) = [] }",
8587 : "{ x: (foo.bar) }",
8588 : "{ x: (foo['bar']) }",
8589 : "[ ...(a) ]",
8590 : "[ ...(foo['bar']) ]",
8591 : "[ ...(foo.bar) ]",
8592 : "[ (y) ]",
8593 : "[ (foo.bar) ]",
8594 : "[ (foo['bar']) ]",
8595 :
8596 5 : nullptr};
8597 : // clang-format on
8598 5 : RunParserSyncTest(context_data, data, kSuccess);
8599 :
8600 5 : RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
8601 :
8602 : const char* empty_context_data[][2] = {
8603 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8604 :
8605 : // CoverInitializedName ambiguity handling in various contexts
8606 : const char* ambiguity_data[] = {
8607 : "var foo = { x = 10 } = {};",
8608 : "var foo = { q } = { x = 10 } = {};",
8609 : "var foo; foo = { x = 10 } = {};",
8610 : "var foo; foo = { q } = { x = 10 } = {};",
8611 : "var x; ({ x = 10 } = {});",
8612 : "var q, x; ({ q } = { x = 10 } = {});",
8613 : "var x; [{ x = 10 } = {}]",
8614 : "var x; (true ? { x = true } = {} : { x = false } = {})",
8615 : "var q, x; (q, { x = 10 } = {});",
8616 : "var { x = 10 } = { x = 20 } = {};",
8617 : "var { __proto__: x, __proto__: y } = {}",
8618 : "({ __proto__: x, __proto__: y } = {})",
8619 : "var { x = 10 } = (o = { x = 20 } = {});",
8620 : "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
8621 : nullptr,
8622 5 : };
8623 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
8624 5 : }
8625 :
8626 :
8627 26644 : TEST(DestructuringAssignmentNegativeTests) {
8628 : const char* context_data[][2] = {
8629 : {"'use strict'; let x, y, z; (", " = {});"},
8630 : {"var x, y, z; (", " = {});"},
8631 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8632 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8633 : {"var x, y, z; for (x in ", " = {});"},
8634 : {"var x, y, z; for (x of ", " = {});"},
8635 5 : {nullptr, nullptr}};
8636 :
8637 : // clang-format off
8638 : const char* data[] = {
8639 : "{ x : ++y }",
8640 : "{ x : y * 2 }",
8641 : "{ get x() {} }",
8642 : "{ set x() {} }",
8643 : "{ x: y() }",
8644 : "{ this }",
8645 : "{ x: this }",
8646 : "{ x: this = 1 }",
8647 : "{ super }",
8648 : "{ x: super }",
8649 : "{ x: super = 1 }",
8650 : "{ new.target }",
8651 : "{ x: new.target }",
8652 : "{ x: new.target = 1 }",
8653 : "{ import.meta }",
8654 : "{ x: import.meta }",
8655 : "{ x: import.meta = 1 }",
8656 : "[x--]",
8657 : "[--x = 1]",
8658 : "[x()]",
8659 : "[this]",
8660 : "[this = 1]",
8661 : "[new.target]",
8662 : "[new.target = 1]",
8663 : "[import.meta]",
8664 : "[import.meta = 1]",
8665 : "[super]",
8666 : "[super = 1]",
8667 : "[function f() {}]",
8668 : "[async function f() {}]",
8669 : "[function* f() {}]",
8670 : "[50]",
8671 : "[(50)]",
8672 : "[(function() {})]",
8673 : "[(async function() {})]",
8674 : "[(function*() {})]",
8675 : "[(foo())]",
8676 : "{ x: 50 }",
8677 : "{ x: (50) }",
8678 : "['str']",
8679 : "{ x: 'str' }",
8680 : "{ x: ('str') }",
8681 : "{ x: (foo()) }",
8682 : "{ x: function() {} }",
8683 : "{ x: async function() {} }",
8684 : "{ x: function*() {} }",
8685 : "{ x: (function() {}) }",
8686 : "{ x: (async function() {}) }",
8687 : "{ x: (function*() {}) }",
8688 : "{ x: y } = 'str'",
8689 : "[x, y] = 'str'",
8690 : "[(x,y) => z]",
8691 : "[async(x,y) => z]",
8692 : "[async x => z]",
8693 : "{x: (y) => z}",
8694 : "{x: (y,w) => z}",
8695 : "{x: async (y) => z}",
8696 : "{x: async (y,w) => z}",
8697 : "[x, ...y, z]",
8698 : "[...x,]",
8699 : "[x, y, ...z = 1]",
8700 : "[...z = 1]",
8701 : "[x, y, ...[z] = [1]]",
8702 : "[...[z] = [1]]",
8703 :
8704 : "[...++x]",
8705 : "[...x--]",
8706 : "[...!x]",
8707 : "[...x + y]",
8708 :
8709 : // v8:4657
8710 : "({ x: x4, x: (x+=1e4) })",
8711 : "(({ x: x4, x: (x+=1e4) }))",
8712 : "({ x: x4, x: (x+=1e4) } = {})",
8713 : "(({ x: x4, x: (x+=1e4) } = {}))",
8714 : "(({ x: x4, x: (x+=1e4) }) = {})",
8715 : "({ x: y } = {})",
8716 : "(({ x: y } = {}))",
8717 : "(({ x: y }) = {})",
8718 : "([a])",
8719 : "(([a]))",
8720 : "([a] = [])",
8721 : "(([a] = []))",
8722 : "(([a]) = [])",
8723 :
8724 : // v8:4662
8725 : "{ x: ([y]) }",
8726 : "{ x: ([y] = []) }",
8727 : "{ x: ({y}) }",
8728 : "{ x: ({y} = {}) }",
8729 : "{ x: (++y) }",
8730 : "[ (...[a]) ]",
8731 : "[ ...([a]) ]",
8732 : "[ ...([a] = [])",
8733 : "[ ...[ ( [ a ] ) ] ]",
8734 : "[ ([a]) ]",
8735 : "[ (...[a]) ]",
8736 : "[ ([a] = []) ]",
8737 : "[ (++y) ]",
8738 : "[ ...(++y) ]",
8739 :
8740 : "[ x += x ]",
8741 : "{ foo: x += x }",
8742 :
8743 5 : nullptr};
8744 : // clang-format on
8745 5 : RunParserSyncTest(context_data, data, kError);
8746 :
8747 : const char* empty_context_data[][2] = {
8748 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8749 :
8750 : // CoverInitializedName ambiguity handling in various contexts
8751 : const char* ambiguity_data[] = {
8752 : "var foo = { x = 10 };", "var foo = { q } = { x = 10 };",
8753 : "var foo; foo = { x = 10 };", "var foo; foo = { q } = { x = 10 };",
8754 : "var x; ({ x = 10 });", "var q, x; ({ q } = { x = 10 });",
8755 : "var x; [{ x = 10 }]", "var x; (true ? { x = true } : { x = false })",
8756 : "var q, x; (q, { x = 10 });", "var { x = 10 } = { x = 20 };",
8757 : "var { x = 10 } = (o = { x = 20 });",
8758 : "var x; (({ x = 10 } = { x = 20 }) => x)({})",
8759 :
8760 : // Not ambiguous, but uses same context data
8761 : "switch([window %= []] = []) { default: }",
8762 :
8763 : nullptr,
8764 5 : };
8765 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kError);
8766 :
8767 : // Strict mode errors
8768 : const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
8769 : {"'use strict'; for (", " of {}) {}"},
8770 : {"'use strict'; for (", " in {}) {}"},
8771 5 : {nullptr, nullptr}};
8772 : const char* strict_data[] = {
8773 : "{ eval }", "{ arguments }", "{ foo: eval }", "{ foo: arguments }",
8774 : "{ eval = 0 }", "{ arguments = 0 }", "{ foo: eval = 0 }",
8775 : "{ foo: arguments = 0 }", "[ eval ]", "[ arguments ]", "[ eval = 0 ]",
8776 : "[ arguments = 0 ]",
8777 :
8778 : // v8:4662
8779 : "{ x: (eval) }", "{ x: (arguments) }", "{ x: (eval = 0) }",
8780 : "{ x: (arguments = 0) }", "{ x: (eval) = 0 }", "{ x: (arguments) = 0 }",
8781 : "[ (eval) ]", "[ (arguments) ]", "[ (eval = 0) ]", "[ (arguments = 0) ]",
8782 : "[ (eval) = 0 ]", "[ (arguments) = 0 ]", "[ ...(eval) ]",
8783 : "[ ...(arguments) ]", "[ ...(eval = 0) ]", "[ ...(arguments = 0) ]",
8784 : "[ ...(eval) = 0 ]", "[ ...(arguments) = 0 ]",
8785 :
8786 5 : nullptr};
8787 5 : RunParserSyncTest(strict_context_data, strict_data, kError);
8788 5 : }
8789 :
8790 :
8791 26644 : TEST(DestructuringDisallowPatternsInForVarIn) {
8792 : const char* context_data[][2] = {
8793 5 : {"", ""}, {"function f() {", "}"}, {nullptr, nullptr}};
8794 : // clang-format off
8795 : const char* error_data[] = {
8796 : "for (let x = {} in null);",
8797 : "for (let x = {} of null);",
8798 5 : nullptr};
8799 : // clang-format on
8800 5 : RunParserSyncTest(context_data, error_data, kError);
8801 :
8802 : // clang-format off
8803 : const char* success_data[] = {
8804 : "for (var x = {} in null);",
8805 5 : nullptr};
8806 : // clang-format on
8807 5 : RunParserSyncTest(context_data, success_data, kSuccess);
8808 5 : }
8809 :
8810 :
8811 26644 : TEST(DestructuringDuplicateParams) {
8812 : const char* context_data[][2] = {{"'use strict';", ""},
8813 : {"function outer() { 'use strict';", "}"},
8814 5 : {nullptr, nullptr}};
8815 :
8816 :
8817 : // clang-format off
8818 : const char* error_data[] = {
8819 : "function f(x,x){}",
8820 : "function f(x, {x : x}){}",
8821 : "function f(x, {x}){}",
8822 : "function f({x,x}) {}",
8823 : "function f([x,x]) {}",
8824 : "function f(x, [y,{z:x}]) {}",
8825 : "function f([x,{y:x}]) {}",
8826 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8827 : "function f(x, x, {a}) {}",
8828 5 : nullptr};
8829 : // clang-format on
8830 5 : RunParserSyncTest(context_data, error_data, kError);
8831 5 : }
8832 :
8833 :
8834 26644 : TEST(DestructuringDuplicateParamsSloppy) {
8835 : const char* context_data[][2] = {
8836 5 : {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
8837 :
8838 :
8839 : // clang-format off
8840 : const char* error_data[] = {
8841 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8842 : "function f(x, {x : x}){}",
8843 : "function f(x, {x}){}",
8844 : "function f({x,x}) {}",
8845 : "function f(x, x, {a}) {}",
8846 5 : nullptr};
8847 : // clang-format on
8848 5 : RunParserSyncTest(context_data, error_data, kError);
8849 5 : }
8850 :
8851 :
8852 26644 : TEST(DestructuringDisallowPatternsInSingleParamArrows) {
8853 : const char* context_data[][2] = {{"'use strict';", ""},
8854 : {"function outer() { 'use strict';", "}"},
8855 : {"", ""},
8856 : {"function outer() { ", "}"},
8857 5 : {nullptr, nullptr}};
8858 :
8859 : // clang-format off
8860 : const char* error_data[] = {
8861 : "var f = {x} => {};",
8862 : "var f = {x,y} => {};",
8863 5 : nullptr};
8864 : // clang-format on
8865 5 : RunParserSyncTest(context_data, error_data, kError);
8866 5 : }
8867 :
8868 :
8869 26644 : TEST(DefaultParametersYieldInInitializers) {
8870 : // clang-format off
8871 : const char* sloppy_function_context_data[][2] = {
8872 : {"(function f(", ") { });"},
8873 : {nullptr, nullptr}
8874 5 : };
8875 :
8876 : const char* strict_function_context_data[][2] = {
8877 : {"'use strict'; (function f(", ") { });"},
8878 : {nullptr, nullptr}
8879 5 : };
8880 :
8881 : const char* sloppy_arrow_context_data[][2] = {
8882 : {"((", ")=>{});"},
8883 : {nullptr, nullptr}
8884 5 : };
8885 :
8886 : const char* strict_arrow_context_data[][2] = {
8887 : {"'use strict'; ((", ")=>{});"},
8888 : {nullptr, nullptr}
8889 5 : };
8890 :
8891 : const char* generator_context_data[][2] = {
8892 : {"'use strict'; (function *g(", ") { });"},
8893 : {"(function *g(", ") { });"},
8894 : // Arrow function within generator has the same rules.
8895 : {"'use strict'; (function *g() { (", ") => {} });"},
8896 : {"(function *g() { (", ") => {} });"},
8897 : // And similarly for arrow functions in the parameter list.
8898 : {"'use strict'; (function *g(z = (", ") => {}) { });"},
8899 : {"(function *g(z = (", ") => {}) { });"},
8900 : {nullptr, nullptr}
8901 5 : };
8902 :
8903 : const char* parameter_data[] = {
8904 : "x=yield",
8905 : "x, y=yield",
8906 : "{x=yield}",
8907 : "[x=yield]",
8908 :
8909 : "x=(yield)",
8910 : "x, y=(yield)",
8911 : "{x=(yield)}",
8912 : "[x=(yield)]",
8913 :
8914 : "x=f(yield)",
8915 : "x, y=f(yield)",
8916 : "{x=f(yield)}",
8917 : "[x=f(yield)]",
8918 :
8919 : "{x}=yield",
8920 : "[x]=yield",
8921 :
8922 : "{x}=(yield)",
8923 : "[x]=(yield)",
8924 :
8925 : "{x}=f(yield)",
8926 : "[x]=f(yield)",
8927 : nullptr
8928 5 : };
8929 :
8930 : // Because classes are always in strict mode, these are always errors.
8931 : const char* always_error_param_data[] = {
8932 : "x = class extends (yield) { }",
8933 : "x = class extends f(yield) { }",
8934 : "x = class extends (null, yield) { }",
8935 : "x = class extends (a ? null : yield) { }",
8936 : "[x] = [class extends (a ? null : yield) { }]",
8937 : "[x = class extends (a ? null : yield) { }]",
8938 : "[x = class extends (a ? null : yield) { }] = [null]",
8939 : "x = class { [yield]() { } }",
8940 : "x = class { static [yield]() { } }",
8941 : "x = class { [(yield, 1)]() { } }",
8942 : "x = class { [y = (yield, 1)]() { } }",
8943 : nullptr
8944 5 : };
8945 : // clang-format on
8946 :
8947 5 : RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
8948 5 : RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
8949 :
8950 5 : RunParserSyncTest(strict_function_context_data, parameter_data, kError);
8951 5 : RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
8952 :
8953 5 : RunParserSyncTest(generator_context_data, parameter_data, kError);
8954 5 : RunParserSyncTest(generator_context_data, always_error_param_data, kError);
8955 5 : }
8956 :
8957 26644 : TEST(SpreadArray) {
8958 : const char* context_data[][2] = {
8959 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8960 :
8961 : // clang-format off
8962 : const char* data[] = {
8963 : "[...a]",
8964 : "[a, ...b]",
8965 : "[...a,]",
8966 : "[...a, ,]",
8967 : "[, ...a]",
8968 : "[...a, ...b]",
8969 : "[...a, , ...b]",
8970 : "[...[...a]]",
8971 : "[, ...a]",
8972 : "[, , ...a]",
8973 5 : nullptr};
8974 : // clang-format on
8975 5 : RunParserSyncTest(context_data, data, kSuccess);
8976 5 : }
8977 :
8978 :
8979 26644 : TEST(SpreadArrayError) {
8980 : const char* context_data[][2] = {
8981 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8982 :
8983 : // clang-format off
8984 : const char* data[] = {
8985 : "[...]",
8986 : "[a, ...]",
8987 : "[..., ]",
8988 : "[..., ...]",
8989 : "[ (...a)]",
8990 5 : nullptr};
8991 : // clang-format on
8992 5 : RunParserSyncTest(context_data, data, kError);
8993 5 : }
8994 :
8995 :
8996 26644 : TEST(NewTarget) {
8997 : // clang-format off
8998 : const char* good_context_data[][2] = {
8999 : {"function f() {", "}"},
9000 : {"'use strict'; function f() {", "}"},
9001 : {"var f = function() {", "}"},
9002 : {"'use strict'; var f = function() {", "}"},
9003 : {"({m: function() {", "}})"},
9004 : {"'use strict'; ({m: function() {", "}})"},
9005 : {"({m() {", "}})"},
9006 : {"'use strict'; ({m() {", "}})"},
9007 : {"({get x() {", "}})"},
9008 : {"'use strict'; ({get x() {", "}})"},
9009 : {"({set x(_) {", "}})"},
9010 : {"'use strict'; ({set x(_) {", "}})"},
9011 : {"class C {m() {", "}}"},
9012 : {"class C {get x() {", "}}"},
9013 : {"class C {set x(_) {", "}}"},
9014 : {nullptr}
9015 5 : };
9016 :
9017 : const char* bad_context_data[][2] = {
9018 : {"", ""},
9019 : {"'use strict';", ""},
9020 : {nullptr}
9021 5 : };
9022 :
9023 : const char* data[] = {
9024 : "new.target",
9025 : "{ new.target }",
9026 : "() => { new.target }",
9027 : "() => new.target",
9028 : "if (1) { new.target }",
9029 : "if (1) {} else { new.target }",
9030 : "while (0) { new.target }",
9031 : "do { new.target } while (0)",
9032 : nullptr
9033 5 : };
9034 :
9035 : // clang-format on
9036 :
9037 5 : RunParserSyncTest(good_context_data, data, kSuccess);
9038 5 : RunParserSyncTest(bad_context_data, data, kError);
9039 5 : }
9040 :
9041 26644 : TEST(ImportMetaSuccess) {
9042 : // clang-format off
9043 : const char* context_data[][2] = {
9044 : {"", ""},
9045 : {"'use strict';", ""},
9046 : {"function f() {", "}"},
9047 : {"'use strict'; function f() {", "}"},
9048 : {"var f = function() {", "}"},
9049 : {"'use strict'; var f = function() {", "}"},
9050 : {"({m: function() {", "}})"},
9051 : {"'use strict'; ({m: function() {", "}})"},
9052 : {"({m() {", "}})"},
9053 : {"'use strict'; ({m() {", "}})"},
9054 : {"({get x() {", "}})"},
9055 : {"'use strict'; ({get x() {", "}})"},
9056 : {"({set x(_) {", "}})"},
9057 : {"'use strict'; ({set x(_) {", "}})"},
9058 : {"class C {m() {", "}}"},
9059 : {"class C {get x() {", "}}"},
9060 : {"class C {set x(_) {", "}}"},
9061 : {nullptr}
9062 5 : };
9063 :
9064 : const char* data[] = {
9065 : "import.meta",
9066 : "() => { import.meta }",
9067 : "() => import.meta",
9068 : "if (1) { import.meta }",
9069 : "if (1) {} else { import.meta }",
9070 : "while (0) { import.meta }",
9071 : "do { import.meta } while (0)",
9072 : "import.meta.url",
9073 : "import.meta[0]",
9074 : "import.meta.couldBeMutable = true",
9075 : "import.meta()",
9076 : "new import.meta.MagicClass",
9077 : "new import.meta",
9078 : "t = [...import.meta]",
9079 : "f = {...import.meta}",
9080 : "delete import.meta",
9081 : nullptr
9082 5 : };
9083 :
9084 : // clang-format on
9085 :
9086 : // Making sure the same *wouldn't* parse without the flags
9087 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9088 : nullptr, 0, true, true);
9089 :
9090 : static const ParserFlag flags[] = {
9091 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9092 : };
9093 : // 2.1.1 Static Semantics: Early Errors
9094 : // ImportMeta
9095 : // * It is an early Syntax Error if Module is not the syntactic goal symbol.
9096 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9097 5 : arraysize(flags));
9098 : // Making sure the same wouldn't parse without the flags either
9099 5 : RunParserSyncTest(context_data, data, kError);
9100 :
9101 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
9102 : arraysize(flags));
9103 5 : }
9104 :
9105 26644 : TEST(ImportMetaFailure) {
9106 : // clang-format off
9107 : const char* context_data[][2] = {
9108 : {"var ", ""},
9109 : {"let ", ""},
9110 : {"const ", ""},
9111 : {"var [", "] = [1]"},
9112 : {"([", "] = [1])"},
9113 : {"({", "} = {1})"},
9114 : {"var {", " = 1} = 1"},
9115 : {"for (var ", " of [1]) {}"},
9116 : {"(", ") => {}"},
9117 : {"let f = ", " => {}"},
9118 : {nullptr}
9119 5 : };
9120 :
9121 : const char* data[] = {
9122 : "import.meta",
9123 : nullptr
9124 5 : };
9125 :
9126 : // clang-format on
9127 :
9128 : static const ParserFlag flags[] = {
9129 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9130 : };
9131 :
9132 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9133 5 : arraysize(flags));
9134 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9135 : arraysize(flags));
9136 :
9137 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9138 : nullptr, 0, true, true);
9139 5 : RunParserSyncTest(context_data, data, kError);
9140 5 : }
9141 :
9142 26644 : TEST(ConstSloppy) {
9143 : // clang-format off
9144 : const char* context_data[][2] = {
9145 : {"", ""},
9146 : {"{", "}"},
9147 : {nullptr, nullptr}
9148 5 : };
9149 :
9150 : const char* data[] = {
9151 : "const x = 1",
9152 : "for (const x = 1; x < 1; x++) {}",
9153 : "for (const x in {}) {}",
9154 : "for (const x of []) {}",
9155 : nullptr
9156 5 : };
9157 : // clang-format on
9158 5 : RunParserSyncTest(context_data, data, kSuccess);
9159 5 : }
9160 :
9161 :
9162 26644 : TEST(LetSloppy) {
9163 : // clang-format off
9164 : const char* context_data[][2] = {
9165 : {"", ""},
9166 : {"'use strict';", ""},
9167 : {"{", "}"},
9168 : {nullptr, nullptr}
9169 5 : };
9170 :
9171 : const char* data[] = {
9172 : "let x",
9173 : "let x = 1",
9174 : "for (let x = 1; x < 1; x++) {}",
9175 : "for (let x in {}) {}",
9176 : "for (let x of []) {}",
9177 : nullptr
9178 5 : };
9179 : // clang-format on
9180 :
9181 5 : RunParserSyncTest(context_data, data, kSuccess);
9182 5 : }
9183 :
9184 :
9185 26644 : TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
9186 : // TC39 deemed "use strict" directives to be an error when occurring in the
9187 : // body of a function with non-simple parameter list, on 29/7/2015.
9188 : // https://goo.gl/ueA7Ln
9189 : const char* context_data[][2] = {
9190 : {"function f(", ") { 'use strict'; }"},
9191 : {"function* g(", ") { 'use strict'; }"},
9192 : {"class c { foo(", ") { 'use strict' }"},
9193 : {"var a = (", ") => { 'use strict'; }"},
9194 : {"var o = { m(", ") { 'use strict'; }"},
9195 : {"var o = { *gm(", ") { 'use strict'; }"},
9196 : {"var c = { m(", ") { 'use strict'; }"},
9197 : {"var c = { *gm(", ") { 'use strict'; }"},
9198 :
9199 : {"'use strict'; function f(", ") { 'use strict'; }"},
9200 : {"'use strict'; function* g(", ") { 'use strict'; }"},
9201 : {"'use strict'; class c { foo(", ") { 'use strict' }"},
9202 : {"'use strict'; var a = (", ") => { 'use strict'; }"},
9203 : {"'use strict'; var o = { m(", ") { 'use strict'; }"},
9204 : {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
9205 : {"'use strict'; var c = { m(", ") { 'use strict'; }"},
9206 : {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
9207 :
9208 5 : {nullptr, nullptr}};
9209 :
9210 : const char* data[] = {
9211 : // TODO(@caitp): support formal parameter initializers
9212 : "{}",
9213 : "[]",
9214 : "[{}]",
9215 : "{a}",
9216 : "a, {b}",
9217 : "a, b, {c, d, e}",
9218 : "initializer = true",
9219 : "a, b, c = 1",
9220 : "...args",
9221 : "a, b, ...rest",
9222 : "[a, b, ...rest]",
9223 : "{ bindingPattern = {} }",
9224 : "{ initializedBindingPattern } = { initializedBindingPattern: true }",
9225 5 : nullptr};
9226 :
9227 5 : RunParserSyncTest(context_data, data, kError);
9228 5 : }
9229 :
9230 :
9231 26644 : TEST(LetSloppyOnly) {
9232 : // clang-format off
9233 : const char* context_data[][2] = {
9234 : {"", ""},
9235 : {"{", "}"},
9236 : {"(function() {", "})()"},
9237 : {nullptr, nullptr}
9238 5 : };
9239 :
9240 : const char* data[] = {
9241 : "let",
9242 : "let = 1",
9243 : "for (let = 1; let < 1; let++) {}",
9244 : "for (let in {}) {}",
9245 : "for (var let = 1; let < 1; let++) {}",
9246 : "for (var let in {}) {}",
9247 : "for (var [let] = 1; let < 1; let++) {}",
9248 : "for (var [let] in {}) {}",
9249 : "var let",
9250 : "var [let] = []",
9251 : nullptr
9252 5 : };
9253 : // clang-format on
9254 :
9255 5 : RunParserSyncTest(context_data, data, kSuccess);
9256 :
9257 : // Some things should be rejected even in sloppy mode
9258 : // This addresses BUG(v8:4403).
9259 :
9260 : // clang-format off
9261 : const char* fail_data[] = {
9262 : "let let = 1",
9263 : "for (let let = 1; let < 1; let++) {}",
9264 : "for (let let in {}) {}",
9265 : "for (let let of []) {}",
9266 : "const let = 1",
9267 : "for (const let = 1; let < 1; let++) {}",
9268 : "for (const let in {}) {}",
9269 : "for (const let of []) {}",
9270 : "let [let] = 1",
9271 : "for (let [let] = 1; let < 1; let++) {}",
9272 : "for (let [let] in {}) {}",
9273 : "for (let [let] of []) {}",
9274 : "const [let] = 1",
9275 : "for (const [let] = 1; let < 1; let++) {}",
9276 : "for (const [let] in {}) {}",
9277 : "for (const [let] of []) {}",
9278 :
9279 : // Sprinkle in the escaped version too.
9280 : "let l\\u0065t = 1",
9281 : "const l\\u0065t = 1",
9282 : "let [l\\u0065t] = 1",
9283 : "const [l\\u0065t] = 1",
9284 : "for (let l\\u0065t in {}) {}",
9285 : nullptr
9286 5 : };
9287 : // clang-format on
9288 :
9289 5 : RunParserSyncTest(context_data, fail_data, kError);
9290 5 : }
9291 :
9292 :
9293 26644 : TEST(EscapedKeywords) {
9294 : // clang-format off
9295 : const char* sloppy_context_data[][2] = {
9296 : {"", ""},
9297 : {nullptr, nullptr}
9298 5 : };
9299 :
9300 : const char* strict_context_data[][2] = {
9301 : {"'use strict';", ""},
9302 : {nullptr, nullptr}
9303 5 : };
9304 :
9305 : const char* fail_data[] = {
9306 : "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
9307 : "cl\\u0061ss Foo {}",
9308 : "var x = cl\\u0061ss {}",
9309 : "\\u0063onst foo = 1;",
9310 : "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
9311 : "d\\u0065bugger;",
9312 : "d\\u0065lete this.a;",
9313 : "\\u0063o { } while(0)",
9314 : "if (d\\u006f { true }) {}",
9315 : "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
9316 : "e\\u0078port var foo;",
9317 : "try { } catch (e) {} f\\u0069nally { }",
9318 : "f\\u006fr (var i = 0; i < 10; ++i);",
9319 : "f\\u0075nction fn() {}",
9320 : "var f = f\\u0075nction() {}",
9321 : "\\u0069f (true) { }",
9322 : "\\u0069mport blah from './foo.js';",
9323 : "n\\u0065w function f() {}",
9324 : "(function() { r\\u0065turn; })()",
9325 : "class C extends function() {} { constructor() { sup\\u0065r() } }",
9326 : "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
9327 : "sw\\u0069tch (this.a) {}",
9328 : "var x = th\\u0069s;",
9329 : "th\\u0069s.a = 1;",
9330 : "thr\\u006fw 'boo';",
9331 : "t\\u0072y { true } catch (e) {}",
9332 : "var x = typ\\u0065of 'blah'",
9333 : "v\\u0061r a = true",
9334 : "var v\\u0061r = true",
9335 : "(function() { return v\\u006fid 0; })()",
9336 : "wh\\u0069le (true) { }",
9337 : "w\\u0069th (this.scope) { }",
9338 : "(function*() { y\\u0069eld 1; })()",
9339 : "(function*() { var y\\u0069eld = 1; })()",
9340 :
9341 : "var \\u0065num = 1;",
9342 : "var { \\u0065num } = {}",
9343 : "(\\u0065num = 1);",
9344 :
9345 : // Null / Boolean literals
9346 : "(x === n\\u0075ll);",
9347 : "var x = n\\u0075ll;",
9348 : "var n\\u0075ll = 1;",
9349 : "var { n\\u0075ll } = { 1 };",
9350 : "n\\u0075ll = 1;",
9351 : "(x === tr\\u0075e);",
9352 : "var x = tr\\u0075e;",
9353 : "var tr\\u0075e = 1;",
9354 : "var { tr\\u0075e } = {};",
9355 : "tr\\u0075e = 1;",
9356 : "(x === f\\u0061lse);",
9357 : "var x = f\\u0061lse;",
9358 : "var f\\u0061lse = 1;",
9359 : "var { f\\u0061lse } = {};",
9360 : "f\\u0061lse = 1;",
9361 :
9362 : // TODO(caitp): consistent error messages for labeled statements and
9363 : // expressions
9364 : "switch (this.a) { c\\u0061se 6: break; }",
9365 : "try { } c\\u0061tch (e) {}",
9366 : "switch (this.a) { d\\u0065fault: break; }",
9367 : "class C \\u0065xtends function B() {} {}",
9368 : "for (var a i\\u006e this) {}",
9369 : "if ('foo' \\u0069n this) {}",
9370 : "if (this \\u0069nstanceof Array) {}",
9371 : "(n\\u0065w function f() {})",
9372 : "(typ\\u0065of 123)",
9373 : "(v\\u006fid 0)",
9374 : "do { ; } wh\\u0069le (true) { }",
9375 : "(function*() { return (n++, y\\u0069eld 1); })()",
9376 : "class C { st\\u0061tic bar() {} }",
9377 : "class C { st\\u0061tic *bar() {} }",
9378 : "class C { st\\u0061tic get bar() {} }",
9379 : "class C { st\\u0061tic set bar() {} }",
9380 : "(async ()=>{\\u0061wait 100})()",
9381 : "({\\u0067et get(){}})",
9382 : "({\\u0073et set(){}})",
9383 : "(async ()=>{var \\u0061wait = 100})()",
9384 : nullptr
9385 5 : };
9386 : // clang-format on
9387 :
9388 5 : RunParserSyncTest(sloppy_context_data, fail_data, kError);
9389 5 : RunParserSyncTest(strict_context_data, fail_data, kError);
9390 : RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
9391 :
9392 : // clang-format off
9393 : const char* let_data[] = {
9394 : "var l\\u0065t = 1;",
9395 : "l\\u0065t = 1;",
9396 : "(l\\u0065t === 1);",
9397 : "(y\\u0069eld);",
9398 : "var y\\u0069eld = 1;",
9399 : "var { y\\u0069eld } = {};",
9400 : nullptr
9401 5 : };
9402 : // clang-format on
9403 :
9404 5 : RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
9405 5 : RunParserSyncTest(strict_context_data, let_data, kError);
9406 :
9407 : // Non-errors in sloppy mode
9408 : const char* valid_data[] = {"(\\u0069mplements = 1);",
9409 : "var impl\\u0065ments = 1;",
9410 : "var { impl\\u0065ments } = {};",
9411 : "(\\u0069nterface = 1);",
9412 : "var int\\u0065rface = 1;",
9413 : "var { int\\u0065rface } = {};",
9414 : "(p\\u0061ckage = 1);",
9415 : "var packa\\u0067e = 1;",
9416 : "var { packa\\u0067e } = {};",
9417 : "(p\\u0072ivate = 1);",
9418 : "var p\\u0072ivate;",
9419 : "var { p\\u0072ivate } = {};",
9420 : "(prot\\u0065cted);",
9421 : "var prot\\u0065cted = 1;",
9422 : "var { prot\\u0065cted } = {};",
9423 : "(publ\\u0069c);",
9424 : "var publ\\u0069c = 1;",
9425 : "var { publ\\u0069c } = {};",
9426 : "(st\\u0061tic);",
9427 : "var st\\u0061tic = 1;",
9428 : "var { st\\u0061tic } = {};",
9429 5 : nullptr};
9430 5 : RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
9431 5 : RunParserSyncTest(strict_context_data, valid_data, kError);
9432 : RunModuleParserSyncTest(strict_context_data, valid_data, kError);
9433 5 : }
9434 :
9435 :
9436 26644 : TEST(MiscSyntaxErrors) {
9437 : // clang-format off
9438 : const char* context_data[][2] = {
9439 : { "'use strict'", "" },
9440 : { "", "" },
9441 : { nullptr, nullptr }
9442 5 : };
9443 : const char* error_data[] = {
9444 : "for (();;) {}",
9445 :
9446 : // crbug.com/582626
9447 : "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
9448 : nullptr
9449 5 : };
9450 : // clang-format on
9451 :
9452 5 : RunParserSyncTest(context_data, error_data, kError);
9453 5 : }
9454 :
9455 :
9456 26644 : TEST(EscapeSequenceErrors) {
9457 : // clang-format off
9458 : const char* context_data[][2] = {
9459 : { "'", "'" },
9460 : { "\"", "\"" },
9461 : { "`", "`" },
9462 : { "`${'", "'}`" },
9463 : { "`${\"", "\"}`" },
9464 : { "`${`", "`}`" },
9465 : { nullptr, nullptr }
9466 5 : };
9467 : const char* error_data[] = {
9468 : "\\uABCG",
9469 : "\\u{ZZ}",
9470 : "\\u{FFZ}",
9471 : "\\u{FFFFFFFFFF }",
9472 : "\\u{110000}",
9473 : "\\u{110000",
9474 : "\\u{FFFD }",
9475 : "\\xZF",
9476 : nullptr
9477 5 : };
9478 : // clang-format on
9479 :
9480 5 : RunParserSyncTest(context_data, error_data, kError);
9481 5 : }
9482 :
9483 26644 : TEST(NewTargetErrors) {
9484 : // clang-format off
9485 : const char* context_data[][2] = {
9486 : { "'use strict'", "" },
9487 : { "", "" },
9488 : { nullptr, nullptr }
9489 5 : };
9490 : const char* error_data[] = {
9491 : "var x = new.target",
9492 : "function f() { return new.t\\u0061rget; }",
9493 : nullptr
9494 5 : };
9495 : // clang-format on
9496 5 : RunParserSyncTest(context_data, error_data, kError);
9497 5 : }
9498 :
9499 26644 : TEST(FunctionDeclarationError) {
9500 : // clang-format off
9501 : const char* strict_context[][2] = {
9502 : { "'use strict';", "" },
9503 : { "'use strict'; { ", "}" },
9504 : {"(function() { 'use strict';", "})()"},
9505 : {"(function() { 'use strict'; {", "} })()"},
9506 : { nullptr, nullptr }
9507 5 : };
9508 : const char* sloppy_context[][2] = {
9509 : { "", "" },
9510 : { "{", "}" },
9511 : {"(function() {", "})()"},
9512 : {"(function() { {", "} })()"},
9513 : { nullptr, nullptr }
9514 5 : };
9515 : // Invalid in all contexts
9516 : const char* error_data[] = {
9517 : "try function foo() {} catch (e) {}",
9518 : "do function foo() {} while (0);",
9519 : "for (;false;) function foo() {}",
9520 : "for (var i = 0; i < 1; i++) function f() { };",
9521 : "for (var x in {a: 1}) function f() { };",
9522 : "for (var x in {}) function f() { };",
9523 : "for (var x in {}) function foo() {}",
9524 : "for (x in {a: 1}) function f() { };",
9525 : "for (x in {}) function f() { };",
9526 : "var x; for (x in {}) function foo() {}",
9527 : "with ({}) function f() { };",
9528 : "do label: function foo() {} while (0);",
9529 : "for (;false;) label: function foo() {}",
9530 : "for (var i = 0; i < 1; i++) label: function f() { };",
9531 : "for (var x in {a: 1}) label: function f() { };",
9532 : "for (var x in {}) label: function f() { };",
9533 : "for (var x in {}) label: function foo() {}",
9534 : "for (x in {a: 1}) label: function f() { };",
9535 : "for (x in {}) label: function f() { };",
9536 : "var x; for (x in {}) label: function foo() {}",
9537 : "with ({}) label: function f() { };",
9538 : "if (true) label: function f() {}",
9539 : "if (true) {} else label: function f() {}",
9540 : "if (true) function* f() { }",
9541 : "label: function* f() { }",
9542 : "if (true) async function f() { }",
9543 : "label: async function f() { }",
9544 : "if (true) async function* f() { }",
9545 : "label: async function* f() { }",
9546 : nullptr
9547 5 : };
9548 : // Valid only in sloppy mode.
9549 : const char* sloppy_data[] = {
9550 : "if (true) function foo() {}",
9551 : "if (false) {} else function f() { };",
9552 : "label: function f() { }",
9553 : "label: if (true) function f() { }",
9554 : "label: if (true) {} else function f() { }",
9555 : "label: label2: function f() { }",
9556 : nullptr
9557 5 : };
9558 : // clang-format on
9559 :
9560 : // Nothing parses in strict mode without a SyntaxError
9561 5 : RunParserSyncTest(strict_context, error_data, kError);
9562 5 : RunParserSyncTest(strict_context, sloppy_data, kError);
9563 :
9564 : // In sloppy mode, sloppy_data is successful
9565 5 : RunParserSyncTest(sloppy_context, error_data, kError);
9566 5 : RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
9567 5 : }
9568 :
9569 26644 : TEST(ExponentiationOperator) {
9570 : // clang-format off
9571 : const char* context_data[][2] = {
9572 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9573 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9574 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9575 : { nullptr, nullptr }
9576 5 : };
9577 : const char* data[] = {
9578 : "(delete O.p) ** 10",
9579 : "(delete x) ** 10",
9580 : "(~O.p) ** 10",
9581 : "(~x) ** 10",
9582 : "(!O.p) ** 10",
9583 : "(!x) ** 10",
9584 : "(+O.p) ** 10",
9585 : "(+x) ** 10",
9586 : "(-O.p) ** 10",
9587 : "(-x) ** 10",
9588 : "(typeof O.p) ** 10",
9589 : "(typeof x) ** 10",
9590 : "(void 0) ** 10",
9591 : "(void O.p) ** 10",
9592 : "(void x) ** 10",
9593 : "++O.p ** 10",
9594 : "++x ** 10",
9595 : "--O.p ** 10",
9596 : "--x ** 10",
9597 : "O.p++ ** 10",
9598 : "x++ ** 10",
9599 : "O.p-- ** 10",
9600 : "x-- ** 10",
9601 : nullptr
9602 5 : };
9603 : // clang-format on
9604 :
9605 5 : RunParserSyncTest(context_data, data, kSuccess);
9606 5 : }
9607 :
9608 26644 : TEST(ExponentiationOperatorErrors) {
9609 : // clang-format off
9610 : const char* context_data[][2] = {
9611 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9612 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9613 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9614 : { nullptr, nullptr }
9615 5 : };
9616 : const char* error_data[] = {
9617 : "delete O.p ** 10",
9618 : "delete x ** 10",
9619 : "~O.p ** 10",
9620 : "~x ** 10",
9621 : "!O.p ** 10",
9622 : "!x ** 10",
9623 : "+O.p ** 10",
9624 : "+x ** 10",
9625 : "-O.p ** 10",
9626 : "-x ** 10",
9627 : "typeof O.p ** 10",
9628 : "typeof x ** 10",
9629 : "void ** 10",
9630 : "void O.p ** 10",
9631 : "void x ** 10",
9632 : "++delete O.p ** 10",
9633 : "--delete O.p ** 10",
9634 : "++~O.p ** 10",
9635 : "++~x ** 10",
9636 : "--!O.p ** 10",
9637 : "--!x ** 10",
9638 : "++-O.p ** 10",
9639 : "++-x ** 10",
9640 : "--+O.p ** 10",
9641 : "--+x ** 10",
9642 : "[ x ] **= [ 2 ]",
9643 : "[ x **= 2 ] = [ 2 ]",
9644 : "{ x } **= { x: 2 }",
9645 : "{ x: x **= 2 ] = { x: 2 }",
9646 : // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
9647 : // "Array() **= 10",
9648 : nullptr
9649 5 : };
9650 : // clang-format on
9651 :
9652 5 : RunParserSyncTest(context_data, error_data, kError);
9653 5 : }
9654 :
9655 26644 : TEST(AsyncAwait) {
9656 : // clang-format off
9657 : const char* context_data[][2] = {
9658 : { "'use strict';", "" },
9659 : { "", "" },
9660 : { nullptr, nullptr }
9661 5 : };
9662 :
9663 : const char* data[] = {
9664 : "var asyncFn = async function() { await 1; };",
9665 : "var asyncFn = async function withName() { await 1; };",
9666 : "var asyncFn = async () => await 'test';",
9667 : "var asyncFn = async x => await x + 'test';",
9668 : "async function asyncFn() { await 1; }",
9669 : "var O = { async method() { await 1; } }",
9670 : "var O = { async ['meth' + 'od']() { await 1; } }",
9671 : "var O = { async 'method'() { await 1; } }",
9672 : "var O = { async 0() { await 1; } }",
9673 : "async function await() {}",
9674 :
9675 : "var asyncFn = async({ foo = 1 }) => foo;",
9676 : "var asyncFn = async({ foo = 1 } = {}) => foo;",
9677 :
9678 : "function* g() { var f = async(yield); }",
9679 : "function* g() { var f = async(x = yield); }",
9680 :
9681 : // v8:7817 assert that `await` is still allowed in the body of an arrow fn
9682 : // within formal parameters
9683 : "async(a = a => { var await = 1; return 1; }) => a()",
9684 : "async(a = await => 1); async(a) => 1",
9685 : "(async(a = await => 1), async(a) => 1)",
9686 : "async(a = await => 1, b = async() => 1);",
9687 :
9688 : nullptr
9689 5 : };
9690 : // clang-format on
9691 :
9692 5 : RunParserSyncTest(context_data, data, kSuccess);
9693 :
9694 : // clang-format off
9695 : const char* async_body_context_data[][2] = {
9696 : { "async function f() {", "}" },
9697 : { "var f = async function() {", "}" },
9698 : { "var f = async() => {", "}" },
9699 : { "var O = { async method() {", "} }" },
9700 : { "'use strict'; async function f() {", "}" },
9701 : { "'use strict'; var f = async function() {", "}" },
9702 : { "'use strict'; var f = async() => {", "}" },
9703 : { "'use strict'; var O = { async method() {", "} }" },
9704 : { nullptr, nullptr }
9705 5 : };
9706 :
9707 : const char* body_context_data[][2] = {
9708 : { "function f() {", "}" },
9709 : { "function* g() {", "}" },
9710 : { "var f = function() {", "}" },
9711 : { "var g = function*() {", "}" },
9712 : { "var O = { method() {", "} }" },
9713 : { "var O = { *method() {", "} }" },
9714 : { "var f = () => {", "}" },
9715 : { "'use strict'; function f() {", "}" },
9716 : { "'use strict'; function* g() {", "}" },
9717 : { "'use strict'; var f = function() {", "}" },
9718 : { "'use strict'; var g = function*() {", "}" },
9719 : { "'use strict'; var O = { method() {", "} }" },
9720 : { "'use strict'; var O = { *method() {", "} }" },
9721 : { "'use strict'; var f = () => {", "}" },
9722 : { nullptr, nullptr }
9723 5 : };
9724 :
9725 : const char* body_data[] = {
9726 : "var async = 1; return async;",
9727 : "let async = 1; return async;",
9728 : "const async = 1; return async;",
9729 : "function async() {} return async();",
9730 : "var async = async => async; return async();",
9731 : "function foo() { var await = 1; return await; }",
9732 : "function foo(await) { return await; }",
9733 : "function* foo() { var await = 1; return await; }",
9734 : "function* foo(await) { return await; }",
9735 : "var f = () => { var await = 1; return await; }",
9736 : "var O = { method() { var await = 1; return await; } };",
9737 : "var O = { method(await) { return await; } };",
9738 : "var O = { *method() { var await = 1; return await; } };",
9739 : "var O = { *method(await) { return await; } };",
9740 : "var asyncFn = async function*() {}",
9741 : "async function* f() {}",
9742 : "var O = { async *method() {} };",
9743 :
9744 : "(function await() {})",
9745 : nullptr
9746 5 : };
9747 : // clang-format on
9748 :
9749 5 : RunParserSyncTest(async_body_context_data, body_data, kSuccess);
9750 5 : RunParserSyncTest(body_context_data, body_data, kSuccess);
9751 5 : }
9752 :
9753 26644 : TEST(AsyncAwaitErrors) {
9754 : // clang-format off
9755 : const char* context_data[][2] = {
9756 : { "'use strict';", "" },
9757 : { "", "" },
9758 : { nullptr, nullptr }
9759 5 : };
9760 :
9761 : const char* strict_context_data[][2] = {
9762 : { "'use strict';", "" },
9763 : { nullptr, nullptr }
9764 5 : };
9765 :
9766 : const char* error_data[] = {
9767 : "var asyncFn = async function await() {};",
9768 : "var asyncFn = async () => var await = 'test';",
9769 : "var asyncFn = async await => await + 'test';",
9770 : "var asyncFn = async function(await) {};",
9771 : "var asyncFn = async (await) => 'test';",
9772 : "async function f(await) {}",
9773 :
9774 : "var O = { async method(a, a) {} }",
9775 : "var O = { async ['meth' + 'od'](a, a) {} }",
9776 : "var O = { async 'method'(a, a) {} }",
9777 : "var O = { async 0(a, a) {} }",
9778 :
9779 : "var f = async() => await;",
9780 :
9781 : "var O = { *async method() {} };",
9782 : "var O = { async method*() {} };",
9783 :
9784 : "var asyncFn = async function(x = await 1) { return x; }",
9785 : "async function f(x = await 1) { return x; }",
9786 : "var f = async(x = await 1) => x;",
9787 : "var O = { async method(x = await 1) { return x; } };",
9788 :
9789 : "function* g() { var f = async yield => 1; }",
9790 : "function* g() { var f = async(yield) => 1; }",
9791 : "function* g() { var f = async(x = yield) => 1; }",
9792 : "function* g() { var f = async({x = yield}) => 1; }",
9793 :
9794 : "class C { async constructor() {} }",
9795 : "class C {}; class C2 extends C { async constructor() {} }",
9796 : "class C { static async prototype() {} }",
9797 : "class C {}; class C2 extends C { static async prototype() {} }",
9798 :
9799 : "var f = async() => ((async(x = await 1) => x)();",
9800 :
9801 : // Henrique Ferreiro's bug (tm)
9802 : "(async function foo1() { } foo2 => 1)",
9803 : "(async function foo3() { } () => 1)",
9804 : "(async function foo4() { } => 1)",
9805 : "(async function() { } foo5 => 1)",
9806 : "(async function() { } () => 1)",
9807 : "(async function() { } => 1)",
9808 : "(async.foo6 => 1)",
9809 : "(async.foo7 foo8 => 1)",
9810 : "(async.foo9 () => 1)",
9811 : "(async().foo10 => 1)",
9812 : "(async().foo11 foo12 => 1)",
9813 : "(async().foo13 () => 1)",
9814 : "(async['foo14'] => 1)",
9815 : "(async['foo15'] foo16 => 1)",
9816 : "(async['foo17'] () => 1)",
9817 : "(async()['foo18'] => 1)",
9818 : "(async()['foo19'] foo20 => 1)",
9819 : "(async()['foo21'] () => 1)",
9820 : "(async`foo22` => 1)",
9821 : "(async`foo23` foo24 => 1)",
9822 : "(async`foo25` () => 1)",
9823 : "(async`foo26`.bar27 => 1)",
9824 : "(async`foo28`.bar29 foo30 => 1)",
9825 : "(async`foo31`.bar32 () => 1)",
9826 :
9827 : // v8:5148 assert that errors are still thrown for calls that may have been
9828 : // async functions
9829 : "async({ foo33 = 1 })",
9830 :
9831 : "async(...a = b) => b",
9832 : "async(...a,) => b",
9833 : "async(...a, b) => b",
9834 :
9835 : // v8:7817 assert that `await` is an invalid identifier in arrow formal
9836 : // parameters nested within an async arrow function
9837 : "async(a = await => 1) => a",
9838 : "async(a = (await) => 1) => a",
9839 : "async(a = (...await) => 1) => a",
9840 : nullptr
9841 5 : };
9842 :
9843 : const char* strict_error_data[] = {
9844 : "var O = { async method(eval) {} }",
9845 : "var O = { async ['meth' + 'od'](eval) {} }",
9846 : "var O = { async 'method'(eval) {} }",
9847 : "var O = { async 0(eval) {} }",
9848 :
9849 : "var O = { async method(arguments) {} }",
9850 : "var O = { async ['meth' + 'od'](arguments) {} }",
9851 : "var O = { async 'method'(arguments) {} }",
9852 : "var O = { async 0(arguments) {} }",
9853 :
9854 : "var O = { async method(dupe, dupe) {} }",
9855 :
9856 : // TODO(caitp): preparser needs to report duplicate parameter errors, too.
9857 : // "var f = async(dupe, dupe) => {}",
9858 :
9859 : nullptr
9860 5 : };
9861 :
9862 5 : RunParserSyncTest(context_data, error_data, kError);
9863 5 : RunParserSyncTest(strict_context_data, strict_error_data, kError);
9864 :
9865 : // clang-format off
9866 : const char* async_body_context_data[][2] = {
9867 : { "async function f() {", "}" },
9868 : { "var f = async function() {", "}" },
9869 : { "var f = async() => {", "}" },
9870 : { "var O = { async method() {", "} }" },
9871 : { "'use strict'; async function f() {", "}" },
9872 : { "'use strict'; var f = async function() {", "}" },
9873 : { "'use strict'; var f = async() => {", "}" },
9874 : { "'use strict'; var O = { async method() {", "} }" },
9875 : { nullptr, nullptr }
9876 5 : };
9877 :
9878 : const char* async_body_error_data[] = {
9879 : "var await = 1;",
9880 : "var { await } = 1;",
9881 : "var [ await ] = 1;",
9882 : "return async (await) => {};",
9883 : "var O = { async [await](a, a) {} }",
9884 : "await;",
9885 :
9886 : "function await() {}",
9887 :
9888 : "var f = await => 42;",
9889 : "var f = (await) => 42;",
9890 : "var f = (await, a) => 42;",
9891 : "var f = (...await) => 42;",
9892 :
9893 : "var e = (await);",
9894 : "var e = (await, f);",
9895 : "var e = (await = 42)",
9896 :
9897 : "var e = [await];",
9898 : "var e = {await};",
9899 :
9900 : nullptr
9901 5 : };
9902 : // clang-format on
9903 :
9904 5 : RunParserSyncTest(async_body_context_data, async_body_error_data, kError);
9905 5 : }
9906 :
9907 26644 : TEST(Regress7173) {
9908 : // Await expression is an invalid destructuring target, and should not crash
9909 :
9910 : // clang-format off
9911 : const char* error_context_data[][2] = {
9912 : { "'use strict'; async function f() {", "}" },
9913 : { "async function f() {", "}" },
9914 : { "'use strict'; function f() {", "}" },
9915 : { "function f() {", "}" },
9916 : { "let f = async() => {", "}" },
9917 : { "let f = () => {", "}" },
9918 : { "'use strict'; async function* f() {", "}" },
9919 : { "async function* f() {", "}" },
9920 : { "'use strict'; function* f() {", "}" },
9921 : { "function* f() {", "}" },
9922 : { nullptr, nullptr }
9923 5 : };
9924 :
9925 : const char* error_data[] = {
9926 : "var [await f] = [];",
9927 : "let [await f] = [];",
9928 : "const [await f] = [];",
9929 :
9930 : "var [...await f] = [];",
9931 : "let [...await f] = [];",
9932 : "const [...await f] = [];",
9933 :
9934 : "var { await f } = {};",
9935 : "let { await f } = {};",
9936 : "const { await f } = {};",
9937 :
9938 : "var { ...await f } = {};",
9939 : "let { ...await f } = {};",
9940 : "const { ...await f } = {};",
9941 :
9942 : "var { f: await f } = {};",
9943 : "let { f: await f } = {};",
9944 : "const { f: await f } = {};"
9945 :
9946 : "var { f: ...await f } = {};",
9947 : "let { f: ...await f } = {};",
9948 : "const { f: ...await f } = {};"
9949 :
9950 : "var { [f]: await f } = {};",
9951 : "let { [f]: await f } = {};",
9952 : "const { [f]: await f } = {};",
9953 :
9954 : "var { [f]: ...await f } = {};",
9955 : "let { [f]: ...await f } = {};",
9956 : "const { [f]: ...await f } = {};",
9957 :
9958 : nullptr
9959 5 : };
9960 : // clang-format on
9961 :
9962 5 : RunParserSyncTest(error_context_data, error_data, kError);
9963 5 : }
9964 :
9965 26644 : TEST(AsyncAwaitFormalParameters) {
9966 : // clang-format off
9967 : const char* context_for_formal_parameters[][2] = {
9968 : { "async function f(", ") {}" },
9969 : { "var f = async function f(", ") {}" },
9970 : { "var f = async(", ") => {}" },
9971 : { "'use strict'; async function f(", ") {}" },
9972 : { "'use strict'; var f = async function f(", ") {}" },
9973 : { "'use strict'; var f = async(", ") => {}" },
9974 : { nullptr, nullptr }
9975 5 : };
9976 :
9977 : const char* good_formal_parameters[] = {
9978 : "x = function await() {}",
9979 : "x = function *await() {}",
9980 : "x = function() { let await = 0; }",
9981 : "x = () => { let await = 0; }",
9982 : nullptr
9983 5 : };
9984 :
9985 : const char* bad_formal_parameters[] = {
9986 : "{ await }",
9987 : "{ await = 1 }",
9988 : "{ await } = {}",
9989 : "{ await = 1 } = {}",
9990 : "[await]",
9991 : "[await] = []",
9992 : "[await = 1]",
9993 : "[await = 1] = []",
9994 : "...await",
9995 : "await",
9996 : "await = 1",
9997 : "...[await]",
9998 : "x = await",
9999 :
10000 : // v8:5190
10001 : "1) => 1",
10002 : "'str') => 1",
10003 : "/foo/) => 1",
10004 : "{ foo = async(1) => 1 }) => 1",
10005 : "{ foo = async(a) => 1 })",
10006 :
10007 : "x = async(await)",
10008 : "x = { [await]: 1 }",
10009 : "x = class extends (await) { }",
10010 : "x = class { static [await]() {} }",
10011 : "{ x = await }",
10012 :
10013 : // v8:6714
10014 : "x = class await {}",
10015 : "x = 1 ? class await {} : 0",
10016 : "x = async function await() {}",
10017 :
10018 : "x = y[await]",
10019 : "x = `${await}`",
10020 : "x = y()[await]",
10021 :
10022 : nullptr
10023 5 : };
10024 : // clang-format on
10025 :
10026 : RunParserSyncTest(context_for_formal_parameters, good_formal_parameters,
10027 5 : kSuccess);
10028 :
10029 : RunParserSyncTest(context_for_formal_parameters, bad_formal_parameters,
10030 5 : kError);
10031 5 : }
10032 :
10033 26644 : TEST(AsyncAwaitModule) {
10034 : // clang-format off
10035 : const char* context_data[][2] = {
10036 : { "", "" },
10037 : { nullptr, nullptr }
10038 5 : };
10039 :
10040 : const char* data[] = {
10041 : "export default async function() { await 1; }",
10042 : "export default async function async() { await 1; }",
10043 : "export async function async() { await 1; }",
10044 : nullptr
10045 5 : };
10046 : // clang-format on
10047 :
10048 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
10049 : nullptr, 0, false);
10050 5 : }
10051 :
10052 26644 : TEST(AsyncAwaitModuleErrors) {
10053 : // clang-format off
10054 : const char* context_data[][2] = {
10055 : { "", "" },
10056 : { nullptr, nullptr }
10057 5 : };
10058 :
10059 : const char* error_data[] = {
10060 : "export default (async function await() {})",
10061 : "export default async function await() {}",
10062 : "export async function await() {}",
10063 : "export async function() {}",
10064 : "export async",
10065 : "export async\nfunction async() { await 1; }",
10066 : nullptr
10067 5 : };
10068 : // clang-format on
10069 :
10070 : RunModuleParserSyncTest(context_data, error_data, kError, nullptr, 0, nullptr,
10071 : 0, nullptr, 0, false);
10072 5 : }
10073 :
10074 26644 : TEST(RestrictiveForInErrors) {
10075 : // clang-format off
10076 : const char* strict_context_data[][2] = {
10077 : { "'use strict'", "" },
10078 : { nullptr, nullptr }
10079 5 : };
10080 : const char* sloppy_context_data[][2] = {
10081 : { "", "" },
10082 : { nullptr, nullptr }
10083 5 : };
10084 : const char* error_data[] = {
10085 : "for (const x = 0 in {});",
10086 : "for (let x = 0 in {});",
10087 : nullptr
10088 5 : };
10089 : const char* sloppy_data[] = {
10090 : "for (var x = 0 in {});",
10091 : nullptr
10092 5 : };
10093 : // clang-format on
10094 :
10095 5 : RunParserSyncTest(strict_context_data, error_data, kError);
10096 5 : RunParserSyncTest(strict_context_data, sloppy_data, kError);
10097 5 : RunParserSyncTest(sloppy_context_data, error_data, kError);
10098 5 : RunParserSyncTest(sloppy_context_data, sloppy_data, kSuccess);
10099 5 : }
10100 :
10101 26644 : TEST(NoDuplicateGeneratorsInBlock) {
10102 : const char* block_context_data[][2] = {
10103 : {"'use strict'; {", "}"},
10104 : {"{", "}"},
10105 : {"(function() { {", "} })()"},
10106 : {"(function() {'use strict'; {", "} })()"},
10107 5 : {nullptr, nullptr}};
10108 : const char* top_level_context_data[][2] = {
10109 : {"'use strict';", ""},
10110 : {"", ""},
10111 : {"(function() {", "})()"},
10112 : {"(function() {'use strict';", "})()"},
10113 5 : {nullptr, nullptr}};
10114 : const char* error_data[] = {"function* x() {} function* x() {}",
10115 : "function x() {} function* x() {}",
10116 5 : "function* x() {} function x() {}", nullptr};
10117 : // The preparser doesn't enforce the restriction, so turn it off.
10118 : bool test_preparser = false;
10119 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10120 5 : 0, nullptr, 0, false, test_preparser);
10121 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10122 5 : }
10123 :
10124 26644 : TEST(NoDuplicateAsyncFunctionInBlock) {
10125 : const char* block_context_data[][2] = {
10126 : {"'use strict'; {", "}"},
10127 : {"{", "}"},
10128 : {"(function() { {", "} })()"},
10129 : {"(function() {'use strict'; {", "} })()"},
10130 5 : {nullptr, nullptr}};
10131 : const char* top_level_context_data[][2] = {
10132 : {"'use strict';", ""},
10133 : {"", ""},
10134 : {"(function() {", "})()"},
10135 : {"(function() {'use strict';", "})()"},
10136 5 : {nullptr, nullptr}};
10137 : const char* error_data[] = {"async function x() {} async function x() {}",
10138 : "function x() {} async function x() {}",
10139 : "async function x() {} function x() {}",
10140 : "function* x() {} async function x() {}",
10141 : "function* x() {} async function x() {}",
10142 : "async function x() {} function* x() {}",
10143 : "function* x() {} async function x() {}",
10144 5 : nullptr};
10145 : // The preparser doesn't enforce the restriction, so turn it off.
10146 : bool test_preparser = false;
10147 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10148 5 : 0, nullptr, 0, false, test_preparser);
10149 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10150 5 : }
10151 :
10152 26644 : TEST(TrailingCommasInParameters) {
10153 : // clang-format off
10154 : const char* context_data[][2] = {
10155 : { "", "" },
10156 : { "'use strict';", "" },
10157 : { "function foo() {", "}" },
10158 : { "function foo() {'use strict';", "}" },
10159 : { nullptr, nullptr }
10160 5 : };
10161 :
10162 : const char* data[] = {
10163 : " function a(b,) {}",
10164 : " function* a(b,) {}",
10165 : "(function a(b,) {});",
10166 : "(function* a(b,) {});",
10167 : "(function (b,) {});",
10168 : "(function* (b,) {});",
10169 : " function a(b,c,d,) {}",
10170 : " function* a(b,c,d,) {}",
10171 : "(function a(b,c,d,) {});",
10172 : "(function* a(b,c,d,) {});",
10173 : "(function (b,c,d,) {});",
10174 : "(function* (b,c,d,) {});",
10175 : "(b,) => {};",
10176 : "(b,c,d,) => {};",
10177 : "a(1,);",
10178 : "a(1,2,3,);",
10179 : "a(...[],);",
10180 : "a(1, 2, ...[],);",
10181 : "a(...[], 2, ...[],);",
10182 : nullptr
10183 5 : };
10184 : // clang-format on
10185 :
10186 5 : RunParserSyncTest(context_data, data, kSuccess);
10187 5 : }
10188 :
10189 26644 : TEST(TrailingCommasInParametersErrors) {
10190 : // clang-format off
10191 : const char* context_data[][2] = {
10192 : { "", "" },
10193 : { "'use strict';", "" },
10194 : { "function foo() {", "}" },
10195 : { "function foo() {'use strict';", "}" },
10196 : { nullptr, nullptr }
10197 5 : };
10198 :
10199 : const char* data[] = {
10200 : // too many trailing commas
10201 : " function a(b,,) {}",
10202 : " function* a(b,,) {}",
10203 : "(function a(b,,) {});",
10204 : "(function* a(b,,) {});",
10205 : "(function (b,,) {});",
10206 : "(function* (b,,) {});",
10207 : " function a(b,c,d,,) {}",
10208 : " function* a(b,c,d,,) {}",
10209 : "(function a(b,c,d,,) {});",
10210 : "(function* a(b,c,d,,) {});",
10211 : "(function (b,c,d,,) {});",
10212 : "(function* (b,c,d,,) {});",
10213 : "(b,,) => {};",
10214 : "(b,c,d,,) => {};",
10215 : "a(1,,);",
10216 : "a(1,2,3,,);",
10217 : // only a trailing comma and no parameters
10218 : " function a1(,) {}",
10219 : " function* a2(,) {}",
10220 : "(function a3(,) {});",
10221 : "(function* a4(,) {});",
10222 : "(function (,) {});",
10223 : "(function* (,) {});",
10224 : "(,) => {};",
10225 : "a1(,);",
10226 : // no trailing commas after rest parameter declaration
10227 : " function a(...b,) {}",
10228 : " function* a(...b,) {}",
10229 : "(function a(...b,) {});",
10230 : "(function* a(...b,) {});",
10231 : "(function (...b,) {});",
10232 : "(function* (...b,) {});",
10233 : " function a(b, c, ...d,) {}",
10234 : " function* a(b, c, ...d,) {}",
10235 : "(function a(b, c, ...d,) {});",
10236 : "(function* a(b, c, ...d,) {});",
10237 : "(function (b, c, ...d,) {});",
10238 : "(function* (b, c, ...d,) {});",
10239 : "(...b,) => {};",
10240 : "(b, c, ...d,) => {};",
10241 : // parenthesized trailing comma without arrow is still an error
10242 : "(,);",
10243 : "(a,);",
10244 : "(a,b,c,);",
10245 : nullptr
10246 5 : };
10247 : // clang-format on
10248 :
10249 5 : RunParserSyncTest(context_data, data, kError);
10250 5 : }
10251 :
10252 26644 : TEST(ArgumentsRedeclaration) {
10253 : {
10254 : // clang-format off
10255 : const char* context_data[][2] = {
10256 : { "function f(", ") {}" },
10257 : { nullptr, nullptr }
10258 5 : };
10259 : const char* success_data[] = {
10260 : "{arguments}",
10261 : "{arguments = false}",
10262 : "arg1, arguments",
10263 : "arg1, ...arguments",
10264 : nullptr
10265 5 : };
10266 : // clang-format on
10267 5 : RunParserSyncTest(context_data, success_data, kSuccess);
10268 : }
10269 :
10270 : {
10271 : // clang-format off
10272 : const char* context_data[][2] = {
10273 : { "function f() {", "}" },
10274 : { nullptr, nullptr }
10275 5 : };
10276 : const char* data[] = {
10277 : "const arguments = 1",
10278 : "let arguments",
10279 : "var arguments",
10280 : nullptr
10281 5 : };
10282 : // clang-format on
10283 5 : RunParserSyncTest(context_data, data, kSuccess);
10284 : }
10285 5 : }
10286 :
10287 :
10288 : // Test that lazily parsed inner functions don't result in overly pessimistic
10289 : // context allocations.
10290 26644 : TEST(NoPessimisticContextAllocation) {
10291 : i::Isolate* isolate = CcTest::i_isolate();
10292 : i::Factory* factory = isolate->factory();
10293 : i::HandleScope scope(isolate);
10294 5 : LocalContext env;
10295 :
10296 : const char* prefix = "(function outer() { var my_var; ";
10297 : const char* suffix = " })();";
10298 5 : int prefix_len = Utf8LengthHelper(prefix);
10299 5 : int suffix_len = Utf8LengthHelper(suffix);
10300 :
10301 : // Test both normal inner functions and inner arrow functions.
10302 : const char* inner_functions[] = {"function inner(%s) { %s }",
10303 5 : "(%s) => { %s }"};
10304 :
10305 : struct {
10306 : const char* params;
10307 : const char* source;
10308 : bool ctxt_allocate;
10309 : } inners[] = {
10310 : // Context allocating because we need to:
10311 : {"", "my_var;", true},
10312 : {"", "if (true) { let my_var; } my_var;", true},
10313 : {"", "eval('foo');", true},
10314 : {"", "function inner2() { my_var; }", true},
10315 : {"", "function inner2() { eval('foo'); }", true},
10316 : {"", "var {my_var : a} = {my_var};", true},
10317 : {"", "let {my_var : a} = {my_var};", true},
10318 : {"", "const {my_var : a} = {my_var};", true},
10319 : {"", "var [a, b = my_var] = [1, 2];", true},
10320 : {"", "var [a, b = my_var] = [1, 2]; my_var;", true},
10321 : {"", "let [a, b = my_var] = [1, 2];", true},
10322 : {"", "let [a, b = my_var] = [1, 2]; my_var;", true},
10323 : {"", "const [a, b = my_var] = [1, 2];", true},
10324 : {"", "const [a, b = my_var] = [1, 2]; my_var;", true},
10325 : {"", "var {a = my_var} = {}", true},
10326 : {"", "var {a: b = my_var} = {}", true},
10327 : {"", "let {a = my_var} = {}", true},
10328 : {"", "let {a: b = my_var} = {}", true},
10329 : {"", "const {a = my_var} = {}", true},
10330 : {"", "const {a: b = my_var} = {}", true},
10331 : {"a = my_var", "", true},
10332 : {"a = my_var", "let my_var;", true},
10333 : {"", "function inner2(a = my_var) { }", true},
10334 : {"", "(a = my_var) => { }", true},
10335 : {"{a} = {a: my_var}", "", true},
10336 : {"", "function inner2({a} = {a: my_var}) { }", true},
10337 : {"", "({a} = {a: my_var}) => { }", true},
10338 : {"[a] = [my_var]", "", true},
10339 : {"", "function inner2([a] = [my_var]) { }", true},
10340 : {"", "([a] = [my_var]) => { }", true},
10341 : {"", "function inner2(a = eval('')) { }", true},
10342 : {"", "(a = eval('')) => { }", true},
10343 : {"", "try { } catch (my_var) { } my_var;", true},
10344 : {"", "for (my_var in {}) { my_var; }", true},
10345 : {"", "for (my_var in {}) { }", true},
10346 : {"", "for (my_var of []) { my_var; }", true},
10347 : {"", "for (my_var of []) { }", true},
10348 : {"", "for ([a, my_var, b] in {}) { my_var; }", true},
10349 : {"", "for ([a, my_var, b] of []) { my_var; }", true},
10350 : {"", "for ({x: my_var} in {}) { my_var; }", true},
10351 : {"", "for ({x: my_var} of []) { my_var; }", true},
10352 : {"", "for ({my_var} in {}) { my_var; }", true},
10353 : {"", "for ({my_var} of []) { my_var; }", true},
10354 : {"", "for ({y, x: my_var} in {}) { my_var; }", true},
10355 : {"", "for ({y, x: my_var} of []) { my_var; }", true},
10356 : {"", "for ({a, my_var} in {}) { my_var; }", true},
10357 : {"", "for ({a, my_var} of []) { my_var; }", true},
10358 : {"", "for (let my_var in {}) { } my_var;", true},
10359 : {"", "for (let my_var of []) { } my_var;", true},
10360 : {"", "for (let [a, my_var, b] in {}) { } my_var;", true},
10361 : {"", "for (let [a, my_var, b] of []) { } my_var;", true},
10362 : {"", "for (let {x: my_var} in {}) { } my_var;", true},
10363 : {"", "for (let {x: my_var} of []) { } my_var;", true},
10364 : {"", "for (let {my_var} in {}) { } my_var;", true},
10365 : {"", "for (let {my_var} of []) { } my_var;", true},
10366 : {"", "for (let {y, x: my_var} in {}) { } my_var;", true},
10367 : {"", "for (let {y, x: my_var} of []) { } my_var;", true},
10368 : {"", "for (let {a, my_var} in {}) { } my_var;", true},
10369 : {"", "for (let {a, my_var} of []) { } my_var;", true},
10370 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { } my_var;", true},
10371 : {"", "'use strict'; if (true) { function my_var() {} } my_var;", true},
10372 : {"",
10373 : "'use strict'; function inner2() { if (true) { function my_var() {} } "
10374 : "my_var; }",
10375 : true},
10376 : {"",
10377 : "function inner2() { 'use strict'; if (true) { function my_var() {} } "
10378 : "my_var; }",
10379 : true},
10380 : {"",
10381 : "() => { 'use strict'; if (true) { function my_var() {} } my_var; }",
10382 : true},
10383 : {"",
10384 : "if (true) { let my_var; if (true) { function my_var() {} } } my_var;",
10385 : true},
10386 : {"", "function inner2(a = my_var) {}", true},
10387 : {"", "function inner2(a = my_var) { let my_var; }", true},
10388 : {"", "(a = my_var) => {}", true},
10389 : {"", "(a = my_var) => { let my_var; }", true},
10390 : // No pessimistic context allocation:
10391 : {"", "var my_var; my_var;", false},
10392 : {"", "var my_var;", false},
10393 : {"", "var my_var = 0;", false},
10394 : {"", "if (true) { var my_var; } my_var;", false},
10395 : {"", "let my_var; my_var;", false},
10396 : {"", "let my_var;", false},
10397 : {"", "let my_var = 0;", false},
10398 : {"", "const my_var = 0; my_var;", false},
10399 : {"", "const my_var = 0;", false},
10400 : {"", "var [a, my_var] = [1, 2]; my_var;", false},
10401 : {"", "let [a, my_var] = [1, 2]; my_var;", false},
10402 : {"", "const [a, my_var] = [1, 2]; my_var;", false},
10403 : {"", "var {a: my_var} = {a: 3}; my_var;", false},
10404 : {"", "let {a: my_var} = {a: 3}; my_var;", false},
10405 : {"", "const {a: my_var} = {a: 3}; my_var;", false},
10406 : {"", "var {my_var} = {my_var: 3}; my_var;", false},
10407 : {"", "let {my_var} = {my_var: 3}; my_var;", false},
10408 : {"", "const {my_var} = {my_var: 3}; my_var;", false},
10409 : {"my_var", "my_var;", false},
10410 : {"my_var", "", false},
10411 : {"my_var = 5", "my_var;", false},
10412 : {"my_var = 5", "", false},
10413 : {"...my_var", "my_var;", false},
10414 : {"...my_var", "", false},
10415 : {"[a, my_var, b]", "my_var;", false},
10416 : {"[a, my_var, b]", "", false},
10417 : {"[a, my_var, b] = [1, 2, 3]", "my_var;", false},
10418 : {"[a, my_var, b] = [1, 2, 3]", "", false},
10419 : {"{x: my_var}", "my_var;", false},
10420 : {"{x: my_var}", "", false},
10421 : {"{x: my_var} = {x: 0}", "my_var;", false},
10422 : {"{x: my_var} = {x: 0}", "", false},
10423 : {"{my_var}", "my_var;", false},
10424 : {"{my_var}", "", false},
10425 : {"{my_var} = {my_var: 0}", "my_var;", false},
10426 : {"{my_var} = {my_var: 0}", "", false},
10427 : {"", "function inner2(my_var) { my_var; }", false},
10428 : {"", "function inner2(my_var) { }", false},
10429 : {"", "function inner2(my_var = 5) { my_var; }", false},
10430 : {"", "function inner2(my_var = 5) { }", false},
10431 : {"", "function inner2(...my_var) { my_var; }", false},
10432 : {"", "function inner2(...my_var) { }", false},
10433 : {"", "function inner2([a, my_var, b]) { my_var; }", false},
10434 : {"", "function inner2([a, my_var, b]) { }", false},
10435 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { my_var; }", false},
10436 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { }", false},
10437 : {"", "function inner2({x: my_var}) { my_var; }", false},
10438 : {"", "function inner2({x: my_var}) { }", false},
10439 : {"", "function inner2({x: my_var} = {x: 0}) { my_var; }", false},
10440 : {"", "function inner2({x: my_var} = {x: 0}) { }", false},
10441 : {"", "function inner2({my_var}) { my_var; }", false},
10442 : {"", "function inner2({my_var}) { }", false},
10443 : {"", "function inner2({my_var} = {my_var: 8}) { my_var; } ", false},
10444 : {"", "function inner2({my_var} = {my_var: 8}) { }", false},
10445 : {"", "my_var => my_var;", false},
10446 : {"", "my_var => { }", false},
10447 : {"", "(my_var = 5) => my_var;", false},
10448 : {"", "(my_var = 5) => { }", false},
10449 : {"", "(...my_var) => my_var;", false},
10450 : {"", "(...my_var) => { }", false},
10451 : {"", "([a, my_var, b]) => my_var;", false},
10452 : {"", "([a, my_var, b]) => { }", false},
10453 : {"", "([a, my_var, b] = [1, 2, 3]) => my_var;", false},
10454 : {"", "([a, my_var, b] = [1, 2, 3]) => { }", false},
10455 : {"", "({x: my_var}) => my_var;", false},
10456 : {"", "({x: my_var}) => { }", false},
10457 : {"", "({x: my_var} = {x: 0}) => my_var;", false},
10458 : {"", "({x: my_var} = {x: 0}) => { }", false},
10459 : {"", "({my_var}) => my_var;", false},
10460 : {"", "({my_var}) => { }", false},
10461 : {"", "({my_var} = {my_var: 5}) => my_var;", false},
10462 : {"", "({my_var} = {my_var: 5}) => { }", false},
10463 : {"", "({a, my_var}) => my_var;", false},
10464 : {"", "({a, my_var}) => { }", false},
10465 : {"", "({a, my_var} = {a: 0, my_var: 5}) => my_var;", false},
10466 : {"", "({a, my_var} = {a: 0, my_var: 5}) => { }", false},
10467 : {"", "({y, x: my_var}) => my_var;", false},
10468 : {"", "({y, x: my_var}) => { }", false},
10469 : {"", "({y, x: my_var} = {y: 0, x: 0}) => my_var;", false},
10470 : {"", "({y, x: my_var} = {y: 0, x: 0}) => { }", false},
10471 : {"", "try { } catch (my_var) { my_var; }", false},
10472 : {"", "try { } catch ([a, my_var, b]) { my_var; }", false},
10473 : {"", "try { } catch ({x: my_var}) { my_var; }", false},
10474 : {"", "try { } catch ({y, x: my_var}) { my_var; }", false},
10475 : {"", "try { } catch ({my_var}) { my_var; }", false},
10476 : {"", "for (let my_var in {}) { my_var; }", false},
10477 : {"", "for (let my_var in {}) { }", false},
10478 : {"", "for (let my_var of []) { my_var; }", false},
10479 : {"", "for (let my_var of []) { }", false},
10480 : {"", "for (let [a, my_var, b] in {}) { my_var; }", false},
10481 : {"", "for (let [a, my_var, b] of []) { my_var; }", false},
10482 : {"", "for (let {x: my_var} in {}) { my_var; }", false},
10483 : {"", "for (let {x: my_var} of []) { my_var; }", false},
10484 : {"", "for (let {my_var} in {}) { my_var; }", false},
10485 : {"", "for (let {my_var} of []) { my_var; }", false},
10486 : {"", "for (let {y, x: my_var} in {}) { my_var; }", false},
10487 : {"", "for (let {y, x: my_var} of []) { my_var; }", false},
10488 : {"", "for (let {a, my_var} in {}) { my_var; }", false},
10489 : {"", "for (let {a, my_var} of []) { my_var; }", false},
10490 : {"", "for (var my_var in {}) { my_var; }", false},
10491 : {"", "for (var my_var in {}) { }", false},
10492 : {"", "for (var my_var of []) { my_var; }", false},
10493 : {"", "for (var my_var of []) { }", false},
10494 : {"", "for (var [a, my_var, b] in {}) { my_var; }", false},
10495 : {"", "for (var [a, my_var, b] of []) { my_var; }", false},
10496 : {"", "for (var {x: my_var} in {}) { my_var; }", false},
10497 : {"", "for (var {x: my_var} of []) { my_var; }", false},
10498 : {"", "for (var {my_var} in {}) { my_var; }", false},
10499 : {"", "for (var {my_var} of []) { my_var; }", false},
10500 : {"", "for (var {y, x: my_var} in {}) { my_var; }", false},
10501 : {"", "for (var {y, x: my_var} of []) { my_var; }", false},
10502 : {"", "for (var {a, my_var} in {}) { my_var; }", false},
10503 : {"", "for (var {a, my_var} of []) { my_var; }", false},
10504 : {"", "for (var my_var in {}) { } my_var;", false},
10505 : {"", "for (var my_var of []) { } my_var;", false},
10506 : {"", "for (var [a, my_var, b] in {}) { } my_var;", false},
10507 : {"", "for (var [a, my_var, b] of []) { } my_var;", false},
10508 : {"", "for (var {x: my_var} in {}) { } my_var;", false},
10509 : {"", "for (var {x: my_var} of []) { } my_var;", false},
10510 : {"", "for (var {my_var} in {}) { } my_var;", false},
10511 : {"", "for (var {my_var} of []) { } my_var;", false},
10512 : {"", "for (var {y, x: my_var} in {}) { } my_var;", false},
10513 : {"", "for (var {y, x: my_var} of []) { } my_var;", false},
10514 : {"", "for (var {a, my_var} in {}) { } my_var;", false},
10515 : {"", "for (var {a, my_var} of []) { } my_var;", false},
10516 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10517 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10518 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { } my_var; ", false},
10519 : {"", "for (let a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10520 : false},
10521 : {"", "for (var a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10522 : false},
10523 : {"", "class my_var {}; my_var; ", false},
10524 : {"", "function my_var() {} my_var;", false},
10525 : {"", "if (true) { function my_var() {} } my_var;", false},
10526 : {"", "function inner2() { if (true) { function my_var() {} } my_var; }",
10527 : false},
10528 : {"", "() => { if (true) { function my_var() {} } my_var; }", false},
10529 : {"",
10530 : "if (true) { var my_var; if (true) { function my_var() {} } } my_var;",
10531 : false},
10532 5 : };
10533 :
10534 25 : for (unsigned inner_ix = 0; inner_ix < arraysize(inner_functions);
10535 : ++inner_ix) {
10536 10 : const char* inner_function = inner_functions[inner_ix];
10537 10 : int inner_function_len = Utf8LengthHelper(inner_function) - 4;
10538 :
10539 4110 : for (unsigned i = 0; i < arraysize(inners); ++i) {
10540 2050 : int params_len = Utf8LengthHelper(inners[i].params);
10541 2050 : int source_len = Utf8LengthHelper(inners[i].source);
10542 2050 : int len = prefix_len + inner_function_len + params_len + source_len +
10543 2050 : suffix_len;
10544 :
10545 2050 : i::ScopedVector<char> program(len + 1);
10546 2050 : i::SNPrintF(program, "%s", prefix);
10547 2050 : i::SNPrintF(program + prefix_len, inner_function, inners[i].params,
10548 2050 : inners[i].source);
10549 2050 : i::SNPrintF(
10550 2050 : program + prefix_len + inner_function_len + params_len + source_len,
10551 2050 : "%s", suffix);
10552 :
10553 : i::Handle<i::String> source =
10554 2050 : factory->InternalizeUtf8String(program.start());
10555 4100 : source->PrintOn(stdout);
10556 : printf("\n");
10557 :
10558 2050 : i::Handle<i::Script> script = factory->NewScript(source);
10559 4100 : i::ParseInfo info(isolate, script);
10560 :
10561 2050 : CHECK(i::parsing::ParseProgram(&info, isolate));
10562 2050 : CHECK(i::Compiler::Analyze(&info));
10563 2050 : CHECK_NOT_NULL(info.literal());
10564 :
10565 : i::Scope* scope = info.literal()->scope()->inner_scope();
10566 : DCHECK_NOT_NULL(scope);
10567 : DCHECK_NULL(scope->sibling());
10568 : DCHECK(scope->is_function_scope());
10569 : const i::AstRawString* var_name =
10570 2050 : info.ast_value_factory()->GetOneByteString("my_var");
10571 : i::Variable* var = scope->LookupForTesting(var_name);
10572 2050 : CHECK_EQ(inners[i].ctxt_allocate,
10573 : i::ScopeTestHelper::MustAllocateInContext(var));
10574 : }
10575 : }
10576 5 : }
10577 :
10578 26644 : TEST(EscapedStrictReservedWord) {
10579 : // Test that identifiers which are both escaped and only reserved in the
10580 : // strict mode are accepted in non-strict mode.
10581 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
10582 :
10583 : const char* statement_data[] = {"if (true) l\\u0065t: ;",
10584 : "function l\\u0065t() { }",
10585 : "(function l\\u0065t() { })",
10586 : "async function l\\u0065t() { }",
10587 : "(async function l\\u0065t() { })",
10588 : "l\\u0065t => 42",
10589 : "async l\\u0065t => 42",
10590 : "function packag\\u0065() {}",
10591 : "function impl\\u0065ments() {}",
10592 : "function privat\\u0065() {}",
10593 5 : nullptr};
10594 :
10595 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
10596 5 : }
10597 :
10598 26644 : TEST(ForAwaitOf) {
10599 : // clang-format off
10600 : const char* context_data[][2] = {
10601 : { "async function f() { for await ", " ; }" },
10602 : { "async function f() { for await ", " { } }" },
10603 : { "async function * f() { for await ", " { } }" },
10604 : { "async function f() { 'use strict'; for await ", " ; }" },
10605 : { "async function f() { 'use strict'; for await ", " { } }" },
10606 : { "async function * f() { 'use strict'; for await ", " { } }" },
10607 : { "async function f() { for\nawait ", " ; }" },
10608 : { "async function f() { for\nawait ", " { } }" },
10609 : { "async function * f() { for\nawait ", " { } }" },
10610 : { "async function f() { 'use strict'; for\nawait ", " ; }" },
10611 : { "async function f() { 'use strict'; for\nawait ", " { } }" },
10612 : { "async function * f() { 'use strict'; for\nawait ", " { } }" },
10613 : { "async function f() { for await\n", " ; }" },
10614 : { "async function f() { for await\n", " { } }" },
10615 : { "async function * f() { for await\n", " { } }" },
10616 : { "async function f() { 'use strict'; for await\n", " ; }" },
10617 : { "async function f() { 'use strict'; for await\n", " { } }" },
10618 : { "async function * f() { 'use strict'; for await\n", " { } }" },
10619 : { nullptr, nullptr }
10620 5 : };
10621 :
10622 : const char* context_data2[][2] = {
10623 : { "async function f() { let a; for await ", " ; }" },
10624 : { "async function f() { let a; for await ", " { } }" },
10625 : { "async function * f() { let a; for await ", " { } }" },
10626 : { "async function f() { 'use strict'; let a; for await ", " ; }" },
10627 : { "async function f() { 'use strict'; let a; for await ", " { } }" },
10628 : { "async function * f() { 'use strict'; let a; for await ", " { } }" },
10629 : { "async function f() { let a; for\nawait ", " ; }" },
10630 : { "async function f() { let a; for\nawait ", " { } }" },
10631 : { "async function * f() { let a; for\nawait ", " { } }" },
10632 : { "async function f() { 'use strict'; let a; for\nawait ", " ; }" },
10633 : { "async function f() { 'use strict'; let a; for\nawait ", " { } }" },
10634 : { "async function * f() { 'use strict'; let a; for\nawait ", " { } }" },
10635 : { "async function f() { let a; for await\n", " ; }" },
10636 : { "async function f() { let a; for await\n", " { } }" },
10637 : { "async function * f() { let a; for await\n", " { } }" },
10638 : { "async function f() { 'use strict'; let a; for await\n", " ; }" },
10639 : { "async function f() { 'use strict'; let a; for await\n", " { } }" },
10640 : { "async function * f() { 'use strict'; let a; for await\n", " { } }" },
10641 : { nullptr, nullptr }
10642 5 : };
10643 :
10644 : const char* expr_data[] = {
10645 : // Primary Expressions
10646 : "(a of [])",
10647 : "(a.b of [])",
10648 : "([a] of [])",
10649 : "([a = 1] of [])",
10650 : "([a = 1, ...b] of [])",
10651 : "({a} of [])",
10652 : "({a: a} of [])",
10653 : "({'a': a} of [])",
10654 : "({\"a\": a} of [])",
10655 : "({[Symbol.iterator]: a} of [])",
10656 : "({0: a} of [])",
10657 : "({a = 1} of [])",
10658 : "({a: a = 1} of [])",
10659 : "({'a': a = 1} of [])",
10660 : "({\"a\": a = 1} of [])",
10661 : "({[Symbol.iterator]: a = 1} of [])",
10662 : "({0: a = 1} of [])",
10663 : nullptr
10664 5 : };
10665 :
10666 : const char* var_data[] = {
10667 : // VarDeclarations
10668 : "(var a of [])",
10669 : "(var [a] of [])",
10670 : "(var [a = 1] of [])",
10671 : "(var [a = 1, ...b] of [])",
10672 : "(var {a} of [])",
10673 : "(var {a: a} of [])",
10674 : "(var {'a': a} of [])",
10675 : "(var {\"a\": a} of [])",
10676 : "(var {[Symbol.iterator]: a} of [])",
10677 : "(var {0: a} of [])",
10678 : "(var {a = 1} of [])",
10679 : "(var {a: a = 1} of [])",
10680 : "(var {'a': a = 1} of [])",
10681 : "(var {\"a\": a = 1} of [])",
10682 : "(var {[Symbol.iterator]: a = 1} of [])",
10683 : "(var {0: a = 1} of [])",
10684 : nullptr
10685 5 : };
10686 :
10687 : const char* lexical_data[] = {
10688 : // LexicalDeclartions
10689 : "(let a of [])",
10690 : "(let [a] of [])",
10691 : "(let [a = 1] of [])",
10692 : "(let [a = 1, ...b] of [])",
10693 : "(let {a} of [])",
10694 : "(let {a: a} of [])",
10695 : "(let {'a': a} of [])",
10696 : "(let {\"a\": a} of [])",
10697 : "(let {[Symbol.iterator]: a} of [])",
10698 : "(let {0: a} of [])",
10699 : "(let {a = 1} of [])",
10700 : "(let {a: a = 1} of [])",
10701 : "(let {'a': a = 1} of [])",
10702 : "(let {\"a\": a = 1} of [])",
10703 : "(let {[Symbol.iterator]: a = 1} of [])",
10704 : "(let {0: a = 1} of [])",
10705 :
10706 : "(const a of [])",
10707 : "(const [a] of [])",
10708 : "(const [a = 1] of [])",
10709 : "(const [a = 1, ...b] of [])",
10710 : "(const {a} of [])",
10711 : "(const {a: a} of [])",
10712 : "(const {'a': a} of [])",
10713 : "(const {\"a\": a} of [])",
10714 : "(const {[Symbol.iterator]: a} of [])",
10715 : "(const {0: a} of [])",
10716 : "(const {a = 1} of [])",
10717 : "(const {a: a = 1} of [])",
10718 : "(const {'a': a = 1} of [])",
10719 : "(const {\"a\": a = 1} of [])",
10720 : "(const {[Symbol.iterator]: a = 1} of [])",
10721 : "(const {0: a = 1} of [])",
10722 : nullptr
10723 5 : };
10724 : // clang-format on
10725 5 : RunParserSyncTest(context_data, expr_data, kSuccess);
10726 5 : RunParserSyncTest(context_data2, expr_data, kSuccess);
10727 :
10728 5 : RunParserSyncTest(context_data, var_data, kSuccess);
10729 : // TODO(marja): PreParser doesn't report early errors.
10730 : // (https://bugs.chromium.org/p/v8/issues/detail?id=2728)
10731 : // RunParserSyncTest(context_data2, var_data, kError, nullptr, 0,
10732 : // always_flags,
10733 : // arraysize(always_flags));
10734 :
10735 5 : RunParserSyncTest(context_data, lexical_data, kSuccess);
10736 5 : RunParserSyncTest(context_data2, lexical_data, kSuccess);
10737 5 : }
10738 :
10739 26644 : TEST(ForAwaitOfErrors) {
10740 : // clang-format off
10741 : const char* context_data[][2] = {
10742 : { "async function f() { for await ", " ; }" },
10743 : { "async function f() { for await ", " { } }" },
10744 : { "async function f() { 'use strict'; for await ", " ; }" },
10745 : { "async function f() { 'use strict'; for await ", " { } }" },
10746 : { "async function * f() { for await ", " ; }" },
10747 : { "async function * f() { for await ", " { } }" },
10748 : { "async function * f() { 'use strict'; for await ", " ; }" },
10749 : { "async function * f() { 'use strict'; for await ", " { } }" },
10750 : { nullptr, nullptr }
10751 5 : };
10752 :
10753 : const char* data[] = {
10754 : // Primary Expressions
10755 : "(a = 1 of [])",
10756 : "(a = 1) of [])",
10757 : "(a.b = 1 of [])",
10758 : "((a.b = 1) of [])",
10759 : "([a] = 1 of [])",
10760 : "(([a] = 1) of [])",
10761 : "([a = 1] = 1 of [])",
10762 : "(([a = 1] = 1) of [])",
10763 : "([a = 1 = 1, ...b] = 1 of [])",
10764 : "(([a = 1 = 1, ...b] = 1) of [])",
10765 : "({a} = 1 of [])",
10766 : "(({a} = 1) of [])",
10767 : "({a: a} = 1 of [])",
10768 : "(({a: a} = 1) of [])",
10769 : "({'a': a} = 1 of [])",
10770 : "(({'a': a} = 1) of [])",
10771 : "({\"a\": a} = 1 of [])",
10772 : "(({\"a\": a} = 1) of [])",
10773 : "({[Symbol.iterator]: a} = 1 of [])",
10774 : "(({[Symbol.iterator]: a} = 1) of [])",
10775 : "({0: a} = 1 of [])",
10776 : "(({0: a} = 1) of [])",
10777 : "({a = 1} = 1 of [])",
10778 : "(({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 : "({\"a\": a = 1} = 1 of [])",
10784 : "(({\"a\": a = 1} = 1) of [])",
10785 : "({[Symbol.iterator]: a = 1} = 1 of [])",
10786 : "(({[Symbol.iterator]: a = 1} = 1) of [])",
10787 : "({0: a = 1} = 1 of [])",
10788 : "(({0: a = 1} = 1) of [])",
10789 : "(function a() {} of [])",
10790 : "([1] of [])",
10791 : "({a: 1} of [])"
10792 :
10793 : // VarDeclarations
10794 : "(var a = 1 of [])",
10795 : "(var a, b of [])",
10796 : "(var [a] = 1 of [])",
10797 : "(var [a], b of [])",
10798 : "(var [a = 1] = 1 of [])",
10799 : "(var [a = 1], b of [])",
10800 : "(var [a = 1 = 1, ...b] of [])",
10801 : "(var [a = 1, ...b], c of [])",
10802 : "(var {a} = 1 of [])",
10803 : "(var {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 {\"a\": a} = 1 of [])",
10809 : "(var {\"a\": a}, b of [])",
10810 : "(var {[Symbol.iterator]: a} = 1 of [])",
10811 : "(var {[Symbol.iterator]: a}, b of [])",
10812 : "(var {0: a} = 1 of [])",
10813 : "(var {0: a}, b of [])",
10814 : "(var {a = 1} = 1 of [])",
10815 : "(var {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 {\"a\": a = 1} = 1 of [])",
10821 : "(var {\"a\": a = 1}, b of [])",
10822 : "(var {[Symbol.iterator]: a = 1} = 1 of [])",
10823 : "(var {[Symbol.iterator]: a = 1}, b of [])",
10824 : "(var {0: a = 1} = 1 of [])",
10825 : "(var {0: a = 1}, b of [])",
10826 :
10827 : // LexicalDeclartions
10828 : "(let a = 1 of [])",
10829 : "(let a, b of [])",
10830 : "(let [a] = 1 of [])",
10831 : "(let [a], b of [])",
10832 : "(let [a = 1] = 1 of [])",
10833 : "(let [a = 1], b of [])",
10834 : "(let [a = 1, ...b] = 1 of [])",
10835 : "(let [a = 1, ...b], c of [])",
10836 : "(let {a} = 1 of [])",
10837 : "(let {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 {\"a\": a} = 1 of [])",
10843 : "(let {\"a\": a}, b of [])",
10844 : "(let {[Symbol.iterator]: a} = 1 of [])",
10845 : "(let {[Symbol.iterator]: a}, b of [])",
10846 : "(let {0: a} = 1 of [])",
10847 : "(let {0: a}, b of [])",
10848 : "(let {a = 1} = 1 of [])",
10849 : "(let {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 {\"a\": a = 1} = 1 of [])",
10855 : "(let {\"a\": a = 1}, b of [])",
10856 : "(let {[Symbol.iterator]: a = 1} = 1 of [])",
10857 : "(let {[Symbol.iterator]: a = 1}, b of [])",
10858 : "(let {0: a = 1} = 1 of [])",
10859 : "(let {0: a = 1}, b of [])",
10860 :
10861 : "(const a = 1 of [])",
10862 : "(const a, b of [])",
10863 : "(const [a] = 1 of [])",
10864 : "(const [a], b of [])",
10865 : "(const [a = 1] = 1 of [])",
10866 : "(const [a = 1], b of [])",
10867 : "(const [a = 1, ...b] = 1 of [])",
10868 : "(const [a = 1, ...b], b of [])",
10869 : "(const {a} = 1 of [])",
10870 : "(const {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 {\"a\": a} = 1 of [])",
10876 : "(const {\"a\": a}, b of [])",
10877 : "(const {[Symbol.iterator]: a} = 1 of [])",
10878 : "(const {[Symbol.iterator]: a}, b of [])",
10879 : "(const {0: a} = 1 of [])",
10880 : "(const {0: a}, b of [])",
10881 : "(const {a = 1} = 1 of [])",
10882 : "(const {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 {\"a\": a = 1} = 1 of [])",
10888 : "(const {\"a\": a = 1}, b of [])",
10889 : "(const {[Symbol.iterator]: a = 1} = 1 of [])",
10890 : "(const {[Symbol.iterator]: a = 1}, b of [])",
10891 : "(const {0: a = 1} = 1 of [])",
10892 : "(const {0: a = 1}, b of [])",
10893 :
10894 : nullptr
10895 5 : };
10896 : // clang-format on
10897 5 : RunParserSyncTest(context_data, data, kError);
10898 5 : }
10899 :
10900 26644 : TEST(ForAwaitOfFunctionDeclaration) {
10901 : // clang-format off
10902 : const char* context_data[][2] = {
10903 : { "async function f() {", "}" },
10904 : { "async function f() { 'use strict'; ", "}" },
10905 : { nullptr, nullptr }
10906 5 : };
10907 :
10908 : const char* data[] = {
10909 : "for await (x of []) function d() {};",
10910 : "for await (x of []) function d() {}; return d;",
10911 : "for await (x of []) function* g() {};",
10912 : "for await (x of []) function* g() {}; return g;",
10913 : // TODO(caitp): handle async function declarations in ParseScopedStatement.
10914 : // "for await (x of []) async function a() {};",
10915 : // "for await (x of []) async function a() {}; return a;",
10916 : nullptr
10917 5 : };
10918 :
10919 : // clang-format on
10920 5 : RunParserSyncTest(context_data, data, kError);
10921 5 : }
10922 :
10923 26644 : TEST(AsyncGenerator) {
10924 : // clang-format off
10925 : const char* context_data[][2] = {
10926 : { "async function * gen() {", "}" },
10927 : { "(async function * gen() {", "})" },
10928 : { "(async function * () {", "})" },
10929 : { "({ async * gen () {", "} })" },
10930 : { nullptr, nullptr }
10931 5 : };
10932 :
10933 : const char* statement_data[] = {
10934 : // An async generator without a body is valid.
10935 : ""
10936 : // Valid yield expressions inside generators.
10937 : "yield 2;",
10938 : "yield * 2;",
10939 : "yield * \n 2;",
10940 : "yield yield 1;",
10941 : "yield * yield * 1;",
10942 : "yield 3 + (yield 4);",
10943 : "yield * 3 + (yield * 4);",
10944 : "(yield * 3) + (yield * 4);",
10945 : "yield 3; yield 4;",
10946 : "yield * 3; yield * 4;",
10947 : "(function (yield) { })",
10948 : "(function yield() { })",
10949 : "(function (await) { })",
10950 : "(function await() { })",
10951 : "yield { yield: 12 }",
10952 : "yield /* comment */ { yield: 12 }",
10953 : "yield * \n { yield: 12 }",
10954 : "yield /* comment */ * \n { yield: 12 }",
10955 : // You can return in an async generator.
10956 : "yield 1; return",
10957 : "yield * 1; return",
10958 : "yield 1; return 37",
10959 : "yield * 1; return 37",
10960 : "yield 1; return 37; yield 'dead';",
10961 : "yield * 1; return 37; yield * 'dead';",
10962 : // Yield/Await are still a valid key in object literals.
10963 : "({ yield: 1 })",
10964 : "({ get yield() { } })",
10965 : "({ await: 1 })",
10966 : "({ get await() { } })",
10967 : // And in assignment pattern computed properties
10968 : "({ [yield]: x } = { })",
10969 : "({ [await 1]: x } = { })",
10970 : // Yield without RHS.
10971 : "yield;",
10972 : "yield",
10973 : "yield\n",
10974 : "yield /* comment */"
10975 : "yield // comment\n"
10976 : "(yield)",
10977 : "[yield]",
10978 : "{yield}",
10979 : "yield, yield",
10980 : "yield; yield",
10981 : "(yield) ? yield : yield",
10982 : "(yield) \n ? yield : yield",
10983 : // If there is a newline before the next token, we don't look for RHS.
10984 : "yield\nfor (;;) {}",
10985 : "x = class extends (yield) {}",
10986 : "x = class extends f(yield) {}",
10987 : "x = class extends (null, yield) { }",
10988 : "x = class extends (a ? null : yield) { }",
10989 : "x = class extends (await 10) {}",
10990 : "x = class extends f(await 10) {}",
10991 : "x = class extends (null, await 10) { }",
10992 : "x = class extends (a ? null : await 10) { }",
10993 :
10994 : // More tests featuring AwaitExpressions
10995 : "await 10",
10996 : "await 10; return",
10997 : "await 10; return 20",
10998 : "await 10; return 20; yield 'dead'",
10999 : "await (yield 10)",
11000 : "await (yield 10); return",
11001 : "await (yield 10); return 20",
11002 : "await (yield 10); return 20; yield 'dead'",
11003 : "yield await 10",
11004 : "yield await 10; return",
11005 : "yield await 10; return 20",
11006 : "yield await 10; return 20; yield 'dead'",
11007 : "await /* comment */ 10",
11008 : "await // comment\n 10",
11009 : "yield await /* comment\n */ 10",
11010 : "yield await // comment\n 10",
11011 : "await (yield /* comment */)",
11012 : "await (yield // comment\n)",
11013 : nullptr
11014 5 : };
11015 : // clang-format on
11016 :
11017 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
11018 5 : }
11019 :
11020 26644 : TEST(AsyncGeneratorErrors) {
11021 : // clang-format off
11022 : const char* context_data[][2] = {
11023 : { "async function * gen() {", "}" },
11024 : { "\"use strict\"; async function * gen() {", "}" },
11025 : { nullptr, nullptr }
11026 5 : };
11027 :
11028 : const char* statement_data[] = {
11029 : // Invalid yield expressions inside generators.
11030 : "var yield;",
11031 : "var await;",
11032 : "var foo, yield;",
11033 : "var foo, await;",
11034 : "try { } catch (yield) { }",
11035 : "try { } catch (await) { }",
11036 : "function yield() { }",
11037 : "function await() { }",
11038 : // The name of the NFE is bound in the generator, which does not permit
11039 : // yield or await to be identifiers.
11040 : "(async function * yield() { })",
11041 : "(async function * await() { })",
11042 : // Yield and Await aren't valid as a formal parameter for generators.
11043 : "async function * foo(yield) { }",
11044 : "(async function * foo(yield) { })",
11045 : "async function * foo(await) { }",
11046 : "(async function * foo(await) { })",
11047 : "yield = 1;",
11048 : "await = 1;",
11049 : "var foo = yield = 1;",
11050 : "var foo = await = 1;",
11051 : "++yield;",
11052 : "++await;",
11053 : "yield++;",
11054 : "await++;",
11055 : "yield *",
11056 : "(yield *)",
11057 : // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
11058 : // is invalid.
11059 : "yield 3 + yield 4;",
11060 : "yield: 34",
11061 : "yield ? 1 : 2",
11062 : // Parses as yield (/ yield): invalid.
11063 : "yield / yield",
11064 : "+ yield",
11065 : "+ yield 3",
11066 : // Invalid (no newline allowed between yield and *).
11067 : "yield\n*3",
11068 : // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
11069 : // object literal, and yield is not a valid label).
11070 : "yield\n{yield: 42}",
11071 : "yield /* comment */\n {yield: 42}",
11072 : "yield //comment\n {yield: 42}",
11073 : // Destructuring binding and assignment are both disallowed
11074 : "var [yield] = [42];",
11075 : "var [await] = [42];",
11076 : "var {foo: yield} = {a: 42};",
11077 : "var {foo: await} = {a: 42};",
11078 : "[yield] = [42];",
11079 : "[await] = [42];",
11080 : "({a: yield} = {a: 42});",
11081 : "({a: await} = {a: 42});",
11082 : // Also disallow full yield/await expressions on LHS
11083 : "var [yield 24] = [42];",
11084 : "var [await 24] = [42];",
11085 : "var {foo: yield 24} = {a: 42};",
11086 : "var {foo: await 24} = {a: 42};",
11087 : "[yield 24] = [42];",
11088 : "[await 24] = [42];",
11089 : "({a: yield 24} = {a: 42});",
11090 : "({a: await 24} = {a: 42});",
11091 : "for (yield 'x' in {});",
11092 : "for (await 'x' in {});",
11093 : "for (yield 'x' of {});",
11094 : "for (await 'x' of {});",
11095 : "for (yield 'x' in {} in {});",
11096 : "for (await 'x' in {} in {});",
11097 : "for (yield 'x' in {} of {});",
11098 : "for (await 'x' in {} of {});",
11099 : "class C extends yield { }",
11100 : "class C extends await { }",
11101 : nullptr
11102 5 : };
11103 : // clang-format on
11104 :
11105 5 : RunParserSyncTest(context_data, statement_data, kError);
11106 5 : }
11107 :
11108 26644 : TEST(LexicalLoopVariable) {
11109 : i::Isolate* isolate = CcTest::i_isolate();
11110 : i::HandleScope scope(isolate);
11111 5 : LocalContext env;
11112 : typedef std::function<void(const i::ParseInfo& info, i::DeclarationScope*)>
11113 : TestCB;
11114 200 : auto TestProgram = [isolate](const char* program, TestCB test) {
11115 : i::Factory* const factory = isolate->factory();
11116 : i::Handle<i::String> source =
11117 100 : factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
11118 50 : i::Handle<i::Script> script = factory->NewScript(source);
11119 100 : i::ParseInfo info(isolate, script);
11120 :
11121 : info.set_allow_lazy_parsing(false);
11122 50 : CHECK(i::parsing::ParseProgram(&info, isolate));
11123 50 : CHECK(i::Rewriter::Rewrite(&info));
11124 50 : CHECK(i::DeclarationScope::Analyze(&info));
11125 50 : i::DeclarationScope::AllocateScopeInfos(&info, isolate);
11126 50 : CHECK_NOT_NULL(info.literal());
11127 :
11128 : i::DeclarationScope* script_scope = info.literal()->scope();
11129 50 : CHECK(script_scope->is_script_scope());
11130 :
11131 : test(info, script_scope);
11132 55 : };
11133 :
11134 : // Check `let` loop variables is a stack local when not captured by
11135 : // an eval or closure within the area of the loop body.
11136 : const char* local_bindings[] = {
11137 : "function loop() {"
11138 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11139 : " }"
11140 : " eval('0');"
11141 : "}",
11142 :
11143 : "function loop() {"
11144 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11145 : " }"
11146 : " function foo() {}"
11147 : " foo();"
11148 : "}",
11149 5 : };
11150 25 : for (const char* source : local_bindings) {
11151 20 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11152 : i::Scope* fn = s->inner_scope();
11153 10 : CHECK(fn->is_function_scope());
11154 :
11155 : i::Scope* loop_block = fn->inner_scope();
11156 10 : if (loop_block->is_function_scope()) loop_block = loop_block->sibling();
11157 10 : CHECK(loop_block->is_block_scope());
11158 :
11159 : const i::AstRawString* var_name =
11160 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11161 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11162 10 : CHECK_NOT_NULL(loop_var);
11163 10 : CHECK(loop_var->IsStackLocal());
11164 10 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11165 10 : CHECK_NULL(loop_block->inner_scope());
11166 20 : });
11167 : }
11168 :
11169 : // Check `let` loop variable is not a stack local, and is duplicated in the
11170 : // loop body to ensure capturing can work correctly.
11171 : // In this version of the test, the inner loop block's duplicate `loop_var`
11172 : // binding is not captured, and is a local.
11173 : const char* context_bindings1[] = {
11174 : "function loop() {"
11175 : " for (let loop_var = eval('0'); loop_var < 10; ++loop_var) {"
11176 : " }"
11177 : "}",
11178 :
11179 : "function loop() {"
11180 : " for (let loop_var = (() => (loop_var, 0))(); loop_var < 10;"
11181 : " ++loop_var) {"
11182 : " }"
11183 5 : "}"};
11184 25 : for (const char* source : context_bindings1) {
11185 20 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11186 : i::Scope* fn = s->inner_scope();
11187 10 : CHECK(fn->is_function_scope());
11188 :
11189 : i::Scope* loop_block = fn->inner_scope();
11190 10 : CHECK(loop_block->is_block_scope());
11191 :
11192 : const i::AstRawString* var_name =
11193 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11194 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11195 10 : CHECK_NOT_NULL(loop_var);
11196 10 : CHECK(loop_var->IsContextSlot());
11197 10 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11198 :
11199 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11200 10 : CHECK_NE(loop_var, loop_var2);
11201 10 : CHECK(loop_var2->IsStackLocal());
11202 10 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
11203 20 : });
11204 : }
11205 :
11206 : // Check `let` loop variable is not a stack local, and is duplicated in the
11207 : // loop body to ensure capturing can work correctly.
11208 : // In this version of the test, the inner loop block's duplicate `loop_var`
11209 : // binding is captured, and must be context allocated.
11210 : const char* context_bindings2[] = {
11211 : "function loop() {"
11212 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11213 : " eval('0');"
11214 : " }"
11215 : "}",
11216 :
11217 : "function loop() {"
11218 : " for (let loop_var = 0; loop_var < eval('10'); ++loop_var) {"
11219 : " }"
11220 : "}",
11221 :
11222 : "function loop() {"
11223 : " for (let loop_var = 0; loop_var < 10; eval('++loop_var')) {"
11224 : " }"
11225 : "}",
11226 5 : };
11227 :
11228 35 : for (const char* source : context_bindings2) {
11229 30 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11230 : i::Scope* fn = s->inner_scope();
11231 15 : CHECK(fn->is_function_scope());
11232 :
11233 : i::Scope* loop_block = fn->inner_scope();
11234 15 : CHECK(loop_block->is_block_scope());
11235 :
11236 : const i::AstRawString* var_name =
11237 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11238 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11239 15 : CHECK_NOT_NULL(loop_var);
11240 15 : CHECK(loop_var->IsContextSlot());
11241 15 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11242 :
11243 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11244 15 : CHECK_NE(loop_var, loop_var2);
11245 15 : CHECK(loop_var2->IsContextSlot());
11246 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11247 30 : });
11248 : }
11249 :
11250 : // Similar to the above, but the first block scope's variables are not
11251 : // captured due to the closure occurring in a nested scope.
11252 : const char* context_bindings3[] = {
11253 : "function loop() {"
11254 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11255 : " (() => loop_var)();"
11256 : " }"
11257 : "}",
11258 :
11259 : "function loop() {"
11260 : " for (let loop_var = 0; loop_var < (() => (loop_var, 10))();"
11261 : " ++loop_var) {"
11262 : " }"
11263 : "}",
11264 :
11265 : "function loop() {"
11266 : " for (let loop_var = 0; loop_var < 10; (() => ++loop_var)()) {"
11267 : " }"
11268 : "}",
11269 5 : };
11270 :
11271 35 : for (const char* source : context_bindings3) {
11272 30 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11273 : i::Scope* fn = s->inner_scope();
11274 15 : CHECK(fn->is_function_scope());
11275 :
11276 : i::Scope* loop_block = fn->inner_scope();
11277 15 : CHECK(loop_block->is_block_scope());
11278 :
11279 : const i::AstRawString* var_name =
11280 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11281 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11282 15 : CHECK_NOT_NULL(loop_var);
11283 15 : CHECK(loop_var->IsStackLocal());
11284 15 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11285 :
11286 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11287 15 : CHECK_NE(loop_var, loop_var2);
11288 15 : CHECK(loop_var2->IsContextSlot());
11289 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11290 30 : });
11291 : }
11292 5 : }
11293 :
11294 26644 : TEST(PrivateNamesSyntaxErrorEarly) {
11295 : i::Isolate* isolate = CcTest::i_isolate();
11296 : i::HandleScope scope(isolate);
11297 5 : LocalContext env;
11298 :
11299 : const char* context_data[][2] = {
11300 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
11301 :
11302 : const char* statement_data[] = {
11303 : "class A {"
11304 : " foo() { return this.#bar; }"
11305 : "}",
11306 :
11307 : "let A = class {"
11308 : " foo() { return this.#bar; }"
11309 : "}",
11310 :
11311 : "class A {"
11312 : " #foo; "
11313 : " bar() { return this.#baz; }"
11314 : "}",
11315 :
11316 : "let A = class {"
11317 : " #foo; "
11318 : " bar() { return this.#baz; }"
11319 : "}",
11320 :
11321 : "class A {"
11322 : " bar() {"
11323 : " class D { #baz = 1; };"
11324 : " return this.#baz;"
11325 : " }"
11326 : "}",
11327 :
11328 : "let A = class {"
11329 : " bar() {"
11330 : " class D { #baz = 1; };"
11331 : " return this.#baz;"
11332 : " }"
11333 : "}",
11334 :
11335 : "a.#bar",
11336 :
11337 : "class Foo {};"
11338 : "Foo.#bar;",
11339 :
11340 : "let Foo = class {};"
11341 : "Foo.#bar;",
11342 :
11343 : "class Foo {};"
11344 : "(new Foo).#bar;",
11345 :
11346 : "let Foo = class {};"
11347 : "(new Foo).#bar;",
11348 :
11349 : "class Foo { #bar; };"
11350 : "(new Foo).#bar;",
11351 :
11352 : "let Foo = class { #bar; };"
11353 : "(new Foo).#bar;",
11354 :
11355 : "function t(){"
11356 : " class Foo { getA() { return this.#foo; } }"
11357 : "}",
11358 :
11359 : "function t(){"
11360 : " return class { getA() { return this.#foo; } }"
11361 : "}",
11362 :
11363 5 : nullptr};
11364 :
11365 : static const ParserFlag flags[] = {kAllowHarmonyPrivateFields};
11366 5 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1);
11367 5 : RunParserSyncTest(context_data, statement_data, kError);
11368 5 : }
11369 :
11370 26644 : TEST(HashbangSyntax) {
11371 : const char* context_data[][2] = {
11372 : {"#!\n", ""},
11373 : {"#!---IGNORED---\n", ""},
11374 : {"#!---IGNORED---\r", ""},
11375 : {"#!---IGNORED---\xE2\x80\xA8", ""}, // <U+2028>
11376 : {"#!---IGNORED---\xE2\x80\xA9", ""}, // <U+2029>
11377 5 : {nullptr, nullptr}};
11378 :
11379 5 : const char* data[] = {"function\nFN\n(\n)\n {\n}\nFN();", nullptr};
11380 :
11381 5 : i::FLAG_harmony_hashbang = true;
11382 5 : RunParserSyncTest(context_data, data, kSuccess);
11383 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
11384 5 : nullptr, 0, true);
11385 :
11386 5 : i::FLAG_harmony_hashbang = false;
11387 5 : RunParserSyncTest(context_data, data, kError);
11388 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0, nullptr,
11389 5 : 0, true);
11390 5 : }
11391 :
11392 26644 : TEST(HashbangSyntaxErrors) {
11393 5 : const char* file_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
11394 : const char* other_context_data[][2] = {{"/**/", ""},
11395 : {"//---\n", ""},
11396 : {";", ""},
11397 : {"function fn() {", "}"},
11398 : {"function* fn() {", "}"},
11399 : {"async function fn() {", "}"},
11400 : {"async function* fn() {", "}"},
11401 : {"() => {", "}"},
11402 : {"() => ", ""},
11403 : {"function fn(a = ", ") {}"},
11404 : {"function* fn(a = ", ") {}"},
11405 : {"async function fn(a = ", ") {}"},
11406 : {"async function* fn(a = ", ") {}"},
11407 : {"(a = ", ") => {}"},
11408 : {"(a = ", ") => a"},
11409 : {"class k {", "}"},
11410 : {"[", "]"},
11411 : {"{", "}"},
11412 : {"({", "})"},
11413 5 : {nullptr, nullptr}};
11414 :
11415 : const char* invalid_hashbang_data[] = {// Encoded characters are not allowed
11416 : "#\\u0021\n"
11417 : "#\\u{21}\n",
11418 : "#\\x21\n",
11419 : "#\\041\n",
11420 : "\\u0023!\n",
11421 : "\\u{23}!\n",
11422 : "\\x23!\n",
11423 : "\\043!\n",
11424 : "\\u0023\\u0021\n",
11425 :
11426 : "\n#!---IGNORED---\n",
11427 : " #!---IGNORED---\n",
11428 5 : nullptr};
11429 5 : const char* hashbang_data[] = {"#!\n", "#!---IGNORED---\n", nullptr};
11430 :
11431 15 : auto SyntaxErrorTest = [](const char* context_data[][2], const char* data[]) {
11432 15 : i::FLAG_harmony_hashbang = true;
11433 15 : RunParserSyncTest(context_data, data, kError);
11434 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11435 15 : nullptr, 0, true);
11436 :
11437 15 : i::FLAG_harmony_hashbang = false;
11438 15 : RunParserSyncTest(context_data, data, kError);
11439 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11440 15 : nullptr, 0, true);
11441 15 : };
11442 :
11443 5 : SyntaxErrorTest(file_context_data, invalid_hashbang_data);
11444 5 : SyntaxErrorTest(other_context_data, invalid_hashbang_data);
11445 5 : SyntaxErrorTest(other_context_data, hashbang_data);
11446 5 : }
11447 :
11448 : } // namespace test_parsing
11449 : } // namespace internal
11450 79917 : } // namespace v8
|