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 :
54 : #include "test/cctest/cctest.h"
55 : #include "test/cctest/scope-test-helper.h"
56 : #include "test/cctest/unicode-helpers.h"
57 :
58 : namespace v8 {
59 : namespace internal {
60 : namespace test_parsing {
61 :
62 : namespace {
63 :
64 : int* global_use_counts = nullptr;
65 :
66 30 : void MockUseCounterCallback(v8::Isolate* isolate,
67 : v8::Isolate::UseCounterFeature feature) {
68 30 : ++global_use_counts[feature];
69 30 : }
70 :
71 : } // namespace
72 :
73 0 : bool TokenIsAutoSemicolon(Token::Value token) {
74 550 : switch (token) {
75 : case Token::SEMICOLON:
76 : case Token::EOS:
77 : case Token::RBRACE:
78 : return true;
79 : default:
80 0 : return false;
81 : }
82 : }
83 :
84 28342 : TEST(AutoSemicolonToken) {
85 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
86 : Token::Value token = static_cast<Token::Value>(i);
87 1100 : CHECK_EQ(TokenIsAutoSemicolon(token), Token::IsAutoSemicolon(token));
88 : }
89 5 : }
90 :
91 0 : bool TokenIsAnyIdentifier(Token::Value token) {
92 550 : switch (token) {
93 : case Token::IDENTIFIER:
94 : case Token::ASYNC:
95 : case Token::AWAIT:
96 : case Token::YIELD:
97 : case Token::LET:
98 : case Token::STATIC:
99 : case Token::FUTURE_STRICT_RESERVED_WORD:
100 : case Token::ESCAPED_STRICT_RESERVED_WORD:
101 : return true;
102 : default:
103 0 : return false;
104 : }
105 : }
106 :
107 28342 : TEST(AnyIdentifierToken) {
108 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
109 : Token::Value token = static_cast<Token::Value>(i);
110 1100 : CHECK_EQ(TokenIsAnyIdentifier(token), Token::IsAnyIdentifier(token));
111 : }
112 5 : }
113 :
114 0 : bool TokenIsCallable(Token::Value token) {
115 550 : switch (token) {
116 : case Token::SUPER:
117 : case Token::IDENTIFIER:
118 : case Token::ASYNC:
119 : case Token::AWAIT:
120 : case Token::YIELD:
121 : case Token::LET:
122 : case Token::STATIC:
123 : case Token::FUTURE_STRICT_RESERVED_WORD:
124 : case Token::ESCAPED_STRICT_RESERVED_WORD:
125 : return true;
126 : default:
127 0 : return false;
128 : }
129 : }
130 :
131 28342 : TEST(CallableToken) {
132 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
133 : Token::Value token = static_cast<Token::Value>(i);
134 1100 : CHECK_EQ(TokenIsCallable(token), Token::IsCallable(token));
135 : }
136 5 : }
137 :
138 0 : bool TokenIsValidIdentifier(Token::Value token, LanguageMode language_mode,
139 : bool is_generator, bool disallow_await) {
140 4400 : switch (token) {
141 : case Token::IDENTIFIER:
142 : case Token::ASYNC:
143 : return true;
144 : case Token::YIELD:
145 40 : return !is_generator && is_sloppy(language_mode);
146 : case Token::AWAIT:
147 40 : return !disallow_await;
148 : case Token::LET:
149 : case Token::STATIC:
150 : case Token::FUTURE_STRICT_RESERVED_WORD:
151 : case Token::ESCAPED_STRICT_RESERVED_WORD:
152 0 : return is_sloppy(language_mode);
153 : default:
154 0 : return false;
155 : }
156 : UNREACHABLE();
157 : }
158 :
159 28342 : TEST(IsValidIdentifierToken) {
160 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
161 : Token::Value token = static_cast<Token::Value>(i);
162 1100 : for (size_t raw_language_mode = 0; raw_language_mode < LanguageModeSize;
163 : raw_language_mode++) {
164 1100 : LanguageMode mode = static_cast<LanguageMode>(raw_language_mode);
165 3300 : for (int is_generator = 0; is_generator < 2; is_generator++) {
166 4400 : for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
167 8800 : CHECK_EQ(
168 : TokenIsValidIdentifier(token, mode, is_generator, disallow_await),
169 : Token::IsValidIdentifier(token, mode, is_generator,
170 : disallow_await));
171 : }
172 : }
173 : }
174 : }
175 5 : }
176 :
177 0 : bool TokenIsStrictReservedWord(Token::Value token) {
178 550 : switch (token) {
179 : case Token::LET:
180 : case Token::YIELD:
181 : case Token::STATIC:
182 : case Token::FUTURE_STRICT_RESERVED_WORD:
183 : case Token::ESCAPED_STRICT_RESERVED_WORD:
184 : return true;
185 : default:
186 0 : return false;
187 : }
188 : UNREACHABLE();
189 : }
190 :
191 28342 : TEST(IsStrictReservedWord) {
192 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
193 : Token::Value token = static_cast<Token::Value>(i);
194 1100 : CHECK_EQ(TokenIsStrictReservedWord(token),
195 : Token::IsStrictReservedWord(token));
196 : }
197 5 : }
198 :
199 0 : bool TokenIsLiteral(Token::Value token) {
200 550 : switch (token) {
201 : case Token::NULL_LITERAL:
202 : case Token::TRUE_LITERAL:
203 : case Token::FALSE_LITERAL:
204 : case Token::NUMBER:
205 : case Token::SMI:
206 : case Token::BIGINT:
207 : case Token::STRING:
208 : return true;
209 : default:
210 0 : return false;
211 : }
212 : UNREACHABLE();
213 : }
214 :
215 28342 : TEST(IsLiteralToken) {
216 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
217 : Token::Value token = static_cast<Token::Value>(i);
218 1100 : CHECK_EQ(TokenIsLiteral(token), Token::IsLiteral(token));
219 : }
220 5 : }
221 :
222 0 : bool TokenIsAssignmentOp(Token::Value token) {
223 1095 : switch (token) {
224 : case Token::INIT:
225 : case Token::ASSIGN:
226 : #define T(name, string, precedence) case Token::name:
227 : BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_ASSIGN_TOKEN)
228 : #undef T
229 : return true;
230 : default:
231 0 : return false;
232 : }
233 : }
234 :
235 28342 : TEST(AssignmentOp) {
236 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
237 : Token::Value token = static_cast<Token::Value>(i);
238 1100 : CHECK_EQ(TokenIsAssignmentOp(token), Token::IsAssignmentOp(token));
239 : }
240 5 : }
241 :
242 0 : bool TokenIsArrowOrAssignmentOp(Token::Value token) {
243 1095 : return token == Token::ARROW || TokenIsAssignmentOp(token);
244 : }
245 :
246 28342 : TEST(ArrowOrAssignmentOp) {
247 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
248 : Token::Value token = static_cast<Token::Value>(i);
249 1100 : CHECK_EQ(TokenIsArrowOrAssignmentOp(token),
250 : Token::IsArrowOrAssignmentOp(token));
251 : }
252 5 : }
253 :
254 0 : bool TokenIsBinaryOp(Token::Value token) {
255 550 : switch (token) {
256 : case Token::COMMA:
257 : case Token::OR:
258 : case Token::AND:
259 : #define T(name, string, precedence) case Token::name:
260 : BINARY_OP_TOKEN_LIST(T, EXPAND_BINOP_TOKEN)
261 : #undef T
262 : return true;
263 : default:
264 0 : return false;
265 : }
266 : }
267 :
268 28342 : TEST(BinaryOp) {
269 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
270 : Token::Value token = static_cast<Token::Value>(i);
271 1100 : CHECK_EQ(TokenIsBinaryOp(token), Token::IsBinaryOp(token));
272 : }
273 5 : }
274 :
275 0 : bool TokenIsCompareOp(Token::Value token) {
276 550 : switch (token) {
277 : case Token::EQ:
278 : case Token::EQ_STRICT:
279 : case Token::NE:
280 : case Token::NE_STRICT:
281 : case Token::LT:
282 : case Token::GT:
283 : case Token::LTE:
284 : case Token::GTE:
285 : case Token::INSTANCEOF:
286 : case Token::IN:
287 : return true;
288 : default:
289 0 : return false;
290 : }
291 : }
292 :
293 28342 : TEST(CompareOp) {
294 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
295 : Token::Value token = static_cast<Token::Value>(i);
296 1100 : CHECK_EQ(TokenIsCompareOp(token), Token::IsCompareOp(token));
297 : }
298 5 : }
299 :
300 0 : bool TokenIsOrderedRelationalCompareOp(Token::Value token) {
301 550 : switch (token) {
302 : case Token::LT:
303 : case Token::GT:
304 : case Token::LTE:
305 : case Token::GTE:
306 : return true;
307 : default:
308 0 : return false;
309 : }
310 : }
311 :
312 28342 : TEST(IsOrderedRelationalCompareOp) {
313 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
314 : Token::Value token = static_cast<Token::Value>(i);
315 1100 : CHECK_EQ(TokenIsOrderedRelationalCompareOp(token),
316 : Token::IsOrderedRelationalCompareOp(token));
317 : }
318 5 : }
319 :
320 0 : bool TokenIsEqualityOp(Token::Value token) {
321 550 : switch (token) {
322 : case Token::EQ:
323 : case Token::EQ_STRICT:
324 : return true;
325 : default:
326 0 : return false;
327 : }
328 : }
329 :
330 28342 : TEST(IsEqualityOp) {
331 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
332 : Token::Value token = static_cast<Token::Value>(i);
333 1100 : CHECK_EQ(TokenIsEqualityOp(token), Token::IsEqualityOp(token));
334 : }
335 5 : }
336 :
337 0 : bool TokenIsBitOp(Token::Value token) {
338 : switch (token) {
339 : case Token::BIT_OR:
340 : case Token::BIT_XOR:
341 : case Token::BIT_AND:
342 : case Token::SHL:
343 : case Token::SAR:
344 : case Token::SHR:
345 : case Token::BIT_NOT:
346 : return true;
347 : default:
348 0 : return false;
349 : }
350 : }
351 :
352 28342 : TEST(IsBitOp) {
353 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
354 : Token::Value token = static_cast<Token::Value>(i);
355 1100 : CHECK_EQ(TokenIsBitOp(token), Token::IsBitOp(token));
356 : }
357 5 : }
358 :
359 0 : bool TokenIsUnaryOp(Token::Value token) {
360 1100 : switch (token) {
361 : case Token::NOT:
362 : case Token::BIT_NOT:
363 : case Token::DELETE:
364 : case Token::TYPEOF:
365 : case Token::VOID:
366 : case Token::ADD:
367 : case Token::SUB:
368 : return true;
369 : default:
370 0 : return false;
371 : }
372 : }
373 :
374 28342 : TEST(IsUnaryOp) {
375 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
376 : Token::Value token = static_cast<Token::Value>(i);
377 1100 : CHECK_EQ(TokenIsUnaryOp(token), Token::IsUnaryOp(token));
378 : }
379 5 : }
380 :
381 0 : bool TokenIsPropertyOrCall(Token::Value token) {
382 550 : switch (token) {
383 : case Token::TEMPLATE_SPAN:
384 : case Token::TEMPLATE_TAIL:
385 : case Token::PERIOD:
386 : case Token::LBRACK:
387 : case Token::LPAREN:
388 : return true;
389 : default:
390 0 : return false;
391 : }
392 : }
393 :
394 28342 : TEST(IsPropertyOrCall) {
395 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
396 : Token::Value token = static_cast<Token::Value>(i);
397 1100 : CHECK_EQ(TokenIsPropertyOrCall(token), Token::IsPropertyOrCall(token));
398 : }
399 5 : }
400 :
401 0 : bool TokenIsMember(Token::Value token) {
402 550 : switch (token) {
403 : case Token::TEMPLATE_SPAN:
404 : case Token::TEMPLATE_TAIL:
405 : case Token::PERIOD:
406 : case Token::LBRACK:
407 : return true;
408 : default:
409 0 : return false;
410 : }
411 : }
412 :
413 0 : bool TokenIsTemplate(Token::Value token) {
414 550 : switch (token) {
415 : case Token::TEMPLATE_SPAN:
416 : case Token::TEMPLATE_TAIL:
417 : return true;
418 : default:
419 0 : return false;
420 : }
421 : }
422 :
423 0 : bool TokenIsProperty(Token::Value token) {
424 550 : switch (token) {
425 : case Token::PERIOD:
426 : case Token::LBRACK:
427 : return true;
428 : default:
429 0 : return false;
430 : }
431 : }
432 :
433 28342 : TEST(IsMember) {
434 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
435 : Token::Value token = static_cast<Token::Value>(i);
436 1100 : CHECK_EQ(TokenIsMember(token), Token::IsMember(token));
437 : }
438 5 : }
439 :
440 28342 : TEST(IsTemplate) {
441 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
442 : Token::Value token = static_cast<Token::Value>(i);
443 1100 : CHECK_EQ(TokenIsTemplate(token), Token::IsTemplate(token));
444 : }
445 5 : }
446 :
447 28342 : TEST(IsProperty) {
448 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
449 : Token::Value token = static_cast<Token::Value>(i);
450 1100 : CHECK_EQ(TokenIsProperty(token), Token::IsProperty(token));
451 : }
452 5 : }
453 :
454 0 : bool TokenIsCountOp(Token::Value token) {
455 1065 : switch (token) {
456 : case Token::INC:
457 : case Token::DEC:
458 : return true;
459 : default:
460 0 : return false;
461 : }
462 : }
463 :
464 28342 : TEST(IsCountOp) {
465 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
466 : Token::Value token = static_cast<Token::Value>(i);
467 1100 : CHECK_EQ(TokenIsCountOp(token), Token::IsCountOp(token));
468 : }
469 5 : }
470 :
471 28342 : TEST(IsUnaryOrCountOp) {
472 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
473 : Token::Value token = static_cast<Token::Value>(i);
474 1615 : CHECK_EQ(TokenIsUnaryOp(token) || TokenIsCountOp(token),
475 : Token::IsUnaryOrCountOp(token));
476 : }
477 5 : }
478 :
479 0 : bool TokenIsShiftOp(Token::Value token) {
480 550 : switch (token) {
481 : case Token::SHL:
482 : case Token::SAR:
483 : case Token::SHR:
484 : return true;
485 : default:
486 0 : return false;
487 : }
488 : }
489 :
490 28342 : TEST(IsShiftOp) {
491 555 : for (int i = 0; i < Token::NUM_TOKENS; i++) {
492 : Token::Value token = static_cast<Token::Value>(i);
493 1100 : CHECK_EQ(TokenIsShiftOp(token), Token::IsShiftOp(token));
494 : }
495 5 : }
496 :
497 28342 : TEST(ScanKeywords) {
498 : struct KeywordToken {
499 : const char* keyword;
500 : i::Token::Value token;
501 : };
502 :
503 : static const KeywordToken keywords[] = {
504 : #define KEYWORD(t, s, d) { s, i::Token::t },
505 : TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
506 : #undef KEYWORD
507 : {nullptr, i::Token::IDENTIFIER}};
508 :
509 : KeywordToken key_token;
510 : char buffer[32];
511 210 : for (int i = 0; (key_token = keywords[i]).keyword != nullptr; i++) {
512 : const char* keyword = key_token.keyword;
513 205 : size_t length = strlen(key_token.keyword);
514 205 : CHECK(static_cast<int>(sizeof(buffer)) >= length);
515 : {
516 205 : auto stream = i::ScannerStream::ForTesting(keyword, length);
517 410 : i::Scanner scanner(stream.get(), false);
518 205 : scanner.Initialize();
519 205 : CHECK_EQ(key_token.token, scanner.Next());
520 205 : CHECK_EQ(i::Token::EOS, scanner.Next());
521 : }
522 : // Removing characters will make keyword matching fail.
523 : {
524 205 : auto stream = i::ScannerStream::ForTesting(keyword, length - 1);
525 410 : i::Scanner scanner(stream.get(), false);
526 205 : scanner.Initialize();
527 205 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
528 205 : CHECK_EQ(i::Token::EOS, scanner.Next());
529 : }
530 : // Adding characters will make keyword matching fail.
531 : static const char chars_to_append[] = { 'z', '0', '_' };
532 820 : for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
533 : i::MemMove(buffer, keyword, length);
534 615 : buffer[length] = chars_to_append[j];
535 615 : auto stream = i::ScannerStream::ForTesting(buffer, length + 1);
536 1230 : i::Scanner scanner(stream.get(), false);
537 615 : scanner.Initialize();
538 615 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
539 615 : CHECK_EQ(i::Token::EOS, scanner.Next());
540 : }
541 : // Replacing characters will make keyword matching fail.
542 : {
543 : i::MemMove(buffer, keyword, length);
544 205 : buffer[length - 1] = '_';
545 205 : auto stream = i::ScannerStream::ForTesting(buffer, length);
546 410 : i::Scanner scanner(stream.get(), false);
547 205 : scanner.Initialize();
548 205 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
549 205 : CHECK_EQ(i::Token::EOS, scanner.Next());
550 : }
551 : }
552 5 : }
553 :
554 :
555 28342 : TEST(ScanHTMLEndComments) {
556 5 : v8::V8::Initialize();
557 5 : v8::Isolate* isolate = CcTest::isolate();
558 360 : i::Isolate* i_isolate = CcTest::i_isolate();
559 5 : v8::HandleScope handles(isolate);
560 :
561 : // Regression test. See:
562 : // http://code.google.com/p/chromium/issues/detail?id=53548
563 : // Tests that --> is correctly interpreted as comment-to-end-of-line if there
564 : // is only whitespace before it on the line (with comments considered as
565 : // whitespace, even a multiline-comment containing a newline).
566 : // This was not the case if it occurred before the first real token
567 : // in the input.
568 : // clang-format off
569 : const char* tests[] = {
570 : // Before first real token.
571 : "-->",
572 : "--> is eol-comment",
573 : "--> is eol-comment\nvar y = 37;\n",
574 : "\n --> is eol-comment\nvar y = 37;\n",
575 : "\n-->is eol-comment\nvar y = 37;\n",
576 : "\n-->\nvar y = 37;\n",
577 : "/* precomment */ --> is eol-comment\nvar y = 37;\n",
578 : "/* precomment */-->eol-comment\nvar y = 37;\n",
579 : "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
580 : "\n/*precomment*/-->eol-comment\nvar y = 37;\n",
581 : // After first real token.
582 : "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
583 : "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
584 : "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
585 : "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
586 : "var x = 42;/*\n*/-->is eol-comment\nvar y = 37;\n",
587 : // With multiple comments preceding HTMLEndComment
588 : "/* MLC \n */ /* SLDC */ --> is eol-comment\nvar y = 37;\n",
589 : "/* MLC \n */ /* SLDC1 */ /* SLDC2 */ --> is eol-comment\nvar y = 37;\n",
590 : "/* MLC1 \n */ /* MLC2 \n */ --> is eol-comment\nvar y = 37;\n",
591 : "/* SLDC */ /* MLC \n */ --> is eol-comment\nvar y = 37;\n",
592 : "/* MLC1 \n */ /* SLDC1 */ /* MLC2 \n */ /* SLDC2 */ --> is eol-comment\n"
593 : "var y = 37;\n",
594 : nullptr
595 5 : };
596 :
597 : const char* fail_tests[] = {
598 : "x --> is eol-comment\nvar y = 37;\n",
599 : "\"\\n\" --> is eol-comment\nvar y = 37;\n",
600 : "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
601 : "var x = 42; --> is eol-comment\nvar y = 37;\n",
602 : nullptr
603 5 : };
604 : // clang-format on
605 :
606 : // Parser/Scanner needs a stack limit.
607 5 : i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
608 5 : 128 * 1024);
609 5 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
610 105 : for (int i = 0; tests[i]; i++) {
611 : const char* source = tests[i];
612 100 : auto stream = i::ScannerStream::ForTesting(source);
613 200 : i::Scanner scanner(stream.get(), false);
614 100 : scanner.Initialize();
615 200 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
616 : i::AstValueFactory ast_value_factory(&zone,
617 : i_isolate->ast_string_constants(),
618 200 : i_isolate->heap()->HashSeed());
619 : i::PendingCompilationErrorHandler pending_error_handler;
620 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
621 : &pending_error_handler,
622 : i_isolate->counters()->runtime_call_stats(),
623 100 : i_isolate->logger());
624 100 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
625 100 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
626 100 : CHECK(!pending_error_handler.has_pending_error());
627 : }
628 :
629 20 : for (int i = 0; fail_tests[i]; i++) {
630 : const char* source = fail_tests[i];
631 20 : auto stream = i::ScannerStream::ForTesting(source);
632 40 : i::Scanner scanner(stream.get(), false);
633 20 : scanner.Initialize();
634 40 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
635 : i::AstValueFactory ast_value_factory(&zone,
636 : i_isolate->ast_string_constants(),
637 40 : i_isolate->heap()->HashSeed());
638 : i::PendingCompilationErrorHandler pending_error_handler;
639 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
640 : &pending_error_handler,
641 : i_isolate->counters()->runtime_call_stats(),
642 20 : i_isolate->logger());
643 20 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
644 : // Even in the case of a syntax error, kPreParseSuccess is returned.
645 20 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
646 20 : CHECK(pending_error_handler.has_pending_error() ||
647 : pending_error_handler.has_error_unidentifiable_by_preparser());
648 5 : }
649 5 : }
650 :
651 28342 : TEST(ScanHtmlComments) {
652 : const char* src = "a <!-- b --> c";
653 : // Disallow HTML comments.
654 : {
655 5 : auto stream = i::ScannerStream::ForTesting(src);
656 10 : i::Scanner scanner(stream.get(), true);
657 5 : scanner.Initialize();
658 5 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
659 5 : CHECK_EQ(i::Token::ILLEGAL, scanner.Next());
660 : }
661 :
662 : // Skip HTML comments:
663 : {
664 5 : auto stream = i::ScannerStream::ForTesting(src);
665 10 : i::Scanner scanner(stream.get(), false);
666 5 : scanner.Initialize();
667 5 : CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
668 5 : CHECK_EQ(i::Token::EOS, scanner.Next());
669 : }
670 5 : }
671 :
672 0 : class ScriptResource : public v8::String::ExternalOneByteStringResource {
673 : public:
674 : ScriptResource(const char* data, size_t length)
675 : : data_(data), length_(length) { }
676 :
677 0 : const char* data() const override { return data_; }
678 0 : size_t length() const override { return length_; }
679 :
680 : private:
681 : const char* data_;
682 : size_t length_;
683 : };
684 :
685 :
686 28342 : TEST(StandAlonePreParser) {
687 5 : v8::V8::Initialize();
688 90 : i::Isolate* i_isolate = CcTest::i_isolate();
689 :
690 5 : i_isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
691 5 : 128 * 1024);
692 :
693 : const char* programs[] = {"{label: 42}",
694 : "var x = 42;",
695 : "function foo(x, y) { return x + y; }",
696 : "%ArgleBargle(glop);",
697 : "var x = new new Function('this.x = 42');",
698 : "var f = (x, y) => x + y;",
699 5 : nullptr};
700 :
701 5 : uintptr_t stack_limit = i_isolate->stack_guard()->real_climit();
702 35 : for (int i = 0; programs[i]; i++) {
703 30 : auto stream = i::ScannerStream::ForTesting(programs[i]);
704 60 : i::Scanner scanner(stream.get(), false);
705 30 : scanner.Initialize();
706 :
707 60 : i::Zone zone(i_isolate->allocator(), ZONE_NAME);
708 : i::AstValueFactory ast_value_factory(&zone,
709 : i_isolate->ast_string_constants(),
710 60 : i_isolate->heap()->HashSeed());
711 : i::PendingCompilationErrorHandler pending_error_handler;
712 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
713 : &pending_error_handler,
714 : i_isolate->counters()->runtime_call_stats(),
715 30 : i_isolate->logger());
716 : preparser.set_allow_natives(true);
717 30 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
718 30 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
719 30 : CHECK(!pending_error_handler.has_pending_error());
720 : }
721 5 : }
722 :
723 :
724 28342 : TEST(StandAlonePreParserNoNatives) {
725 5 : v8::V8::Initialize();
726 :
727 10 : i::Isolate* isolate = CcTest::i_isolate();
728 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
729 10 : i::GetCurrentStackPosition() - 128 * 1024);
730 :
731 : const char* programs[] = {"%ArgleBargle(glop);", "var x = %_IsSmi(42);",
732 5 : nullptr};
733 :
734 5 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
735 15 : for (int i = 0; programs[i]; i++) {
736 10 : auto stream = i::ScannerStream::ForTesting(programs[i]);
737 20 : i::Scanner scanner(stream.get(), false);
738 10 : scanner.Initialize();
739 :
740 : // Preparser defaults to disallowing natives syntax.
741 20 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
742 : i::AstValueFactory ast_value_factory(
743 : &zone, CcTest::i_isolate()->ast_string_constants(),
744 20 : CcTest::i_isolate()->heap()->HashSeed());
745 : i::PendingCompilationErrorHandler pending_error_handler;
746 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
747 : &pending_error_handler,
748 : isolate->counters()->runtime_call_stats(),
749 10 : isolate->logger());
750 10 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
751 10 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
752 10 : CHECK(pending_error_handler.has_pending_error() ||
753 : pending_error_handler.has_error_unidentifiable_by_preparser());
754 : }
755 5 : }
756 :
757 :
758 28342 : TEST(RegressChromium62639) {
759 5 : v8::V8::Initialize();
760 5 : i::Isolate* isolate = CcTest::i_isolate();
761 :
762 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
763 5 : 128 * 1024);
764 :
765 : const char* program = "var x = 'something';\n"
766 : "escape: function() {}";
767 : // Fails parsing expecting an identifier after "function".
768 : // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
769 : // and then used the invalid currently scanned literal. This always
770 : // failed in debug mode, and sometimes crashed in release mode.
771 :
772 5 : auto stream = i::ScannerStream::ForTesting(program);
773 10 : i::Scanner scanner(stream.get(), false);
774 5 : scanner.Initialize();
775 10 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
776 : i::AstValueFactory ast_value_factory(
777 : &zone, CcTest::i_isolate()->ast_string_constants(),
778 10 : CcTest::i_isolate()->heap()->HashSeed());
779 : i::PendingCompilationErrorHandler pending_error_handler;
780 : i::PreParser preparser(
781 : &zone, &scanner, CcTest::i_isolate()->stack_guard()->real_climit(),
782 : &ast_value_factory, &pending_error_handler,
783 10 : isolate->counters()->runtime_call_stats(), isolate->logger());
784 5 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
785 : // Even in the case of a syntax error, kPreParseSuccess is returned.
786 5 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
787 5 : CHECK(pending_error_handler.has_pending_error() ||
788 : pending_error_handler.has_error_unidentifiable_by_preparser());
789 5 : }
790 :
791 :
792 28342 : TEST(PreParseOverflow) {
793 5 : v8::V8::Initialize();
794 5 : i::Isolate* isolate = CcTest::i_isolate();
795 :
796 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
797 5 : 128 * 1024);
798 :
799 : size_t kProgramSize = 1024 * 1024;
800 5 : std::unique_ptr<char[]> program(i::NewArray<char>(kProgramSize + 1));
801 : memset(program.get(), '(', kProgramSize);
802 5 : program[kProgramSize] = '\0';
803 :
804 5 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
805 :
806 5 : auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize);
807 10 : i::Scanner scanner(stream.get(), false);
808 5 : scanner.Initialize();
809 :
810 10 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
811 : i::AstValueFactory ast_value_factory(
812 : &zone, CcTest::i_isolate()->ast_string_constants(),
813 10 : CcTest::i_isolate()->heap()->HashSeed());
814 : i::PendingCompilationErrorHandler pending_error_handler;
815 : i::PreParser preparser(
816 : &zone, &scanner, stack_limit, &ast_value_factory, &pending_error_handler,
817 5 : isolate->counters()->runtime_call_stats(), isolate->logger());
818 5 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
819 5 : CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
820 5 : }
821 :
822 35 : void TestStreamScanner(i::Utf16CharacterStream* stream,
823 : i::Token::Value* expected_tokens,
824 : int skip_pos = 0, // Zero means not skipping.
825 : int skip_to = 0) {
826 35 : i::Scanner scanner(stream, false);
827 35 : scanner.Initialize();
828 :
829 : int i = 0;
830 190 : do {
831 190 : i::Token::Value expected = expected_tokens[i];
832 190 : i::Token::Value actual = scanner.Next();
833 190 : CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
834 190 : if (scanner.location().end_pos == skip_pos) {
835 30 : scanner.SeekForward(skip_to);
836 : }
837 190 : i++;
838 225 : } while (expected_tokens[i] != i::Token::ILLEGAL);
839 35 : }
840 :
841 :
842 28342 : TEST(StreamScanner) {
843 5 : v8::V8::Initialize();
844 : const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
845 : std::unique_ptr<i::Utf16CharacterStream> stream1(
846 5 : i::ScannerStream::ForTesting(str1));
847 : i::Token::Value expectations1[] = {
848 : i::Token::LBRACE,
849 : i::Token::IDENTIFIER,
850 : i::Token::IDENTIFIER,
851 : i::Token::FOR,
852 : i::Token::COLON,
853 : i::Token::MUL,
854 : i::Token::DIV,
855 : i::Token::LT,
856 : i::Token::SUB,
857 : i::Token::IDENTIFIER,
858 : i::Token::EOS,
859 : i::Token::ILLEGAL
860 5 : };
861 5 : TestStreamScanner(stream1.get(), expectations1, 0, 0);
862 :
863 : const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
864 : std::unique_ptr<i::Utf16CharacterStream> stream2(
865 5 : i::ScannerStream::ForTesting(str2));
866 : i::Token::Value expectations2[] = {
867 : i::Token::CASE,
868 : i::Token::DEFAULT,
869 : i::Token::CONST,
870 : i::Token::LBRACE,
871 : // Skipped part here
872 : i::Token::RBRACE,
873 : i::Token::DO,
874 : i::Token::EOS,
875 : i::Token::ILLEGAL
876 5 : };
877 : CHECK_EQ('{', str2[19]);
878 : CHECK_EQ('}', str2[37]);
879 5 : TestStreamScanner(stream2.get(), expectations2, 20, 37);
880 :
881 : const char* str3 = "{}}}}";
882 : i::Token::Value expectations3[] = {
883 : i::Token::LBRACE,
884 : i::Token::RBRACE,
885 : i::Token::RBRACE,
886 : i::Token::RBRACE,
887 : i::Token::RBRACE,
888 : i::Token::EOS,
889 : i::Token::ILLEGAL
890 5 : };
891 : // Skip zero-four RBRACEs.
892 35 : for (int i = 0; i <= 4; i++) {
893 25 : expectations3[6 - i] = i::Token::ILLEGAL;
894 25 : expectations3[5 - i] = i::Token::EOS;
895 : std::unique_ptr<i::Utf16CharacterStream> stream3(
896 25 : i::ScannerStream::ForTesting(str3));
897 50 : TestStreamScanner(stream3.get(), expectations3, 1, 1 + i);
898 : }
899 5 : }
900 :
901 110 : void TestScanRegExp(const char* re_source, const char* expected) {
902 110 : auto stream = i::ScannerStream::ForTesting(re_source);
903 : i::HandleScope scope(CcTest::i_isolate());
904 220 : i::Scanner scanner(stream.get(), false);
905 110 : scanner.Initialize();
906 :
907 : i::Token::Value start = scanner.peek();
908 110 : CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
909 110 : CHECK(scanner.ScanRegExpPattern());
910 110 : scanner.Next(); // Current token is now the regexp literal.
911 220 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
912 : i::AstValueFactory ast_value_factory(
913 : &zone, CcTest::i_isolate()->ast_string_constants(),
914 220 : CcTest::i_isolate()->heap()->HashSeed());
915 110 : const i::AstRawString* current_symbol =
916 110 : scanner.CurrentSymbol(&ast_value_factory);
917 110 : ast_value_factory.Internalize(CcTest::i_isolate());
918 : i::Handle<i::String> val = current_symbol->string();
919 : i::DisallowHeapAllocation no_alloc;
920 110 : i::String::FlatContent content = val->GetFlatContent(no_alloc);
921 110 : CHECK(content.IsOneByte());
922 110 : i::Vector<const uint8_t> actual = content.ToOneByteVector();
923 510 : for (int i = 0; i < actual.length(); i++) {
924 400 : CHECK_NE('\0', expected[i]);
925 800 : CHECK_EQ(expected[i], actual[i]);
926 : }
927 110 : }
928 :
929 :
930 28342 : TEST(RegExpScanning) {
931 5 : v8::V8::Initialize();
932 :
933 : // RegExp token with added garbage at the end. The scanner should only
934 : // scan the RegExp until the terminating slash just before "flipperwald".
935 5 : TestScanRegExp("/b/flipperwald", "b");
936 : // Incomplete escape sequences doesn't hide the terminating slash.
937 5 : TestScanRegExp("/\\x/flipperwald", "\\x");
938 5 : TestScanRegExp("/\\u/flipperwald", "\\u");
939 5 : TestScanRegExp("/\\u1/flipperwald", "\\u1");
940 5 : TestScanRegExp("/\\u12/flipperwald", "\\u12");
941 5 : TestScanRegExp("/\\u123/flipperwald", "\\u123");
942 5 : TestScanRegExp("/\\c/flipperwald", "\\c");
943 5 : TestScanRegExp("/\\c//flipperwald", "\\c");
944 : // Slashes inside character classes are not terminating.
945 5 : TestScanRegExp("/[/]/flipperwald", "[/]");
946 5 : TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
947 : // Incomplete escape sequences inside a character class doesn't hide
948 : // the end of the character class.
949 5 : TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
950 5 : TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
951 5 : TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
952 5 : TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
953 5 : TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
954 5 : TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
955 5 : TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
956 5 : TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
957 : // Escaped ']'s wont end the character class.
958 5 : TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
959 : // Escaped slashes are not terminating.
960 5 : TestScanRegExp("/\\//flipperwald", "\\/");
961 : // Starting with '=' works too.
962 5 : TestScanRegExp("/=/", "=");
963 5 : TestScanRegExp("/=?/", "=?");
964 5 : }
965 :
966 28342 : TEST(ScopeUsesArgumentsSuperThis) {
967 : static const struct {
968 : const char* prefix;
969 : const char* suffix;
970 : } surroundings[] = {
971 : { "function f() {", "}" },
972 : { "var f = () => {", "};" },
973 : { "class C { constructor() {", "} }" },
974 : };
975 :
976 : enum Expected {
977 : NONE = 0,
978 : ARGUMENTS = 1,
979 : SUPER_PROPERTY = 1 << 1,
980 : THIS = 1 << 2,
981 : EVAL = 1 << 4
982 : };
983 :
984 : // clang-format off
985 : static const struct {
986 : const char* body;
987 : int expected;
988 : } source_data[] = {
989 : {"", NONE},
990 : {"return this", THIS},
991 : {"return arguments", ARGUMENTS},
992 : {"return super.x", SUPER_PROPERTY},
993 : {"return arguments[0]", ARGUMENTS},
994 : {"return this + arguments[0]", ARGUMENTS | THIS},
995 : {"return this + arguments[0] + super.x",
996 : ARGUMENTS | SUPER_PROPERTY | THIS},
997 : {"return x => this + x", THIS},
998 : {"return x => super.f() + x", SUPER_PROPERTY},
999 : {"this.foo = 42;", THIS},
1000 : {"this.foo();", THIS},
1001 : {"if (foo()) { this.f() }", THIS},
1002 : {"if (foo()) { super.f() }", SUPER_PROPERTY},
1003 : {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
1004 : {"while (true) { this.f() }", THIS},
1005 : {"while (true) { super.f() }", SUPER_PROPERTY},
1006 : {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
1007 : // Multiple nesting levels must work as well.
1008 : {"while (true) { while (true) { while (true) return this } }", THIS},
1009 : {"while (true) { while (true) { while (true) return super.f() } }",
1010 : SUPER_PROPERTY},
1011 : {"if (1) { return () => { while (true) new this() } }", THIS},
1012 : {"return function (x) { return this + x }", NONE},
1013 : {"return { m(x) { return super.m() + x } }", NONE},
1014 : {"var x = function () { this.foo = 42 };", NONE},
1015 : {"var x = { m() { super.foo = 42 } };", NONE},
1016 : {"if (1) { return function () { while (true) new this() } }", NONE},
1017 : {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1018 : {"return function (x) { return () => this }", NONE},
1019 : {"return { m(x) { return () => super.m() } }", NONE},
1020 : // Flags must be correctly set when using block scoping.
1021 : {"\"use strict\"; while (true) { let x; this, arguments; }",
1022 : THIS},
1023 : {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1024 : SUPER_PROPERTY | THIS},
1025 : {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
1026 : {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
1027 : {"\"use strict\"; if (1) {"
1028 : " let x; return { m() { return this + super.m() + arguments } }"
1029 : "}",
1030 : NONE},
1031 : {"eval(42)", EVAL},
1032 : {"if (1) { eval(42) }", EVAL},
1033 : {"eval('super.x')", EVAL},
1034 : {"eval('this.x')", EVAL},
1035 : {"eval('arguments')", EVAL},
1036 : };
1037 : // clang-format on
1038 :
1039 : i::Isolate* isolate = CcTest::i_isolate();
1040 : i::Factory* factory = isolate->factory();
1041 :
1042 5 : v8::HandleScope handles(CcTest::isolate());
1043 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1044 : v8::Context::Scope context_scope(context);
1045 :
1046 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1047 5 : 128 * 1024);
1048 :
1049 20 : for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1050 570 : for (unsigned i = 0; i < arraysize(source_data); ++i) {
1051 : // Super property is only allowed in constructor and method.
1052 570 : if (((source_data[i].expected & SUPER_PROPERTY) ||
1053 270 : (source_data[i].expected == NONE)) && j != 2) {
1054 180 : continue;
1055 : }
1056 780 : int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1057 390 : i::StrLength(surroundings[j].suffix) +
1058 780 : i::StrLength(source_data[i].body);
1059 390 : i::ScopedVector<char> program(kProgramByteSize + 1);
1060 : i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1061 390 : source_data[i].body, surroundings[j].suffix);
1062 : i::Handle<i::String> source =
1063 : factory->NewStringFromUtf8(i::CStrVector(program.start()))
1064 780 : .ToHandleChecked();
1065 390 : i::Handle<i::Script> script = factory->NewScript(source);
1066 780 : i::ParseInfo info(isolate, script);
1067 : // The information we're checking is only produced when eager parsing.
1068 : info.set_allow_lazy_parsing(false);
1069 390 : CHECK(i::parsing::ParseProgram(&info, isolate));
1070 390 : CHECK(i::Rewriter::Rewrite(&info));
1071 390 : info.ast_value_factory()->Internalize(isolate);
1072 390 : CHECK(i::DeclarationScope::Analyze(&info));
1073 390 : i::DeclarationScope::AllocateScopeInfos(&info, isolate);
1074 390 : CHECK_NOT_NULL(info.literal());
1075 :
1076 390 : i::DeclarationScope* script_scope = info.literal()->scope();
1077 390 : CHECK(script_scope->is_script_scope());
1078 :
1079 190 : i::Scope* scope = script_scope->inner_scope();
1080 : DCHECK_NOT_NULL(scope);
1081 : DCHECK_NULL(scope->sibling());
1082 : // Adjust for constructor scope.
1083 390 : if (j == 2) {
1084 : scope = scope->inner_scope();
1085 : DCHECK_NOT_NULL(scope);
1086 : DCHECK_NULL(scope->sibling());
1087 : }
1088 : // Arrows themselves never get an arguments object.
1089 470 : if ((source_data[i].expected & ARGUMENTS) != 0 &&
1090 80 : !scope->AsDeclarationScope()->is_arrow_scope()) {
1091 55 : CHECK_NOT_NULL(scope->AsDeclarationScope()->arguments());
1092 : }
1093 780 : if (IsClassConstructor(scope->AsDeclarationScope()->function_kind())) {
1094 190 : CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0 ||
1095 : (source_data[i].expected & EVAL) != 0,
1096 : scope->AsDeclarationScope()->NeedsHomeObject());
1097 : } else {
1098 200 : CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1099 : scope->AsDeclarationScope()->NeedsHomeObject());
1100 : }
1101 390 : if ((source_data[i].expected & THIS) != 0) {
1102 : // Currently the is_used() flag is conservative; all variables in a
1103 : // script scope are marked as used.
1104 615 : CHECK(scope->LookupForTesting(info.ast_value_factory()->this_string())
1105 : ->is_used());
1106 : }
1107 390 : if (is_sloppy(scope->language_mode())) {
1108 360 : CHECK_EQ((source_data[i].expected & EVAL) != 0,
1109 : scope->AsDeclarationScope()->calls_sloppy_eval());
1110 : }
1111 : }
1112 5 : }
1113 5 : }
1114 :
1115 75 : static void CheckParsesToNumber(const char* source) {
1116 75 : v8::V8::Initialize();
1117 75 : HandleAndZoneScope handles;
1118 :
1119 : i::Isolate* isolate = CcTest::i_isolate();
1120 : i::Factory* factory = isolate->factory();
1121 :
1122 75 : std::string full_source = "function f() { return ";
1123 : full_source += source;
1124 : full_source += "; }";
1125 :
1126 : i::Handle<i::String> source_code =
1127 : factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1128 150 : .ToHandleChecked();
1129 :
1130 75 : i::Handle<i::Script> script = factory->NewScript(source_code);
1131 :
1132 150 : i::ParseInfo info(isolate, script);
1133 : info.set_allow_lazy_parsing(false);
1134 : info.set_toplevel(true);
1135 :
1136 75 : CHECK(i::parsing::ParseProgram(&info, isolate));
1137 :
1138 150 : CHECK_EQ(1, info.scope()->declarations()->LengthForTest());
1139 75 : i::Declaration* decl = info.scope()->declarations()->AtForTest(0);
1140 150 : i::FunctionLiteral* fun = decl->AsFunctionDeclaration()->fun();
1141 75 : CHECK_EQ(fun->body()->length(), 1);
1142 150 : CHECK(fun->body()->at(0)->IsReturnStatement());
1143 150 : i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1144 75 : i::Literal* lit = ret->expression()->AsLiteral();
1145 150 : CHECK(lit->IsNumberLiteral());
1146 75 : }
1147 :
1148 :
1149 28342 : TEST(ParseNumbers) {
1150 5 : CheckParsesToNumber("1.");
1151 5 : CheckParsesToNumber("1.34");
1152 5 : CheckParsesToNumber("134");
1153 5 : CheckParsesToNumber("134e44");
1154 5 : CheckParsesToNumber("134.e44");
1155 5 : CheckParsesToNumber("134.44e44");
1156 5 : CheckParsesToNumber(".44");
1157 :
1158 5 : CheckParsesToNumber("-1.");
1159 5 : CheckParsesToNumber("-1.0");
1160 5 : CheckParsesToNumber("-1.34");
1161 5 : CheckParsesToNumber("-134");
1162 5 : CheckParsesToNumber("-134e44");
1163 5 : CheckParsesToNumber("-134.e44");
1164 5 : CheckParsesToNumber("-134.44e44");
1165 5 : CheckParsesToNumber("-.44");
1166 5 : }
1167 :
1168 :
1169 28342 : TEST(ScopePositions) {
1170 : // Test the parser for correctly setting the start and end positions
1171 : // of a scope. We check the scope positions of exactly one scope
1172 : // nested in the global scope of a program. 'inner source' is the
1173 : // source code that determines the part of the source belonging
1174 : // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1175 : // parts of the source that belong to the global scope.
1176 : struct SourceData {
1177 : const char* outer_prefix;
1178 : const char* inner_source;
1179 : const char* outer_suffix;
1180 : i::ScopeType scope_type;
1181 : i::LanguageMode language_mode;
1182 : };
1183 :
1184 : const SourceData source_data[] = {
1185 : {" with ({}) ", "{ block; }", " more;", i::WITH_SCOPE,
1186 : i::LanguageMode::kSloppy},
1187 : {" with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE,
1188 : i::LanguageMode::kSloppy},
1189 : {" with ({}) ",
1190 : "{\n"
1191 : " block;\n"
1192 : " }",
1193 : "\n"
1194 : " more;",
1195 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1196 : {" with ({}) ", "statement;", " more;", i::WITH_SCOPE,
1197 : i::LanguageMode::kSloppy},
1198 : {" with ({}) ", "statement",
1199 : "\n"
1200 : " more;",
1201 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1202 : {" with ({})\n"
1203 : " ",
1204 : "statement;",
1205 : "\n"
1206 : " more;",
1207 : i::WITH_SCOPE, i::LanguageMode::kSloppy},
1208 : {" try {} catch ", "(e) { block; }", " more;", i::CATCH_SCOPE,
1209 : i::LanguageMode::kSloppy},
1210 : {" try {} catch ", "(e) { block; }", "; more;", i::CATCH_SCOPE,
1211 : i::LanguageMode::kSloppy},
1212 : {" try {} catch ",
1213 : "(e) {\n"
1214 : " block;\n"
1215 : " }",
1216 : "\n"
1217 : " more;",
1218 : i::CATCH_SCOPE, i::LanguageMode::kSloppy},
1219 : {" try {} catch ", "(e) { block; }", " finally { block; } more;",
1220 : i::CATCH_SCOPE, i::LanguageMode::kSloppy},
1221 : {" start;\n"
1222 : " ",
1223 : "{ let block; }", " more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1224 : {" start;\n"
1225 : " ",
1226 : "{ let block; }", "; more;", i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1227 : {" start;\n"
1228 : " ",
1229 : "{\n"
1230 : " let block;\n"
1231 : " }",
1232 : "\n"
1233 : " more;",
1234 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1235 : {" start;\n"
1236 : " function fun",
1237 : "(a,b) { infunction; }", " more;", i::FUNCTION_SCOPE,
1238 : i::LanguageMode::kSloppy},
1239 : {" start;\n"
1240 : " function fun",
1241 : "(a,b) {\n"
1242 : " infunction;\n"
1243 : " }",
1244 : "\n"
1245 : " more;",
1246 : i::FUNCTION_SCOPE, i::LanguageMode::kSloppy},
1247 : {" start;\n", "(a,b) => a + b", "; more;", i::FUNCTION_SCOPE,
1248 : i::LanguageMode::kSloppy},
1249 : {" start;\n", "(a,b) => { return a+b; }", "\nmore;", i::FUNCTION_SCOPE,
1250 : i::LanguageMode::kSloppy},
1251 : {" start;\n"
1252 : " (function fun",
1253 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1254 : i::LanguageMode::kSloppy},
1255 : {" for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
1256 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1257 : {" for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
1258 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1259 : {" for ",
1260 : "(let x = 1 ; x < 10; ++ x) {\n"
1261 : " block;\n"
1262 : " }",
1263 : "\n"
1264 : " more;",
1265 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1266 : {" for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
1267 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1268 : {" for ", "(let x = 1 ; x < 10; ++ x) statement",
1269 : "\n"
1270 : " more;",
1271 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1272 : {" for ",
1273 : "(let x = 1 ; x < 10; ++ x)\n"
1274 : " statement;",
1275 : "\n"
1276 : " more;",
1277 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1278 : {" for ", "(let x in {}) { block; }", " more;", i::BLOCK_SCOPE,
1279 : i::LanguageMode::kStrict},
1280 : {" for ", "(let x in {}) { block; }", "; more;", i::BLOCK_SCOPE,
1281 : i::LanguageMode::kStrict},
1282 : {" for ",
1283 : "(let x in {}) {\n"
1284 : " block;\n"
1285 : " }",
1286 : "\n"
1287 : " more;",
1288 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1289 : {" for ", "(let x in {}) statement;", " more;", i::BLOCK_SCOPE,
1290 : i::LanguageMode::kStrict},
1291 : {" for ", "(let x in {}) statement",
1292 : "\n"
1293 : " more;",
1294 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1295 : {" for ",
1296 : "(let x in {})\n"
1297 : " statement;",
1298 : "\n"
1299 : " more;",
1300 : i::BLOCK_SCOPE, i::LanguageMode::kStrict},
1301 : // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1302 : // the preparser off in terms of byte offsets.
1303 : // 2 surrogates, encode a character that doesn't need a surrogate.
1304 : {" 'foo\xED\xA0\x81\xED\xB0\x89';\n"
1305 : " (function fun",
1306 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1307 : i::LanguageMode::kSloppy},
1308 : // 4-byte encoding.
1309 : {" 'foo\xF0\x90\x90\x8A';\n"
1310 : " (function fun",
1311 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1312 : i::LanguageMode::kSloppy},
1313 : // 3-byte encoding of \u0FFF.
1314 : {" 'foo\xE0\xBF\xBF';\n"
1315 : " (function fun",
1316 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1317 : i::LanguageMode::kSloppy},
1318 : // 3-byte surrogate, followed by broken 2-byte surrogate w/ impossible 2nd
1319 : // byte and last byte missing.
1320 : {" 'foo\xED\xA0\x81\xED\x89';\n"
1321 : " (function fun",
1322 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1323 : i::LanguageMode::kSloppy},
1324 : // Broken 3-byte encoding of \u0FFF with missing last byte.
1325 : {" 'foo\xE0\xBF';\n"
1326 : " (function fun",
1327 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1328 : i::LanguageMode::kSloppy},
1329 : // Broken 3-byte encoding of \u0FFF with missing 2 last bytes.
1330 : {" 'foo\xE0';\n"
1331 : " (function fun",
1332 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1333 : i::LanguageMode::kSloppy},
1334 : // Broken 3-byte encoding of \u00FF should be a 2-byte encoding.
1335 : {" 'foo\xE0\x83\xBF';\n"
1336 : " (function fun",
1337 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1338 : i::LanguageMode::kSloppy},
1339 : // Broken 3-byte encoding of \u007F should be a 2-byte encoding.
1340 : {" 'foo\xE0\x81\xBF';\n"
1341 : " (function fun",
1342 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1343 : i::LanguageMode::kSloppy},
1344 : // Unpaired lead surrogate.
1345 : {" 'foo\xED\xA0\x81';\n"
1346 : " (function fun",
1347 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1348 : i::LanguageMode::kSloppy},
1349 : // Unpaired lead surrogate where the following code point is a 3-byte
1350 : // sequence.
1351 : {" 'foo\xED\xA0\x81\xE0\xBF\xBF';\n"
1352 : " (function fun",
1353 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1354 : i::LanguageMode::kSloppy},
1355 : // Unpaired lead surrogate where the following code point is a 4-byte
1356 : // encoding of a trail surrogate.
1357 : {" 'foo\xED\xA0\x81\xF0\x8D\xB0\x89';\n"
1358 : " (function fun",
1359 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1360 : i::LanguageMode::kSloppy},
1361 : // Unpaired trail surrogate.
1362 : {" 'foo\xED\xB0\x89';\n"
1363 : " (function fun",
1364 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1365 : i::LanguageMode::kSloppy},
1366 : // 2-byte encoding of \u00FF.
1367 : {" 'foo\xC3\xBF';\n"
1368 : " (function fun",
1369 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1370 : i::LanguageMode::kSloppy},
1371 : // Broken 2-byte encoding of \u00FF with missing last byte.
1372 : {" 'foo\xC3';\n"
1373 : " (function fun",
1374 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1375 : i::LanguageMode::kSloppy},
1376 : // Broken 2-byte encoding of \u007F should be a 1-byte encoding.
1377 : {" 'foo\xC1\xBF';\n"
1378 : " (function fun",
1379 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1380 : i::LanguageMode::kSloppy},
1381 : // Illegal 5-byte encoding.
1382 : {" 'foo\xF8\xBF\xBF\xBF\xBF';\n"
1383 : " (function fun",
1384 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1385 : i::LanguageMode::kSloppy},
1386 : // Illegal 6-byte encoding.
1387 : {" 'foo\xFC\xBF\xBF\xBF\xBF\xBF';\n"
1388 : " (function fun",
1389 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1390 : i::LanguageMode::kSloppy},
1391 : // Illegal 0xFE byte
1392 : {" 'foo\xFE\xBF\xBF\xBF\xBF\xBF\xBF';\n"
1393 : " (function fun",
1394 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1395 : i::LanguageMode::kSloppy},
1396 : // Illegal 0xFF byte
1397 : {" 'foo\xFF\xBF\xBF\xBF\xBF\xBF\xBF\xBF';\n"
1398 : " (function fun",
1399 : "(a,b) { infunction; }", ")();", i::FUNCTION_SCOPE,
1400 : i::LanguageMode::kSloppy},
1401 : {" 'foo';\n"
1402 : " (function fun",
1403 : "(a,b) { 'bar\xED\xA0\x81\xED\xB0\x8B'; }", ")();", i::FUNCTION_SCOPE,
1404 : i::LanguageMode::kSloppy},
1405 : {" 'foo';\n"
1406 : " (function fun",
1407 : "(a,b) { 'bar\xF0\x90\x90\x8C'; }", ")();", i::FUNCTION_SCOPE,
1408 : i::LanguageMode::kSloppy},
1409 5 : {nullptr, nullptr, nullptr, i::EVAL_SCOPE, i::LanguageMode::kSloppy}};
1410 :
1411 : i::Isolate* isolate = CcTest::i_isolate();
1412 : i::Factory* factory = isolate->factory();
1413 :
1414 5 : v8::HandleScope handles(CcTest::isolate());
1415 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1416 : v8::Context::Scope context_scope(context);
1417 :
1418 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1419 5 : 128 * 1024);
1420 :
1421 260 : for (int i = 0; source_data[i].outer_prefix; i++) {
1422 255 : int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1423 255 : int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1424 255 : int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1425 : int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1426 : int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1427 : int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1428 255 : int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1429 255 : int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1430 255 : i::ScopedVector<char> program(kProgramByteSize + 1);
1431 : i::SNPrintF(program, "%s%s%s",
1432 : source_data[i].outer_prefix,
1433 : source_data[i].inner_source,
1434 255 : source_data[i].outer_suffix);
1435 :
1436 : // Parse program source.
1437 : i::Handle<i::String> source = factory->NewStringFromUtf8(
1438 510 : i::CStrVector(program.start())).ToHandleChecked();
1439 255 : CHECK_EQ(source->length(), kProgramSize);
1440 255 : i::Handle<i::Script> script = factory->NewScript(source);
1441 510 : i::ParseInfo info(isolate, script);
1442 255 : info.set_language_mode(source_data[i].language_mode);
1443 255 : i::parsing::ParseProgram(&info, isolate);
1444 255 : CHECK_NOT_NULL(info.literal());
1445 :
1446 : // Check scope types and positions.
1447 1020 : i::Scope* scope = info.literal()->scope();
1448 255 : CHECK(scope->is_script_scope());
1449 255 : CHECK_EQ(0, scope->start_position());
1450 255 : CHECK_EQ(scope->end_position(), kProgramSize);
1451 :
1452 765 : i::Scope* inner_scope = scope->inner_scope();
1453 : DCHECK_NOT_NULL(inner_scope);
1454 : DCHECK_NULL(inner_scope->sibling());
1455 510 : CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1456 255 : CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1457 : // The end position of a token is one position after the last
1458 : // character belonging to that token.
1459 255 : CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1460 5 : }
1461 5 : }
1462 :
1463 :
1464 28342 : TEST(DiscardFunctionBody) {
1465 : // Test that inner function bodies are discarded if possible.
1466 : // See comments in ParseFunctionLiteral in parser.cc.
1467 : const char* discard_sources[] = {
1468 : "(function f() { function g() { var a; } })();",
1469 : "(function f() { function g() { { function h() { } } } })();",
1470 : /* TODO(conradw): In future it may be possible to apply this optimisation
1471 : * to these productions.
1472 : "(function f() { 0, function g() { var a; } })();",
1473 : "(function f() { 0, { g() { var a; } } })();",
1474 : "(function f() { 0, class c { g() { var a; } } })();", */
1475 5 : nullptr};
1476 :
1477 : i::Isolate* isolate = CcTest::i_isolate();
1478 : i::Factory* factory = isolate->factory();
1479 5 : v8::HandleScope handles(CcTest::isolate());
1480 : i::FunctionLiteral* function;
1481 :
1482 15 : for (int i = 0; discard_sources[i]; i++) {
1483 : const char* source = discard_sources[i];
1484 : i::Handle<i::String> source_code =
1485 20 : factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
1486 10 : i::Handle<i::Script> script = factory->NewScript(source_code);
1487 10 : i::ParseInfo info(isolate, script);
1488 10 : i::parsing::ParseProgram(&info, isolate);
1489 10 : function = info.literal();
1490 10 : CHECK_NOT_NULL(function);
1491 10 : CHECK_EQ(1, function->body()->length());
1492 10 : i::FunctionLiteral* inner =
1493 20 : function->body()->first()->AsExpressionStatement()->expression()->
1494 20 : AsCall()->expression()->AsFunctionLiteral();
1495 : i::Scope* inner_scope = inner->scope();
1496 : i::FunctionLiteral* fun = nullptr;
1497 10 : if (!inner_scope->declarations()->is_empty()) {
1498 : fun = inner_scope->declarations()
1499 : ->AtForTest(0)
1500 : ->AsFunctionDeclaration()
1501 20 : ->fun();
1502 : } else {
1503 : // TODO(conradw): This path won't be hit until the other test cases can be
1504 : // uncommented.
1505 0 : UNREACHABLE();
1506 : CHECK(inner->ShouldEagerCompile());
1507 : CHECK_GE(2, inner->body()->length());
1508 : i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
1509 : expression()->AsBinaryOperation()->right();
1510 : if (exp->IsFunctionLiteral()) {
1511 : fun = exp->AsFunctionLiteral();
1512 : } else if (exp->IsObjectLiteral()) {
1513 : fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
1514 : AsFunctionLiteral();
1515 : } else {
1516 : fun = exp->AsClassLiteral()->properties()->at(0)->value()->
1517 : AsFunctionLiteral();
1518 : }
1519 : }
1520 10 : CHECK(!fun->ShouldEagerCompile());
1521 15 : }
1522 5 : }
1523 :
1524 :
1525 0 : const char* ReadString(unsigned* start) {
1526 0 : int length = start[0];
1527 0 : char* result = i::NewArray<char>(length + 1);
1528 0 : for (int i = 0; i < length; i++) {
1529 0 : result[i] = start[i + 1];
1530 : }
1531 0 : result[length] = '\0';
1532 0 : return result;
1533 : }
1534 :
1535 : enum ParserFlag {
1536 : kAllowLazy,
1537 : kAllowNatives,
1538 : kAllowHarmonyPublicFields,
1539 : kAllowHarmonyPrivateFields,
1540 : kAllowHarmonyPrivateMethods,
1541 : kAllowHarmonyStaticFields,
1542 : kAllowHarmonyDynamicImport,
1543 : kAllowHarmonyImportMeta,
1544 : kAllowHarmonyNumericSeparator
1545 : };
1546 :
1547 : enum ParserSyncTestResult {
1548 : kSuccessOrError,
1549 : kSuccess,
1550 : kError
1551 : };
1552 :
1553 510389 : void SetGlobalFlags(base::EnumSet<ParserFlag> flags) {
1554 510389 : i::FLAG_allow_natives_syntax = flags.contains(kAllowNatives);
1555 510389 : i::FLAG_harmony_public_fields = flags.contains(kAllowHarmonyPublicFields);
1556 510389 : i::FLAG_harmony_private_fields = flags.contains(kAllowHarmonyPrivateFields);
1557 510389 : i::FLAG_harmony_private_methods = flags.contains(kAllowHarmonyPrivateMethods);
1558 510389 : i::FLAG_harmony_static_fields = flags.contains(kAllowHarmonyStaticFields);
1559 510389 : i::FLAG_harmony_dynamic_import = flags.contains(kAllowHarmonyDynamicImport);
1560 510389 : i::FLAG_harmony_import_meta = flags.contains(kAllowHarmonyImportMeta);
1561 : i::FLAG_harmony_numeric_separator =
1562 510389 : flags.contains(kAllowHarmonyNumericSeparator);
1563 510389 : }
1564 :
1565 509409 : void SetParserFlags(i::PreParser* parser, base::EnumSet<ParserFlag> flags) {
1566 : parser->set_allow_natives(flags.contains(kAllowNatives));
1567 : parser->set_allow_harmony_public_fields(
1568 : flags.contains(kAllowHarmonyPublicFields));
1569 : parser->set_allow_harmony_private_fields(
1570 : flags.contains(kAllowHarmonyPrivateFields));
1571 : parser->set_allow_harmony_private_methods(
1572 : flags.contains(kAllowHarmonyPrivateMethods));
1573 : parser->set_allow_harmony_static_fields(
1574 : flags.contains(kAllowHarmonyStaticFields));
1575 : parser->set_allow_harmony_dynamic_import(
1576 : flags.contains(kAllowHarmonyDynamicImport));
1577 : parser->set_allow_harmony_import_meta(
1578 : flags.contains(kAllowHarmonyImportMeta));
1579 : parser->set_allow_harmony_numeric_separator(
1580 : flags.contains(kAllowHarmonyNumericSeparator));
1581 509409 : }
1582 :
1583 510389 : void TestParserSyncWithFlags(i::Handle<i::String> source,
1584 : base::EnumSet<ParserFlag> flags,
1585 : ParserSyncTestResult result,
1586 : bool is_module = false, bool test_preparser = true,
1587 : bool ignore_error_msg = false) {
1588 509409 : i::Isolate* isolate = CcTest::i_isolate();
1589 : i::Factory* factory = isolate->factory();
1590 :
1591 510389 : uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1592 :
1593 : // Preparse the data.
1594 : i::PendingCompilationErrorHandler pending_error_handler;
1595 510389 : if (test_preparser) {
1596 : std::unique_ptr<i::Utf16CharacterStream> stream(
1597 509409 : i::ScannerStream::For(isolate, source));
1598 1018818 : i::Scanner scanner(stream.get(), is_module);
1599 1018818 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
1600 : i::AstValueFactory ast_value_factory(
1601 : &zone, CcTest::i_isolate()->ast_string_constants(),
1602 1018818 : CcTest::i_isolate()->heap()->HashSeed());
1603 : i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory,
1604 : &pending_error_handler,
1605 : isolate->counters()->runtime_call_stats(),
1606 509409 : isolate->logger(), -1, is_module);
1607 509409 : SetParserFlags(&preparser, flags);
1608 509409 : scanner.Initialize();
1609 509409 : i::PreParser::PreParseResult result = preparser.PreParseProgram();
1610 509409 : CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1611 : }
1612 :
1613 : // Parse the data
1614 : i::FunctionLiteral* function;
1615 : {
1616 510389 : SetGlobalFlags(flags);
1617 510389 : i::Handle<i::Script> script = factory->NewScript(source);
1618 510389 : i::ParseInfo info(isolate, script);
1619 : info.set_allow_lazy_parsing(flags.contains(kAllowLazy));
1620 510389 : if (is_module) info.set_module();
1621 510389 : i::parsing::ParseProgram(&info, isolate);
1622 510389 : function = info.literal();
1623 : }
1624 :
1625 : // Check that preparsing fails iff parsing fails.
1626 510389 : if (function == nullptr) {
1627 : // Extract exception from the parser.
1628 262030 : CHECK(isolate->has_pending_exception());
1629 : i::Handle<i::JSObject> exception_handle(
1630 : i::JSObject::cast(isolate->pending_exception()), isolate);
1631 : i::Handle<i::String> message_string = i::Handle<i::String>::cast(
1632 262030 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1633 524060 : .ToHandleChecked());
1634 262030 : isolate->clear_pending_exception();
1635 :
1636 262030 : if (result == kSuccess) {
1637 0 : FATAL(
1638 : "Parser failed on:\n"
1639 : "\t%s\n"
1640 : "with error:\n"
1641 : "\t%s\n"
1642 : "However, we expected no error.",
1643 0 : source->ToCString().get(), message_string->ToCString().get());
1644 : }
1645 :
1646 262030 : if (test_preparser && !pending_error_handler.has_pending_error() &&
1647 0 : !pending_error_handler.has_error_unidentifiable_by_preparser()) {
1648 0 : FATAL(
1649 : "Parser failed on:\n"
1650 : "\t%s\n"
1651 : "with error:\n"
1652 : "\t%s\n"
1653 : "However, the preparser succeeded",
1654 0 : source->ToCString().get(), message_string->ToCString().get());
1655 : }
1656 : // Check that preparser and parser produce the same error, except for cases
1657 : // where we do not track errors in the preparser.
1658 511820 : if (test_preparser && !ignore_error_msg &&
1659 249790 : !pending_error_handler.has_error_unidentifiable_by_preparser()) {
1660 : i::Handle<i::String> preparser_message =
1661 2502 : pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate());
1662 2502 : if (!i::String::Equals(isolate, message_string, preparser_message)) {
1663 0 : FATAL(
1664 : "Expected parser and preparser to produce the same error on:\n"
1665 : "\t%s\n"
1666 : "However, found the following error messages\n"
1667 : "\tparser: %s\n"
1668 : "\tpreparser: %s\n",
1669 : source->ToCString().get(), message_string->ToCString().get(),
1670 0 : preparser_message->ToCString().get());
1671 : }
1672 : }
1673 248359 : } else if (test_preparser && pending_error_handler.has_pending_error()) {
1674 0 : FATAL(
1675 : "Preparser failed on:\n"
1676 : "\t%s\n"
1677 : "with error:\n"
1678 : "\t%s\n"
1679 : "However, the parser succeeded",
1680 : source->ToCString().get(),
1681 : pending_error_handler.FormatErrorMessageForTest(CcTest::i_isolate())
1682 : ->ToCString()
1683 0 : .get());
1684 248359 : } else if (result == kError) {
1685 0 : FATAL(
1686 : "Expected error on:\n"
1687 : "\t%s\n"
1688 : "However, parser and preparser succeeded",
1689 0 : source->ToCString().get());
1690 : }
1691 510389 : }
1692 :
1693 130488 : void TestParserSync(const char* source, const ParserFlag* varying_flags,
1694 : size_t varying_flags_length,
1695 : ParserSyncTestResult result = kSuccessOrError,
1696 : const ParserFlag* always_true_flags = nullptr,
1697 : size_t always_true_flags_length = 0,
1698 : const ParserFlag* always_false_flags = nullptr,
1699 : size_t always_false_flags_length = 0,
1700 : bool is_module = false, bool test_preparser = true,
1701 : bool ignore_error_msg = false) {
1702 : i::Handle<i::String> str =
1703 : CcTest::i_isolate()
1704 : ->factory()
1705 260976 : ->NewStringFromUtf8(Vector<const char>(source, strlen(source)))
1706 260976 : .ToHandleChecked();
1707 640877 : for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1708 : base::EnumSet<ParserFlag> flags;
1709 1011492 : for (size_t flag_index = 0; flag_index < varying_flags_length;
1710 : ++flag_index) {
1711 1011492 : if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1712 : }
1713 146530 : for (size_t flag_index = 0; flag_index < always_true_flags_length;
1714 : ++flag_index) {
1715 146530 : flags.Add(always_true_flags[flag_index]);
1716 : }
1717 0 : for (size_t flag_index = 0; flag_index < always_false_flags_length;
1718 : ++flag_index) {
1719 0 : flags.Remove(always_false_flags[flag_index]);
1720 : }
1721 : TestParserSyncWithFlags(str, flags, result, is_module, test_preparser,
1722 510389 : ignore_error_msg);
1723 : }
1724 130488 : }
1725 :
1726 :
1727 28338 : TEST(ParserSync) {
1728 : const char* context_data[][2] = {{"", ""},
1729 : {"{", "}"},
1730 : {"if (true) ", " else {}"},
1731 : {"if (true) {} else ", ""},
1732 : {"if (true) ", ""},
1733 : {"do ", " while (false)"},
1734 : {"while (false) ", ""},
1735 : {"for (;;) ", ""},
1736 : {"with ({})", ""},
1737 : {"switch (12) { case 12: ", "}"},
1738 : {"switch (12) { default: ", "}"},
1739 : {"switch (12) { ", "case 12: }"},
1740 : {"label2: ", ""},
1741 1 : {nullptr, nullptr}};
1742 :
1743 : const char* statement_data[] = {
1744 : "{}", "var x", "var x = 1", "const x", "const x = 1", ";", "12",
1745 : "if (false) {} else ;", "if (false) {} else {}", "if (false) {} else 12",
1746 : "if (false) ;", "if (false) {}", "if (false) 12", "do {} while (false)",
1747 : "for (;;) ;", "for (;;) {}", "for (;;) 12", "continue", "continue label",
1748 : "continue\nlabel", "break", "break label", "break\nlabel",
1749 : // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1750 : // "return",
1751 : // "return 12",
1752 : // "return\n12",
1753 : "with ({}) ;", "with ({}) {}", "with ({}) 12", "switch ({}) { default: }",
1754 : "label3: ", "throw", "throw 12", "throw\n12", "try {} catch(e) {}",
1755 : "try {} finally {}", "try {} catch(e) {} finally {}", "debugger",
1756 1 : nullptr};
1757 :
1758 1 : const char* termination_data[] = {"", ";", "\n", ";\n", "\n;", nullptr};
1759 :
1760 1 : v8::HandleScope handles(CcTest::isolate());
1761 1 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1762 : v8::Context::Scope context_scope(context);
1763 :
1764 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1765 2 : i::GetCurrentStackPosition() - 128 * 1024);
1766 :
1767 14 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1768 455 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1769 2275 : for (int k = 0; termination_data[k] != nullptr; ++k) {
1770 : int kPrefixLen = i::StrLength(context_data[i][0]);
1771 : int kStatementLen = i::StrLength(statement_data[j]);
1772 : int kTerminationLen = i::StrLength(termination_data[k]);
1773 2275 : int kSuffixLen = i::StrLength(context_data[i][1]);
1774 2275 : int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1775 2275 : + kSuffixLen + i::StrLength("label: for (;;) { }");
1776 :
1777 : // Plug the source code pieces together.
1778 2275 : i::ScopedVector<char> program(kProgramSize + 1);
1779 : int length = i::SNPrintF(program,
1780 : "label: for (;;) { %s%s%s%s }",
1781 : context_data[i][0],
1782 : statement_data[j],
1783 : termination_data[k],
1784 2275 : context_data[i][1]);
1785 2275 : CHECK_EQ(length, kProgramSize);
1786 2275 : TestParserSync(program.start(), nullptr, 0);
1787 : }
1788 : }
1789 : }
1790 :
1791 : // Neither Harmony numeric literals nor our natives syntax have any
1792 : // interaction with the flags above, so test these separately to reduce
1793 : // the combinatorial explosion.
1794 1 : TestParserSync("0o1234", nullptr, 0);
1795 1 : TestParserSync("0b1011", nullptr, 0);
1796 :
1797 : static const ParserFlag flags3[] = { kAllowNatives };
1798 2 : TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1799 1 : }
1800 :
1801 :
1802 28342 : TEST(StrictOctal) {
1803 : // Test that syntax error caused by octal literal is reported correctly as
1804 : // such (issue 2220).
1805 5 : v8::V8::Initialize();
1806 5 : v8::Isolate* isolate = CcTest::isolate();
1807 5 : v8::HandleScope scope(isolate);
1808 10 : v8::Context::Scope context_scope(v8::Context::New(isolate));
1809 :
1810 10 : v8::TryCatch try_catch(isolate);
1811 : const char* script =
1812 : "\"use strict\"; \n"
1813 : "a = function() { \n"
1814 : " b = function() { \n"
1815 : " 01; \n"
1816 : " }; \n"
1817 : "}; \n";
1818 5 : v8_compile(v8_str(script));
1819 5 : CHECK(try_catch.HasCaught());
1820 10 : v8::String::Utf8Value exception(isolate, try_catch.Exception());
1821 5 : CHECK_EQ(0,
1822 : strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1823 5 : *exception));
1824 5 : }
1825 :
1826 1570 : void RunParserSyncTest(
1827 : const char* context_data[][2], const char* statement_data[],
1828 : ParserSyncTestResult result, const ParserFlag* flags = nullptr,
1829 : int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
1830 : int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
1831 : int always_false_len = 0, bool is_module = false,
1832 : bool test_preparser = true, bool ignore_error_msg = false) {
1833 1570 : v8::HandleScope handles(CcTest::isolate());
1834 1570 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1835 : v8::Context::Scope context_scope(context);
1836 :
1837 : CcTest::i_isolate()->stack_guard()->SetStackLimit(
1838 3140 : i::GetCurrentStackPosition() - 128 * 1024);
1839 :
1840 : // Experimental feature flags should not go here; pass the flags as
1841 : // always_true_flags if the test needs them.
1842 : static const ParserFlag default_flags[] = {
1843 : kAllowLazy,
1844 : kAllowNatives,
1845 : };
1846 : ParserFlag* generated_flags = nullptr;
1847 1570 : if (flags == nullptr) {
1848 : flags = default_flags;
1849 : flags_len = arraysize(default_flags);
1850 1550 : if (always_true_flags != nullptr || always_false_flags != nullptr) {
1851 : // Remove always_true/false_flags from default_flags (if present).
1852 185 : CHECK((always_true_flags != nullptr) == (always_true_len > 0));
1853 185 : CHECK((always_false_flags != nullptr) == (always_false_len > 0));
1854 185 : generated_flags = new ParserFlag[flags_len + always_true_len];
1855 : int flag_index = 0;
1856 555 : for (int i = 0; i < flags_len; ++i) {
1857 : bool use_flag = true;
1858 560 : for (int j = 0; use_flag && j < always_true_len; ++j) {
1859 560 : if (flags[i] == always_true_flags[j]) use_flag = false;
1860 : }
1861 0 : for (int j = 0; use_flag && j < always_false_len; ++j) {
1862 0 : if (flags[i] == always_false_flags[j]) use_flag = false;
1863 : }
1864 370 : if (use_flag) generated_flags[flag_index++] = flags[i];
1865 : }
1866 : flags_len = flag_index;
1867 : flags = generated_flags;
1868 : }
1869 : }
1870 8285 : for (int i = 0; context_data[i][0] != nullptr; ++i) {
1871 128210 : for (int j = 0; statement_data[j] != nullptr; ++j) {
1872 128210 : int kPrefixLen = i::StrLength(context_data[i][0]);
1873 : int kStatementLen = i::StrLength(statement_data[j]);
1874 128210 : int kSuffixLen = i::StrLength(context_data[i][1]);
1875 128210 : int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1876 :
1877 : // Plug the source code pieces together.
1878 128210 : i::ScopedVector<char> program(kProgramSize + 1);
1879 : int length = i::SNPrintF(program,
1880 : "%s%s%s",
1881 : context_data[i][0],
1882 : statement_data[j],
1883 128210 : context_data[i][1]);
1884 128210 : PrintF("%s\n", program.start());
1885 128210 : CHECK_EQ(length, kProgramSize);
1886 : TestParserSync(program.start(), flags, flags_len, result,
1887 : always_true_flags, always_true_len, always_false_flags,
1888 : always_false_len, is_module, test_preparser,
1889 128210 : ignore_error_msg);
1890 : }
1891 : }
1892 3140 : delete[] generated_flags;
1893 1570 : }
1894 :
1895 0 : void RunModuleParserSyncTest(
1896 : const char* context_data[][2], const char* statement_data[],
1897 : ParserSyncTestResult result, const ParserFlag* flags = nullptr,
1898 : int flags_len = 0, const ParserFlag* always_true_flags = nullptr,
1899 : int always_true_len = 0, const ParserFlag* always_false_flags = nullptr,
1900 : int always_false_len = 0, bool test_preparser = true,
1901 : bool ignore_error_msg = false) {
1902 : RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1903 : always_true_flags, always_true_len, always_false_flags,
1904 95 : always_false_len, true, test_preparser, ignore_error_msg);
1905 0 : }
1906 :
1907 28342 : TEST(NumericSeparator) {
1908 5 : v8::HandleScope handles(CcTest::isolate());
1909 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1910 : v8::Context::Scope context_scope(context);
1911 :
1912 : const char* context_data[][2] = {
1913 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1914 : const char* statement_data[] = {
1915 : "1_0_0_0", "1_0e+1", "1_0e+1_0", "0xF_F_FF", "0o7_7_7", "0b0_1_0_1_0",
1916 5 : ".3_2_1", "0.0_2_1", "1_0.0_1", ".0_1_2", nullptr};
1917 :
1918 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1919 : RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0, flags,
1920 5 : 1);
1921 :
1922 10 : RunParserSyncTest(context_data, statement_data, kError);
1923 5 : }
1924 :
1925 28342 : TEST(NumericSeparatorErrors) {
1926 5 : v8::HandleScope handles(CcTest::isolate());
1927 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1928 : v8::Context::Scope context_scope(context);
1929 :
1930 : const char* context_data[][2] = {
1931 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1932 : const char* statement_data[] = {
1933 : "1_0_0_0_", "1e_1", "1e+_1", "1_e+1", "1__0", "0x_1",
1934 : "0x1__1", "0x1_", "0_x1", "0_x_1", "0b_0101", "0b11_",
1935 : "0b1__1", "0_b1", "0_b_1", "0o777_", "0o_777", "0o7__77",
1936 5 : "0.0_2_1_", "0.0__21", "0_.01", "0._01", nullptr};
1937 :
1938 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1939 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
1940 5 : nullptr, 0, false, true, true);
1941 :
1942 10 : RunParserSyncTest(context_data, statement_data, kError);
1943 5 : }
1944 :
1945 28342 : TEST(NumericSeparatorImplicitOctalsErrors) {
1946 5 : v8::HandleScope handles(CcTest::isolate());
1947 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1948 : v8::Context::Scope context_scope(context);
1949 :
1950 : const char* context_data[][2] = {
1951 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
1952 : const char* statement_data[] = {"00_122", "0_012", "07_7_7",
1953 : "0_7_7_7", "0_777", "07_7_7_",
1954 5 : "07__77", "0__777", nullptr};
1955 :
1956 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1957 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1,
1958 5 : nullptr, 0, false, true, true);
1959 :
1960 10 : RunParserSyncTest(context_data, statement_data, kError);
1961 5 : }
1962 :
1963 28342 : TEST(NumericSeparatorUnicodeEscapeSequencesErrors) {
1964 5 : v8::HandleScope handles(CcTest::isolate());
1965 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
1966 : v8::Context::Scope context_scope(context);
1967 :
1968 : const char* context_data[][2] = {
1969 5 : {"", ""}, {"'use strict'", ""}, {nullptr, nullptr}};
1970 : // https://github.com/tc39/proposal-numeric-separator/issues/25
1971 5 : const char* statement_data[] = {"\\u{10_FFFF}", nullptr};
1972 :
1973 : static const ParserFlag flags[] = {kAllowHarmonyNumericSeparator};
1974 5 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags, 1);
1975 :
1976 10 : RunParserSyncTest(context_data, statement_data, kError);
1977 5 : }
1978 :
1979 28342 : TEST(ErrorsEvalAndArguments) {
1980 : // Tests that both preparsing and parsing produce the right kind of errors for
1981 : // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1982 : // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1983 : // isn't.
1984 : const char* context_data[][2] = {
1985 : {"\"use strict\";", ""},
1986 : {"var eval; function test_func() {\"use strict\"; ", "}"},
1987 5 : {nullptr, nullptr}};
1988 :
1989 : const char* statement_data[] = {"var eval;",
1990 : "var arguments",
1991 : "var foo, eval;",
1992 : "var foo, arguments;",
1993 : "try { } catch (eval) { }",
1994 : "try { } catch (arguments) { }",
1995 : "function eval() { }",
1996 : "function arguments() { }",
1997 : "function foo(eval) { }",
1998 : "function foo(arguments) { }",
1999 : "function foo(bar, eval) { }",
2000 : "function foo(bar, arguments) { }",
2001 : "(eval) => { }",
2002 : "(arguments) => { }",
2003 : "(foo, eval) => { }",
2004 : "(foo, arguments) => { }",
2005 : "eval = 1;",
2006 : "arguments = 1;",
2007 : "var foo = eval = 1;",
2008 : "var foo = arguments = 1;",
2009 : "++eval;",
2010 : "++arguments;",
2011 : "eval++;",
2012 : "arguments++;",
2013 5 : nullptr};
2014 :
2015 5 : RunParserSyncTest(context_data, statement_data, kError);
2016 5 : }
2017 :
2018 :
2019 28342 : TEST(NoErrorsEvalAndArgumentsSloppy) {
2020 : // Tests that both preparsing and parsing accept "eval" and "arguments" as
2021 : // identifiers when needed.
2022 : const char* context_data[][2] = {
2023 5 : {"", ""}, {"function test_func() {", "}"}, {nullptr, nullptr}};
2024 :
2025 : const char* statement_data[] = {"var eval;",
2026 : "var arguments",
2027 : "var foo, eval;",
2028 : "var foo, arguments;",
2029 : "try { } catch (eval) { }",
2030 : "try { } catch (arguments) { }",
2031 : "function eval() { }",
2032 : "function arguments() { }",
2033 : "function foo(eval) { }",
2034 : "function foo(arguments) { }",
2035 : "function foo(bar, eval) { }",
2036 : "function foo(bar, arguments) { }",
2037 : "eval = 1;",
2038 : "arguments = 1;",
2039 : "var foo = eval = 1;",
2040 : "var foo = arguments = 1;",
2041 : "++eval;",
2042 : "++arguments;",
2043 : "eval++;",
2044 : "arguments++;",
2045 5 : nullptr};
2046 :
2047 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2048 5 : }
2049 :
2050 :
2051 28342 : TEST(NoErrorsEvalAndArgumentsStrict) {
2052 : const char* context_data[][2] = {
2053 : {"\"use strict\";", ""},
2054 : {"function test_func() { \"use strict\";", "}"},
2055 : {"() => { \"use strict\"; ", "}"},
2056 5 : {nullptr, nullptr}};
2057 :
2058 : const char* statement_data[] = {"eval;",
2059 : "arguments;",
2060 : "var foo = eval;",
2061 : "var foo = arguments;",
2062 : "var foo = { eval: 1 };",
2063 : "var foo = { arguments: 1 };",
2064 : "var foo = { }; foo.eval = {};",
2065 : "var foo = { }; foo.arguments = {};",
2066 5 : nullptr};
2067 :
2068 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2069 5 : }
2070 :
2071 : #define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2072 : V(implements) \
2073 : V(interface) \
2074 : V(package) \
2075 : V(private) \
2076 : V(protected) \
2077 : V(public) \
2078 : V(static) \
2079 : V(yield)
2080 :
2081 : #define FUTURE_STRICT_RESERVED_WORDS(V) \
2082 : V(let) \
2083 : FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
2084 :
2085 : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2086 : V(implements) \
2087 : V(static) \
2088 : V(yield)
2089 :
2090 : #define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
2091 : V(let) \
2092 : LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
2093 :
2094 : #define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2095 : "var " #NAME ";", \
2096 : "var foo, " #NAME ";", \
2097 : "try { } catch (" #NAME ") { }", \
2098 : "function " #NAME "() { }", \
2099 : "(function " #NAME "() { })", \
2100 : "function foo(" #NAME ") { }", \
2101 : "function foo(bar, " #NAME ") { }", \
2102 : #NAME " = 1;", \
2103 : #NAME " += 1;", \
2104 : "var foo = " #NAME " = 1;", \
2105 : "++" #NAME ";", \
2106 : #NAME " ++;",
2107 :
2108 : // clang-format off
2109 : #define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
2110 : "let " #NAME ";", \
2111 : "for (let " #NAME "; false; ) {}", \
2112 : "for (let " #NAME " in {}) {}", \
2113 : "for (let " #NAME " of []) {}", \
2114 : "const " #NAME " = null;", \
2115 : "for (const " #NAME " = null; false; ) {}", \
2116 : "for (const " #NAME " in {}) {}", \
2117 : "for (const " #NAME " of []) {}",
2118 : // clang-format on
2119 :
2120 28342 : TEST(ErrorsFutureStrictReservedWords) {
2121 : // Tests that both preparsing and parsing produce the right kind of errors for
2122 : // using future strict reserved words as identifiers. Without the strict mode,
2123 : // it's ok to use future strict reserved words as identifiers. With the strict
2124 : // mode, it isn't.
2125 : const char* strict_contexts[][2] = {
2126 : {"function test_func() {\"use strict\"; ", "}"},
2127 : {"() => { \"use strict\"; ", "}"},
2128 5 : {nullptr, nullptr}};
2129 :
2130 : // clang-format off
2131 : const char* statement_data[] {
2132 : LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
2133 : LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
2134 : nullptr
2135 5 : };
2136 : // clang-format on
2137 :
2138 5 : RunParserSyncTest(strict_contexts, statement_data, kError);
2139 :
2140 : // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
2141 : //
2142 : // > LexicalDeclaration : LetOrConst BindingList ;
2143 : // >
2144 : // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
2145 : const char* non_strict_contexts[][2] = {{"", ""},
2146 : {"function test_func() {", "}"},
2147 : {"() => {", "}"},
2148 5 : {nullptr, nullptr}};
2149 : const char* invalid_statements[] = {
2150 5 : FUTURE_STRICT_RESERVED_LEX_BINDINGS(let) nullptr};
2151 :
2152 5 : RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
2153 5 : }
2154 :
2155 : #undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2156 :
2157 :
2158 28342 : TEST(NoErrorsFutureStrictReservedWords) {
2159 : const char* context_data[][2] = {{"", ""},
2160 : {"function test_func() {", "}"},
2161 : {"() => {", "}"},
2162 5 : {nullptr, nullptr}};
2163 :
2164 : // clang-format off
2165 : const char* statement_data[] = {
2166 : FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
2167 : FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
2168 : nullptr
2169 5 : };
2170 : // clang-format on
2171 :
2172 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2173 5 : }
2174 :
2175 :
2176 28342 : TEST(ErrorsReservedWords) {
2177 : // Tests that both preparsing and parsing produce the right kind of errors for
2178 : // using future reserved words as identifiers. These tests don't depend on the
2179 : // strict mode.
2180 : const char* context_data[][2] = {
2181 : {"", ""},
2182 : {"\"use strict\";", ""},
2183 : {"var eval; function test_func() {", "}"},
2184 : {"var eval; function test_func() {\"use strict\"; ", "}"},
2185 : {"var eval; () => {", "}"},
2186 : {"var eval; () => {\"use strict\"; ", "}"},
2187 5 : {nullptr, nullptr}};
2188 :
2189 : const char* statement_data[] = {"var super;",
2190 : "var foo, super;",
2191 : "try { } catch (super) { }",
2192 : "function super() { }",
2193 : "function foo(super) { }",
2194 : "function foo(bar, super) { }",
2195 : "(super) => { }",
2196 : "(bar, super) => { }",
2197 : "super = 1;",
2198 : "var foo = super = 1;",
2199 : "++super;",
2200 : "super++;",
2201 : "function foo super",
2202 5 : nullptr};
2203 :
2204 5 : RunParserSyncTest(context_data, statement_data, kError);
2205 5 : }
2206 :
2207 :
2208 28342 : TEST(NoErrorsLetSloppyAllModes) {
2209 : // In sloppy mode, it's okay to use "let" as identifier.
2210 : const char* context_data[][2] = {{"", ""},
2211 : {"function f() {", "}"},
2212 : {"(function f() {", "})"},
2213 5 : {nullptr, nullptr}};
2214 :
2215 : const char* statement_data[] = {
2216 : "var let;",
2217 : "var foo, let;",
2218 : "try { } catch (let) { }",
2219 : "function let() { }",
2220 : "(function let() { })",
2221 : "function foo(let) { }",
2222 : "function foo(bar, let) { }",
2223 : "let = 1;",
2224 : "var foo = let = 1;",
2225 : "let * 2;",
2226 : "++let;",
2227 : "let++;",
2228 : "let: 34",
2229 : "function let(let) { let: let(let + let(0)); }",
2230 : "({ let: 1 })",
2231 : "({ get let() { 1 } })",
2232 : "let(100)",
2233 : "L: let\nx",
2234 : "L: let\n{x}",
2235 5 : nullptr};
2236 :
2237 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2238 5 : }
2239 :
2240 :
2241 28342 : TEST(NoErrorsYieldSloppyAllModes) {
2242 : // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2243 : // generator (see other test).
2244 : const char* context_data[][2] = {{"", ""},
2245 : {"function not_gen() {", "}"},
2246 : {"(function not_gen() {", "})"},
2247 5 : {nullptr, nullptr}};
2248 :
2249 : const char* statement_data[] = {
2250 : "var yield;",
2251 : "var foo, yield;",
2252 : "try { } catch (yield) { }",
2253 : "function yield() { }",
2254 : "(function yield() { })",
2255 : "function foo(yield) { }",
2256 : "function foo(bar, yield) { }",
2257 : "yield = 1;",
2258 : "var foo = yield = 1;",
2259 : "yield * 2;",
2260 : "++yield;",
2261 : "yield++;",
2262 : "yield: 34",
2263 : "function yield(yield) { yield: yield (yield + yield(0)); }",
2264 : "({ yield: 1 })",
2265 : "({ get yield() { 1 } })",
2266 : "yield(100)",
2267 : "yield[100]",
2268 5 : nullptr};
2269 :
2270 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2271 5 : }
2272 :
2273 :
2274 28342 : TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2275 : // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2276 : // generator (see next test).
2277 : const char* context_data[][2] = {
2278 : {"", ""},
2279 : {"function not_gen() {", "}"},
2280 : {"function * gen() { function not_gen() {", "} }"},
2281 : {"(function not_gen() {", "})"},
2282 : {"(function * gen() { (function not_gen() {", "}) })"},
2283 5 : {nullptr, nullptr}};
2284 :
2285 : const char* statement_data[] = {
2286 : "var yield;",
2287 : "var foo, yield;",
2288 : "try { } catch (yield) { }",
2289 : "function yield() { }",
2290 : "(function yield() { })",
2291 : "function foo(yield) { }",
2292 : "function foo(bar, yield) { }",
2293 : "function * yield() { }",
2294 : "yield = 1;",
2295 : "var foo = yield = 1;",
2296 : "yield * 2;",
2297 : "++yield;",
2298 : "yield++;",
2299 : "yield: 34",
2300 : "function yield(yield) { yield: yield (yield + yield(0)); }",
2301 : "({ yield: 1 })",
2302 : "({ get yield() { 1 } })",
2303 : "yield(100)",
2304 : "yield[100]",
2305 5 : nullptr};
2306 :
2307 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2308 5 : }
2309 :
2310 :
2311 28342 : TEST(ErrorsYieldStrict) {
2312 : const char* context_data[][2] = {
2313 : {"\"use strict\";", ""},
2314 : {"\"use strict\"; function not_gen() {", "}"},
2315 : {"function test_func() {\"use strict\"; ", "}"},
2316 : {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2317 : {"\"use strict\"; (function not_gen() {", "})"},
2318 : {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2319 : {"() => {\"use strict\"; ", "}"},
2320 5 : {nullptr, nullptr}};
2321 :
2322 : const char* statement_data[] = {"var yield;",
2323 : "var foo, yield;",
2324 : "try { } catch (yield) { }",
2325 : "function yield() { }",
2326 : "(function yield() { })",
2327 : "function foo(yield) { }",
2328 : "function foo(bar, yield) { }",
2329 : "function * yield() { }",
2330 : "(function * yield() { })",
2331 : "yield = 1;",
2332 : "var foo = yield = 1;",
2333 : "++yield;",
2334 : "yield++;",
2335 : "yield: 34;",
2336 5 : nullptr};
2337 :
2338 5 : RunParserSyncTest(context_data, statement_data, kError);
2339 5 : }
2340 :
2341 :
2342 28342 : TEST(ErrorsYieldSloppy) {
2343 : const char* context_data[][2] = {{"", ""},
2344 : {"function not_gen() {", "}"},
2345 : {"(function not_gen() {", "})"},
2346 5 : {nullptr, nullptr}};
2347 :
2348 5 : const char* statement_data[] = {"(function * yield() { })", nullptr};
2349 :
2350 5 : RunParserSyncTest(context_data, statement_data, kError);
2351 5 : }
2352 :
2353 :
2354 28342 : TEST(NoErrorsGenerator) {
2355 : // clang-format off
2356 : const char* context_data[][2] = {
2357 : { "function * gen() {", "}" },
2358 : { "(function * gen() {", "})" },
2359 : { "(function * () {", "})" },
2360 : { nullptr, nullptr }
2361 5 : };
2362 :
2363 : const char* statement_data[] = {
2364 : // A generator without a body is valid.
2365 : ""
2366 : // Valid yield expressions inside generators.
2367 : "yield 2;",
2368 : "yield * 2;",
2369 : "yield * \n 2;",
2370 : "yield yield 1;",
2371 : "yield * yield * 1;",
2372 : "yield 3 + (yield 4);",
2373 : "yield * 3 + (yield * 4);",
2374 : "(yield * 3) + (yield * 4);",
2375 : "yield 3; yield 4;",
2376 : "yield * 3; yield * 4;",
2377 : "(function (yield) { })",
2378 : "(function yield() { })",
2379 : "yield { yield: 12 }",
2380 : "yield /* comment */ { yield: 12 }",
2381 : "yield * \n { yield: 12 }",
2382 : "yield /* comment */ * \n { yield: 12 }",
2383 : // You can return in a generator.
2384 : "yield 1; return",
2385 : "yield * 1; return",
2386 : "yield 1; return 37",
2387 : "yield * 1; return 37",
2388 : "yield 1; return 37; yield 'dead';",
2389 : "yield * 1; return 37; yield * 'dead';",
2390 : // Yield is still a valid key in object literals.
2391 : "({ yield: 1 })",
2392 : "({ get yield() { } })",
2393 : // And in assignment pattern computed properties
2394 : "({ [yield]: x } = { })",
2395 : // Yield without RHS.
2396 : "yield;",
2397 : "yield",
2398 : "yield\n",
2399 : "yield /* comment */"
2400 : "yield // comment\n"
2401 : "(yield)",
2402 : "[yield]",
2403 : "{yield}",
2404 : "yield, yield",
2405 : "yield; yield",
2406 : "(yield) ? yield : yield",
2407 : "(yield) \n ? yield : yield",
2408 : // If there is a newline before the next token, we don't look for RHS.
2409 : "yield\nfor (;;) {}",
2410 : "x = class extends (yield) {}",
2411 : "x = class extends f(yield) {}",
2412 : "x = class extends (null, yield) { }",
2413 : "x = class extends (a ? null : yield) { }",
2414 : nullptr
2415 5 : };
2416 : // clang-format on
2417 :
2418 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2419 5 : }
2420 :
2421 :
2422 28342 : TEST(ErrorsYieldGenerator) {
2423 : // clang-format off
2424 : const char* context_data[][2] = {
2425 : { "function * gen() {", "}" },
2426 : { "\"use strict\"; function * gen() {", "}" },
2427 : { nullptr, nullptr }
2428 5 : };
2429 :
2430 : const char* statement_data[] = {
2431 : // Invalid yield expressions inside generators.
2432 : "var yield;",
2433 : "var foo, yield;",
2434 : "try { } catch (yield) { }",
2435 : "function yield() { }",
2436 : // The name of the NFE is bound in the generator, which does not permit
2437 : // yield to be an identifier.
2438 : "(function * yield() { })",
2439 : // Yield isn't valid as a formal parameter for generators.
2440 : "function * foo(yield) { }",
2441 : "(function * foo(yield) { })",
2442 : "yield = 1;",
2443 : "var foo = yield = 1;",
2444 : "++yield;",
2445 : "yield++;",
2446 : "yield *",
2447 : "(yield *)",
2448 : // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2449 : // is invalid.
2450 : "yield 3 + yield 4;",
2451 : "yield: 34",
2452 : "yield ? 1 : 2",
2453 : // Parses as yield (/ yield): invalid.
2454 : "yield / yield",
2455 : "+ yield",
2456 : "+ yield 3",
2457 : // Invalid (no newline allowed between yield and *).
2458 : "yield\n*3",
2459 : // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2460 : // object literal, and yield is not a valid label).
2461 : "yield\n{yield: 42}",
2462 : "yield /* comment */\n {yield: 42}",
2463 : "yield //comment\n {yield: 42}",
2464 : // Destructuring binding and assignment are both disallowed
2465 : "var [yield] = [42];",
2466 : "var {foo: yield} = {a: 42};",
2467 : "[yield] = [42];",
2468 : "({a: yield} = {a: 42});",
2469 : // Also disallow full yield expressions on LHS
2470 : "var [yield 24] = [42];",
2471 : "var {foo: yield 24} = {a: 42};",
2472 : "[yield 24] = [42];",
2473 : "({a: yield 24} = {a: 42});",
2474 : "for (yield 'x' in {});",
2475 : "for (yield 'x' of {});",
2476 : "for (yield 'x' in {} in {});",
2477 : "for (yield 'x' in {} of {});",
2478 : "class C extends yield { }",
2479 : nullptr
2480 5 : };
2481 : // clang-format on
2482 :
2483 5 : RunParserSyncTest(context_data, statement_data, kError);
2484 5 : }
2485 :
2486 :
2487 28342 : TEST(ErrorsNameOfStrictFunction) {
2488 : // Tests that illegal tokens as names of a strict function produce the correct
2489 : // errors.
2490 : const char* context_data[][2] = {{"function ", ""},
2491 : {"\"use strict\"; function", ""},
2492 : {"function * ", ""},
2493 : {"\"use strict\"; function * ", ""},
2494 5 : {nullptr, nullptr}};
2495 :
2496 : const char* statement_data[] = {
2497 : "eval() {\"use strict\";}", "arguments() {\"use strict\";}",
2498 : "interface() {\"use strict\";}", "yield() {\"use strict\";}",
2499 : // Future reserved words are always illegal
2500 5 : "super() { }", "super() {\"use strict\";}", nullptr};
2501 :
2502 5 : RunParserSyncTest(context_data, statement_data, kError);
2503 5 : }
2504 :
2505 :
2506 28342 : TEST(NoErrorsNameOfStrictFunction) {
2507 5 : const char* context_data[][2] = {{"function ", ""}, {nullptr, nullptr}};
2508 :
2509 : const char* statement_data[] = {"eval() { }", "arguments() { }",
2510 5 : "interface() { }", "yield() { }", nullptr};
2511 :
2512 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2513 5 : }
2514 :
2515 :
2516 28342 : TEST(NoErrorsNameOfStrictGenerator) {
2517 5 : const char* context_data[][2] = {{"function * ", ""}, {nullptr, nullptr}};
2518 :
2519 : const char* statement_data[] = {"eval() { }", "arguments() { }",
2520 5 : "interface() { }", "yield() { }", nullptr};
2521 :
2522 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2523 5 : }
2524 :
2525 :
2526 28342 : TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2527 : // Using future reserved words as labels is always an error.
2528 : const char* context_data[][2] = {{"", ""},
2529 : {"function test_func() {", "}"},
2530 : {"() => {", "}"},
2531 5 : {nullptr, nullptr}};
2532 :
2533 : const char* statement_data[] = {"super: while(true) { break super; }",
2534 5 : nullptr};
2535 :
2536 5 : RunParserSyncTest(context_data, statement_data, kError);
2537 5 : }
2538 :
2539 :
2540 28342 : TEST(ErrorsIllegalWordsAsLabelsStrict) {
2541 : // Tests that illegal tokens as labels produce the correct errors.
2542 : const char* context_data[][2] = {
2543 : {"\"use strict\";", ""},
2544 : {"function test_func() {\"use strict\"; ", "}"},
2545 : {"() => {\"use strict\"; ", "}"},
2546 5 : {nullptr, nullptr}};
2547 :
2548 : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2549 : const char* statement_data[] = {
2550 : "super: while(true) { break super; }",
2551 5 : FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
2552 : #undef LABELLED_WHILE
2553 :
2554 5 : RunParserSyncTest(context_data, statement_data, kError);
2555 5 : }
2556 :
2557 :
2558 28342 : TEST(NoErrorsIllegalWordsAsLabels) {
2559 : // Using eval and arguments as labels is legal even in strict mode.
2560 : const char* context_data[][2] = {
2561 : {"", ""},
2562 : {"function test_func() {", "}"},
2563 : {"() => {", "}"},
2564 : {"\"use strict\";", ""},
2565 : {"\"use strict\"; function test_func() {", "}"},
2566 : {"\"use strict\"; () => {", "}"},
2567 5 : {nullptr, nullptr}};
2568 :
2569 : const char* statement_data[] = {"mylabel: while(true) { break mylabel; }",
2570 : "eval: while(true) { break eval; }",
2571 : "arguments: while(true) { break arguments; }",
2572 5 : nullptr};
2573 :
2574 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2575 5 : }
2576 :
2577 :
2578 28342 : TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2579 : const char* context_data[][2] = {{"", ""},
2580 : {"function test_func() {", "}"},
2581 : {"() => {", "}"},
2582 5 : {nullptr, nullptr}};
2583 :
2584 : #define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2585 : const char* statement_data[]{
2586 5 : FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE) nullptr};
2587 : #undef LABELLED_WHILE
2588 :
2589 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2590 5 : }
2591 :
2592 :
2593 28342 : TEST(ErrorsParenthesizedLabels) {
2594 : // Parenthesized identifiers shouldn't be recognized as labels.
2595 : const char* context_data[][2] = {{"", ""},
2596 : {"function test_func() {", "}"},
2597 : {"() => {", "}"},
2598 5 : {nullptr, nullptr}};
2599 :
2600 : const char* statement_data[] = {"(mylabel): while(true) { break mylabel; }",
2601 5 : nullptr};
2602 :
2603 5 : RunParserSyncTest(context_data, statement_data, kError);
2604 5 : }
2605 :
2606 :
2607 28342 : TEST(NoErrorsParenthesizedDirectivePrologue) {
2608 : // Parenthesized directive prologue shouldn't be recognized.
2609 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2610 :
2611 5 : const char* statement_data[] = {"(\"use strict\"); var eval;", nullptr};
2612 :
2613 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2614 5 : }
2615 :
2616 :
2617 28342 : TEST(ErrorsNotAnIdentifierName) {
2618 : const char* context_data[][2] = {
2619 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
2620 :
2621 : const char* statement_data[] = {"var foo = {}; foo.{;",
2622 : "var foo = {}; foo.};",
2623 : "var foo = {}; foo.=;",
2624 : "var foo = {}; foo.888;",
2625 : "var foo = {}; foo.-;",
2626 : "var foo = {}; foo.--;",
2627 5 : nullptr};
2628 :
2629 5 : RunParserSyncTest(context_data, statement_data, kError);
2630 5 : }
2631 :
2632 :
2633 28342 : TEST(NoErrorsIdentifierNames) {
2634 : // Keywords etc. are valid as property names.
2635 : const char* context_data[][2] = {
2636 5 : {"", ""}, {"\"use strict\";", ""}, {nullptr, nullptr}};
2637 :
2638 : const char* statement_data[] = {"var foo = {}; foo.if;",
2639 : "var foo = {}; foo.yield;",
2640 : "var foo = {}; foo.super;",
2641 : "var foo = {}; foo.interface;",
2642 : "var foo = {}; foo.eval;",
2643 : "var foo = {}; foo.arguments;",
2644 5 : nullptr};
2645 :
2646 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2647 5 : }
2648 :
2649 28342 : TEST(FunctionDeclaresItselfStrict) {
2650 : // Tests that we produce the right kinds of errors when a function declares
2651 : // itself strict (we cannot produce there errors as soon as we see the
2652 : // offending identifiers, because we don't know at that point whether the
2653 : // function is strict or not).
2654 : const char* context_data[][2] = {{"function eval() {", "}"},
2655 : {"function arguments() {", "}"},
2656 : {"function yield() {", "}"},
2657 : {"function interface() {", "}"},
2658 : {"function foo(eval) {", "}"},
2659 : {"function foo(arguments) {", "}"},
2660 : {"function foo(yield) {", "}"},
2661 : {"function foo(interface) {", "}"},
2662 : {"function foo(bar, eval) {", "}"},
2663 : {"function foo(bar, arguments) {", "}"},
2664 : {"function foo(bar, yield) {", "}"},
2665 : {"function foo(bar, interface) {", "}"},
2666 : {"function foo(bar, bar) {", "}"},
2667 5 : {nullptr, nullptr}};
2668 :
2669 5 : const char* strict_statement_data[] = {"\"use strict\";", nullptr};
2670 :
2671 5 : const char* non_strict_statement_data[] = {";", nullptr};
2672 :
2673 5 : RunParserSyncTest(context_data, strict_statement_data, kError);
2674 5 : RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2675 5 : }
2676 :
2677 :
2678 28342 : TEST(ErrorsTryWithoutCatchOrFinally) {
2679 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2680 :
2681 : const char* statement_data[] = {"try { }", "try { } foo();",
2682 : "try { } catch (e) foo();",
2683 5 : "try { } finally foo();", nullptr};
2684 :
2685 5 : RunParserSyncTest(context_data, statement_data, kError);
2686 5 : }
2687 :
2688 :
2689 28342 : TEST(NoErrorsTryCatchFinally) {
2690 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2691 :
2692 : const char* statement_data[] = {"try { } catch (e) { }",
2693 : "try { } catch (e) { } finally { }",
2694 5 : "try { } finally { }", nullptr};
2695 :
2696 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2697 5 : }
2698 :
2699 28342 : TEST(OptionalCatchBinding) {
2700 : // clang-format off
2701 : const char* context_data[][2] = {
2702 : {"", ""},
2703 : {"'use strict';", ""},
2704 : {"try {", "} catch (e) { }"},
2705 : {"try {} catch (e) {", "}"},
2706 : {"try {", "} catch ({e}) { }"},
2707 : {"try {} catch ({e}) {", "}"},
2708 : {"function f() {", "}"},
2709 : { nullptr, nullptr }
2710 5 : };
2711 :
2712 : const char* statement_data[] = {
2713 : "try { } catch { }",
2714 : "try { } catch { } finally { }",
2715 : "try { let e; } catch { let e; }",
2716 : "try { let e; } catch { let e; } finally { let e; }",
2717 : nullptr
2718 5 : };
2719 : // clang-format on
2720 :
2721 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2722 5 : }
2723 :
2724 28342 : TEST(ErrorsRegexpLiteral) {
2725 5 : const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
2726 :
2727 5 : const char* statement_data[] = {"/unterminated", nullptr};
2728 :
2729 5 : RunParserSyncTest(context_data, statement_data, kError);
2730 5 : }
2731 :
2732 :
2733 28342 : TEST(NoErrorsRegexpLiteral) {
2734 5 : const char* context_data[][2] = {{"var r = ", ""}, {nullptr, nullptr}};
2735 :
2736 5 : const char* statement_data[] = {"/foo/", "/foo/g", nullptr};
2737 :
2738 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2739 5 : }
2740 :
2741 :
2742 28342 : TEST(NoErrorsNewExpression) {
2743 : const char* context_data[][2] = {
2744 5 : {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
2745 :
2746 : const char* statement_data[] = {
2747 : "new foo", "new foo();", "new foo(1);", "new foo(1, 2);",
2748 : // The first () will be processed as a part of the NewExpression and the
2749 : // second () will be processed as part of LeftHandSideExpression.
2750 : "new foo()();",
2751 : // The first () will be processed as a part of the inner NewExpression and
2752 : // the second () will be processed as a part of the outer NewExpression.
2753 : "new new foo()();", "new foo.bar;", "new foo.bar();", "new foo.bar.baz;",
2754 : "new foo.bar().baz;", "new foo[bar];", "new foo[bar]();",
2755 : "new foo[bar][baz];", "new foo[bar]()[baz];",
2756 : "new foo[bar].baz(baz)()[bar].baz;",
2757 : "new \"foo\"", // Runtime error
2758 : "new 1", // Runtime error
2759 : // This even runs:
2760 : "(new new Function(\"this.x = 1\")).x;",
2761 5 : "new new Test_Two(String, 2).v(0123).length;", nullptr};
2762 :
2763 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2764 5 : }
2765 :
2766 :
2767 28342 : TEST(ErrorsNewExpression) {
2768 : const char* context_data[][2] = {
2769 5 : {"", ""}, {"var f =", ""}, {nullptr, nullptr}};
2770 :
2771 : const char* statement_data[] = {"new foo bar", "new ) foo", "new ++foo",
2772 5 : "new foo ++", nullptr};
2773 :
2774 5 : RunParserSyncTest(context_data, statement_data, kError);
2775 5 : }
2776 :
2777 :
2778 28342 : TEST(StrictObjectLiteralChecking) {
2779 : const char* context_data[][2] = {{"\"use strict\"; var myobject = {", "};"},
2780 : {"\"use strict\"; var myobject = {", ",};"},
2781 : {"var myobject = {", "};"},
2782 : {"var myobject = {", ",};"},
2783 5 : {nullptr, nullptr}};
2784 :
2785 : // These are only errors in strict mode.
2786 : const char* statement_data[] = {
2787 : "foo: 1, foo: 2", "\"foo\": 1, \"foo\": 2", "foo: 1, \"foo\": 2",
2788 : "1: 1, 1: 2", "1: 1, \"1\": 2",
2789 : "get: 1, get: 2", // Not a getter for real, just a property called get.
2790 : "set: 1, set: 2", // Not a setter for real, just a property called set.
2791 5 : nullptr};
2792 :
2793 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2794 5 : }
2795 :
2796 :
2797 28342 : TEST(ErrorsObjectLiteralChecking) {
2798 : // clang-format off
2799 : const char* context_data[][2] = {
2800 : {"\"use strict\"; var myobject = {", "};"},
2801 : {"var myobject = {", "};"},
2802 : { nullptr, nullptr }
2803 5 : };
2804 :
2805 : const char* statement_data[] = {
2806 : ",",
2807 : // Wrong number of parameters
2808 : "get bar(x) {}",
2809 : "get bar(x, y) {}",
2810 : "set bar() {}",
2811 : "set bar(x, y) {}",
2812 : // Parsing FunctionLiteral for getter or setter fails
2813 : "get foo( +",
2814 : "get foo() \"error\"",
2815 : // Various forbidden forms
2816 : "static x: 0",
2817 : "static x(){}",
2818 : "static async x(){}",
2819 : "static get x(){}",
2820 : "static get x : 0",
2821 : "static x",
2822 : "static 0",
2823 : "*x: 0",
2824 : "*x",
2825 : "*get x(){}",
2826 : "*set x(y){}",
2827 : "get *x(){}",
2828 : "set *x(y){}",
2829 : "get x*(){}",
2830 : "set x*(y){}",
2831 : "x = 0",
2832 : "* *x(){}",
2833 : "x*(){}",
2834 : "static async x(){}",
2835 : "static async x : 0",
2836 : "static async get x : 0",
2837 : "async static x(){}",
2838 : "*async x(){}",
2839 : "async x*(){}",
2840 : "async x : 0",
2841 : "async 0 : 0",
2842 : "async get x(){}",
2843 : "async get *x(){}",
2844 : "async set x(y){}",
2845 : "async get : 0",
2846 : nullptr
2847 5 : };
2848 : // clang-format on
2849 :
2850 5 : RunParserSyncTest(context_data, statement_data, kError);
2851 5 : }
2852 :
2853 :
2854 28342 : TEST(NoErrorsObjectLiteralChecking) {
2855 : // clang-format off
2856 : const char* context_data[][2] = {
2857 : {"var myobject = {", "};"},
2858 : {"var myobject = {", ",};"},
2859 : {"\"use strict\"; var myobject = {", "};"},
2860 : {"\"use strict\"; var myobject = {", ",};"},
2861 : { nullptr, nullptr }
2862 5 : };
2863 :
2864 : const char* statement_data[] = {
2865 : "foo: 1, get foo() {}",
2866 : "foo: 1, set foo(v) {}",
2867 : "\"foo\": 1, get \"foo\"() {}",
2868 : "\"foo\": 1, set \"foo\"(v) {}",
2869 : "1: 1, get 1() {}",
2870 : "1: 1, set 1(v) {}",
2871 : "get foo() {}, get foo() {}",
2872 : "set foo(_) {}, set foo(v) {}",
2873 : "foo: 1, get \"foo\"() {}",
2874 : "foo: 1, set \"foo\"(v) {}",
2875 : "\"foo\": 1, get foo() {}",
2876 : "\"foo\": 1, set foo(v) {}",
2877 : "1: 1, get \"1\"() {}",
2878 : "1: 1, set \"1\"(v) {}",
2879 : "\"1\": 1, get 1() {}",
2880 : "\"1\": 1, set 1(v) {}",
2881 : "foo: 1, bar: 2",
2882 : "\"foo\": 1, \"bar\": 2",
2883 : "1: 1, 2: 2",
2884 : // Syntax: IdentifierName ':' AssignmentExpression
2885 : "foo: bar = 5 + baz",
2886 : // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2887 : "get foo() {}",
2888 : "get \"foo\"() {}",
2889 : "get 1() {}",
2890 : // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2891 : // '{' FunctionBody '}'
2892 : "set foo(v) {}",
2893 : "set \"foo\"(v) {}",
2894 : "set 1(v) {}",
2895 : // Non-colliding getters and setters -> no errors
2896 : "foo: 1, get bar() {}",
2897 : "foo: 1, set bar(v) {}",
2898 : "\"foo\": 1, get \"bar\"() {}",
2899 : "\"foo\": 1, set \"bar\"(v) {}",
2900 : "1: 1, get 2() {}",
2901 : "1: 1, set 2(v) {}",
2902 : "get: 1, get foo() {}",
2903 : "set: 1, set foo(_) {}",
2904 : // Potentially confusing cases
2905 : "get(){}",
2906 : "set(){}",
2907 : "static(){}",
2908 : "async(){}",
2909 : "*get() {}",
2910 : "*set() {}",
2911 : "*static() {}",
2912 : "*async(){}",
2913 : "get : 0",
2914 : "set : 0",
2915 : "static : 0",
2916 : "async : 0",
2917 : // Keywords, future reserved and strict future reserved are also allowed as
2918 : // property names.
2919 : "if: 4",
2920 : "interface: 5",
2921 : "super: 6",
2922 : "eval: 7",
2923 : "arguments: 8",
2924 : "async x(){}",
2925 : "async 0(){}",
2926 : "async get(){}",
2927 : "async set(){}",
2928 : "async static(){}",
2929 : "async async(){}",
2930 : "async : 0",
2931 : "async(){}",
2932 : "*async(){}",
2933 : nullptr
2934 5 : };
2935 : // clang-format on
2936 :
2937 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
2938 5 : }
2939 :
2940 :
2941 28342 : TEST(TooManyArguments) {
2942 5 : const char* context_data[][2] = {{"foo(", "0)"}, {nullptr, nullptr}};
2943 :
2944 : using v8::internal::Code;
2945 : char statement[Code::kMaxArguments * 2 + 1];
2946 327675 : for (int i = 0; i < Code::kMaxArguments; ++i) {
2947 327670 : statement[2 * i] = '0';
2948 327670 : statement[2 * i + 1] = ',';
2949 : }
2950 5 : statement[Code::kMaxArguments * 2] = 0;
2951 :
2952 5 : const char* statement_data[] = {statement, nullptr};
2953 :
2954 : // The test is quite slow, so run it with a reduced set of flags.
2955 : static const ParserFlag empty_flags[] = {kAllowLazy};
2956 5 : RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2957 5 : }
2958 :
2959 :
2960 28342 : TEST(StrictDelete) {
2961 : // "delete <Identifier>" is not allowed in strict mode.
2962 : const char* strict_context_data[][2] = {{"\"use strict\"; ", ""},
2963 5 : {nullptr, nullptr}};
2964 :
2965 5 : const char* sloppy_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
2966 :
2967 : // These are errors in the strict mode.
2968 : const char* sloppy_statement_data[] = {"delete foo;", "delete foo + 1;",
2969 : "delete (foo);", "delete eval;",
2970 5 : "delete interface;", nullptr};
2971 :
2972 : // These are always OK
2973 : const char* good_statement_data[] = {"delete this;",
2974 : "delete 1;",
2975 : "delete 1 + 2;",
2976 : "delete foo();",
2977 : "delete foo.bar;",
2978 : "delete foo[bar];",
2979 : "delete foo--;",
2980 : "delete --foo;",
2981 : "delete new foo();",
2982 : "delete new foo(bar);",
2983 5 : nullptr};
2984 :
2985 : // These are always errors
2986 5 : const char* bad_statement_data[] = {"delete if;", nullptr};
2987 :
2988 5 : RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
2989 5 : RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
2990 :
2991 5 : RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
2992 5 : RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
2993 :
2994 5 : RunParserSyncTest(strict_context_data, bad_statement_data, kError);
2995 5 : RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
2996 5 : }
2997 :
2998 :
2999 28342 : TEST(NoErrorsDeclsInCase) {
3000 : const char* context_data[][2] = {
3001 : {"'use strict'; switch(x) { case 1:", "}"},
3002 : {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3003 : {"'use strict'; switch(x) { case 1: case 2:", "}"},
3004 : {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3005 : {"'use strict'; switch(x) { default:", "}"},
3006 : {"function foo() {'use strict'; switch(x) { default:", "}}"},
3007 : {"'use strict'; switch(x) { case 1: default:", "}"},
3008 : {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3009 : { nullptr, nullptr }
3010 5 : };
3011 :
3012 : const char* statement_data[] = {
3013 : "function f() { }",
3014 : "class C { }",
3015 : "class C extends Q {}",
3016 : "function f() { } class C {}",
3017 : "function f() { }; class C {}",
3018 : "class C {}; function f() {}",
3019 : nullptr
3020 5 : };
3021 :
3022 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
3023 5 : }
3024 :
3025 :
3026 28342 : TEST(InvalidLeftHandSide) {
3027 : const char* assignment_context_data[][2] = {
3028 5 : {"", " = 1;"}, {"\"use strict\"; ", " = 1;"}, {nullptr, nullptr}};
3029 :
3030 : const char* prefix_context_data[][2] = {
3031 : {"++", ";"}, {"\"use strict\"; ++", ";"}, {nullptr, nullptr},
3032 5 : };
3033 :
3034 : const char* postfix_context_data[][2] = {
3035 5 : {"", "++;"}, {"\"use strict\"; ", "++;"}, {nullptr, nullptr}};
3036 :
3037 : // Good left hand sides for assigment or prefix / postfix operations.
3038 : const char* good_statement_data[] = {"foo",
3039 : "foo.bar",
3040 : "foo[bar]",
3041 : "foo()[bar]",
3042 : "foo().bar",
3043 : "this.foo",
3044 : "this[foo]",
3045 : "new foo()[bar]",
3046 : "new foo().bar",
3047 : "foo()",
3048 : "foo(bar)",
3049 : "foo[bar]()",
3050 : "foo.bar()",
3051 : "this()",
3052 : "this.foo()",
3053 : "this[foo].bar()",
3054 : "this.foo[foo].bar(this)(bar)[foo]()",
3055 5 : nullptr};
3056 :
3057 : // Bad left hand sides for assigment or prefix / postfix operations.
3058 : const char* bad_statement_data_common[] = {
3059 : "2",
3060 : "new foo",
3061 : "new foo()",
3062 : "null",
3063 : "if", // Unexpected token
3064 : "{x: 1}", // Unexpected token
3065 : "this",
3066 : "\"bar\"",
3067 : "(foo + bar)",
3068 : "new new foo()[bar]", // means: new (new foo()[bar])
3069 : "new new foo().bar", // means: new (new foo()[bar])
3070 5 : nullptr};
3071 :
3072 : // These are not okay for assignment, but okay for prefix / postix.
3073 : const char* bad_statement_data_for_assignment[] = {"++foo", "foo++",
3074 5 : "foo + bar", nullptr};
3075 :
3076 5 : RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3077 5 : RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3078 : RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3079 5 : kError);
3080 :
3081 5 : RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3082 5 : RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3083 :
3084 5 : RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3085 5 : RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3086 5 : }
3087 :
3088 :
3089 28342 : TEST(FuncNameInferrerBasic) {
3090 : // Tests that function names are inferred properly.
3091 5 : i::FLAG_allow_natives_syntax = true;
3092 5 : v8::Isolate* isolate = CcTest::isolate();
3093 5 : v8::HandleScope scope(isolate);
3094 10 : LocalContext env;
3095 : CompileRun("var foo1 = function() {}; "
3096 : "var foo2 = function foo3() {}; "
3097 : "function not_ctor() { "
3098 : " var foo4 = function() {}; "
3099 : " return %FunctionGetInferredName(foo4); "
3100 : "} "
3101 : "function Ctor() { "
3102 : " var foo5 = function() {}; "
3103 : " return %FunctionGetInferredName(foo5); "
3104 : "} "
3105 : "var obj1 = { foo6: function() {} }; "
3106 : "var obj2 = { 'foo7': function() {} }; "
3107 : "var obj3 = {}; "
3108 : "obj3[1] = function() {}; "
3109 : "var obj4 = {}; "
3110 : "obj4[1] = function foo8() {}; "
3111 : "var obj5 = {}; "
3112 : "obj5['foo9'] = function() {}; "
3113 : "var obj6 = { obj7 : { foo10: function() {} } };");
3114 5 : ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3115 : // foo2 is not unnamed -> its name is not inferred.
3116 5 : ExpectString("%FunctionGetInferredName(foo2)", "");
3117 5 : ExpectString("not_ctor()", "foo4");
3118 5 : ExpectString("Ctor()", "Ctor.foo5");
3119 5 : ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3120 5 : ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3121 : ExpectString("%FunctionGetInferredName(obj3[1])",
3122 5 : "obj3.(anonymous function)");
3123 5 : ExpectString("%FunctionGetInferredName(obj4[1])", "");
3124 5 : ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3125 10 : ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3126 5 : }
3127 :
3128 :
3129 28342 : TEST(FuncNameInferrerTwoByte) {
3130 : // Tests function name inferring in cases where some parts of the inferred
3131 : // function name are two-byte strings.
3132 5 : i::FLAG_allow_natives_syntax = true;
3133 5 : v8::Isolate* isolate = CcTest::isolate();
3134 5 : v8::HandleScope scope(isolate);
3135 10 : LocalContext env;
3136 : uint16_t* two_byte_source = AsciiToTwoByteString(
3137 : "var obj1 = { oXj2 : { foo1: function() {} } }; "
3138 5 : "%FunctionGetInferredName(obj1.oXj2.foo1)");
3139 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3140 : // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3141 5 : two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010D;
3142 : v8::Local<v8::String> source =
3143 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3144 : v8::NewStringType::kNormal)
3145 10 : .ToLocalChecked();
3146 5 : v8::Local<v8::Value> result = CompileRun(source);
3147 5 : CHECK(result->IsString());
3148 : v8::Local<v8::String> expected_name =
3149 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3150 : v8::NewStringType::kNormal)
3151 5 : .ToLocalChecked();
3152 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3153 : i::DeleteArray(two_byte_source);
3154 5 : i::DeleteArray(two_byte_name);
3155 5 : }
3156 :
3157 :
3158 28342 : TEST(FuncNameInferrerEscaped) {
3159 : // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3160 : // character as a Unicode escape.
3161 5 : i::FLAG_allow_natives_syntax = true;
3162 5 : v8::Isolate* isolate = CcTest::isolate();
3163 5 : v8::HandleScope scope(isolate);
3164 10 : LocalContext env;
3165 : uint16_t* two_byte_source = AsciiToTwoByteString(
3166 : "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3167 5 : "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3168 5 : uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3169 : // Fix to correspond to the non-ASCII name in two_byte_source.
3170 5 : two_byte_name[6] = 0x010D;
3171 : v8::Local<v8::String> source =
3172 : v8::String::NewFromTwoByte(isolate, two_byte_source,
3173 : v8::NewStringType::kNormal)
3174 10 : .ToLocalChecked();
3175 5 : v8::Local<v8::Value> result = CompileRun(source);
3176 5 : CHECK(result->IsString());
3177 : v8::Local<v8::String> expected_name =
3178 : v8::String::NewFromTwoByte(isolate, two_byte_name,
3179 : v8::NewStringType::kNormal)
3180 5 : .ToLocalChecked();
3181 10 : CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
3182 : i::DeleteArray(two_byte_source);
3183 5 : i::DeleteArray(two_byte_name);
3184 5 : }
3185 :
3186 :
3187 28342 : TEST(RegressionLazyFunctionWithErrorWithArg) {
3188 : // Test only applies when lazy parsing.
3189 5 : if (!i::FLAG_lazy) return;
3190 :
3191 : // The bug occurred when a lazy function had an error which requires a
3192 : // parameter (such as "unknown label" here). The error message was processed
3193 : // before the AstValueFactory containing the error message string was
3194 : // internalized.
3195 5 : v8::Isolate* isolate = CcTest::isolate();
3196 5 : v8::HandleScope scope(isolate);
3197 10 : LocalContext env;
3198 5 : i::FLAG_lazy = true;
3199 : CompileRun("function this_is_lazy() {\n"
3200 : " break p;\n"
3201 : "}\n"
3202 5 : "this_is_lazy();\n");
3203 : }
3204 :
3205 :
3206 28342 : TEST(SerializationOfMaybeAssignmentFlag) {
3207 5 : i::Isolate* isolate = CcTest::i_isolate();
3208 : i::Factory* factory = isolate->factory();
3209 : i::HandleScope scope(isolate);
3210 10 : LocalContext env;
3211 :
3212 : const char* src =
3213 : "function h() {"
3214 : " var result = [];"
3215 : " function f() {"
3216 : " result.push(2);"
3217 : " }"
3218 : " function assertResult(r) {"
3219 : " f();"
3220 : " result = [];"
3221 : " }"
3222 : " assertResult([2]);"
3223 : " assertResult([2]);"
3224 : " return f;"
3225 : "};"
3226 : "h();";
3227 :
3228 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3229 5 : i::SNPrintF(program, "%s", src);
3230 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3231 10 : source->PrintOn(stdout);
3232 : printf("\n");
3233 10 : i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
3234 : v8::Local<v8::Value> v = CompileRun(src);
3235 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3236 5 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3237 5 : i::Context context = f->context();
3238 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3239 10 : isolate->heap()->HashSeed());
3240 10 : const i::AstRawString* name = avf.GetOneByteString("result");
3241 5 : avf.Internalize(isolate);
3242 : i::Handle<i::String> str = name->string();
3243 10 : CHECK(str->IsInternalizedString());
3244 : i::DeclarationScope* script_scope =
3245 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3246 : i::Scope* s = i::Scope::DeserializeScopeChain(
3247 : isolate, &zone, context->scope_info(), script_scope, &avf,
3248 5 : i::Scope::DeserializationMode::kIncludingVariables);
3249 5 : CHECK(s != script_scope);
3250 5 : CHECK_NOT_NULL(name);
3251 :
3252 : // Get result from h's function context (that is f's context)
3253 5 : i::Variable* var = s->LookupForTesting(name);
3254 :
3255 5 : CHECK_NOT_NULL(var);
3256 : // Maybe assigned should survive deserialization
3257 5 : CHECK_EQ(var->maybe_assigned(), i::kMaybeAssigned);
3258 : // TODO(sigurds) Figure out if is_used should survive context serialization.
3259 5 : }
3260 :
3261 :
3262 28342 : TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3263 10 : i::Isolate* isolate = CcTest::i_isolate();
3264 : i::Factory* factory = isolate->factory();
3265 : i::HandleScope scope(isolate);
3266 10 : LocalContext env;
3267 :
3268 : const char* src =
3269 : "function f(x) {"
3270 : " var a = arguments;"
3271 : " function g(i) {"
3272 : " ++a[0];"
3273 : " };"
3274 : " return g;"
3275 : " }"
3276 : "f(0);";
3277 :
3278 5 : i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3279 5 : i::SNPrintF(program, "%s", src);
3280 5 : i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3281 10 : source->PrintOn(stdout);
3282 : printf("\n");
3283 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
3284 : v8::Local<v8::Value> v = CompileRun(src);
3285 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3286 5 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3287 5 : i::Context context = f->context();
3288 : i::AstValueFactory avf(&zone, isolate->ast_string_constants(),
3289 10 : isolate->heap()->HashSeed());
3290 5 : const i::AstRawString* name_x = avf.GetOneByteString("x");
3291 5 : avf.Internalize(isolate);
3292 :
3293 : i::DeclarationScope* script_scope =
3294 5 : new (&zone) i::DeclarationScope(&zone, &avf);
3295 : i::Scope* s = i::Scope::DeserializeScopeChain(
3296 : isolate, &zone, context->scope_info(), script_scope, &avf,
3297 5 : i::Scope::DeserializationMode::kIncludingVariables);
3298 5 : CHECK(s != script_scope);
3299 :
3300 : // Get result from f's function context (that is g's outer context)
3301 5 : i::Variable* var_x = s->LookupForTesting(name_x);
3302 5 : CHECK_NOT_NULL(var_x);
3303 5 : CHECK_EQ(var_x->maybe_assigned(), i::kMaybeAssigned);
3304 5 : }
3305 :
3306 :
3307 28342 : TEST(InnerAssignment) {
3308 : i::Isolate* isolate = CcTest::i_isolate();
3309 : i::Factory* factory = isolate->factory();
3310 : i::HandleScope scope(isolate);
3311 10 : LocalContext env;
3312 :
3313 : const char* prefix = "function f() {";
3314 : const char* midfix = " function g() {";
3315 : const char* suffix = "}}; f";
3316 : struct {
3317 : const char* source;
3318 : bool assigned;
3319 : bool strict;
3320 : } outers[] = {
3321 : // Actual assignments.
3322 : {"var x; var x = 5;", true, false},
3323 : {"var x; { var x = 5; }", true, false},
3324 : {"'use strict'; let x; x = 6;", true, true},
3325 : {"var x = 5; function x() {}", true, false},
3326 : {"var x = 4; var x = 5;", true, false},
3327 : {"var [x, x] = [4, 5];", true, false},
3328 : {"var x; [x, x] = [4, 5];", true, false},
3329 : {"var {a: x, b: x} = {a: 4, b: 5};", true, false},
3330 : {"var x = {a: 4, b: (x = 5)};", true, false},
3331 : {"var {x=1} = {a: 4, b: (x = 5)};", true, false},
3332 : {"var {x} = {x: 4, b: (x = 5)};", true, false},
3333 : // Actual non-assignments.
3334 : {"var x;", false, false},
3335 : {"var x = 5;", false, false},
3336 : {"'use strict'; let x;", false, true},
3337 : {"'use strict'; let x = 6;", false, true},
3338 : {"'use strict'; var x = 0; { let x = 6; }", false, true},
3339 : {"'use strict'; var x = 0; { let x; x = 6; }", false, true},
3340 : {"'use strict'; let x = 0; { let x = 6; }", false, true},
3341 : {"'use strict'; let x = 0; { let x; x = 6; }", false, true},
3342 : {"var x; try {} catch (x) { x = 5; }", false, false},
3343 : {"function x() {}", false, false},
3344 : // Eval approximation.
3345 : {"var x; eval('');", true, false},
3346 : {"eval(''); var x;", true, false},
3347 : {"'use strict'; let x; eval('');", true, true},
3348 : {"'use strict'; eval(''); let x;", true, true},
3349 : // Non-assignments not recognized, because the analysis is approximative.
3350 : {"var x; var x;", true, false},
3351 : {"var x = 5; var x;", true, false},
3352 : {"var x; { var x; }", true, false},
3353 : {"var x; function x() {}", true, false},
3354 : {"function x() {}; var x;", true, false},
3355 : {"var x; try {} catch (x) { var x = 5; }", true, false},
3356 5 : };
3357 :
3358 : // We set allow_error_in_inner_function to true in cases where our handling of
3359 : // assigned variables in lazy inner functions is currently overly pessimistic.
3360 : // FIXME(marja): remove it when no longer needed.
3361 : struct {
3362 : const char* source;
3363 : bool assigned;
3364 : bool with;
3365 : bool allow_error_in_inner_function;
3366 : } inners[] = {
3367 : // Actual assignments.
3368 : {"x = 1;", true, false, false},
3369 : {"x++;", true, false, false},
3370 : {"++x;", true, false, false},
3371 : {"x--;", true, false, false},
3372 : {"--x;", true, false, false},
3373 : {"{ x = 1; }", true, false, false},
3374 : {"'use strict'; { let x; }; x = 0;", true, false, false},
3375 : {"'use strict'; { const x = 1; }; x = 0;", true, false, false},
3376 : {"'use strict'; { function x() {} }; x = 0;", true, false, false},
3377 : {"with ({}) { x = 1; }", true, true, false},
3378 : {"eval('');", true, false, false},
3379 : {"'use strict'; { let y; eval('') }", true, false, false},
3380 : {"function h() { x = 0; }", true, false, false},
3381 : {"(function() { x = 0; })", true, false, false},
3382 : {"(function() { x = 0; })", true, false, false},
3383 : {"with ({}) (function() { x = 0; })", true, true, false},
3384 : {"for (x of [1,2,3]) {}", true, false, false},
3385 : {"for (x in {a: 1}) {}", true, false, false},
3386 : {"for ([x] of [[1],[2],[3]]) {}", true, false, false},
3387 : {"for ([x] in {ab: 1}) {}", true, false, false},
3388 : {"for ([...x] in {ab: 1}) {}", true, false, false},
3389 : {"[x] = [1]", true, false, false},
3390 : // Actual non-assignments.
3391 : {"", false, false, false},
3392 : {"x;", false, false, false},
3393 : {"var x;", false, false, false},
3394 : {"var x = 8;", false, false, false},
3395 : {"var x; x = 8;", false, false, false},
3396 : {"'use strict'; let x;", false, false, false},
3397 : {"'use strict'; let x = 8;", false, false, false},
3398 : {"'use strict'; let x; x = 8;", false, false, false},
3399 : {"'use strict'; const x = 8;", false, false, false},
3400 : {"function x() {}", false, false, false},
3401 : {"function x() { x = 0; }", false, false, true},
3402 : {"function h(x) { x = 0; }", false, false, false},
3403 : {"'use strict'; { let x; x = 0; }", false, false, false},
3404 : {"{ var x; }; x = 0;", false, false, false},
3405 : {"with ({}) {}", false, true, false},
3406 : {"var x; { with ({}) { x = 1; } }", false, true, false},
3407 : {"try {} catch(x) { x = 0; }", false, false, true},
3408 : {"try {} catch(x) { with ({}) { x = 1; } }", false, true, true},
3409 : // Eval approximation.
3410 : {"eval('');", true, false, false},
3411 : {"function h() { eval(''); }", true, false, false},
3412 : {"(function() { eval(''); })", true, false, false},
3413 : // Shadowing not recognized because of eval approximation.
3414 : {"var x; eval('');", true, false, false},
3415 : {"'use strict'; let x; eval('');", true, false, false},
3416 : {"try {} catch(x) { eval(''); }", true, false, false},
3417 : {"function x() { eval(''); }", true, false, false},
3418 : {"(function(x) { eval(''); })", true, false, false},
3419 5 : };
3420 :
3421 5 : int prefix_len = Utf8LengthHelper(prefix);
3422 5 : int midfix_len = Utf8LengthHelper(midfix);
3423 5 : int suffix_len = Utf8LengthHelper(suffix);
3424 160 : for (unsigned i = 0; i < arraysize(outers); ++i) {
3425 155 : const char* outer = outers[i].source;
3426 155 : int outer_len = Utf8LengthHelper(outer);
3427 7595 : for (unsigned j = 0; j < arraysize(inners); ++j) {
3428 14880 : for (unsigned lazy = 0; lazy < 2; ++lazy) {
3429 15330 : if (outers[i].strict && inners[j].with) continue;
3430 14430 : const char* inner = inners[j].source;
3431 14430 : int inner_len = Utf8LengthHelper(inner);
3432 :
3433 14430 : int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len;
3434 14430 : i::ScopedVector<char> program(len + 1);
3435 :
3436 : i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner,
3437 14430 : suffix);
3438 :
3439 : std::unique_ptr<i::ParseInfo> info;
3440 14430 : if (lazy) {
3441 : printf("%s\n", program.start());
3442 : v8::Local<v8::Value> v = CompileRun(program.start());
3443 7215 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3444 7215 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3445 : i::Handle<i::SharedFunctionInfo> shared =
3446 14430 : i::handle(f->shared(), isolate);
3447 14430 : info =
3448 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3449 7215 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3450 : } else {
3451 : i::Handle<i::String> source =
3452 7215 : factory->InternalizeUtf8String(program.start());
3453 14430 : source->PrintOn(stdout);
3454 : printf("\n");
3455 7215 : i::Handle<i::Script> script = factory->NewScript(source);
3456 14430 : info =
3457 7215 : std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3458 : info->set_allow_lazy_parsing(false);
3459 7215 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3460 : }
3461 14430 : CHECK(i::Compiler::Analyze(info.get()));
3462 14430 : CHECK_NOT_NULL(info->literal());
3463 :
3464 21645 : i::Scope* scope = info->literal()->scope();
3465 14430 : if (!lazy) {
3466 : scope = scope->inner_scope();
3467 : }
3468 : DCHECK_NOT_NULL(scope);
3469 : DCHECK_NULL(scope->sibling());
3470 : DCHECK(scope->is_function_scope());
3471 : const i::AstRawString* var_name =
3472 14430 : info->ast_value_factory()->GetOneByteString("x");
3473 14430 : i::Variable* var = scope->LookupForTesting(var_name);
3474 14430 : bool expected = outers[i].assigned || inners[j].assigned;
3475 14430 : CHECK_NOT_NULL(var);
3476 14430 : CHECK(var->is_used() || !expected);
3477 14430 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3478 14430 : CHECK(is_maybe_assigned == expected ||
3479 : (is_maybe_assigned && inners[j].allow_error_in_inner_function));
3480 : }
3481 : }
3482 : }
3483 5 : }
3484 :
3485 28342 : TEST(MaybeAssignedParameters) {
3486 : i::Isolate* isolate = CcTest::i_isolate();
3487 : i::HandleScope scope(isolate);
3488 10 : LocalContext env;
3489 :
3490 : struct {
3491 : bool arg_assigned;
3492 : const char* source;
3493 : } tests[] = {
3494 : {false, "function f(arg) {}"},
3495 : {false, "function f(arg) {g(arg)}"},
3496 : {false, "function f(arg) {function h() { g(arg) }; h()}"},
3497 : {false, "function f(arg) {function h() { g(arg) }; return h}"},
3498 : {false, "function f(arg=1) {}"},
3499 : {false, "function f(arg=1) {g(arg)}"},
3500 : {false, "function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3501 : {false,
3502 : "function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)}"},
3503 : {false,
3504 : "function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)}"},
3505 : {false, "function f(...arg) {g(arg); arguments[0] = 42; g(arg)}"},
3506 : {false,
3507 : "function f(arg) {g(arg); g(function() {arguments[0] = 42}); g(arg)}"},
3508 :
3509 : // strict arguments object
3510 : {false, "function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)}"},
3511 : {false, "function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)}"},
3512 : {false, "function f(arg=1) {g(arg); arguments[0] = 42; g(arg)}"},
3513 : {false,
3514 : "function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)}"},
3515 : {false, "function f(arg) {g(arg); f.arguments[0] = 42; g(arg)}"},
3516 : {false, "function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)}"},
3517 :
3518 : {true, "function f(arg) {g(arg); arg = 42; g(arg)}"},
3519 : {true, "function f(arg) {g(arg); eval('arg = 42'); g(arg)}"},
3520 : {true, "function f(arg) {g(arg); var arg = 42; g(arg)}"},
3521 : {true, "function f(arg, x=1) {g(arg); arg = 42; g(arg)}"},
3522 : {true, "function f(arg, ...x) {g(arg); arg = 42; g(arg)}"},
3523 : {true, "function f(arg=1) {g(arg); arg = 42; g(arg)}"},
3524 : {true, "function f(arg) {'use strict'; g(arg); arg = 42; g(arg)}"},
3525 : {true, "function f(arg, {a=(g(arg), arg=42)}) {g(arg)}"},
3526 : {true, "function f(arg) {g(arg); g(function() {arg = 42}); g(arg)}"},
3527 : {true,
3528 : "function f(arg) {g(arg); g(function() {eval('arg = 42')}); g(arg)}"},
3529 : {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"},
3530 : {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"},
3531 : {true, "function f(...arg) {g(arg); eval('arg = 42'); g(arg)}"},
3532 :
3533 : // sloppy arguments object
3534 : {true, "function f(arg) {g(arg); arguments[0] = 42; g(arg)}"},
3535 : {true, "function f(arg) {g(arg); h(arguments); g(arg)}"},
3536 : {true,
3537 : "function f(arg) {((args) => {arguments[0] = 42})(arguments); "
3538 : "g(arg)}"},
3539 : {true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"},
3540 : {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
3541 5 : };
3542 :
3543 : const char* suffix = "; f";
3544 :
3545 180 : for (unsigned i = 0; i < arraysize(tests); ++i) {
3546 175 : bool assigned = tests[i].arg_assigned;
3547 175 : const char* source = tests[i].source;
3548 525 : for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) {
3549 700 : i::ScopedVector<char> program(Utf8LengthHelper(source) +
3550 700 : Utf8LengthHelper(suffix) + 1);
3551 350 : i::SNPrintF(program, "%s%s", source, suffix);
3552 : std::unique_ptr<i::ParseInfo> info;
3553 : printf("%s\n", program.start());
3554 : v8::Local<v8::Value> v = CompileRun(program.start());
3555 350 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3556 350 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3557 700 : i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared(), isolate);
3558 350 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, shared));
3559 : info->set_allow_lazy_parsing(allow_lazy);
3560 350 : CHECK(i::parsing::ParseFunction(info.get(), shared, isolate));
3561 350 : CHECK(i::Compiler::Analyze(info.get()));
3562 350 : CHECK_NOT_NULL(info->literal());
3563 :
3564 1050 : i::Scope* scope = info->literal()->scope();
3565 700 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3566 350 : CHECK_NULL(scope->sibling());
3567 350 : CHECK(scope->is_function_scope());
3568 : const i::AstRawString* var_name =
3569 350 : info->ast_value_factory()->GetOneByteString("arg");
3570 350 : i::Variable* var = scope->LookupForTesting(var_name);
3571 350 : CHECK(var->is_used() || !assigned);
3572 350 : bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned;
3573 350 : CHECK_EQ(is_maybe_assigned, assigned);
3574 : }
3575 : }
3576 5 : }
3577 :
3578 65800 : struct Input {
3579 : bool assigned;
3580 : std::string source;
3581 : std::vector<unsigned> location; // "Directions" to the relevant scope.
3582 : };
3583 :
3584 15000 : static void TestMaybeAssigned(Input input, const char* variable, bool module,
3585 : bool allow_lazy_parsing) {
3586 : i::Isolate* isolate = CcTest::i_isolate();
3587 : i::Factory* factory = isolate->factory();
3588 : i::Handle<i::String> string =
3589 15000 : factory->InternalizeUtf8String(input.source.c_str());
3590 30000 : string->PrintOn(stdout);
3591 : printf("\n");
3592 15000 : i::Handle<i::Script> script = factory->NewScript(string);
3593 :
3594 : std::unique_ptr<i::ParseInfo> info;
3595 15000 : info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(isolate, script));
3596 : info->set_module(module);
3597 : info->set_allow_lazy_parsing(allow_lazy_parsing);
3598 :
3599 15000 : CHECK(i::parsing::ParseProgram(info.get(), isolate));
3600 15000 : CHECK(i::Compiler::Analyze(info.get()));
3601 :
3602 15000 : CHECK_NOT_NULL(info->literal());
3603 45000 : i::Scope* scope = info->literal()->scope();
3604 30000 : CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
3605 15000 : CHECK_NULL(scope->sibling());
3606 30000 : CHECK(module ? scope->is_module_scope() : scope->is_script_scope());
3607 :
3608 15000 : i::Variable* var;
3609 : {
3610 : // Find the variable.
3611 15000 : scope = i::ScopeTestHelper::FindScope(scope, input.location);
3612 : const i::AstRawString* var_name =
3613 15000 : info->ast_value_factory()->GetOneByteString(variable);
3614 : var = scope->LookupForTesting(var_name);
3615 : }
3616 :
3617 15000 : CHECK_NOT_NULL(var);
3618 15000 : CHECK(var->is_used());
3619 : STATIC_ASSERT(true == i::kMaybeAssigned);
3620 15000 : CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
3621 15000 : }
3622 :
3623 4200 : static Input wrap(Input input) {
3624 : Input result;
3625 4200 : result.assigned = input.assigned;
3626 16800 : result.source = "function WRAPPED() { " + input.source + " }";
3627 8400 : result.location.push_back(0);
3628 11780 : for (auto n : input.location) {
3629 3380 : result.location.push_back(n);
3630 : }
3631 4200 : return result;
3632 : }
3633 :
3634 28342 : TEST(MaybeAssignedInsideLoop) {
3635 : i::Isolate* isolate = CcTest::i_isolate();
3636 : i::HandleScope scope(isolate);
3637 10 : LocalContext env;
3638 :
3639 : std::vector<unsigned> top; // Can't use {} in initializers below.
3640 :
3641 : Input module_and_script_tests[] = {
3642 : {true, "for (j=x; j<10; ++j) { foo = j }", top},
3643 : {true, "for (j=x; j<10; ++j) { [foo] = [j] }", top},
3644 : {true, "for (j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3645 : {true, "for (j=x; j<10; ++j) { var foo = j }", top},
3646 : {true, "for (j=x; j<10; ++j) { var [foo] = [j] }", top},
3647 : {true, "for (j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3648 : {true, "for (j=x; j<10; ++j) { var foo; foo = j }", top},
3649 : {true, "for (j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3650 : {true, "for (j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3651 : {true, "for (j=x; j<10; ++j) { let foo; foo = j }", {0}},
3652 : {true, "for (j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3653 : {true, "for (j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3654 : {false, "for (j=x; j<10; ++j) { let foo = j }", {0}},
3655 : {false, "for (j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3656 : {false, "for (j=x; j<10; ++j) { const foo = j }", {0}},
3657 : {false, "for (j=x; j<10; ++j) { const [foo] = [j] }", {0}},
3658 : {false, "for (j=x; j<10; ++j) { function foo() {return j} }", {0}},
3659 :
3660 : {true, "for ({j}=x; j<10; ++j) { foo = j }", top},
3661 : {true, "for ({j}=x; j<10; ++j) { [foo] = [j] }", top},
3662 : {true, "for ({j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3663 : {true, "for ({j}=x; j<10; ++j) { var foo = j }", top},
3664 : {true, "for ({j}=x; j<10; ++j) { var [foo] = [j] }", top},
3665 : {true, "for ({j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3666 : {true, "for ({j}=x; j<10; ++j) { var foo; foo = j }", top},
3667 : {true, "for ({j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3668 : {true, "for ({j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3669 : {true, "for ({j}=x; j<10; ++j) { let foo; foo = j }", {0}},
3670 : {true, "for ({j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3671 : {true, "for ({j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3672 : {false, "for ({j}=x; j<10; ++j) { let foo = j }", {0}},
3673 : {false, "for ({j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3674 : {false, "for ({j}=x; j<10; ++j) { const foo = j }", {0}},
3675 : {false, "for ({j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
3676 : {false, "for ({j}=x; j<10; ++j) { function foo() {return j} }", {0}},
3677 :
3678 : {true, "for (var j=x; j<10; ++j) { foo = j }", top},
3679 : {true, "for (var j=x; j<10; ++j) { [foo] = [j] }", top},
3680 : {true, "for (var j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3681 : {true, "for (var j=x; j<10; ++j) { var foo = j }", top},
3682 : {true, "for (var j=x; j<10; ++j) { var [foo] = [j] }", top},
3683 : {true, "for (var j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3684 : {true, "for (var j=x; j<10; ++j) { var foo; foo = j }", top},
3685 : {true, "for (var j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3686 : {true, "for (var j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3687 : {true, "for (var j=x; j<10; ++j) { let foo; foo = j }", {0}},
3688 : {true, "for (var j=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3689 : {true, "for (var j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3690 : {false, "for (var j=x; j<10; ++j) { let foo = j }", {0}},
3691 : {false, "for (var j=x; j<10; ++j) { let [foo] = [j] }", {0}},
3692 : {false, "for (var j=x; j<10; ++j) { const foo = j }", {0}},
3693 : {false, "for (var j=x; j<10; ++j) { const [foo] = [j] }", {0}},
3694 : {false, "for (var j=x; j<10; ++j) { function foo() {return j} }", {0}},
3695 :
3696 : {true, "for (var {j}=x; j<10; ++j) { foo = j }", top},
3697 : {true, "for (var {j}=x; j<10; ++j) { [foo] = [j] }", top},
3698 : {true, "for (var {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3699 : {true, "for (var {j}=x; j<10; ++j) { var foo = j }", top},
3700 : {true, "for (var {j}=x; j<10; ++j) { var [foo] = [j] }", top},
3701 : {true, "for (var {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3702 : {true, "for (var {j}=x; j<10; ++j) { var foo; foo = j }", top},
3703 : {true, "for (var {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3704 : {true, "for (var {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3705 : {true, "for (var {j}=x; j<10; ++j) { let foo; foo = j }", {0}},
3706 : {true, "for (var {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0}},
3707 : {true, "for (var {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0}},
3708 : {false, "for (var {j}=x; j<10; ++j) { let foo = j }", {0}},
3709 : {false, "for (var {j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
3710 : {false, "for (var {j}=x; j<10; ++j) { const foo = j }", {0}},
3711 : {false, "for (var {j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
3712 : {false, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", {0}},
3713 :
3714 : {true, "for (let j=x; j<10; ++j) { foo = j }", top},
3715 : {true, "for (let j=x; j<10; ++j) { [foo] = [j] }", top},
3716 : {true, "for (let j=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3717 : {true, "for (let j=x; j<10; ++j) { var foo = j }", top},
3718 : {true, "for (let j=x; j<10; ++j) { var [foo] = [j] }", top},
3719 : {true, "for (let j=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3720 : {true, "for (let j=x; j<10; ++j) { var foo; foo = j }", top},
3721 : {true, "for (let j=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3722 : {true, "for (let j=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3723 : {true, "for (let j=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
3724 : {true, "for (let j=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
3725 : {true, "for (let j=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }", {0, 0}},
3726 : {false, "for (let j=x; j<10; ++j) { let foo = j }", {0, 0}},
3727 : {false, "for (let j=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
3728 : {false, "for (let j=x; j<10; ++j) { const foo = j }", {0, 0}},
3729 : {false, "for (let j=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3730 : {false,
3731 : "for (let j=x; j<10; ++j) { function foo() {return j} }",
3732 : {0, 0, 0}},
3733 :
3734 : {true, "for (let {j}=x; j<10; ++j) { foo = j }", top},
3735 : {true, "for (let {j}=x; j<10; ++j) { [foo] = [j] }", top},
3736 : {true, "for (let {j}=x; j<10; ++j) { [[foo]=[42]] = [] }", top},
3737 : {true, "for (let {j}=x; j<10; ++j) { var foo = j }", top},
3738 : {true, "for (let {j}=x; j<10; ++j) { var [foo] = [j] }", top},
3739 : {true, "for (let {j}=x; j<10; ++j) { var [[foo]=[42]] = [] }", top},
3740 : {true, "for (let {j}=x; j<10; ++j) { var foo; foo = j }", top},
3741 : {true, "for (let {j}=x; j<10; ++j) { var foo; [foo] = [j] }", top},
3742 : {true, "for (let {j}=x; j<10; ++j) { var foo; [[foo]=[42]] = [] }", top},
3743 : {true, "for (let {j}=x; j<10; ++j) { let foo; foo = j }", {0, 0}},
3744 : {true, "for (let {j}=x; j<10; ++j) { let foo; [foo] = [j] }", {0, 0}},
3745 : {true,
3746 : "for (let {j}=x; j<10; ++j) { let foo; [[foo]=[42]] = [] }",
3747 : {0, 0}},
3748 : {false, "for (let {j}=x; j<10; ++j) { let foo = j }", {0, 0}},
3749 : {false, "for (let {j}=x; j<10; ++j) { let [foo] = [j] }", {0, 0}},
3750 : {false, "for (let {j}=x; j<10; ++j) { const foo = j }", {0, 0}},
3751 : {false, "for (let {j}=x; j<10; ++j) { const [foo] = [j] }", {0, 0}},
3752 : {false,
3753 : "for (let {j}=x; j<10; ++j) { function foo(){return j} }",
3754 : {0, 0, 0}},
3755 :
3756 : {true, "for (j of x) { foo = j }", top},
3757 : {true, "for (j of x) { [foo] = [j] }", top},
3758 : {true, "for (j of x) { [[foo]=[42]] = [] }", top},
3759 : {true, "for (j of x) { var foo = j }", top},
3760 : {true, "for (j of x) { var [foo] = [j] }", top},
3761 : {true, "for (j of x) { var [[foo]=[42]] = [] }", top},
3762 : {true, "for (j of x) { var foo; foo = j }", top},
3763 : {true, "for (j of x) { var foo; [foo] = [j] }", top},
3764 : {true, "for (j of x) { var foo; [[foo]=[42]] = [] }", top},
3765 : {true, "for (j of x) { let foo; foo = j }", {0}},
3766 : {true, "for (j of x) { let foo; [foo] = [j] }", {0}},
3767 : {true, "for (j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3768 : {false, "for (j of x) { let foo = j }", {0}},
3769 : {false, "for (j of x) { let [foo] = [j] }", {0}},
3770 : {false, "for (j of x) { const foo = j }", {0}},
3771 : {false, "for (j of x) { const [foo] = [j] }", {0}},
3772 : {false, "for (j of x) { function foo() {return j} }", {0}},
3773 :
3774 : {true, "for ({j} of x) { foo = j }", top},
3775 : {true, "for ({j} of x) { [foo] = [j] }", top},
3776 : {true, "for ({j} of x) { [[foo]=[42]] = [] }", top},
3777 : {true, "for ({j} of x) { var foo = j }", top},
3778 : {true, "for ({j} of x) { var [foo] = [j] }", top},
3779 : {true, "for ({j} of x) { var [[foo]=[42]] = [] }", top},
3780 : {true, "for ({j} of x) { var foo; foo = j }", top},
3781 : {true, "for ({j} of x) { var foo; [foo] = [j] }", top},
3782 : {true, "for ({j} of x) { var foo; [[foo]=[42]] = [] }", top},
3783 : {true, "for ({j} of x) { let foo; foo = j }", {0}},
3784 : {true, "for ({j} of x) { let foo; [foo] = [j] }", {0}},
3785 : {true, "for ({j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3786 : {false, "for ({j} of x) { let foo = j }", {0}},
3787 : {false, "for ({j} of x) { let [foo] = [j] }", {0}},
3788 : {false, "for ({j} of x) { const foo = j }", {0}},
3789 : {false, "for ({j} of x) { const [foo] = [j] }", {0}},
3790 : {false, "for ({j} of x) { function foo() {return j} }", {0}},
3791 :
3792 : {true, "for (var j of x) { foo = j }", top},
3793 : {true, "for (var j of x) { [foo] = [j] }", top},
3794 : {true, "for (var j of x) { [[foo]=[42]] = [] }", top},
3795 : {true, "for (var j of x) { var foo = j }", top},
3796 : {true, "for (var j of x) { var [foo] = [j] }", top},
3797 : {true, "for (var j of x) { var [[foo]=[42]] = [] }", top},
3798 : {true, "for (var j of x) { var foo; foo = j }", top},
3799 : {true, "for (var j of x) { var foo; [foo] = [j] }", top},
3800 : {true, "for (var j of x) { var foo; [[foo]=[42]] = [] }", top},
3801 : {true, "for (var j of x) { let foo; foo = j }", {0}},
3802 : {true, "for (var j of x) { let foo; [foo] = [j] }", {0}},
3803 : {true, "for (var j of x) { let foo; [[foo]=[42]] = [] }", {0}},
3804 : {false, "for (var j of x) { let foo = j }", {0}},
3805 : {false, "for (var j of x) { let [foo] = [j] }", {0}},
3806 : {false, "for (var j of x) { const foo = j }", {0}},
3807 : {false, "for (var j of x) { const [foo] = [j] }", {0}},
3808 : {false, "for (var j of x) { function foo() {return j} }", {0}},
3809 :
3810 : {true, "for (var {j} of x) { foo = j }", top},
3811 : {true, "for (var {j} of x) { [foo] = [j] }", top},
3812 : {true, "for (var {j} of x) { [[foo]=[42]] = [] }", top},
3813 : {true, "for (var {j} of x) { var foo = j }", top},
3814 : {true, "for (var {j} of x) { var [foo] = [j] }", top},
3815 : {true, "for (var {j} of x) { var [[foo]=[42]] = [] }", top},
3816 : {true, "for (var {j} of x) { var foo; foo = j }", top},
3817 : {true, "for (var {j} of x) { var foo; [foo] = [j] }", top},
3818 : {true, "for (var {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3819 : {true, "for (var {j} of x) { let foo; foo = j }", {0}},
3820 : {true, "for (var {j} of x) { let foo; [foo] = [j] }", {0}},
3821 : {true, "for (var {j} of x) { let foo; [[foo]=[42]] = [] }", {0}},
3822 : {false, "for (var {j} of x) { let foo = j }", {0}},
3823 : {false, "for (var {j} of x) { let [foo] = [j] }", {0}},
3824 : {false, "for (var {j} of x) { const foo = j }", {0}},
3825 : {false, "for (var {j} of x) { const [foo] = [j] }", {0}},
3826 : {false, "for (var {j} of x) { function foo() {return j} }", {0}},
3827 :
3828 : {true, "for (let j of x) { foo = j }", top},
3829 : {true, "for (let j of x) { [foo] = [j] }", top},
3830 : {true, "for (let j of x) { [[foo]=[42]] = [] }", top},
3831 : {true, "for (let j of x) { var foo = j }", top},
3832 : {true, "for (let j of x) { var [foo] = [j] }", top},
3833 : {true, "for (let j of x) { var [[foo]=[42]] = [] }", top},
3834 : {true, "for (let j of x) { var foo; foo = j }", top},
3835 : {true, "for (let j of x) { var foo; [foo] = [j] }", top},
3836 : {true, "for (let j of x) { var foo; [[foo]=[42]] = [] }", top},
3837 : {true, "for (let j of x) { let foo; foo = j }", {0, 0, 0}},
3838 : {true, "for (let j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3839 : {true, "for (let j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3840 : {false, "for (let j of x) { let foo = j }", {0, 0, 0}},
3841 : {false, "for (let j of x) { let [foo] = [j] }", {0, 0, 0}},
3842 : {false, "for (let j of x) { const foo = j }", {0, 0, 0}},
3843 : {false, "for (let j of x) { const [foo] = [j] }", {0, 0, 0}},
3844 : {false, "for (let j of x) { function foo() {return j} }", {0, 0, 0}},
3845 :
3846 : {true, "for (let {j} of x) { foo = j }", top},
3847 : {true, "for (let {j} of x) { [foo] = [j] }", top},
3848 : {true, "for (let {j} of x) { [[foo]=[42]] = [] }", top},
3849 : {true, "for (let {j} of x) { var foo = j }", top},
3850 : {true, "for (let {j} of x) { var [foo] = [j] }", top},
3851 : {true, "for (let {j} of x) { var [[foo]=[42]] = [] }", top},
3852 : {true, "for (let {j} of x) { var foo; foo = j }", top},
3853 : {true, "for (let {j} of x) { var foo; [foo] = [j] }", top},
3854 : {true, "for (let {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3855 : {true, "for (let {j} of x) { let foo; foo = j }", {0, 0, 0}},
3856 : {true, "for (let {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3857 : {true, "for (let {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3858 : {false, "for (let {j} of x) { let foo = j }", {0, 0, 0}},
3859 : {false, "for (let {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3860 : {false, "for (let {j} of x) { const foo = j }", {0, 0, 0}},
3861 : {false, "for (let {j} of x) { const [foo] = [j] }", {0, 0, 0}},
3862 : {false, "for (let {j} of x) { function foo() {return j} }", {0, 0, 0}},
3863 :
3864 : {true, "for (const j of x) { foo = j }", top},
3865 : {true, "for (const j of x) { [foo] = [j] }", top},
3866 : {true, "for (const j of x) { [[foo]=[42]] = [] }", top},
3867 : {true, "for (const j of x) { var foo = j }", top},
3868 : {true, "for (const j of x) { var [foo] = [j] }", top},
3869 : {true, "for (const j of x) { var [[foo]=[42]] = [] }", top},
3870 : {true, "for (const j of x) { var foo; foo = j }", top},
3871 : {true, "for (const j of x) { var foo; [foo] = [j] }", top},
3872 : {true, "for (const j of x) { var foo; [[foo]=[42]] = [] }", top},
3873 : {true, "for (const j of x) { let foo; foo = j }", {0, 0, 0}},
3874 : {true, "for (const j of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3875 : {true, "for (const j of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3876 : {false, "for (const j of x) { let foo = j }", {0, 0, 0}},
3877 : {false, "for (const j of x) { let [foo] = [j] }", {0, 0, 0}},
3878 : {false, "for (const j of x) { const foo = j }", {0, 0, 0}},
3879 : {false, "for (const j of x) { const [foo] = [j] }", {0, 0, 0}},
3880 : {false, "for (const j of x) { function foo() {return j} }", {0, 0, 0}},
3881 :
3882 : {true, "for (const {j} of x) { foo = j }", top},
3883 : {true, "for (const {j} of x) { [foo] = [j] }", top},
3884 : {true, "for (const {j} of x) { [[foo]=[42]] = [] }", top},
3885 : {true, "for (const {j} of x) { var foo = j }", top},
3886 : {true, "for (const {j} of x) { var [foo] = [j] }", top},
3887 : {true, "for (const {j} of x) { var [[foo]=[42]] = [] }", top},
3888 : {true, "for (const {j} of x) { var foo; foo = j }", top},
3889 : {true, "for (const {j} of x) { var foo; [foo] = [j] }", top},
3890 : {true, "for (const {j} of x) { var foo; [[foo]=[42]] = [] }", top},
3891 : {true, "for (const {j} of x) { let foo; foo = j }", {0, 0, 0}},
3892 : {true, "for (const {j} of x) { let foo; [foo] = [j] }", {0, 0, 0}},
3893 : {true, "for (const {j} of x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3894 : {false, "for (const {j} of x) { let foo = j }", {0, 0, 0}},
3895 : {false, "for (const {j} of x) { let [foo] = [j] }", {0, 0, 0}},
3896 : {false, "for (const {j} of x) { const foo = j }", {0, 0, 0}},
3897 : {false, "for (const {j} of x) { const [foo] = [j] }", {0, 0, 0}},
3898 : {false, "for (const {j} of x) { function foo() {return j} }", {0, 0, 0}},
3899 :
3900 : {true, "for (j in x) { foo = j }", top},
3901 : {true, "for (j in x) { [foo] = [j] }", top},
3902 : {true, "for (j in x) { [[foo]=[42]] = [] }", top},
3903 : {true, "for (j in x) { var foo = j }", top},
3904 : {true, "for (j in x) { var [foo] = [j] }", top},
3905 : {true, "for (j in x) { var [[foo]=[42]] = [] }", top},
3906 : {true, "for (j in x) { var foo; foo = j }", top},
3907 : {true, "for (j in x) { var foo; [foo] = [j] }", top},
3908 : {true, "for (j in x) { var foo; [[foo]=[42]] = [] }", top},
3909 : {true, "for (j in x) { let foo; foo = j }", {0}},
3910 : {true, "for (j in x) { let foo; [foo] = [j] }", {0}},
3911 : {true, "for (j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3912 : {false, "for (j in x) { let foo = j }", {0}},
3913 : {false, "for (j in x) { let [foo] = [j] }", {0}},
3914 : {false, "for (j in x) { const foo = j }", {0}},
3915 : {false, "for (j in x) { const [foo] = [j] }", {0}},
3916 : {false, "for (j in x) { function foo() {return j} }", {0}},
3917 :
3918 : {true, "for ({j} in x) { foo = j }", top},
3919 : {true, "for ({j} in x) { [foo] = [j] }", top},
3920 : {true, "for ({j} in x) { [[foo]=[42]] = [] }", top},
3921 : {true, "for ({j} in x) { var foo = j }", top},
3922 : {true, "for ({j} in x) { var [foo] = [j] }", top},
3923 : {true, "for ({j} in x) { var [[foo]=[42]] = [] }", top},
3924 : {true, "for ({j} in x) { var foo; foo = j }", top},
3925 : {true, "for ({j} in x) { var foo; [foo] = [j] }", top},
3926 : {true, "for ({j} in x) { var foo; [[foo]=[42]] = [] }", top},
3927 : {true, "for ({j} in x) { let foo; foo = j }", {0}},
3928 : {true, "for ({j} in x) { let foo; [foo] = [j] }", {0}},
3929 : {true, "for ({j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3930 : {false, "for ({j} in x) { let foo = j }", {0}},
3931 : {false, "for ({j} in x) { let [foo] = [j] }", {0}},
3932 : {false, "for ({j} in x) { const foo = j }", {0}},
3933 : {false, "for ({j} in x) { const [foo] = [j] }", {0}},
3934 : {false, "for ({j} in x) { function foo() {return j} }", {0}},
3935 :
3936 : {true, "for (var j in x) { foo = j }", top},
3937 : {true, "for (var j in x) { [foo] = [j] }", top},
3938 : {true, "for (var j in x) { [[foo]=[42]] = [] }", top},
3939 : {true, "for (var j in x) { var foo = j }", top},
3940 : {true, "for (var j in x) { var [foo] = [j] }", top},
3941 : {true, "for (var j in x) { var [[foo]=[42]] = [] }", top},
3942 : {true, "for (var j in x) { var foo; foo = j }", top},
3943 : {true, "for (var j in x) { var foo; [foo] = [j] }", top},
3944 : {true, "for (var j in x) { var foo; [[foo]=[42]] = [] }", top},
3945 : {true, "for (var j in x) { let foo; foo = j }", {0}},
3946 : {true, "for (var j in x) { let foo; [foo] = [j] }", {0}},
3947 : {true, "for (var j in x) { let foo; [[foo]=[42]] = [] }", {0}},
3948 : {false, "for (var j in x) { let foo = j }", {0}},
3949 : {false, "for (var j in x) { let [foo] = [j] }", {0}},
3950 : {false, "for (var j in x) { const foo = j }", {0}},
3951 : {false, "for (var j in x) { const [foo] = [j] }", {0}},
3952 : {false, "for (var j in x) { function foo() {return j} }", {0}},
3953 :
3954 : {true, "for (var {j} in x) { foo = j }", top},
3955 : {true, "for (var {j} in x) { [foo] = [j] }", top},
3956 : {true, "for (var {j} in x) { [[foo]=[42]] = [] }", top},
3957 : {true, "for (var {j} in x) { var foo = j }", top},
3958 : {true, "for (var {j} in x) { var [foo] = [j] }", top},
3959 : {true, "for (var {j} in x) { var [[foo]=[42]] = [] }", top},
3960 : {true, "for (var {j} in x) { var foo; foo = j }", top},
3961 : {true, "for (var {j} in x) { var foo; [foo] = [j] }", top},
3962 : {true, "for (var {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3963 : {true, "for (var {j} in x) { let foo; foo = j }", {0}},
3964 : {true, "for (var {j} in x) { let foo; [foo] = [j] }", {0}},
3965 : {true, "for (var {j} in x) { let foo; [[foo]=[42]] = [] }", {0}},
3966 : {false, "for (var {j} in x) { let foo = j }", {0}},
3967 : {false, "for (var {j} in x) { let [foo] = [j] }", {0}},
3968 : {false, "for (var {j} in x) { const foo = j }", {0}},
3969 : {false, "for (var {j} in x) { const [foo] = [j] }", {0}},
3970 : {false, "for (var {j} in x) { function foo() {return j} }", {0}},
3971 :
3972 : {true, "for (let j in x) { foo = j }", top},
3973 : {true, "for (let j in x) { [foo] = [j] }", top},
3974 : {true, "for (let j in x) { [[foo]=[42]] = [] }", top},
3975 : {true, "for (let j in x) { var foo = j }", top},
3976 : {true, "for (let j in x) { var [foo] = [j] }", top},
3977 : {true, "for (let j in x) { var [[foo]=[42]] = [] }", top},
3978 : {true, "for (let j in x) { var foo; foo = j }", top},
3979 : {true, "for (let j in x) { var foo; [foo] = [j] }", top},
3980 : {true, "for (let j in x) { var foo; [[foo]=[42]] = [] }", top},
3981 : {true, "for (let j in x) { let foo; foo = j }", {0, 0, 0}},
3982 : {true, "for (let j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
3983 : {true, "for (let j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
3984 : {false, "for (let j in x) { let foo = j }", {0, 0, 0}},
3985 : {false, "for (let j in x) { let [foo] = [j] }", {0, 0, 0}},
3986 : {false, "for (let j in x) { const foo = j }", {0, 0, 0}},
3987 : {false, "for (let j in x) { const [foo] = [j] }", {0, 0, 0}},
3988 : {false, "for (let j in x) { function foo() {return j} }", {0, 0, 0}},
3989 :
3990 : {true, "for (let {j} in x) { foo = j }", top},
3991 : {true, "for (let {j} in x) { [foo] = [j] }", top},
3992 : {true, "for (let {j} in x) { [[foo]=[42]] = [] }", top},
3993 : {true, "for (let {j} in x) { var foo = j }", top},
3994 : {true, "for (let {j} in x) { var [foo] = [j] }", top},
3995 : {true, "for (let {j} in x) { var [[foo]=[42]] = [] }", top},
3996 : {true, "for (let {j} in x) { var foo; foo = j }", top},
3997 : {true, "for (let {j} in x) { var foo; [foo] = [j] }", top},
3998 : {true, "for (let {j} in x) { var foo; [[foo]=[42]] = [] }", top},
3999 : {true, "for (let {j} in x) { let foo; foo = j }", {0, 0, 0}},
4000 : {true, "for (let {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4001 : {true, "for (let {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4002 : {false, "for (let {j} in x) { let foo = j }", {0, 0, 0}},
4003 : {false, "for (let {j} in x) { let [foo] = [j] }", {0, 0, 0}},
4004 : {false, "for (let {j} in x) { const foo = j }", {0, 0, 0}},
4005 : {false, "for (let {j} in x) { const [foo] = [j] }", {0, 0, 0}},
4006 : {false, "for (let {j} in x) { function foo() {return j} }", {0, 0, 0}},
4007 :
4008 : {true, "for (const j in x) { foo = j }", top},
4009 : {true, "for (const j in x) { [foo] = [j] }", top},
4010 : {true, "for (const j in x) { [[foo]=[42]] = [] }", top},
4011 : {true, "for (const j in x) { var foo = j }", top},
4012 : {true, "for (const j in x) { var [foo] = [j] }", top},
4013 : {true, "for (const j in x) { var [[foo]=[42]] = [] }", top},
4014 : {true, "for (const j in x) { var foo; foo = j }", top},
4015 : {true, "for (const j in x) { var foo; [foo] = [j] }", top},
4016 : {true, "for (const j in x) { var foo; [[foo]=[42]] = [] }", top},
4017 : {true, "for (const j in x) { let foo; foo = j }", {0, 0, 0}},
4018 : {true, "for (const j in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4019 : {true, "for (const j in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4020 : {false, "for (const j in x) { let foo = j }", {0, 0, 0}},
4021 : {false, "for (const j in x) { let [foo] = [j] }", {0, 0, 0}},
4022 : {false, "for (const j in x) { const foo = j }", {0, 0, 0}},
4023 : {false, "for (const j in x) { const [foo] = [j] }", {0, 0, 0}},
4024 : {false, "for (const j in x) { function foo() {return j} }", {0, 0, 0}},
4025 :
4026 : {true, "for (const {j} in x) { foo = j }", top},
4027 : {true, "for (const {j} in x) { [foo] = [j] }", top},
4028 : {true, "for (const {j} in x) { [[foo]=[42]] = [] }", top},
4029 : {true, "for (const {j} in x) { var foo = j }", top},
4030 : {true, "for (const {j} in x) { var [foo] = [j] }", top},
4031 : {true, "for (const {j} in x) { var [[foo]=[42]] = [] }", top},
4032 : {true, "for (const {j} in x) { var foo; foo = j }", top},
4033 : {true, "for (const {j} in x) { var foo; [foo] = [j] }", top},
4034 : {true, "for (const {j} in x) { var foo; [[foo]=[42]] = [] }", top},
4035 : {true, "for (const {j} in x) { let foo; foo = j }", {0, 0, 0}},
4036 : {true, "for (const {j} in x) { let foo; [foo] = [j] }", {0, 0, 0}},
4037 : {true, "for (const {j} in x) { let foo; [[foo]=[42]] = [] }", {0, 0, 0}},
4038 : {false, "for (const {j} in x) { let foo = j }", {0, 0, 0}},
4039 : {false, "for (const {j} in x) { let [foo] = [j] }", {0, 0, 0}},
4040 : {false, "for (const {j} in x) { const foo = j }", {0, 0, 0}},
4041 : {false, "for (const {j} in x) { const [foo] = [j] }", {0, 0, 0}},
4042 : {false, "for (const {j} in x) { function foo() {return j} }", {0, 0, 0}},
4043 :
4044 : {true, "while (j) { foo = j }", top},
4045 : {true, "while (j) { [foo] = [j] }", top},
4046 : {true, "while (j) { [[foo]=[42]] = [] }", top},
4047 : {true, "while (j) { var foo = j }", top},
4048 : {true, "while (j) { var [foo] = [j] }", top},
4049 : {true, "while (j) { var [[foo]=[42]] = [] }", top},
4050 : {true, "while (j) { var foo; foo = j }", top},
4051 : {true, "while (j) { var foo; [foo] = [j] }", top},
4052 : {true, "while (j) { var foo; [[foo]=[42]] = [] }", top},
4053 : {true, "while (j) { let foo; foo = j }", {0}},
4054 : {true, "while (j) { let foo; [foo] = [j] }", {0}},
4055 : {true, "while (j) { let foo; [[foo]=[42]] = [] }", {0}},
4056 : {false, "while (j) { let foo = j }", {0}},
4057 : {false, "while (j) { let [foo] = [j] }", {0}},
4058 : {false, "while (j) { const foo = j }", {0}},
4059 : {false, "while (j) { const [foo] = [j] }", {0}},
4060 : {false, "while (j) { function foo() {return j} }", {0}},
4061 :
4062 : {true, "do { foo = j } while (j)", top},
4063 : {true, "do { [foo] = [j] } while (j)", top},
4064 : {true, "do { [[foo]=[42]] = [] } while (j)", top},
4065 : {true, "do { var foo = j } while (j)", top},
4066 : {true, "do { var [foo] = [j] } while (j)", top},
4067 : {true, "do { var [[foo]=[42]] = [] } while (j)", top},
4068 : {true, "do { var foo; foo = j } while (j)", top},
4069 : {true, "do { var foo; [foo] = [j] } while (j)", top},
4070 : {true, "do { var foo; [[foo]=[42]] = [] } while (j)", top},
4071 : {true, "do { let foo; foo = j } while (j)", {0}},
4072 : {true, "do { let foo; [foo] = [j] } while (j)", {0}},
4073 : {true, "do { let foo; [[foo]=[42]] = [] } while (j)", {0}},
4074 : {false, "do { let foo = j } while (j)", {0}},
4075 : {false, "do { let [foo] = [j] } while (j)", {0}},
4076 : {false, "do { const foo = j } while (j)", {0}},
4077 : {false, "do { const [foo] = [j] } while (j)", {0}},
4078 : {false, "do { function foo() {return j} } while (j)", {0}},
4079 3010 : };
4080 :
4081 : Input script_only_tests[] = {
4082 : {true, "for (j=x; j<10; ++j) { function foo() {return j} }", top},
4083 : {true, "for ({j}=x; j<10; ++j) { function foo() {return j} }", top},
4084 : {true, "for (var j=x; j<10; ++j) { function foo() {return j} }", top},
4085 : {true, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", top},
4086 : {true, "for (let j=x; j<10; ++j) { function foo() {return j} }", top},
4087 : {true, "for (let {j}=x; j<10; ++j) { function foo() {return j} }", top},
4088 : {true, "for (j of x) { function foo() {return j} }", top},
4089 : {true, "for ({j} of x) { function foo() {return j} }", top},
4090 : {true, "for (var j of x) { function foo() {return j} }", top},
4091 : {true, "for (var {j} of x) { function foo() {return j} }", top},
4092 : {true, "for (let j of x) { function foo() {return j} }", top},
4093 : {true, "for (let {j} of x) { function foo() {return j} }", top},
4094 : {true, "for (const j of x) { function foo() {return j} }", top},
4095 : {true, "for (const {j} of x) { function foo() {return j} }", top},
4096 : {true, "for (j in x) { function foo() {return j} }", top},
4097 : {true, "for ({j} in x) { function foo() {return j} }", top},
4098 : {true, "for (var j in x) { function foo() {return j} }", top},
4099 : {true, "for (var {j} in x) { function foo() {return j} }", top},
4100 : {true, "for (let j in x) { function foo() {return j} }", top},
4101 : {true, "for (let {j} in x) { function foo() {return j} }", top},
4102 : {true, "for (const j in x) { function foo() {return j} }", top},
4103 : {true, "for (const {j} in x) { function foo() {return j} }", top},
4104 : {true, "while (j) { function foo() {return j} }", top},
4105 : {true, "do { function foo() {return j} } while (j)", top},
4106 130 : };
4107 :
4108 2045 : for (unsigned i = 0; i < arraysize(module_and_script_tests); ++i) {
4109 2040 : Input input = module_and_script_tests[i];
4110 6120 : for (unsigned module = 0; module <= 1; ++module) {
4111 8160 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4112 : ++allow_lazy_parsing) {
4113 8160 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4114 : }
4115 4080 : TestMaybeAssigned(wrap(input), "foo", module, false);
4116 : }
4117 2040 : }
4118 :
4119 120 : for (unsigned i = 0; i < arraysize(script_only_tests); ++i) {
4120 120 : Input input = script_only_tests[i];
4121 360 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4122 : ++allow_lazy_parsing) {
4123 240 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4124 : }
4125 120 : TestMaybeAssigned(wrap(input), "foo", false, false);
4126 120 : }
4127 5 : }
4128 :
4129 28342 : TEST(MaybeAssignedTopLevel) {
4130 : i::Isolate* isolate = CcTest::i_isolate();
4131 : i::HandleScope scope(isolate);
4132 10 : LocalContext env;
4133 :
4134 : const char* prefixes[] = {
4135 : "let foo; ",
4136 : "let foo = 0; ",
4137 : "let [foo] = [1]; ",
4138 : "let {foo} = {foo: 2}; ",
4139 : "let {foo=3} = {}; ",
4140 : "var foo; ",
4141 : "var foo = 0; ",
4142 : "var [foo] = [1]; ",
4143 : "var {foo} = {foo: 2}; ",
4144 : "var {foo=3} = {}; ",
4145 : "{ var foo; }; ",
4146 : "{ var foo = 0; }; ",
4147 : "{ var [foo] = [1]; }; ",
4148 : "{ var {foo} = {foo: 2}; }; ",
4149 : "{ var {foo=3} = {}; }; ",
4150 : "function foo() {}; ",
4151 : "function* foo() {}; ",
4152 : "async function foo() {}; ",
4153 : "class foo {}; ",
4154 : "class foo extends null {}; ",
4155 5 : };
4156 :
4157 : const char* module_and_script_tests[] = {
4158 : "function bar() {foo = 42}; ext(bar); ext(foo)",
4159 : "ext(function() {foo++}); ext(foo)",
4160 : "bar = () => --foo; ext(bar); ext(foo)",
4161 : "function* bar() {eval(ext)}; ext(bar); ext(foo)",
4162 5 : };
4163 :
4164 : const char* script_only_tests[] = {
4165 : "",
4166 : "{ function foo() {}; }; ",
4167 : "{ function* foo() {}; }; ",
4168 : "{ async function foo() {}; }; ",
4169 5 : };
4170 :
4171 105 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4172 400 : for (unsigned j = 0; j < arraysize(module_and_script_tests); ++j) {
4173 400 : std::string source(prefixes[i]);
4174 400 : source += module_and_script_tests[j];
4175 : std::vector<unsigned> top;
4176 800 : Input input({true, source, top});
4177 1200 : for (unsigned module = 0; module <= 1; ++module) {
4178 1600 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4179 : ++allow_lazy_parsing) {
4180 1600 : TestMaybeAssigned(input, "foo", module, allow_lazy_parsing);
4181 : }
4182 : }
4183 : }
4184 : }
4185 :
4186 100 : for (unsigned i = 0; i < arraysize(prefixes); ++i) {
4187 400 : for (unsigned j = 0; j < arraysize(script_only_tests); ++j) {
4188 400 : std::string source(prefixes[i]);
4189 400 : source += script_only_tests[j];
4190 : std::vector<unsigned> top;
4191 800 : Input input({true, source, top});
4192 1200 : for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
4193 : ++allow_lazy_parsing) {
4194 800 : TestMaybeAssigned(input, "foo", false, allow_lazy_parsing);
4195 : }
4196 : }
4197 : }
4198 5 : }
4199 :
4200 : namespace {
4201 :
4202 10 : i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone,
4203 : i::Handle<i::JSObject> m, const char* name) {
4204 : i::AstValueFactory avf(zone, isolate->ast_string_constants(),
4205 10 : isolate->heap()->HashSeed());
4206 : i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(
4207 10 : i::JSReceiver::GetProperty(isolate, m, name).ToHandleChecked());
4208 : i::DeclarationScope* script_scope =
4209 5 : new (zone) i::DeclarationScope(zone, &avf);
4210 : i::Scope* s = i::Scope::DeserializeScopeChain(
4211 10 : isolate, zone, f->context()->scope_info(), script_scope, &avf,
4212 5 : i::Scope::DeserializationMode::kIncludingVariables);
4213 5 : return s;
4214 : }
4215 :
4216 : } // namespace
4217 :
4218 28342 : TEST(AsmModuleFlag) {
4219 5 : i::FLAG_validate_asm = false;
4220 5 : i::Isolate* isolate = CcTest::i_isolate();
4221 : i::HandleScope scope(isolate);
4222 10 : LocalContext env;
4223 :
4224 : const char* src =
4225 : "function m() {"
4226 : " 'use asm';"
4227 : " function f() { return 0 };"
4228 : " return { f:f };"
4229 : "}"
4230 : "m();";
4231 :
4232 10 : i::Zone zone(isolate->allocator(), ZONE_NAME);
4233 : v8::Local<v8::Value> v = CompileRun(src);
4234 5 : i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
4235 5 : i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o);
4236 :
4237 : // The asm.js module should be marked as such.
4238 5 : i::Scope* s = DeserializeFunctionScope(isolate, &zone, m, "f");
4239 10 : CHECK(s->IsAsmModule() && s->AsDeclarationScope()->is_asm_module());
4240 5 : }
4241 :
4242 :
4243 28342 : TEST(UseAsmUseCount) {
4244 : i::Isolate* isolate = CcTest::i_isolate();
4245 : i::HandleScope scope(isolate);
4246 10 : LocalContext env;
4247 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4248 5 : global_use_counts = use_counts;
4249 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4250 : CompileRun("\"use asm\";\n"
4251 : "var foo = 1;\n"
4252 : "function bar() { \"use asm\"; var baz = 1; }");
4253 5 : CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
4254 5 : }
4255 :
4256 :
4257 28342 : TEST(StrictModeUseCount) {
4258 : i::Isolate* isolate = CcTest::i_isolate();
4259 : i::HandleScope scope(isolate);
4260 10 : LocalContext env;
4261 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4262 5 : global_use_counts = use_counts;
4263 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4264 : CompileRun(
4265 : "\"use strict\";\n"
4266 : "function bar() { var baz = 1; }"); // strict mode inherits
4267 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4268 5 : CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
4269 5 : }
4270 :
4271 :
4272 28342 : TEST(SloppyModeUseCount) {
4273 : i::Isolate* isolate = CcTest::i_isolate();
4274 : i::HandleScope scope(isolate);
4275 10 : LocalContext env;
4276 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4277 5 : global_use_counts = use_counts;
4278 : // Force eager parsing (preparser doesn't update use counts).
4279 5 : i::FLAG_lazy = false;
4280 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4281 : CompileRun("function bar() { var baz = 1; }");
4282 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4283 5 : CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
4284 5 : }
4285 :
4286 :
4287 28342 : TEST(BothModesUseCount) {
4288 : i::Isolate* isolate = CcTest::i_isolate();
4289 : i::HandleScope scope(isolate);
4290 10 : LocalContext env;
4291 5 : int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
4292 5 : global_use_counts = use_counts;
4293 : // Force eager parsing (preparser doesn't update use counts).
4294 5 : i::FLAG_lazy = false;
4295 5 : CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
4296 : CompileRun("function bar() { 'use strict'; var baz = 1; }");
4297 5 : CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
4298 5 : CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
4299 5 : }
4300 :
4301 28342 : TEST(LineOrParagraphSeparatorAsLineTerminator) {
4302 : // Tests that both preparsing and parsing accept U+2028 LINE SEPARATOR and
4303 : // U+2029 PARAGRAPH SEPARATOR as LineTerminator symbols outside of string
4304 : // literals.
4305 5 : const char* context_data[][2] = {{"", ""}, {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 28342 : TEST(LineOrParagraphSeparatorInStringLiteral) {
4314 : // Tests that both preparsing and parsing don't treat U+2028 LINE SEPARATOR
4315 : // and U+2029 PARAGRAPH SEPARATOR as line terminators within string literals.
4316 : // https://github.com/tc39/proposal-json-superset
4317 : const char* context_data[][2] = {
4318 5 : {"\"", "\""}, {"'", "'"}, {nullptr, nullptr}};
4319 : const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // 1<U+2028>2
4320 : "\x31\xE2\x80\xA9\x32", // 1<U+2029>2
4321 5 : nullptr};
4322 :
4323 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4324 5 : }
4325 :
4326 28342 : TEST(ErrorsArrowFormalParameters) {
4327 : const char* context_data[][2] = {
4328 : { "()", "=>{}" },
4329 : { "()", "=>{};" },
4330 : { "var x = ()", "=>{}" },
4331 : { "var x = ()", "=>{};" },
4332 :
4333 : { "a", "=>{}" },
4334 : { "a", "=>{};" },
4335 : { "var x = a", "=>{}" },
4336 : { "var x = a", "=>{};" },
4337 :
4338 : { "(a)", "=>{}" },
4339 : { "(a)", "=>{};" },
4340 : { "var x = (a)", "=>{}" },
4341 : { "var x = (a)", "=>{};" },
4342 :
4343 : { "(...a)", "=>{}" },
4344 : { "(...a)", "=>{};" },
4345 : { "var x = (...a)", "=>{}" },
4346 : { "var x = (...a)", "=>{};" },
4347 :
4348 : { "(a,b)", "=>{}" },
4349 : { "(a,b)", "=>{};" },
4350 : { "var x = (a,b)", "=>{}" },
4351 : { "var x = (a,b)", "=>{};" },
4352 :
4353 : { "(a,...b)", "=>{}" },
4354 : { "(a,...b)", "=>{};" },
4355 : { "var x = (a,...b)", "=>{}" },
4356 : { "var x = (a,...b)", "=>{};" },
4357 :
4358 : { nullptr, nullptr }
4359 5 : };
4360 : const char* assignment_expression_suffix_data[] = {
4361 : "?c:d=>{}",
4362 : "=c=>{}",
4363 : "()",
4364 : "(c)",
4365 : "[1]",
4366 : "[c]",
4367 : ".c",
4368 : "-c",
4369 : "+c",
4370 : "c++",
4371 : "`c`",
4372 : "`${c}`",
4373 : "`template-head${c}`",
4374 : "`${c}template-tail`",
4375 : "`template-head${c}template-tail`",
4376 : "`${c}template-tail`",
4377 : nullptr
4378 5 : };
4379 :
4380 5 : RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
4381 5 : }
4382 :
4383 :
4384 28342 : TEST(ErrorsArrowFunctions) {
4385 : // Tests that parser and preparser generate the same kind of errors
4386 : // on invalid arrow function syntax.
4387 :
4388 : // clang-format off
4389 : const char* context_data[][2] = {
4390 : {"", ";"},
4391 : {"v = ", ";"},
4392 : {"bar ? (", ") : baz;"},
4393 : {"bar ? baz : (", ");"},
4394 : {"bar[", "];"},
4395 : {"bar, ", ";"},
4396 : {"", ", bar;"},
4397 : {nullptr, nullptr}
4398 5 : };
4399 :
4400 : const char* statement_data[] = {
4401 : "=> 0",
4402 : "=>",
4403 : "() =>",
4404 : "=> {}",
4405 : ") => {}",
4406 : ", => {}",
4407 : "(,) => {}",
4408 : "return => {}",
4409 : "() => {'value': 42}",
4410 :
4411 : // Check that the early return introduced in ParsePrimaryExpression
4412 : // does not accept stray closing parentheses.
4413 : ")",
4414 : ") => 0",
4415 : "foo[()]",
4416 : "()",
4417 :
4418 : // Parameter lists with extra parens should be recognized as errors.
4419 : "(()) => 0",
4420 : "((x)) => 0",
4421 : "((x, y)) => 0",
4422 : "(x, (y)) => 0",
4423 : "((x, y, z)) => 0",
4424 : "(x, (y, z)) => 0",
4425 : "((x, y), z) => 0",
4426 :
4427 : // Arrow function formal parameters are parsed as StrictFormalParameters,
4428 : // which confusingly only implies that there are no duplicates. Words
4429 : // reserved in strict mode, and eval or arguments, are indeed valid in
4430 : // sloppy mode.
4431 : "eval => { 'use strict'; 0 }",
4432 : "arguments => { 'use strict'; 0 }",
4433 : "yield => { 'use strict'; 0 }",
4434 : "interface => { 'use strict'; 0 }",
4435 : "(eval) => { 'use strict'; 0 }",
4436 : "(arguments) => { 'use strict'; 0 }",
4437 : "(yield) => { 'use strict'; 0 }",
4438 : "(interface) => { 'use strict'; 0 }",
4439 : "(eval, bar) => { 'use strict'; 0 }",
4440 : "(bar, eval) => { 'use strict'; 0 }",
4441 : "(bar, arguments) => { 'use strict'; 0 }",
4442 : "(bar, yield) => { 'use strict'; 0 }",
4443 : "(bar, interface) => { 'use strict'; 0 }",
4444 : // TODO(aperez): Detecting duplicates does not work in PreParser.
4445 : // "(bar, bar) => {}",
4446 :
4447 : // The parameter list is parsed as an expression, but only
4448 : // a comma-separated list of identifier is valid.
4449 : "32 => {}",
4450 : "(32) => {}",
4451 : "(a, 32) => {}",
4452 : "if => {}",
4453 : "(if) => {}",
4454 : "(a, if) => {}",
4455 : "a + b => {}",
4456 : "(a + b) => {}",
4457 : "(a + b, c) => {}",
4458 : "(a, b - c) => {}",
4459 : "\"a\" => {}",
4460 : "(\"a\") => {}",
4461 : "(\"a\", b) => {}",
4462 : "(a, \"b\") => {}",
4463 : "-a => {}",
4464 : "(-a) => {}",
4465 : "(-a, b) => {}",
4466 : "(a, -b) => {}",
4467 : "{} => {}",
4468 : "a++ => {}",
4469 : "(a++) => {}",
4470 : "(a++, b) => {}",
4471 : "(a, b++) => {}",
4472 : "[] => {}",
4473 : "(foo ? bar : baz) => {}",
4474 : "(a, foo ? bar : baz) => {}",
4475 : "(foo ? bar : baz, a) => {}",
4476 : "(a.b, c) => {}",
4477 : "(c, a.b) => {}",
4478 : "(a['b'], c) => {}",
4479 : "(c, a['b']) => {}",
4480 : "(...a = b) => b",
4481 :
4482 : // crbug.com/582626
4483 : "(...rest - a) => b",
4484 : "(a, ...b - 10) => b",
4485 :
4486 : nullptr
4487 5 : };
4488 : // clang-format on
4489 :
4490 : // The test is quite slow, so run it with a reduced set of flags.
4491 : static const ParserFlag flags[] = {kAllowLazy};
4492 : RunParserSyncTest(context_data, statement_data, kError, flags,
4493 5 : arraysize(flags));
4494 :
4495 : // In a context where a concise arrow body is parsed with [~In] variant,
4496 : // ensure that an error is reported in both full parser and preparser.
4497 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4498 5 : {nullptr, nullptr}};
4499 5 : const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
4500 : RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
4501 5 : arraysize(flags));
4502 5 : }
4503 :
4504 :
4505 28342 : TEST(NoErrorsArrowFunctions) {
4506 : // Tests that parser and preparser accept valid arrow functions syntax.
4507 : // clang-format off
4508 : const char* context_data[][2] = {
4509 : {"", ";"},
4510 : {"bar ? (", ") : baz;"},
4511 : {"bar ? baz : (", ");"},
4512 : {"bar, ", ";"},
4513 : {"", ", bar;"},
4514 : {nullptr, nullptr}
4515 5 : };
4516 :
4517 : const char* statement_data[] = {
4518 : "() => {}",
4519 : "() => { return 42 }",
4520 : "x => { return x; }",
4521 : "(x) => { return x; }",
4522 : "(x, y) => { return x + y; }",
4523 : "(x, y, z) => { return x + y + z; }",
4524 : "(x, y) => { x.a = y; }",
4525 : "() => 42",
4526 : "x => x",
4527 : "x => x * x",
4528 : "(x) => x",
4529 : "(x) => x * x",
4530 : "(x, y) => x + y",
4531 : "(x, y, z) => x, y, z",
4532 : "(x, y) => x.a = y",
4533 : "() => ({'value': 42})",
4534 : "x => y => x + y",
4535 : "(x, y) => (u, v) => x*u + y*v",
4536 : "(x, y) => z => z * (x + y)",
4537 : "x => (y, z) => z * (x + y)",
4538 :
4539 : // Those are comma-separated expressions, with arrow functions as items.
4540 : // They stress the code for validating arrow function parameter lists.
4541 : "a, b => 0",
4542 : "a, b, (c, d) => 0",
4543 : "(a, b, (c, d) => 0)",
4544 : "(a, b) => 0, (c, d) => 1",
4545 : "(a, b => {}, a => a + 1)",
4546 : "((a, b) => {}, (a => a + 1))",
4547 : "(a, (a, (b, c) => 0))",
4548 :
4549 : // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
4550 : "foo ? bar : baz => {}",
4551 :
4552 : // Arrows with non-simple parameters.
4553 : "({}) => {}",
4554 : "(a, {}) => {}",
4555 : "({}, a) => {}",
4556 : "([]) => {}",
4557 : "(a, []) => {}",
4558 : "([], a) => {}",
4559 : "(a = b) => {}",
4560 : "(a = b, c) => {}",
4561 : "(a, b = c) => {}",
4562 : "({a}) => {}",
4563 : "(x = 9) => {}",
4564 : "(x, y = 9) => {}",
4565 : "(x = 9, y) => {}",
4566 : "(x, y = 9, z) => {}",
4567 : "(x, y = 9, z = 8) => {}",
4568 : "(...a) => {}",
4569 : "(x, ...a) => {}",
4570 : "(x = 9, ...a) => {}",
4571 : "(x, y = 9, ...a) => {}",
4572 : "(x, y = 9, {b}, z = 8, ...a) => {}",
4573 : "({a} = {}) => {}",
4574 : "([x] = []) => {}",
4575 : "({a = 42}) => {}",
4576 : "([x = 0]) => {}",
4577 : nullptr
4578 5 : };
4579 : // clang-format on
4580 :
4581 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4582 :
4583 : static const ParserFlag flags[] = {kAllowLazy};
4584 : // In a context where a concise arrow body is parsed with [~In] variant,
4585 : // ensure that nested expressions can still use the 'in' operator,
4586 : const char* loop_context_data[][2] = {{"for (", "; 0;);"},
4587 5 : {nullptr, nullptr}};
4588 5 : const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
4589 : RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
4590 5 : arraysize(flags));
4591 5 : }
4592 :
4593 :
4594 28342 : TEST(ArrowFunctionsSloppyParameterNames) {
4595 : const char* strict_context_data[][2] = {{"'use strict'; ", ";"},
4596 : {"'use strict'; bar ? (", ") : baz;"},
4597 : {"'use strict'; bar ? baz : (", ");"},
4598 : {"'use strict'; bar, ", ";"},
4599 : {"'use strict'; ", ", bar;"},
4600 5 : {nullptr, nullptr}};
4601 :
4602 : const char* sloppy_context_data[][2] = {
4603 : {"", ";"}, {"bar ? (", ") : baz;"}, {"bar ? baz : (", ");"},
4604 5 : {"bar, ", ";"}, {"", ", bar;"}, {nullptr, nullptr}};
4605 :
4606 : const char* statement_data[] = {"eval => {}",
4607 : "arguments => {}",
4608 : "yield => {}",
4609 : "interface => {}",
4610 : "(eval) => {}",
4611 : "(arguments) => {}",
4612 : "(yield) => {}",
4613 : "(interface) => {}",
4614 : "(eval, bar) => {}",
4615 : "(bar, eval) => {}",
4616 : "(bar, arguments) => {}",
4617 : "(bar, yield) => {}",
4618 : "(bar, interface) => {}",
4619 : "(interface, eval) => {}",
4620 : "(interface, arguments) => {}",
4621 : "(eval, interface) => {}",
4622 : "(arguments, interface) => {}",
4623 5 : nullptr};
4624 :
4625 5 : RunParserSyncTest(strict_context_data, statement_data, kError);
4626 5 : RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
4627 5 : }
4628 :
4629 :
4630 28342 : TEST(ArrowFunctionsYieldParameterNameInGenerator) {
4631 : const char* sloppy_function_context_data[][2] = {
4632 5 : {"(function f() { (", "); });"}, {nullptr, nullptr}};
4633 :
4634 : const char* strict_function_context_data[][2] = {
4635 5 : {"(function f() {'use strict'; (", "); });"}, {nullptr, nullptr}};
4636 :
4637 : const char* generator_context_data[][2] = {
4638 : {"(function *g() {'use strict'; (", "); });"},
4639 : {"(function *g() { (", "); });"},
4640 5 : {nullptr, nullptr}};
4641 :
4642 : const char* arrow_data[] = {
4643 : "yield => {}", "(yield) => {}", "(a, yield) => {}",
4644 : "(yield, a) => {}", "(yield, ...a) => {}", "(a, ...yield) => {}",
4645 5 : "({yield}) => {}", "([yield]) => {}", nullptr};
4646 :
4647 5 : RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
4648 5 : RunParserSyncTest(strict_function_context_data, arrow_data, kError);
4649 5 : RunParserSyncTest(generator_context_data, arrow_data, kError);
4650 5 : }
4651 :
4652 :
4653 28342 : TEST(SuperNoErrors) {
4654 : // Tests that parser and preparser accept 'super' keyword in right places.
4655 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4656 : {"class C { m() { k = ", "; } }"},
4657 : {"class C { m() { foo(", "); } }"},
4658 : {"class C { m() { () => ", "; } }"},
4659 5 : {nullptr, nullptr}};
4660 :
4661 : const char* statement_data[] = {"super.x", "super[27]",
4662 : "new super.x", "new super.x()",
4663 : "new super[27]", "new super[27]()",
4664 : "z.super", // Ok, property lookup.
4665 5 : nullptr};
4666 :
4667 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
4668 5 : }
4669 :
4670 :
4671 28342 : TEST(SuperErrors) {
4672 : const char* context_data[][2] = {{"class C { m() { ", "; } }"},
4673 : {"class C { m() { k = ", "; } }"},
4674 : {"class C { m() { foo(", "); } }"},
4675 : {"class C { m() { () => ", "; } }"},
4676 5 : {nullptr, nullptr}};
4677 :
4678 : const char* expression_data[] = {"super",
4679 : "super = x",
4680 : "y = super",
4681 : "f(super)",
4682 : "new super",
4683 : "new super()",
4684 : "new super(12, 45)",
4685 : "new new super",
4686 : "new new super()",
4687 : "new new super()()",
4688 5 : nullptr};
4689 :
4690 5 : RunParserSyncTest(context_data, expression_data, kError);
4691 5 : }
4692 :
4693 28342 : TEST(ImportExpressionSuccess) {
4694 : // clang-format off
4695 : const char* context_data[][2] = {
4696 : {"", ""},
4697 : {nullptr, nullptr}
4698 5 : };
4699 :
4700 : const char* data[] = {
4701 : "import(1)",
4702 : "import(y=x)",
4703 : "f(...[import(y=x)])",
4704 : "x = {[import(y=x)]: 1}",
4705 : "var {[import(y=x)]: x} = {}",
4706 : "({[import(y=x)]: x} = {})",
4707 : "async () => { await import(x) }",
4708 : "() => { import(x) }",
4709 : "(import(y=x))",
4710 : "{import(y=x)}",
4711 : "import(import(x))",
4712 : "x = import(x)",
4713 : "var x = import(x)",
4714 : "let x = import(x)",
4715 : "for(x of import(x)) {}",
4716 : "import(x).then()",
4717 : nullptr
4718 5 : };
4719 :
4720 : // clang-format on
4721 :
4722 : // We ignore test error messages because the error message from the
4723 : // parser/preparser is different for the same data depending on the
4724 : // context.
4725 : // For example, a top level "import(" is parsed as an
4726 : // import declaration. The parser parses the import token correctly
4727 : // and then shows an "Unexpected token (" error message. The
4728 : // preparser does not understand the import keyword (this test is
4729 : // run without kAllowHarmonyDynamicImport flag), so this results in
4730 : // an "Unexpected token import" error.
4731 5 : RunParserSyncTest(context_data, data, kError);
4732 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4733 : nullptr, 0, true, true);
4734 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4735 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4736 5 : arraysize(flags));
4737 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
4738 : arraysize(flags));
4739 5 : }
4740 :
4741 28342 : TEST(ImportExpressionErrors) {
4742 : {
4743 : // clang-format off
4744 : const char* context_data[][2] = {
4745 : {"", ""},
4746 : {"var ", ""},
4747 : {"let ", ""},
4748 : {"new ", ""},
4749 : {nullptr, nullptr}
4750 5 : };
4751 :
4752 : const char* data[] = {
4753 : "import(",
4754 : "import)",
4755 : "import()",
4756 : "import('x",
4757 : "import('x']",
4758 : "import['x')",
4759 : "import = x",
4760 : "import[",
4761 : "import[]",
4762 : "import]",
4763 : "import[x]",
4764 : "import{",
4765 : "import{x",
4766 : "import{x}",
4767 : "import(x, y)",
4768 : "import(...y)",
4769 : "import(x,)",
4770 : "import(,)",
4771 : "import(,y)",
4772 : "import(;)",
4773 : "[import]",
4774 : "{import}",
4775 : "import+",
4776 : "import = 1",
4777 : "import.wat",
4778 : "new import(x)",
4779 : nullptr
4780 5 : };
4781 :
4782 : // clang-format on
4783 5 : RunParserSyncTest(context_data, data, kError);
4784 : // We ignore the error messages for the reason explained in the
4785 : // ImportExpressionSuccess test.
4786 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
4787 : nullptr, 0, true, true);
4788 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4789 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4790 5 : arraysize(flags));
4791 :
4792 : // We ignore test error messages because the error message from
4793 : // the parser/preparser is different for the same data depending
4794 : // on the context. For example, a top level "import{" is parsed
4795 : // as an import declaration. The parser parses the import token
4796 : // correctly and then shows an "Unexpected end of input" error
4797 : // message because of the '{'. The preparser shows an "Unexpected
4798 : // token {" because it's not a valid token in a CallExpression.
4799 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4800 : arraysize(flags), nullptr, 0, true, true);
4801 : }
4802 :
4803 : {
4804 : // clang-format off
4805 : const char* context_data[][2] = {
4806 : {"var ", ""},
4807 : {"let ", ""},
4808 : {nullptr, nullptr}
4809 5 : };
4810 :
4811 : const char* data[] = {
4812 : "import('x')",
4813 : nullptr
4814 5 : };
4815 :
4816 : // clang-format on
4817 5 : RunParserSyncTest(context_data, data, kError);
4818 : RunModuleParserSyncTest(context_data, data, kError);
4819 :
4820 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4821 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4822 5 : arraysize(flags));
4823 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4824 : arraysize(flags));
4825 : }
4826 :
4827 : // Import statements as arrow function params and destructuring targets.
4828 : {
4829 : // clang-format off
4830 : const char* context_data[][2] = {
4831 : {"(", ") => {}"},
4832 : {"(a, ", ") => {}"},
4833 : {"(1, ", ") => {}"},
4834 : {"let f = ", " => {}"},
4835 : {"[", "] = [1];"},
4836 : {"{", "} = {'a': 1};"},
4837 : {nullptr, nullptr}
4838 5 : };
4839 :
4840 : const char* data[] = {
4841 : "import(foo)",
4842 : "import(1)",
4843 : "import(y=x)",
4844 : "import(import(x))",
4845 : "import(x).then()",
4846 : nullptr
4847 5 : };
4848 :
4849 : // clang-format on
4850 5 : RunParserSyncTest(context_data, data, kError);
4851 : RunModuleParserSyncTest(context_data, data, kError);
4852 :
4853 : static const ParserFlag flags[] = {kAllowHarmonyDynamicImport};
4854 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4855 5 : arraysize(flags));
4856 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
4857 : arraysize(flags));
4858 : }
4859 5 : }
4860 :
4861 28342 : TEST(SuperCall) {
4862 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
4863 :
4864 : const char* success_data[] = {
4865 : "class C extends B { constructor() { super(); } }",
4866 5 : "class C extends B { constructor() { () => super(); } }", nullptr};
4867 :
4868 5 : RunParserSyncTest(context_data, success_data, kSuccess);
4869 :
4870 : const char* error_data[] = {"class C { constructor() { super(); } }",
4871 : "class C { method() { super(); } }",
4872 : "class C { method() { () => super(); } }",
4873 : "class C { *method() { super(); } }",
4874 : "class C { get x() { super(); } }",
4875 : "class C { set x(_) { super(); } }",
4876 : "({ method() { super(); } })",
4877 : "({ *method() { super(); } })",
4878 : "({ get x() { super(); } })",
4879 : "({ set x(_) { super(); } })",
4880 : "({ f: function() { super(); } })",
4881 : "(function() { super(); })",
4882 : "var f = function() { super(); }",
4883 : "({ f: function*() { super(); } })",
4884 : "(function*() { super(); })",
4885 : "var f = function*() { super(); }",
4886 5 : nullptr};
4887 :
4888 5 : RunParserSyncTest(context_data, error_data, kError);
4889 5 : }
4890 :
4891 :
4892 28342 : TEST(SuperNewNoErrors) {
4893 : const char* context_data[][2] = {{"class C { constructor() { ", " } }"},
4894 : {"class C { *method() { ", " } }"},
4895 : {"class C { get x() { ", " } }"},
4896 : {"class C { set x(_) { ", " } }"},
4897 : {"({ method() { ", " } })"},
4898 : {"({ *method() { ", " } })"},
4899 : {"({ get x() { ", " } })"},
4900 : {"({ set x(_) { ", " } })"},
4901 5 : {nullptr, nullptr}};
4902 :
4903 : const char* expression_data[] = {"new super.x;", "new super.x();",
4904 : "() => new super.x;", "() => new super.x();",
4905 5 : nullptr};
4906 :
4907 5 : RunParserSyncTest(context_data, expression_data, kSuccess);
4908 5 : }
4909 :
4910 :
4911 28342 : TEST(SuperNewErrors) {
4912 : const char* context_data[][2] = {{"class C { method() { ", " } }"},
4913 : {"class C { *method() { ", " } }"},
4914 : {"class C { get x() { ", " } }"},
4915 : {"class C { set x(_) { ", " } }"},
4916 : {"({ method() { ", " } })"},
4917 : {"({ *method() { ", " } })"},
4918 : {"({ get x() { ", " } })"},
4919 : {"({ set x(_) { ", " } })"},
4920 : {"({ f: function() { ", " } })"},
4921 : {"(function() { ", " })"},
4922 : {"var f = function() { ", " }"},
4923 : {"({ f: function*() { ", " } })"},
4924 : {"(function*() { ", " })"},
4925 : {"var f = function*() { ", " }"},
4926 5 : {nullptr, nullptr}};
4927 :
4928 : const char* statement_data[] = {"new super;", "new super();",
4929 : "() => new super;", "() => new super();",
4930 5 : nullptr};
4931 :
4932 5 : RunParserSyncTest(context_data, statement_data, kError);
4933 5 : }
4934 :
4935 :
4936 28342 : TEST(SuperErrorsNonMethods) {
4937 : // super is only allowed in methods, accessors and constructors.
4938 : const char* context_data[][2] = {{"", ";"},
4939 : {"k = ", ";"},
4940 : {"foo(", ");"},
4941 : {"if (", ") {}"},
4942 : {"if (true) {", "}"},
4943 : {"if (false) {} else {", "}"},
4944 : {"while (true) {", "}"},
4945 : {"function f() {", "}"},
4946 : {"class C extends (", ") {}"},
4947 : {"class C { m() { function f() {", "} } }"},
4948 : {"({ m() { function f() {", "} } })"},
4949 5 : {nullptr, nullptr}};
4950 :
4951 : const char* statement_data[] = {
4952 : "super", "super = x", "y = super", "f(super)",
4953 : "super.x", "super[27]", "super.x()", "super[27]()",
4954 : "super()", "new super.x", "new super.x()", "new super[27]",
4955 5 : "new super[27]()", nullptr};
4956 :
4957 5 : RunParserSyncTest(context_data, statement_data, kError);
4958 5 : }
4959 :
4960 :
4961 28342 : TEST(NoErrorsMethodDefinition) {
4962 : const char* context_data[][2] = {{"({", "});"},
4963 : {"'use strict'; ({", "});"},
4964 : {"({*", "});"},
4965 : {"'use strict'; ({*", "});"},
4966 5 : {nullptr, nullptr}};
4967 :
4968 : const char* object_literal_body_data[] = {
4969 : "m() {}", "m(x) { return x; }", "m(x, y) {}, n() {}",
4970 5 : "set(x, y) {}", "get(x, y) {}", nullptr};
4971 :
4972 5 : RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
4973 5 : }
4974 :
4975 :
4976 28342 : TEST(MethodDefinitionNames) {
4977 : const char* context_data[][2] = {{"({", "(x, y) {}});"},
4978 : {"'use strict'; ({", "(x, y) {}});"},
4979 : {"({*", "(x, y) {}});"},
4980 : {"'use strict'; ({*", "(x, y) {}});"},
4981 5 : {nullptr, nullptr}};
4982 :
4983 : const char* name_data[] = {
4984 : "m", "'m'", "\"m\"", "\"m n\"", "true", "false", "null", "0", "1.2",
4985 : "1e1", "1E1", "1e+1", "1e-1",
4986 :
4987 : // Keywords
4988 : "async", "await", "break", "case", "catch", "class", "const", "continue",
4989 : "debugger", "default", "delete", "do", "else", "enum", "export",
4990 : "extends", "finally", "for", "function", "if", "implements", "import",
4991 : "in", "instanceof", "interface", "let", "new", "package", "private",
4992 : "protected", "public", "return", "static", "super", "switch", "this",
4993 : "throw", "try", "typeof", "var", "void", "while", "with", "yield",
4994 5 : nullptr};
4995 :
4996 5 : RunParserSyncTest(context_data, name_data, kSuccess);
4997 5 : }
4998 :
4999 :
5000 28342 : TEST(MethodDefinitionStrictFormalParamereters) {
5001 : const char* context_data[][2] = {{"({method(", "){}});"},
5002 : {"'use strict'; ({method(", "){}});"},
5003 : {"({*method(", "){}});"},
5004 : {"'use strict'; ({*method(", "){}});"},
5005 5 : {nullptr, nullptr}};
5006 :
5007 5 : const char* params_data[] = {"x, x", "x, y, x", "var", "const", nullptr};
5008 :
5009 5 : RunParserSyncTest(context_data, params_data, kError);
5010 5 : }
5011 :
5012 :
5013 28342 : TEST(MethodDefinitionEvalArguments) {
5014 : const char* strict_context_data[][2] = {
5015 : {"'use strict'; ({method(", "){}});"},
5016 : {"'use strict'; ({*method(", "){}});"},
5017 5 : {nullptr, nullptr}};
5018 : const char* sloppy_context_data[][2] = {
5019 5 : {"({method(", "){}});"}, {"({*method(", "){}});"}, {nullptr, nullptr}};
5020 :
5021 5 : const char* data[] = {"eval", "arguments", nullptr};
5022 :
5023 : // Fail in strict mode
5024 5 : RunParserSyncTest(strict_context_data, data, kError);
5025 :
5026 : // OK in sloppy mode
5027 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
5028 5 : }
5029 :
5030 :
5031 28342 : TEST(MethodDefinitionDuplicateEvalArguments) {
5032 : const char* context_data[][2] = {{"'use strict'; ({method(", "){}});"},
5033 : {"'use strict'; ({*method(", "){}});"},
5034 : {"({method(", "){}});"},
5035 : {"({*method(", "){}});"},
5036 5 : {nullptr, nullptr}};
5037 :
5038 : const char* data[] = {"eval, eval", "eval, a, eval", "arguments, arguments",
5039 5 : "arguments, a, arguments", nullptr};
5040 :
5041 : // In strict mode, the error is using "eval" or "arguments" as parameter names
5042 : // In sloppy mode, the error is that eval / arguments are duplicated
5043 5 : RunParserSyncTest(context_data, data, kError);
5044 5 : }
5045 :
5046 :
5047 28342 : TEST(MethodDefinitionDuplicateProperty) {
5048 : const char* context_data[][2] = {{"'use strict'; ({", "});"},
5049 5 : {nullptr, nullptr}};
5050 :
5051 : const char* params_data[] = {"x: 1, x() {}",
5052 : "x() {}, x: 1",
5053 : "x() {}, get x() {}",
5054 : "x() {}, set x(_) {}",
5055 : "x() {}, x() {}",
5056 : "x() {}, y() {}, x() {}",
5057 : "x() {}, \"x\"() {}",
5058 : "x() {}, 'x'() {}",
5059 : "0() {}, '0'() {}",
5060 : "1.0() {}, 1: 1",
5061 :
5062 : "x: 1, *x() {}",
5063 : "*x() {}, x: 1",
5064 : "*x() {}, get x() {}",
5065 : "*x() {}, set x(_) {}",
5066 : "*x() {}, *x() {}",
5067 : "*x() {}, y() {}, *x() {}",
5068 : "*x() {}, *\"x\"() {}",
5069 : "*x() {}, *'x'() {}",
5070 : "*0() {}, *'0'() {}",
5071 : "*1.0() {}, 1: 1",
5072 :
5073 5 : nullptr};
5074 :
5075 5 : RunParserSyncTest(context_data, params_data, kSuccess);
5076 5 : }
5077 :
5078 :
5079 28342 : TEST(ClassExpressionNoErrors) {
5080 : const char* context_data[][2] = {
5081 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
5082 : const char* class_data[] = {"class {}",
5083 : "class name {}",
5084 : "class extends F {}",
5085 : "class name extends F {}",
5086 : "class extends (F, G) {}",
5087 : "class name extends (F, G) {}",
5088 : "class extends class {} {}",
5089 : "class name extends class {} {}",
5090 : "class extends class base {} {}",
5091 : "class name extends class base {} {}",
5092 5 : nullptr};
5093 :
5094 5 : RunParserSyncTest(context_data, class_data, kSuccess);
5095 5 : }
5096 :
5097 :
5098 28342 : TEST(ClassDeclarationNoErrors) {
5099 : const char* context_data[][2] = {{"'use strict'; ", ""},
5100 : {"'use strict'; {", "}"},
5101 : {"'use strict'; if (true) {", "}"},
5102 5 : {nullptr, nullptr}};
5103 : const char* statement_data[] = {"class name {}",
5104 : "class name extends F {}",
5105 : "class name extends (F, G) {}",
5106 : "class name extends class {} {}",
5107 : "class name extends class base {} {}",
5108 5 : nullptr};
5109 :
5110 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
5111 5 : }
5112 :
5113 :
5114 28342 : TEST(ClassBodyNoErrors) {
5115 : // clang-format off
5116 : // Tests that parser and preparser accept valid class syntax.
5117 : const char* context_data[][2] = {{"(class {", "});"},
5118 : {"(class extends Base {", "});"},
5119 : {"class C {", "}"},
5120 : {"class C extends Base {", "}"},
5121 5 : {nullptr, nullptr}};
5122 : const char* class_body_data[] = {
5123 : ";",
5124 : ";;",
5125 : "m() {}",
5126 : "m() {};",
5127 : "; m() {}",
5128 : "m() {}; n(x) {}",
5129 : "get x() {}",
5130 : "set x(v) {}",
5131 : "get() {}",
5132 : "set() {}",
5133 : "*g() {}",
5134 : "*g() {};",
5135 : "; *g() {}",
5136 : "*g() {}; *h(x) {}",
5137 : "async *x(){}",
5138 : "static() {}",
5139 : "get static() {}",
5140 : "set static(v) {}",
5141 : "static m() {}",
5142 : "static get x() {}",
5143 : "static set x(v) {}",
5144 : "static get() {}",
5145 : "static set() {}",
5146 : "static static() {}",
5147 : "static get static() {}",
5148 : "static set static(v) {}",
5149 : "*static() {}",
5150 : "static *static() {}",
5151 : "*get() {}",
5152 : "*set() {}",
5153 : "static *g() {}",
5154 : "async(){}",
5155 : "*async(){}",
5156 : "static async(){}",
5157 : "static *async(){}",
5158 : "static async *x(){}",
5159 :
5160 : // Escaped 'static' should be allowed anywhere
5161 : // static-as-PropertyName is.
5162 : "st\\u0061tic() {}",
5163 : "get st\\u0061tic() {}",
5164 : "set st\\u0061tic(v) {}",
5165 : "static st\\u0061tic() {}",
5166 : "static get st\\u0061tic() {}",
5167 : "static set st\\u0061tic(v) {}",
5168 : "*st\\u0061tic() {}",
5169 : "static *st\\u0061tic() {}",
5170 :
5171 : "static async x(){}",
5172 : "static async(){}",
5173 : "static *async(){}",
5174 : "async x(){}",
5175 : "async 0(){}",
5176 : "async get(){}",
5177 : "async set(){}",
5178 : "async static(){}",
5179 : "async async(){}",
5180 : "async(){}",
5181 : "*async(){}",
5182 5 : nullptr};
5183 : // clang-format on
5184 :
5185 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
5186 5 : }
5187 :
5188 :
5189 28342 : TEST(ClassPropertyNameNoErrors) {
5190 : const char* context_data[][2] = {{"(class {", "() {}});"},
5191 : {"(class { get ", "() {}});"},
5192 : {"(class { set ", "(v) {}});"},
5193 : {"(class { static ", "() {}});"},
5194 : {"(class { static get ", "() {}});"},
5195 : {"(class { static set ", "(v) {}});"},
5196 : {"(class { *", "() {}});"},
5197 : {"(class { static *", "() {}});"},
5198 : {"class C {", "() {}}"},
5199 : {"class C { get ", "() {}}"},
5200 : {"class C { set ", "(v) {}}"},
5201 : {"class C { static ", "() {}}"},
5202 : {"class C { static get ", "() {}}"},
5203 : {"class C { static set ", "(v) {}}"},
5204 : {"class C { *", "() {}}"},
5205 : {"class C { static *", "() {}}"},
5206 5 : {nullptr, nullptr}};
5207 : const char* name_data[] = {
5208 : "42", "42.5", "42e2", "42e+2", "42e-2", "null",
5209 : "false", "true", "'str'", "\"str\"", "static", "get",
5210 : "set", "var", "const", "let", "this", "class",
5211 : "function", "yield", "if", "else", "for", "while",
5212 5 : "do", "try", "catch", "finally", nullptr};
5213 :
5214 5 : RunParserSyncTest(context_data, name_data, kSuccess);
5215 5 : }
5216 :
5217 28342 : TEST(StaticClassFieldsNoErrors) {
5218 : // clang-format off
5219 : // Tests proposed class fields syntax.
5220 : const char* context_data[][2] = {{"(class {", "});"},
5221 : {"(class extends Base {", "});"},
5222 : {"class C {", "}"},
5223 : {"class C extends Base {", "}"},
5224 5 : {nullptr, nullptr}};
5225 : const char* class_body_data[] = {
5226 : // Basic syntax
5227 : "static a = 0;",
5228 : "static a = 0; b",
5229 : "static a = 0; b(){}",
5230 : "static a = 0; *b(){}",
5231 : "static a = 0; ['b'](){}",
5232 : "static a;",
5233 : "static a; b;",
5234 : "static a; b(){}",
5235 : "static a; *b(){}",
5236 : "static a; ['b'](){}",
5237 : "static ['a'] = 0;",
5238 : "static ['a'] = 0; b",
5239 : "static ['a'] = 0; b(){}",
5240 : "static ['a'] = 0; *b(){}",
5241 : "static ['a'] = 0; ['b'](){}",
5242 : "static ['a'];",
5243 : "static ['a']; b;",
5244 : "static ['a']; b(){}",
5245 : "static ['a']; *b(){}",
5246 : "static ['a']; ['b'](){}",
5247 :
5248 : "static 0 = 0;",
5249 : "static 0;",
5250 : "static 'a' = 0;",
5251 : "static 'a';",
5252 :
5253 : "static c = [c] = c",
5254 :
5255 : // ASI
5256 : "static a = 0\n",
5257 : "static a = 0\n b",
5258 : "static a = 0\n b(){}",
5259 : "static a\n",
5260 : "static a\n b\n",
5261 : "static a\n b(){}",
5262 : "static a\n *b(){}",
5263 : "static a\n ['b'](){}",
5264 : "static ['a'] = 0\n",
5265 : "static ['a'] = 0\n b",
5266 : "static ['a'] = 0\n b(){}",
5267 : "static ['a']\n",
5268 : "static ['a']\n b\n",
5269 : "static ['a']\n b(){}",
5270 : "static ['a']\n *b(){}",
5271 : "static ['a']\n ['b'](){}",
5272 :
5273 : "static a = function t() { arguments; }",
5274 : "static a = () => function t() { arguments; }",
5275 :
5276 : // ASI edge cases
5277 : "static a\n get",
5278 : "static get\n *a(){}",
5279 : "static a\n static",
5280 :
5281 : // Misc edge cases
5282 : "static yield",
5283 : "static yield = 0",
5284 : "static yield\n a",
5285 : "static async;",
5286 : "static async = 0;",
5287 : "static async",
5288 : "static async = 0",
5289 : "static async\n a(){}", // a field named async, and a method named a.
5290 : "static async\n a",
5291 : "static await;",
5292 : "static await = 0;",
5293 : "static await\n a",
5294 : nullptr
5295 5 : };
5296 : // clang-format on
5297 :
5298 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5299 : kAllowHarmonyStaticFields};
5300 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5301 5 : always_flags, arraysize(always_flags));
5302 :
5303 : // Without the static flag, all of these are errors
5304 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5305 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5306 5 : no_static_flags, arraysize(no_static_flags));
5307 5 : }
5308 :
5309 28342 : TEST(ClassFieldsNoErrors) {
5310 : // clang-format off
5311 : // Tests proposed class fields syntax.
5312 : const char* context_data[][2] = {{"(class {", "});"},
5313 : {"(class extends Base {", "});"},
5314 : {"class C {", "}"},
5315 : {"class C extends Base {", "}"},
5316 5 : {nullptr, nullptr}};
5317 : const char* class_body_data[] = {
5318 : // Basic syntax
5319 : "a = 0;",
5320 : "a = 0; b",
5321 : "a = 0; b(){}",
5322 : "a = 0; *b(){}",
5323 : "a = 0; ['b'](){}",
5324 : "a;",
5325 : "a; b;",
5326 : "a; b(){}",
5327 : "a; *b(){}",
5328 : "a; ['b'](){}",
5329 : "['a'] = 0;",
5330 : "['a'] = 0; b",
5331 : "['a'] = 0; b(){}",
5332 : "['a'] = 0; *b(){}",
5333 : "['a'] = 0; ['b'](){}",
5334 : "['a'];",
5335 : "['a']; b;",
5336 : "['a']; b(){}",
5337 : "['a']; *b(){}",
5338 : "['a']; ['b'](){}",
5339 :
5340 : "0 = 0;",
5341 : "0;",
5342 : "'a' = 0;",
5343 : "'a';",
5344 :
5345 : "c = [c] = c",
5346 :
5347 : // ASI
5348 : "a = 0\n",
5349 : "a = 0\n b",
5350 : "a = 0\n b(){}",
5351 : "a\n",
5352 : "a\n b\n",
5353 : "a\n b(){}",
5354 : "a\n *b(){}",
5355 : "a\n ['b'](){}",
5356 : "['a'] = 0\n",
5357 : "['a'] = 0\n b",
5358 : "['a'] = 0\n b(){}",
5359 : "['a']\n",
5360 : "['a']\n b\n",
5361 : "['a']\n b(){}",
5362 : "['a']\n *b(){}",
5363 : "['a']\n ['b'](){}",
5364 :
5365 : // ASI edge cases
5366 : "a\n get",
5367 : "get\n *a(){}",
5368 : "a\n static",
5369 :
5370 : "a = function t() { arguments; }",
5371 : "a = () => function() { arguments; }",
5372 :
5373 : // Misc edge cases
5374 : "yield",
5375 : "yield = 0",
5376 : "yield\n a",
5377 : "async;",
5378 : "async = 0;",
5379 : "async",
5380 : "async = 0",
5381 : "async\n a(){}", // a field named async, and a method named a.
5382 : "async\n a",
5383 : "await;",
5384 : "await = 0;",
5385 : "await\n a",
5386 : nullptr
5387 5 : };
5388 : // clang-format on
5389 :
5390 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5391 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5392 5 : always_flags, arraysize(always_flags));
5393 :
5394 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5395 : kAllowHarmonyStaticFields};
5396 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5397 5 : static_flags, arraysize(static_flags));
5398 5 : }
5399 :
5400 28342 : TEST(PrivateMethodsNoErrors) {
5401 : // clang-format off
5402 : // Tests proposed class methods syntax.
5403 : const char* context_data[][2] = {{"(class {", "});"},
5404 : {"(class extends Base {", "});"},
5405 : {"class C {", "}"},
5406 : {"class C extends Base {", "}"},
5407 5 : {nullptr, nullptr}};
5408 : const char* class_body_data[] = {
5409 : // Basic syntax
5410 : "#a() { }",
5411 : "get #a() { }",
5412 : "set #a(foo) { }",
5413 : "*#a() { }",
5414 : "async #a() { }",
5415 : "async *#a() { }",
5416 :
5417 : "#a() { } #b() {}",
5418 : "get #a() { } set #a(foo) {}",
5419 : "get #a() { } get #b() {} set #a(foo) {}",
5420 : "get #a() { } get #b() {} set #a(foo) {} set #b(foo) {}",
5421 : "set #a(foo) { } set #b(foo) {}",
5422 : "get #a() { } get #b() {}",
5423 :
5424 : "#a() { } static a() {}",
5425 : "#a() { } a() {}",
5426 : "#a() { } a() {} static a() {}",
5427 : "get #a() { } get a() {} static get a() {}",
5428 : "set #a(foo) { } set a(foo) {} static set a(foo) {}",
5429 :
5430 : "#a() { } get #b() {}",
5431 : "#a() { } async #b() {}",
5432 : "#a() { } async *#b() {}",
5433 :
5434 : // With arguments
5435 : "#a(...args) { }",
5436 : "#a(a = 1) { }",
5437 : "get #a() { }",
5438 : "set #a(a = (...args) => {}) { }",
5439 :
5440 : // Misc edge cases
5441 : "#get() {}",
5442 : "#set() {}",
5443 : "#yield() {}",
5444 : "#await() {}",
5445 : "#async() {}",
5446 : "#static() {}",
5447 : "#arguments() {}",
5448 : "get #yield() {}",
5449 : "get #await() {}",
5450 : "get #async() {}",
5451 : "get #get() {}",
5452 : "get #static() {}",
5453 : "get #arguments() {}",
5454 : "set #yield(test) {}",
5455 : "set #async(test) {}",
5456 : "set #await(test) {}",
5457 : "set #set(test) {}",
5458 : "set #static(test) {}",
5459 : "set #arguments(test) {}",
5460 : "async #yield() {}",
5461 : "async #async() {}",
5462 : "async #await() {}",
5463 : "async #get() {}",
5464 : "async #set() {}",
5465 : "async #static() {}",
5466 : "async #arguments() {}",
5467 : "*#async() {}",
5468 : "*#await() {}",
5469 : "*#yield() {}",
5470 : "*#get() {}",
5471 : "*#set() {}",
5472 : "*#static() {}",
5473 : "*#arguments() {}",
5474 : "async *#yield() {}",
5475 : "async *#async() {}",
5476 : "async *#await() {}",
5477 : "async *#get() {}",
5478 : "async *#set() {}",
5479 : "async *#static() {}",
5480 : "async *#arguments() {}",
5481 : nullptr
5482 5 : };
5483 : // clang-format on
5484 :
5485 5 : RunParserSyncTest(context_data, class_body_data, kError);
5486 :
5487 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5488 : kAllowHarmonyPrivateMethods};
5489 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5490 5 : private_methods, arraysize(private_methods));
5491 5 : }
5492 :
5493 28342 : TEST(PrivateMethodsAndFieldsNoErrors) {
5494 : // clang-format off
5495 : // Tests proposed class methods syntax in combination with fields
5496 : const char* context_data[][2] = {{"(class {", "});"},
5497 : {"(class extends Base {", "});"},
5498 : {"class C {", "}"},
5499 : {"class C extends Base {", "}"},
5500 5 : {nullptr, nullptr}};
5501 : const char* class_body_data[] = {
5502 : // Basic syntax
5503 : "#b;#a() { }",
5504 : "#b;get #a() { }",
5505 : "#b;set #a(foo) { }",
5506 : "#b;*#a() { }",
5507 : "#b;async #a() { }",
5508 : "#b;async *#a() { }",
5509 : "#b = 1;#a() { }",
5510 : "#b = 1;get #a() { }",
5511 : "#b = 1;set #a(foo) { }",
5512 : "#b = 1;*#a() { }",
5513 : "#b = 1;async #a() { }",
5514 : "#b = 1;async *#a() { }",
5515 :
5516 : // With public fields
5517 : "a;#a() { }",
5518 : "a;get #a() { }",
5519 : "a;set #a(foo) { }",
5520 : "a;*#a() { }",
5521 : "a;async #a() { }",
5522 : "a;async *#a() { }",
5523 : "a = 1;#a() { }",
5524 : "a = 1;get #a() { }",
5525 : "a = 1;set #a(foo) { }",
5526 : "a = 1;*#a() { }",
5527 : "a = 1;async #a() { }",
5528 : "a = 1;async *#a() { }",
5529 :
5530 : // ASI
5531 : "#a = 0\n #b(){}",
5532 : "#a\n *#b(){}",
5533 : "#a = 0\n get #b(){}",
5534 : "#a\n *#b(){}",
5535 :
5536 : "b = 0\n #b(){}",
5537 : "b\n *#b(){}",
5538 : "b = 0\n get #b(){}",
5539 : "b\n *#b(){}",
5540 : nullptr
5541 5 : };
5542 : // clang-format on
5543 :
5544 5 : RunParserSyncTest(context_data, class_body_data, kError);
5545 :
5546 : static const ParserFlag private_methods_and_fields[] = {
5547 : kAllowHarmonyPrivateFields, kAllowHarmonyPublicFields,
5548 : kAllowHarmonyPrivateMethods};
5549 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5550 : private_methods_and_fields,
5551 5 : arraysize(private_methods_and_fields));
5552 5 : }
5553 :
5554 28342 : TEST(PrivateMethodsErrors) {
5555 : // clang-format off
5556 : // Tests proposed class methods syntax in combination with fields
5557 : const char* context_data[][2] = {{"(class {", "});"},
5558 : {"(class extends Base {", "});"},
5559 : {"class C {", "}"},
5560 : {"class C extends Base {", "}"},
5561 5 : {nullptr, nullptr}};
5562 : const char* class_body_data[] = {
5563 : "#a() : 0",
5564 : "#a() =",
5565 : "#a() => {}",
5566 : "#a => {}",
5567 : "*#a() = 0",
5568 : "*#a() => 0",
5569 : "*#a() => {}",
5570 : "get #a()[]",
5571 : "yield #a()[]",
5572 : "yield #a => {}",
5573 : "async #a() = 0",
5574 : "async #a => {}",
5575 : "#a(arguments) {}",
5576 : "set #a(arguments) {}",
5577 :
5578 : "#['a']() { }",
5579 : "get #['a']() { }",
5580 : "set #['a'](foo) { }",
5581 : "*#['a']() { }",
5582 : "async #['a']() { }",
5583 : "async *#['a]() { }",
5584 :
5585 : // TODO(joyee): check duplicate accessors
5586 :
5587 : "#a\n#",
5588 : "#a() c",
5589 : "#a() #",
5590 : "#a(arg) c",
5591 : "#a(arg) #",
5592 : "#a(arg) #c",
5593 : "#a#",
5594 : "#a#b",
5595 : "#a#b(){}",
5596 : "#[test](){}",
5597 :
5598 : "async *#constructor() {}",
5599 : "*#constructor() {}",
5600 : "async #constructor() {}",
5601 : "set #constructor(test) {}",
5602 : "#constructor() {}",
5603 : "get #constructor() {}",
5604 : nullptr
5605 5 : };
5606 : // clang-format on
5607 :
5608 5 : RunParserSyncTest(context_data, class_body_data, kError);
5609 :
5610 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5611 : kAllowHarmonyPrivateMethods};
5612 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5613 5 : private_methods, arraysize(private_methods));
5614 5 : }
5615 :
5616 : // Test that private members do not parse outside class bodies
5617 28342 : TEST(PrivateMembersInNonClassNoErrors) {
5618 : // clang-format off
5619 : const char* context_data[][2] = {{"", ""},
5620 : {"({", "})"},
5621 : {"'use strict'; ({", "});"},
5622 : {"function() {", "}"},
5623 : {"() => {", "}"},
5624 : {"class C { test() {", "} }"},
5625 5 : {nullptr, nullptr}};
5626 : const char* class_body_data[] = {
5627 : "#a = 1",
5628 : "#a = () => {}",
5629 : "#a",
5630 : "#a() { }",
5631 : "get #a() { }",
5632 : "set #a(foo) { }",
5633 : "*#a() { }",
5634 : "async #a() { }",
5635 : "async *#a() { }",
5636 : nullptr
5637 5 : };
5638 : // clang-format on
5639 :
5640 5 : RunParserSyncTest(context_data, class_body_data, kError);
5641 :
5642 : static const ParserFlag private_methods[] = {kAllowHarmonyPrivateFields,
5643 : kAllowHarmonyPrivateMethods};
5644 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5645 5 : private_methods, arraysize(private_methods));
5646 5 : }
5647 :
5648 28342 : TEST(PrivateClassFieldsNoErrors) {
5649 : // clang-format off
5650 : // Tests proposed class fields syntax.
5651 : const char* context_data[][2] = {{"(class {", "});"},
5652 : {"(class extends Base {", "});"},
5653 : {"class C {", "}"},
5654 : {"class C extends Base {", "}"},
5655 5 : {nullptr, nullptr}};
5656 : const char* class_body_data[] = {
5657 : // Basic syntax
5658 : "#a = 0;",
5659 : "#a = 0; #b",
5660 : "#a = 0; b",
5661 : "#a = 0; b(){}",
5662 : "#a = 0; *b(){}",
5663 : "#a = 0; ['b'](){}",
5664 : "#a;",
5665 : "#a; #b;",
5666 : "#a; b;",
5667 : "#a; b(){}",
5668 : "#a; *b(){}",
5669 : "#a; ['b'](){}",
5670 :
5671 : // ASI
5672 : "#a = 0\n",
5673 : "#a = 0\n #b",
5674 : "#a = 0\n b",
5675 : "#a = 0\n b(){}",
5676 : "#a\n",
5677 : "#a\n #b\n",
5678 : "#a\n b\n",
5679 : "#a\n b(){}",
5680 : "#a\n *b(){}",
5681 : "#a\n ['b'](){}",
5682 :
5683 : // ASI edge cases
5684 : "#a\n get",
5685 : "#get\n *a(){}",
5686 : "#a\n static",
5687 :
5688 : "#a = function t() { arguments; }",
5689 : "#a = () => function() { arguments; }",
5690 :
5691 : // Misc edge cases
5692 : "#yield",
5693 : "#yield = 0",
5694 : "#yield\n a",
5695 : "#async;",
5696 : "#async = 0;",
5697 : "#async",
5698 : "#async = 0",
5699 : "#async\n a(){}", // a field named async, and a method named a.
5700 : "#async\n a",
5701 : "#await;",
5702 : "#await = 0;",
5703 : "#await\n a",
5704 : nullptr
5705 5 : };
5706 : // clang-format on
5707 :
5708 5 : RunParserSyncTest(context_data, class_body_data, kError);
5709 :
5710 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5711 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5712 5 : private_fields, arraysize(private_fields));
5713 5 : }
5714 :
5715 28342 : TEST(StaticClassFieldsErrors) {
5716 : // clang-format off
5717 : // Tests proposed class fields syntax.
5718 : const char* context_data[][2] = {{"(class {", "});"},
5719 : {"(class extends Base {", "});"},
5720 : {"class C {", "}"},
5721 : {"class C extends Base {", "}"},
5722 5 : {nullptr, nullptr}};
5723 : const char* class_body_data[] = {
5724 : "static a : 0",
5725 : "static a =",
5726 : "static constructor",
5727 : "static prototype",
5728 : "static *a = 0",
5729 : "static *a",
5730 : "static get a",
5731 : "static get\n a",
5732 : "static yield a",
5733 : "static async a = 0",
5734 : "static async a",
5735 :
5736 : "static a = arguments",
5737 : "static a = () => arguments",
5738 : "static a = () => { arguments }",
5739 : "static a = arguments[0]",
5740 : "static a = delete arguments[0]",
5741 : "static a = f(arguments)",
5742 : "static a = () => () => arguments",
5743 :
5744 : // ASI requires a linebreak
5745 : "static a b",
5746 : "static a = 0 b",
5747 :
5748 : "static c = [1] = [c]",
5749 :
5750 : // ASI requires that the next token is not part of any legal production
5751 : "static a = 0\n *b(){}",
5752 : "static a = 0\n ['b'](){}",
5753 : nullptr
5754 5 : };
5755 : // clang-format on
5756 :
5757 : static const ParserFlag no_static_flags[] = {kAllowHarmonyPublicFields};
5758 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5759 5 : no_static_flags, arraysize(no_static_flags));
5760 :
5761 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields,
5762 : kAllowHarmonyStaticFields};
5763 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5764 5 : always_flags, arraysize(always_flags));
5765 5 : }
5766 :
5767 28342 : TEST(ClassFieldsErrors) {
5768 : // clang-format off
5769 : // Tests proposed class fields syntax.
5770 : const char* context_data[][2] = {{"(class {", "});"},
5771 : {"(class extends Base {", "});"},
5772 : {"class C {", "}"},
5773 : {"class C extends Base {", "}"},
5774 5 : {nullptr, nullptr}};
5775 : const char* class_body_data[] = {
5776 : "a : 0",
5777 : "a =",
5778 : "constructor",
5779 : "*a = 0",
5780 : "*a",
5781 : "get a",
5782 : "yield a",
5783 : "async a = 0",
5784 : "async a",
5785 :
5786 : "a = arguments",
5787 : "a = () => arguments",
5788 : "a = () => { arguments }",
5789 : "a = arguments[0]",
5790 : "a = delete arguments[0]",
5791 : "a = f(arguments)",
5792 : "a = () => () => arguments",
5793 :
5794 : // ASI requires a linebreak
5795 : "a b",
5796 : "a = 0 b",
5797 :
5798 : "c = [1] = [c]",
5799 :
5800 : // ASI requires that the next token is not part of any legal production
5801 : "a = 0\n *b(){}",
5802 : "a = 0\n ['b'](){}",
5803 : "get\n a",
5804 : nullptr
5805 5 : };
5806 : // clang-format on
5807 :
5808 : static const ParserFlag always_flags[] = {kAllowHarmonyPublicFields};
5809 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5810 5 : always_flags, arraysize(always_flags));
5811 :
5812 : static const ParserFlag static_flags[] = {kAllowHarmonyPublicFields,
5813 : kAllowHarmonyStaticFields};
5814 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5815 5 : static_flags, arraysize(static_flags));
5816 5 : }
5817 :
5818 28342 : TEST(PrivateClassFieldsErrors) {
5819 : // clang-format off
5820 : // Tests proposed class fields syntax.
5821 : const char* context_data[][2] = {{"(class {", "});"},
5822 : {"(class extends Base {", "});"},
5823 : {"class C {", "}"},
5824 : {"class C extends Base {", "}"},
5825 5 : {nullptr, nullptr}};
5826 : const char* class_body_data[] = {
5827 : "#a : 0",
5828 : "#a =",
5829 : "#*a = 0",
5830 : "#*a",
5831 : "#get a",
5832 : "#yield a",
5833 : "#async a = 0",
5834 : "#async a",
5835 :
5836 : "#a; #a",
5837 : "#a = 1; #a",
5838 : "#a; #a = 1;",
5839 :
5840 : "#constructor",
5841 : "#constructor = function() {}",
5842 :
5843 : "# a = 0",
5844 : "#a() { }",
5845 : "get #a() { }",
5846 : "#get a() { }",
5847 : "set #a() { }",
5848 : "#set a() { }",
5849 : "*#a() { }",
5850 : "#*a() { }",
5851 : "async #a() { }",
5852 : "async *#a() { }",
5853 : "async #*a() { }",
5854 :
5855 : "#0 = 0;",
5856 : "#0;",
5857 : "#'a' = 0;",
5858 : "#'a';",
5859 :
5860 : "#['a']",
5861 : "#['a'] = 1",
5862 : "#[a]",
5863 : "#[a] = 1",
5864 :
5865 : "#a = arguments",
5866 : "#a = () => arguments",
5867 : "#a = () => { arguments }",
5868 : "#a = arguments[0]",
5869 : "#a = delete arguments[0]",
5870 : "#a = f(arguments)",
5871 : "#a = () => () => arguments",
5872 :
5873 : "foo() { delete this.#a }",
5874 : "foo() { delete this.x.#a }",
5875 : "foo() { delete this.x().#a }",
5876 :
5877 : "foo() { delete f.#a }",
5878 : "foo() { delete f.x.#a }",
5879 : "foo() { delete f.x().#a }",
5880 :
5881 : // ASI requires a linebreak
5882 : "#a b",
5883 : "#a = 0 b",
5884 :
5885 : // ASI requires that the next token is not part of any legal production
5886 : "#a = 0\n *b(){}",
5887 : "#a = 0\n ['b'](){}",
5888 : nullptr
5889 5 : };
5890 : // clang-format on
5891 :
5892 5 : RunParserSyncTest(context_data, class_body_data, kError);
5893 :
5894 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
5895 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5896 5 : private_fields, arraysize(private_fields));
5897 5 : }
5898 :
5899 28342 : TEST(PrivateStaticClassFieldsNoErrors) {
5900 : // clang-format off
5901 : // Tests proposed class fields syntax.
5902 : const char* context_data[][2] = {{"(class {", "});"},
5903 : {"(class extends Base {", "});"},
5904 : {"class C {", "}"},
5905 : {"class C extends Base {", "}"},
5906 5 : {nullptr, nullptr}};
5907 : const char* class_body_data[] = {
5908 : // Basic syntax
5909 : "static #a = 0;",
5910 : "static #a = 0; b",
5911 : "static #a = 0; #b",
5912 : "static #a = 0; b(){}",
5913 : "static #a = 0; *b(){}",
5914 : "static #a = 0; ['b'](){}",
5915 : "static #a;",
5916 : "static #a; b;",
5917 : "static #a; b(){}",
5918 : "static #a; *b(){}",
5919 : "static #a; ['b'](){}",
5920 :
5921 : "#prototype",
5922 : "#prototype = function() {}",
5923 :
5924 : // ASI
5925 : "static #a = 0\n",
5926 : "static #a = 0\n b",
5927 : "static #a = 0\n #b",
5928 : "static #a = 0\n b(){}",
5929 : "static #a\n",
5930 : "static #a\n b\n",
5931 : "static #a\n #b\n",
5932 : "static #a\n b(){}",
5933 : "static #a\n *b(){}",
5934 : "static #a\n ['b'](){}",
5935 :
5936 : "static #a = function t() { arguments; }",
5937 : "static #a = () => function t() { arguments; }",
5938 :
5939 : // ASI edge cases
5940 : "static #a\n get",
5941 : "static #get\n *a(){}",
5942 : "static #a\n static",
5943 :
5944 : // Misc edge cases
5945 : "static #yield",
5946 : "static #yield = 0",
5947 : "static #yield\n a",
5948 : "static #async;",
5949 : "static #async = 0;",
5950 : "static #async",
5951 : "static #async = 0",
5952 : "static #async\n a(){}", // a field named async, and a method named a.
5953 : "static #async\n a",
5954 : "static #await;",
5955 : "static #await = 0;",
5956 : "static #await\n a",
5957 : nullptr
5958 5 : };
5959 : // clang-format on
5960 :
5961 5 : RunParserSyncTest(context_data, class_body_data, kError);
5962 :
5963 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
5964 : kAllowHarmonyStaticFields};
5965 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
5966 5 : public_static_fields, arraysize(public_static_fields));
5967 :
5968 : static const ParserFlag private_static_fields[] = {
5969 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
5970 : kAllowHarmonyPrivateFields};
5971 : RunParserSyncTest(context_data, class_body_data, kSuccess, nullptr, 0,
5972 5 : private_static_fields, arraysize(private_static_fields));
5973 5 : }
5974 :
5975 28342 : TEST(PrivateStaticClassFieldsErrors) {
5976 : // clang-format off
5977 : // Tests proposed class fields syntax.
5978 : const char* context_data[][2] = {{"(class {", "});"},
5979 : {"(class extends Base {", "});"},
5980 : {"class C {", "}"},
5981 : {"class C extends Base {", "}"},
5982 5 : {nullptr, nullptr}};
5983 : const char* class_body_data[] = {
5984 : // Basic syntax
5985 : "static #['a'] = 0;",
5986 : "static #['a'] = 0; b",
5987 : "static #['a'] = 0; #b",
5988 : "static #['a'] = 0; b(){}",
5989 : "static #['a'] = 0; *b(){}",
5990 : "static #['a'] = 0; ['b'](){}",
5991 : "static #['a'];",
5992 : "static #['a']; b;",
5993 : "static #['a']; #b;",
5994 : "static #['a']; b(){}",
5995 : "static #['a']; *b(){}",
5996 : "static #['a']; ['b'](){}",
5997 :
5998 : "static #0 = 0;",
5999 : "static #0;",
6000 : "static #'a' = 0;",
6001 : "static #'a';",
6002 :
6003 : "static # a = 0",
6004 : "static #get a() { }",
6005 : "static #set a() { }",
6006 : "static #*a() { }",
6007 : "static async #*a() { }",
6008 :
6009 : "#a = arguments",
6010 : "#a = () => arguments",
6011 : "#a = () => { arguments }",
6012 : "#a = arguments[0]",
6013 : "#a = delete arguments[0]",
6014 : "#a = f(arguments)",
6015 : "#a = () => () => arguments",
6016 :
6017 : "#a; static #a",
6018 : "static #a; #a",
6019 :
6020 : // TODO(joyee): support static private methods
6021 : "static #a() { }",
6022 : "static get #a() { }",
6023 : "static set #a() { }",
6024 : "static *#a() { }",
6025 : "static async #a() { }",
6026 : "static async *#a() { }",
6027 :
6028 : // ASI
6029 : "static #['a'] = 0\n",
6030 : "static #['a'] = 0\n b",
6031 : "static #['a'] = 0\n #b",
6032 : "static #['a'] = 0\n b(){}",
6033 : "static #['a']\n",
6034 : "static #['a']\n b\n",
6035 : "static #['a']\n #b\n",
6036 : "static #['a']\n b(){}",
6037 : "static #['a']\n *b(){}",
6038 : "static #['a']\n ['b'](){}",
6039 :
6040 : // ASI requires a linebreak
6041 : "static #a b",
6042 : "static #a = 0 b",
6043 :
6044 : // ASI requires that the next token is not part of any legal production
6045 : "static #a = 0\n *b(){}",
6046 : "static #a = 0\n ['b'](){}",
6047 :
6048 : "static #a : 0",
6049 : "static #a =",
6050 : "static #*a = 0",
6051 : "static #*a",
6052 : "static #get a",
6053 : "static #yield a",
6054 : "static #async a = 0",
6055 : "static #async a",
6056 : "static # a = 0",
6057 :
6058 : "#constructor",
6059 : "#constructor = function() {}",
6060 :
6061 : "foo() { delete this.#a }",
6062 : "foo() { delete this.x.#a }",
6063 : "foo() { delete this.x().#a }",
6064 :
6065 : "foo() { delete f.#a }",
6066 : "foo() { delete f.x.#a }",
6067 : "foo() { delete f.x().#a }",
6068 : nullptr
6069 5 : };
6070 : // clang-format on
6071 :
6072 5 : RunParserSyncTest(context_data, class_body_data, kError);
6073 :
6074 : static const ParserFlag public_static_fields[] = {kAllowHarmonyPublicFields,
6075 : kAllowHarmonyStaticFields};
6076 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6077 5 : public_static_fields, arraysize(public_static_fields));
6078 :
6079 : static const ParserFlag private_static_fields[] = {
6080 : kAllowHarmonyPublicFields, kAllowHarmonyStaticFields,
6081 : kAllowHarmonyPrivateFields};
6082 : RunParserSyncTest(context_data, class_body_data, kError, nullptr, 0,
6083 5 : private_static_fields, arraysize(private_static_fields));
6084 5 : }
6085 :
6086 28342 : TEST(PrivateNameNoErrors) {
6087 : // clang-format off
6088 : const char* context_data[][2] = {
6089 : {"", ""},
6090 : {"\"use strict\";", ""},
6091 : {nullptr, nullptr}
6092 5 : };
6093 :
6094 : const char* statement_data[] = {
6095 : "this.#a",
6096 : "this.#a()",
6097 : "this.#b.#a",
6098 : "this.#b.#a()",
6099 :
6100 : "foo.#a",
6101 : "foo.#a()",
6102 : "foo.#b.#a",
6103 : "foo.#b.#a()",
6104 :
6105 : "foo().#a",
6106 : "foo().b.#a",
6107 : "foo().b().#a",
6108 : "foo().b().#a()",
6109 : "foo().b().#a.bar",
6110 : "foo().b().#a.bar()",
6111 :
6112 : "foo(this.#a)",
6113 : "foo(bar().#a)",
6114 :
6115 : "new foo.#a",
6116 : "new foo.#b.#a",
6117 : "new foo.#b.#a()",
6118 :
6119 : "foo.#if;",
6120 : "foo.#yield;",
6121 : "foo.#super;",
6122 : "foo.#interface;",
6123 : "foo.#eval;",
6124 : "foo.#arguments;",
6125 :
6126 : nullptr
6127 5 : };
6128 :
6129 : // clang-format on
6130 5 : RunParserSyncTest(context_data, statement_data, kError);
6131 :
6132 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6133 : RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
6134 5 : private_fields, arraysize(private_fields));
6135 5 : }
6136 :
6137 28342 : TEST(PrivateNameErrors) {
6138 : // clang-format off
6139 : const char* context_data[][2] = {
6140 : {"", ""},
6141 : {"\"use strict\";", ""},
6142 : {nullptr, nullptr}
6143 5 : };
6144 :
6145 : const char* statement_data[] = {
6146 : "#foo",
6147 : "#foo = 1",
6148 :
6149 : "# a;",
6150 : "#\n a;",
6151 : "a, # b",
6152 : "a, #, b;",
6153 :
6154 : "foo.#[a];",
6155 : "foo.#['a'];",
6156 :
6157 : "foo()#a",
6158 : "foo()#[a]",
6159 : "foo()#['a']",
6160 :
6161 : "super.#a;",
6162 : "super.#a = 1;",
6163 : "super.#['a']",
6164 : "super.#[a]",
6165 :
6166 : "new.#a",
6167 : "new.#[a]",
6168 :
6169 : "foo.#{;",
6170 : "foo.#};",
6171 : "foo.#=;",
6172 : "foo.#888;",
6173 : "foo.#-;",
6174 : "foo.#--;",
6175 : nullptr
6176 5 : };
6177 :
6178 : // clang-format on
6179 5 : RunParserSyncTest(context_data, statement_data, kError);
6180 :
6181 : static const ParserFlag private_fields[] = {kAllowHarmonyPrivateFields};
6182 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0,
6183 5 : private_fields, arraysize(private_fields));
6184 5 : }
6185 :
6186 28342 : TEST(ClassExpressionErrors) {
6187 : const char* context_data[][2] = {
6188 5 : {"(", ");"}, {"var C = ", ";"}, {"bar, ", ";"}, {nullptr, nullptr}};
6189 : const char* class_data[] = {
6190 : "class",
6191 : "class name",
6192 : "class name extends",
6193 : "class extends",
6194 : "class {",
6195 : "class { m }",
6196 : "class { m; n }",
6197 : "class { m: 1 }",
6198 : "class { m(); n() }",
6199 : "class { get m }",
6200 : "class { get m() }",
6201 : "class { get m() { }",
6202 : "class { set m() {} }", // Missing required parameter.
6203 : "class { m() {}, n() {} }", // No commas allowed.
6204 5 : nullptr};
6205 :
6206 5 : RunParserSyncTest(context_data, class_data, kError);
6207 5 : }
6208 :
6209 :
6210 28342 : TEST(ClassDeclarationErrors) {
6211 : const char* context_data[][2] = {
6212 5 : {"", ""}, {"{", "}"}, {"if (true) {", "}"}, {nullptr, nullptr}};
6213 : const char* class_data[] = {
6214 : "class",
6215 : "class name",
6216 : "class name extends",
6217 : "class extends",
6218 : "class name {",
6219 : "class name { m }",
6220 : "class name { m; n }",
6221 : "class name { m: 1 }",
6222 : "class name { m(); n() }",
6223 : "class name { get x }",
6224 : "class name { get x() }",
6225 : "class name { set x() {) }", // missing required param
6226 : "class {}", // Name is required for declaration
6227 : "class extends base {}",
6228 : "class name { *",
6229 : "class name { * }",
6230 : "class name { *; }",
6231 : "class name { *get x() {} }",
6232 : "class name { *set x(_) {} }",
6233 : "class name { *static m() {} }",
6234 5 : nullptr};
6235 :
6236 5 : RunParserSyncTest(context_data, class_data, kError);
6237 5 : }
6238 :
6239 28342 : TEST(ClassAsyncErrors) {
6240 : // clang-format off
6241 : const char* context_data[][2] = {{"(class {", "});"},
6242 : {"(class extends Base {", "});"},
6243 : {"class C {", "}"},
6244 : {"class C extends Base {", "}"},
6245 5 : {nullptr, nullptr}};
6246 : const char* async_data[] = {
6247 : "*async x(){}",
6248 : "async *(){}",
6249 : "async get x(){}",
6250 : "async set x(y){}",
6251 : "async x : 0",
6252 : "async : 0",
6253 :
6254 : "async static x(){}",
6255 :
6256 : "static *async x(){}",
6257 : "static async *(){}",
6258 : "static async get x(){}",
6259 : "static async set x(y){}",
6260 : "static async x : 0",
6261 : "static async : 0",
6262 : nullptr
6263 5 : };
6264 : // clang-format on
6265 :
6266 5 : RunParserSyncTest(context_data, async_data, kError);
6267 5 : }
6268 :
6269 28342 : TEST(ClassNameErrors) {
6270 : const char* context_data[][2] = {{"class ", "{}"},
6271 : {"(class ", "{});"},
6272 : {"'use strict'; class ", "{}"},
6273 : {"'use strict'; (class ", "{});"},
6274 5 : {nullptr, nullptr}};
6275 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6276 : "let", "package", "private", "protected",
6277 : "public", "static", "var", "yield",
6278 5 : nullptr};
6279 :
6280 5 : RunParserSyncTest(context_data, class_name, kError);
6281 5 : }
6282 :
6283 :
6284 28342 : TEST(ClassGetterParamNameErrors) {
6285 : const char* context_data[][2] = {
6286 : {"class C { get name(", ") {} }"},
6287 : {"(class { get name(", ") {} });"},
6288 : {"'use strict'; class C { get name(", ") {} }"},
6289 : {"'use strict'; (class { get name(", ") {} })"},
6290 5 : {nullptr, nullptr}};
6291 :
6292 : const char* class_name[] = {"arguments", "eval", "implements", "interface",
6293 : "let", "package", "private", "protected",
6294 : "public", "static", "var", "yield",
6295 5 : nullptr};
6296 :
6297 5 : RunParserSyncTest(context_data, class_name, kError);
6298 5 : }
6299 :
6300 :
6301 28342 : TEST(ClassStaticPrototypeErrors) {
6302 : const char* context_data[][2] = {
6303 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6304 :
6305 : const char* class_body_data[] = {"static prototype() {}",
6306 : "static get prototype() {}",
6307 : "static set prototype(_) {}",
6308 : "static *prototype() {}",
6309 : "static 'prototype'() {}",
6310 : "static *'prototype'() {}",
6311 : "static prot\\u006ftype() {}",
6312 : "static 'prot\\u006ftype'() {}",
6313 : "static get 'prot\\u006ftype'() {}",
6314 : "static set 'prot\\u006ftype'(_) {}",
6315 : "static *'prot\\u006ftype'() {}",
6316 5 : nullptr};
6317 :
6318 5 : RunParserSyncTest(context_data, class_body_data, kError);
6319 5 : }
6320 :
6321 :
6322 28342 : TEST(ClassSpecialConstructorErrors) {
6323 : const char* context_data[][2] = {
6324 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6325 :
6326 : const char* class_body_data[] = {"get constructor() {}",
6327 : "get constructor(_) {}",
6328 : "*constructor() {}",
6329 : "get 'constructor'() {}",
6330 : "*'constructor'() {}",
6331 : "get c\\u006fnstructor() {}",
6332 : "*c\\u006fnstructor() {}",
6333 : "get 'c\\u006fnstructor'() {}",
6334 : "get 'c\\u006fnstructor'(_) {}",
6335 : "*'c\\u006fnstructor'() {}",
6336 5 : nullptr};
6337 :
6338 5 : RunParserSyncTest(context_data, class_body_data, kError);
6339 5 : }
6340 :
6341 :
6342 28342 : TEST(ClassConstructorNoErrors) {
6343 : const char* context_data[][2] = {
6344 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6345 :
6346 : const char* class_body_data[] = {"constructor() {}",
6347 : "static constructor() {}",
6348 : "static get constructor() {}",
6349 : "static set constructor(_) {}",
6350 : "static *constructor() {}",
6351 5 : nullptr};
6352 :
6353 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6354 5 : }
6355 :
6356 :
6357 28342 : TEST(ClassMultipleConstructorErrors) {
6358 : const char* context_data[][2] = {
6359 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6360 :
6361 : const char* class_body_data[] = {"constructor() {}; constructor() {}",
6362 5 : nullptr};
6363 :
6364 5 : RunParserSyncTest(context_data, class_body_data, kError);
6365 5 : }
6366 :
6367 :
6368 28342 : TEST(ClassMultiplePropertyNamesNoErrors) {
6369 : const char* context_data[][2] = {
6370 5 : {"class C {", "}"}, {"(class {", "});"}, {nullptr, nullptr}};
6371 :
6372 : const char* class_body_data[] = {
6373 : "constructor() {}; static constructor() {}",
6374 : "m() {}; static m() {}",
6375 : "m() {}; m() {}",
6376 : "static m() {}; static m() {}",
6377 : "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
6378 5 : nullptr};
6379 :
6380 5 : RunParserSyncTest(context_data, class_body_data, kSuccess);
6381 5 : }
6382 :
6383 :
6384 28342 : TEST(ClassesAreStrictErrors) {
6385 5 : const char* context_data[][2] = {{"", ""}, {"(", ");"}, {nullptr, nullptr}};
6386 :
6387 : const char* class_body_data[] = {
6388 : "class C { method() { with ({}) {} } }",
6389 : "class C extends function() { with ({}) {} } {}",
6390 5 : "class C { *method() { with ({}) {} } }", nullptr};
6391 :
6392 5 : RunParserSyncTest(context_data, class_body_data, kError);
6393 5 : }
6394 :
6395 :
6396 28342 : TEST(ObjectLiteralPropertyShorthandKeywordsError) {
6397 : const char* context_data[][2] = {
6398 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6399 :
6400 : const char* name_data[] = {
6401 : "break", "case", "catch", "class", "const", "continue",
6402 : "debugger", "default", "delete", "do", "else", "enum",
6403 : "export", "extends", "false", "finally", "for", "function",
6404 : "if", "import", "in", "instanceof", "new", "null",
6405 : "return", "super", "switch", "this", "throw", "true",
6406 : "try", "typeof", "var", "void", "while", "with",
6407 5 : nullptr};
6408 :
6409 5 : RunParserSyncTest(context_data, name_data, kError);
6410 5 : }
6411 :
6412 :
6413 28342 : TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
6414 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
6415 :
6416 : const char* name_data[] = {"implements", "interface", "let", "package",
6417 : "private", "protected", "public", "static",
6418 5 : "yield", nullptr};
6419 :
6420 5 : RunParserSyncTest(context_data, name_data, kSuccess);
6421 :
6422 : const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
6423 5 : {nullptr, nullptr}};
6424 5 : RunParserSyncTest(context_strict_data, name_data, kError);
6425 5 : }
6426 :
6427 :
6428 28342 : TEST(ObjectLiteralPropertyShorthandError) {
6429 : const char* context_data[][2] = {
6430 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
6431 :
6432 : const char* name_data[] = {"1", "1.2", "0", "0.1", "1.0",
6433 5 : "1e1", "0x1", "\"s\"", "'s'", nullptr};
6434 :
6435 5 : RunParserSyncTest(context_data, name_data, kError);
6436 5 : }
6437 :
6438 :
6439 28342 : TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
6440 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6441 :
6442 5 : const char* name_data[] = {"function* g() { ({yield}); }", nullptr};
6443 :
6444 5 : RunParserSyncTest(context_data, name_data, kError);
6445 5 : }
6446 :
6447 :
6448 28342 : TEST(ConstParsingInForIn) {
6449 : const char* context_data[][2] = {{"'use strict';", ""},
6450 : {"function foo(){ 'use strict';", "}"},
6451 5 : {nullptr, nullptr}};
6452 :
6453 : const char* data[] = {
6454 : "for(const x = 1; ; ) {}", "for(const x = 1, y = 2;;){}",
6455 5 : "for(const x in [1,2,3]) {}", "for(const x of [1,2,3]) {}", nullptr};
6456 5 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
6457 5 : }
6458 :
6459 :
6460 28342 : TEST(StatementParsingInForIn) {
6461 : const char* context_data[][2] = {{"", ""},
6462 : {"'use strict';", ""},
6463 : {"function foo(){ 'use strict';", "}"},
6464 5 : {nullptr, nullptr}};
6465 :
6466 : const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
6467 : "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
6468 5 : nullptr};
6469 :
6470 5 : RunParserSyncTest(context_data, data, kSuccess);
6471 5 : }
6472 :
6473 :
6474 28342 : TEST(ConstParsingInForInError) {
6475 : const char* context_data[][2] = {{"'use strict';", ""},
6476 : {"function foo(){ 'use strict';", "}"},
6477 5 : {nullptr, nullptr}};
6478 :
6479 : const char* data[] = {
6480 : "for(const x,y = 1; ; ) {}", "for(const x = 4 in [1,2,3]) {}",
6481 : "for(const x = 4, y in [1,2,3]) {}", "for(const x = 4 of [1,2,3]) {}",
6482 : "for(const x = 4, y of [1,2,3]) {}", "for(const x = 1, y = 2 in []) {}",
6483 : "for(const x,y in []) {}", "for(const x = 1, y = 2 of []) {}",
6484 5 : "for(const x,y of []) {}", nullptr};
6485 5 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
6486 5 : }
6487 :
6488 28342 : TEST(InitializedDeclarationsInForInOf) {
6489 : // https://tc39.github.io/ecma262/#sec-initializers-in-forin-statement-heads
6490 :
6491 : // Initialized declarations only allowed for
6492 : // - sloppy mode (not strict mode)
6493 : // - for-in (not for-of)
6494 : // - var (not let / const)
6495 :
6496 : // clang-format off
6497 : const char* strict_context[][2] = {{"'use strict';", ""},
6498 : {"function foo(){ 'use strict';", "}"},
6499 : {"function* foo(){ 'use strict';", "}"},
6500 5 : {nullptr, nullptr}};
6501 :
6502 : const char* sloppy_context[][2] = {{"", ""},
6503 : {"function foo(){ ", "}"},
6504 : {"function* foo(){ ", "}"},
6505 : {"function foo(){ var yield = 0; ", "}"},
6506 5 : {nullptr, nullptr}};
6507 :
6508 : const char* let_const_var_for_of[] = {
6509 : "for (let i = 1 of {}) {}",
6510 : "for (let i = void 0 of [1, 2, 3]) {}",
6511 : "for (const i = 1 of {}) {}",
6512 : "for (const i = void 0 of [1, 2, 3]) {}",
6513 : "for (var i = 1 of {}) {}",
6514 : "for (var i = void 0 of [1, 2, 3]) {}",
6515 5 : nullptr};
6516 :
6517 : const char* let_const_for_in[] = {
6518 : "for (let i = 1 in {}) {}",
6519 : "for (let i = void 0 in [1, 2, 3]) {}",
6520 : "for (const i = 1 in {}) {}",
6521 : "for (const i = void 0 in [1, 2, 3]) {}",
6522 5 : nullptr};
6523 :
6524 : const char* var_for_in[] = {
6525 : "for (var i = 1 in {}) {}",
6526 : "for (var i = void 0 in [1, 2, 3]) {}",
6527 : "for (var i = yield in [1, 2, 3]) {}",
6528 5 : nullptr};
6529 : // clang-format on
6530 :
6531 : // The only allowed case is sloppy + var + for-in.
6532 5 : RunParserSyncTest(sloppy_context, var_for_in, kSuccess);
6533 :
6534 : // Everything else is disallowed.
6535 5 : RunParserSyncTest(sloppy_context, let_const_var_for_of, kError);
6536 5 : RunParserSyncTest(sloppy_context, let_const_for_in, kError);
6537 :
6538 5 : RunParserSyncTest(strict_context, let_const_var_for_of, kError);
6539 5 : RunParserSyncTest(strict_context, let_const_for_in, kError);
6540 5 : RunParserSyncTest(strict_context, var_for_in, kError);
6541 5 : }
6542 :
6543 28342 : TEST(ForInMultipleDeclarationsError) {
6544 : const char* context_data[][2] = {{"", ""},
6545 : {"function foo(){", "}"},
6546 : {"'use strict';", ""},
6547 : {"function foo(){ 'use strict';", "}"},
6548 5 : {nullptr, nullptr}};
6549 :
6550 : const char* data[] = {"for (var i, j in {}) {}",
6551 : "for (var i, j in [1, 2, 3]) {}",
6552 : "for (var i, j = 1 in {}) {}",
6553 : "for (var i, j = void 0 in [1, 2, 3]) {}",
6554 :
6555 : "for (let i, j in {}) {}",
6556 : "for (let i, j in [1, 2, 3]) {}",
6557 : "for (let i, j = 1 in {}) {}",
6558 : "for (let i, j = void 0 in [1, 2, 3]) {}",
6559 :
6560 : "for (const i, j in {}) {}",
6561 : "for (const i, j in [1, 2, 3]) {}",
6562 : "for (const i, j = 1 in {}) {}",
6563 : "for (const i, j = void 0 in [1, 2, 3]) {}",
6564 5 : nullptr};
6565 5 : RunParserSyncTest(context_data, data, kError);
6566 5 : }
6567 :
6568 :
6569 28342 : TEST(ForOfMultipleDeclarationsError) {
6570 : const char* context_data[][2] = {{"", ""},
6571 : {"function foo(){", "}"},
6572 : {"'use strict';", ""},
6573 : {"function foo(){ 'use strict';", "}"},
6574 5 : {nullptr, nullptr}};
6575 :
6576 : const char* data[] = {"for (var i, j of {}) {}",
6577 : "for (var i, j of [1, 2, 3]) {}",
6578 : "for (var i, j = 1 of {}) {}",
6579 : "for (var i, j = void 0 of [1, 2, 3]) {}",
6580 :
6581 : "for (let i, j of {}) {}",
6582 : "for (let i, j of [1, 2, 3]) {}",
6583 : "for (let i, j = 1 of {}) {}",
6584 : "for (let i, j = void 0 of [1, 2, 3]) {}",
6585 :
6586 : "for (const i, j of {}) {}",
6587 : "for (const i, j of [1, 2, 3]) {}",
6588 : "for (const i, j = 1 of {}) {}",
6589 : "for (const i, j = void 0 of [1, 2, 3]) {}",
6590 5 : nullptr};
6591 5 : RunParserSyncTest(context_data, data, kError);
6592 5 : }
6593 :
6594 :
6595 28342 : TEST(ForInNoDeclarationsError) {
6596 : const char* context_data[][2] = {{"", ""},
6597 : {"function foo(){", "}"},
6598 : {"'use strict';", ""},
6599 : {"function foo(){ 'use strict';", "}"},
6600 5 : {nullptr, nullptr}};
6601 :
6602 5 : const char* data[] = {"for (var in {}) {}", "for (const in {}) {}", nullptr};
6603 5 : RunParserSyncTest(context_data, data, kError);
6604 5 : }
6605 :
6606 :
6607 28342 : TEST(ForOfNoDeclarationsError) {
6608 : const char* context_data[][2] = {{"", ""},
6609 : {"function foo(){", "}"},
6610 : {"'use strict';", ""},
6611 : {"function foo(){ 'use strict';", "}"},
6612 5 : {nullptr, nullptr}};
6613 :
6614 : const char* data[] = {"for (var of [1, 2, 3]) {}",
6615 5 : "for (const of [1, 2, 3]) {}", nullptr};
6616 5 : RunParserSyncTest(context_data, data, kError);
6617 5 : }
6618 :
6619 :
6620 28342 : TEST(ForOfInOperator) {
6621 : const char* context_data[][2] = {{"", ""},
6622 : {"'use strict';", ""},
6623 : {"function foo(){ 'use strict';", "}"},
6624 5 : {nullptr, nullptr}};
6625 :
6626 : const char* data[] = {"for(x of 'foo' in {}) {}",
6627 : "for(var x of 'foo' in {}) {}",
6628 : "for(let x of 'foo' in {}) {}",
6629 5 : "for(const x of 'foo' in {}) {}", nullptr};
6630 :
6631 5 : RunParserSyncTest(context_data, data, kSuccess);
6632 5 : }
6633 :
6634 :
6635 28342 : TEST(ForOfYieldIdentifier) {
6636 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
6637 :
6638 : const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
6639 : "for(let x of yield) {}", "for(const x of yield) {}",
6640 5 : nullptr};
6641 :
6642 5 : RunParserSyncTest(context_data, data, kSuccess);
6643 5 : }
6644 :
6645 :
6646 28342 : TEST(ForOfYieldExpression) {
6647 : const char* context_data[][2] = {{"", ""},
6648 : {"'use strict';", ""},
6649 : {"function foo(){ 'use strict';", "}"},
6650 5 : {nullptr, nullptr}};
6651 :
6652 : const char* data[] = {"function* g() { for(x of yield) {} }",
6653 : "function* g() { for(var x of yield) {} }",
6654 : "function* g() { for(let x of yield) {} }",
6655 5 : "function* g() { for(const x of yield) {} }", nullptr};
6656 :
6657 5 : RunParserSyncTest(context_data, data, kSuccess);
6658 5 : }
6659 :
6660 :
6661 28342 : TEST(ForOfExpressionError) {
6662 : const char* context_data[][2] = {{"", ""},
6663 : {"'use strict';", ""},
6664 : {"function foo(){ 'use strict';", "}"},
6665 5 : {nullptr, nullptr}};
6666 :
6667 : const char* data[] = {
6668 : "for(x of [], []) {}", "for(var x of [], []) {}",
6669 : "for(let x of [], []) {}", "for(const x of [], []) {}",
6670 :
6671 : // AssignmentExpression should be validated statically:
6672 : "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
6673 5 : "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", nullptr};
6674 :
6675 5 : RunParserSyncTest(context_data, data, kError);
6676 5 : }
6677 :
6678 :
6679 28342 : TEST(InvalidUnicodeEscapes) {
6680 : const char* context_data[][2] = {
6681 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6682 : const char* data[] = {
6683 : "var foob\\u123r = 0;", "var \\u123roo = 0;", "\"foob\\u123rr\"",
6684 : // No escapes allowed in regexp flags
6685 : "/regex/\\u0069g", "/regex/\\u006g",
6686 : // Braces gone wrong
6687 : "var foob\\u{c481r = 0;", "var foob\\uc481}r = 0;", "var \\u{0052oo = 0;",
6688 : "var \\u0052}oo = 0;", "\"foob\\u{c481r\"", "var foob\\u{}ar = 0;",
6689 : // Too high value for the Unicode code point escape
6690 : "\"\\u{110000}\"",
6691 : // Not a Unicode code point escape
6692 : "var foob\\v1234r = 0;", "var foob\\U1234r = 0;",
6693 5 : "var foob\\v{1234}r = 0;", "var foob\\U{1234}r = 0;", nullptr};
6694 5 : RunParserSyncTest(context_data, data, kError);
6695 5 : }
6696 :
6697 :
6698 28342 : TEST(UnicodeEscapes) {
6699 : const char* context_data[][2] = {
6700 5 : {"", ""}, {"'use strict';", ""}, {nullptr, nullptr}};
6701 : const char* data[] = {
6702 : // Identifier starting with escape
6703 : "var \\u0052oo = 0;", "var \\u{0052}oo = 0;", "var \\u{52}oo = 0;",
6704 : "var \\u{00000000052}oo = 0;",
6705 : // Identifier with an escape but not starting with an escape
6706 : "var foob\\uc481r = 0;", "var foob\\u{c481}r = 0;",
6707 : // String with an escape
6708 : "\"foob\\uc481r\"", "\"foob\\{uc481}r\"",
6709 : // This character is a valid Unicode character, representable as a
6710 : // surrogate pair, not representable as 4 hex digits.
6711 : "\"foo\\u{10e6d}\"",
6712 : // Max value for the Unicode code point escape
6713 5 : "\"\\u{10ffff}\"", nullptr};
6714 5 : RunParserSyncTest(context_data, data, kSuccess);
6715 5 : }
6716 :
6717 28342 : TEST(OctalEscapes) {
6718 : const char* sloppy_context_data[][2] = {{"", ""}, // as a directive
6719 : {"0;", ""}, // as a string literal
6720 5 : {nullptr, nullptr}};
6721 :
6722 : const char* strict_context_data[][2] = {
6723 : {"'use strict';", ""}, // as a directive before 'use strict'
6724 : {"", ";'use strict';"}, // as a directive after 'use strict'
6725 : {"'use strict'; 0;", ""}, // as a string literal
6726 5 : {nullptr, nullptr}};
6727 :
6728 : // clang-format off
6729 : const char* data[] = {
6730 : "'\\1'",
6731 : "'\\01'",
6732 : "'\\001'",
6733 : "'\\08'",
6734 : "'\\09'",
6735 5 : nullptr};
6736 : // clang-format on
6737 :
6738 : // Permitted in sloppy mode
6739 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6740 :
6741 : // Error in strict mode
6742 5 : RunParserSyncTest(strict_context_data, data, kError);
6743 5 : }
6744 :
6745 28342 : TEST(ScanTemplateLiterals) {
6746 : const char* context_data[][2] = {{"'use strict';", ""},
6747 : {"function foo(){ 'use strict';"
6748 : " var a, b, c; return ",
6749 : "}"},
6750 5 : {nullptr, nullptr}};
6751 :
6752 : const char* data[] = {"``",
6753 : "`no-subst-template`",
6754 : "`template-head${a}`",
6755 : "`${a}`",
6756 : "`${a}template-tail`",
6757 : "`template-head${a}template-tail`",
6758 : "`${a}${b}${c}`",
6759 : "`a${a}b${b}c${c}`",
6760 : "`${a}a${b}b${c}c`",
6761 : "`foo\n\nbar\r\nbaz`",
6762 : "`foo\n\n${ bar }\r\nbaz`",
6763 : "`foo${a /* comment */}`",
6764 : "`foo${a // comment\n}`",
6765 : "`foo${a \n}`",
6766 : "`foo${a \r\n}`",
6767 : "`foo${a \r}`",
6768 : "`foo${/* comment */ a}`",
6769 : "`foo${// comment\na}`",
6770 : "`foo${\n a}`",
6771 : "`foo${\r\n a}`",
6772 : "`foo${\r a}`",
6773 : "`foo${'a' in a}`",
6774 5 : nullptr};
6775 5 : RunParserSyncTest(context_data, data, kSuccess);
6776 5 : }
6777 :
6778 :
6779 28342 : TEST(ScanTaggedTemplateLiterals) {
6780 : const char* context_data[][2] = {{"'use strict';", ""},
6781 : {"function foo(){ 'use strict';"
6782 : " function tag() {}"
6783 : " var a, b, c; return ",
6784 : "}"},
6785 5 : {nullptr, nullptr}};
6786 :
6787 : const char* data[] = {"tag ``",
6788 : "tag `no-subst-template`",
6789 : "tag`template-head${a}`",
6790 : "tag `${a}`",
6791 : "tag `${a}template-tail`",
6792 : "tag `template-head${a}template-tail`",
6793 : "tag\n`${a}${b}${c}`",
6794 : "tag\r\n`a${a}b${b}c${c}`",
6795 : "tag `${a}a${b}b${c}c`",
6796 : "tag\t`foo\n\nbar\r\nbaz`",
6797 : "tag\r`foo\n\n${ bar }\r\nbaz`",
6798 : "tag`foo${a /* comment */}`",
6799 : "tag`foo${a // comment\n}`",
6800 : "tag`foo${a \n}`",
6801 : "tag`foo${a \r\n}`",
6802 : "tag`foo${a \r}`",
6803 : "tag`foo${/* comment */ a}`",
6804 : "tag`foo${// comment\na}`",
6805 : "tag`foo${\n a}`",
6806 : "tag`foo${\r\n a}`",
6807 : "tag`foo${\r a}`",
6808 : "tag`foo${'a' in a}`",
6809 5 : nullptr};
6810 5 : RunParserSyncTest(context_data, data, kSuccess);
6811 5 : }
6812 :
6813 :
6814 28342 : TEST(TemplateMaterializedLiterals) {
6815 : const char* context_data[][2] = {{"'use strict';\n"
6816 : "function tag() {}\n"
6817 : "var a, b, c;\n"
6818 : "(",
6819 : ")"},
6820 5 : {nullptr, nullptr}};
6821 :
6822 : const char* data[] = {"tag``", "tag`a`", "tag`a${1}b`", "tag`a${1}b${2}c`",
6823 : "``", "`a`", "`a${1}b`", "`a${1}b${2}c`",
6824 5 : nullptr};
6825 :
6826 5 : RunParserSyncTest(context_data, data, kSuccess);
6827 5 : }
6828 :
6829 :
6830 28342 : TEST(ScanUnterminatedTemplateLiterals) {
6831 : const char* context_data[][2] = {{"'use strict';", ""},
6832 : {"function foo(){ 'use strict';"
6833 : " var a, b, c; return ",
6834 : "}"},
6835 5 : {nullptr, nullptr}};
6836 :
6837 : const char* data[] = {"`no-subst-template",
6838 : "`template-head${a}",
6839 : "`${a}template-tail",
6840 : "`template-head${a}template-tail",
6841 : "`${a}${b}${c}",
6842 : "`a${a}b${b}c${c}",
6843 : "`${a}a${b}b${c}c",
6844 : "`foo\n\nbar\r\nbaz",
6845 : "`foo\n\n${ bar }\r\nbaz",
6846 : "`foo${a /* comment } */`",
6847 : "`foo${a /* comment } `*/",
6848 : "`foo${a // comment}`",
6849 : "`foo${a \n`",
6850 : "`foo${a \r\n`",
6851 : "`foo${a \r`",
6852 : "`foo${/* comment */ a`",
6853 : "`foo${// commenta}`",
6854 : "`foo${\n a`",
6855 : "`foo${\r\n a`",
6856 : "`foo${\r a`",
6857 : "`foo${fn(}`",
6858 : "`foo${1 if}`",
6859 5 : nullptr};
6860 5 : RunParserSyncTest(context_data, data, kError);
6861 5 : }
6862 :
6863 :
6864 28342 : TEST(TemplateLiteralsIllegalTokens) {
6865 : const char* context_data[][2] = {{"'use strict';", ""},
6866 : {"function foo(){ 'use strict';"
6867 : " var a, b, c; return ",
6868 : "}"},
6869 5 : {nullptr, nullptr}};
6870 : const char* data[] = {
6871 : "`hello\\x`", "`hello\\x${1}`", "`hello${1}\\x`",
6872 : "`hello${1}\\x${2}`", "`hello\\x\n`", "`hello\\x\n${1}`",
6873 5 : "`hello${1}\\x\n`", "`hello${1}\\x\n${2}`", nullptr};
6874 :
6875 5 : RunParserSyncTest(context_data, data, kError);
6876 5 : }
6877 :
6878 :
6879 28342 : TEST(ParseRestParameters) {
6880 : const char* context_data[][2] = {{"'use strict';(function(",
6881 : "){ return args;})(1, [], /regexp/, 'str',"
6882 : "function(){});"},
6883 : {"(function(",
6884 : "){ return args;})(1, [],"
6885 : "/regexp/, 'str', function(){});"},
6886 5 : {nullptr, nullptr}};
6887 :
6888 : const char* data[] = {"...args",
6889 : "a, ...args",
6890 : "... args",
6891 : "a, ... args",
6892 : "...\targs",
6893 : "a, ...\targs",
6894 : "...\r\nargs",
6895 : "a, ...\r\nargs",
6896 : "...\rargs",
6897 : "a, ...\rargs",
6898 : "...\t\n\t\t\n args",
6899 : "a, ... \n \n args",
6900 : "...{ length, 0: a, 1: b}",
6901 : "...{}",
6902 : "...[a, b]",
6903 : "...[]",
6904 : "...[...[a, b, ...c]]",
6905 5 : nullptr};
6906 5 : RunParserSyncTest(context_data, data, kSuccess);
6907 5 : }
6908 :
6909 :
6910 28342 : TEST(ParseRestParametersErrors) {
6911 : const char* context_data[][2] = {{"'use strict';(function(",
6912 : "){ return args;}(1, [], /regexp/, 'str',"
6913 : "function(){});"},
6914 : {"(function(",
6915 : "){ return args;}(1, [],"
6916 : "/regexp/, 'str', function(){});"},
6917 5 : {nullptr, nullptr}};
6918 :
6919 : const char* data[] = {"...args, b",
6920 : "a, ...args, b",
6921 : "...args, b",
6922 : "a, ...args, b",
6923 : "...args,\tb",
6924 : "a,...args\t,b",
6925 : "...args\r\n, b",
6926 : "a, ... args,\r\nb",
6927 : "...args\r,b",
6928 : "a, ... args,\rb",
6929 : "...args\t\n\t\t\n, b",
6930 : "a, ... args, \n \n b",
6931 : "a, a, ...args",
6932 : "a,\ta, ...args",
6933 : "a,\ra, ...args",
6934 : "a,\na, ...args",
6935 5 : nullptr};
6936 5 : RunParserSyncTest(context_data, data, kError);
6937 5 : }
6938 :
6939 :
6940 28342 : TEST(RestParameterInSetterMethodError) {
6941 : const char* context_data[][2] = {
6942 : {"'use strict';({ set prop(", ") {} }).prop = 1;"},
6943 : {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
6944 : {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
6945 : {"({ set prop(", ") {} }).prop = 1;"},
6946 : {"(class { static set prop(", ") {} }).prop = 1;"},
6947 : {"(new (class { set prop(", ") {} })).prop = 1;"},
6948 5 : {nullptr, nullptr}};
6949 5 : const char* data[] = {"...a", "...arguments", "...eval", nullptr};
6950 :
6951 5 : RunParserSyncTest(context_data, data, kError);
6952 5 : }
6953 :
6954 :
6955 28342 : TEST(RestParametersEvalArguments) {
6956 : // clang-format off
6957 : const char* strict_context_data[][2] =
6958 : {{"'use strict';(function(",
6959 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6960 5 : {nullptr, nullptr}};
6961 : const char* sloppy_context_data[][2] =
6962 : {{"(function(",
6963 : "){ return;})(1, [],/regexp/, 'str', function(){});"},
6964 5 : {nullptr, nullptr}};
6965 :
6966 : const char* data[] = {
6967 : "...eval",
6968 : "eval, ...args",
6969 : "...arguments",
6970 : // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
6971 : // "arguments, ...args",
6972 5 : nullptr};
6973 : // clang-format on
6974 :
6975 : // Fail in strict mode
6976 5 : RunParserSyncTest(strict_context_data, data, kError);
6977 :
6978 : // OK in sloppy mode
6979 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
6980 5 : }
6981 :
6982 :
6983 28342 : TEST(RestParametersDuplicateEvalArguments) {
6984 : const char* context_data[][2] = {
6985 : {"'use strict';(function(",
6986 : "){ return;})(1, [], /regexp/, 'str',function(){});"},
6987 : {"(function(", "){ return;})(1, [],/regexp/, 'str', function(){});"},
6988 5 : {nullptr, nullptr}};
6989 :
6990 : const char* data[] = {"eval, ...eval", "eval, eval, ...args",
6991 : "arguments, ...arguments",
6992 5 : "arguments, arguments, ...args", nullptr};
6993 :
6994 : // In strict mode, the error is using "eval" or "arguments" as parameter names
6995 : // In sloppy mode, the error is that eval / arguments are duplicated
6996 5 : RunParserSyncTest(context_data, data, kError);
6997 5 : }
6998 :
6999 :
7000 28342 : TEST(SpreadCall) {
7001 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
7002 : {"function fn() {} fn(", ");"},
7003 5 : {nullptr, nullptr}};
7004 :
7005 : const char* data[] = {"...([1, 2, 3])",
7006 : "...'123', ...'456'",
7007 : "...new Set([1, 2, 3]), 4",
7008 : "1, ...[2, 3], 4",
7009 : "...Array(...[1,2,3,4])",
7010 : "...NaN",
7011 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
7012 : "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
7013 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
7014 : "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]",
7015 5 : nullptr};
7016 :
7017 5 : RunParserSyncTest(context_data, data, kSuccess);
7018 5 : }
7019 :
7020 :
7021 28342 : TEST(SpreadCallErrors) {
7022 : const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
7023 : {"function fn() {} fn(", ");"},
7024 5 : {nullptr, nullptr}};
7025 :
7026 5 : const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", nullptr};
7027 :
7028 5 : RunParserSyncTest(context_data, data, kError);
7029 5 : }
7030 :
7031 :
7032 28342 : TEST(BadRestSpread) {
7033 : const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
7034 : {"function fn() { ", "} fn();"},
7035 5 : {nullptr, nullptr}};
7036 : const char* data[] = {"return ...[1,2,3];",
7037 : "var ...x = [1,2,3];",
7038 : "var [...x,] = [1,2,3];",
7039 : "var [...x, y] = [1,2,3];",
7040 : "var { x } = {x: ...[1,2,3]}",
7041 5 : nullptr};
7042 5 : RunParserSyncTest(context_data, data, kError);
7043 5 : }
7044 :
7045 :
7046 28342 : TEST(LexicalScopingSloppyMode) {
7047 : const char* context_data[][2] = {
7048 5 : {"", ""}, {"function f() {", "}"}, {"{", "}"}, {nullptr, nullptr}};
7049 :
7050 5 : const char* good_data[] = {"let = 1;", "for(let = 1;;){}", nullptr};
7051 5 : RunParserSyncTest(context_data, good_data, kSuccess);
7052 5 : }
7053 :
7054 :
7055 28342 : TEST(ComputedPropertyName) {
7056 : const char* context_data[][2] = {{"({[", "]: 1});"},
7057 : {"({get [", "]() {}});"},
7058 : {"({set [", "](_) {}});"},
7059 : {"({[", "]() {}});"},
7060 : {"({*[", "]() {}});"},
7061 : {"(class {get [", "]() {}});"},
7062 : {"(class {set [", "](_) {}});"},
7063 : {"(class {[", "]() {}});"},
7064 : {"(class {*[", "]() {}});"},
7065 5 : {nullptr, nullptr}};
7066 5 : const char* error_data[] = {"1, 2", "var name", nullptr};
7067 :
7068 5 : RunParserSyncTest(context_data, error_data, kError);
7069 :
7070 : const char* name_data[] = {"1", "1 + 2", "'name'", "\"name\"",
7071 5 : "[]", "{}", nullptr};
7072 :
7073 5 : RunParserSyncTest(context_data, name_data, kSuccess);
7074 5 : }
7075 :
7076 :
7077 28342 : TEST(ComputedPropertyNameShorthandError) {
7078 5 : const char* context_data[][2] = {{"({", "});"}, {nullptr, nullptr}};
7079 5 : const char* error_data[] = {"a: 1, [2]", "[1], a: 1", nullptr};
7080 :
7081 5 : RunParserSyncTest(context_data, error_data, kError);
7082 5 : }
7083 :
7084 :
7085 28342 : TEST(BasicImportExportParsing) {
7086 : // clang-format off
7087 : const char* kSources[] = {
7088 : "export let x = 0;",
7089 : "export var y = 0;",
7090 : "export const z = 0;",
7091 : "export function func() { };",
7092 : "export class C { };",
7093 : "export { };",
7094 : "function f() {}; f(); export { f };",
7095 : "var a, b, c; export { a, b as baz, c };",
7096 : "var d, e; export { d as dreary, e, };",
7097 : "export default function f() {}",
7098 : "export default function() {}",
7099 : "export default function*() {}",
7100 : "export default class C {}",
7101 : "export default class {}",
7102 : "export default class extends C {}",
7103 : "export default 42",
7104 : "var x; export default x = 7",
7105 : "export { Q } from 'somemodule.js';",
7106 : "export * from 'somemodule.js';",
7107 : "var foo; export { foo as for };",
7108 : "export { arguments } from 'm.js';",
7109 : "export { for } from 'm.js';",
7110 : "export { yield } from 'm.js'",
7111 : "export { static } from 'm.js'",
7112 : "export { let } from 'm.js'",
7113 : "var a; export { a as b, a as c };",
7114 : "var a; export { a as await };",
7115 : "var a; export { a as enum };",
7116 :
7117 : "import 'somemodule.js';",
7118 : "import { } from 'm.js';",
7119 : "import { a } from 'm.js';",
7120 : "import { a, b as d, c, } from 'm.js';",
7121 : "import * as thing from 'm.js';",
7122 : "import thing from 'm.js';",
7123 : "import thing, * as rest from 'm.js';",
7124 : "import thing, { a, b, c } from 'm.js';",
7125 : "import { arguments as a } from 'm.js';",
7126 : "import { for as f } from 'm.js';",
7127 : "import { yield as y } from 'm.js';",
7128 : "import { static as s } from 'm.js';",
7129 : "import { let as l } from 'm.js';",
7130 :
7131 : "import thing from 'a.js'; export {thing};",
7132 : "export {thing}; import thing from 'a.js';",
7133 : "import {thing} from 'a.js'; export {thing};",
7134 : "export {thing}; import {thing} from 'a.js';",
7135 : "import * as thing from 'a.js'; export {thing};",
7136 : "export {thing}; import * as thing from 'a.js';",
7137 5 : };
7138 : // clang-format on
7139 :
7140 : i::Isolate* isolate = CcTest::i_isolate();
7141 : i::Factory* factory = isolate->factory();
7142 :
7143 5 : v8::HandleScope handles(CcTest::isolate());
7144 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7145 : v8::Context::Scope context_scope(context);
7146 :
7147 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7148 5 : 128 * 1024);
7149 :
7150 240 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7151 : i::Handle<i::String> source =
7152 235 : factory->NewStringFromAsciiChecked(kSources[i]);
7153 :
7154 : // Show that parsing as a module works
7155 : {
7156 235 : i::Handle<i::Script> script = factory->NewScript(source);
7157 235 : i::ParseInfo info(isolate, script);
7158 : info.set_module();
7159 235 : if (!i::parsing::ParseProgram(&info, isolate)) {
7160 : i::Handle<i::JSObject> exception_handle(
7161 : i::JSObject::cast(isolate->pending_exception()), isolate);
7162 : i::Handle<i::String> message_string = i::Handle<i::String>::cast(
7163 0 : i::JSReceiver::GetProperty(isolate, exception_handle, "message")
7164 0 : .ToHandleChecked());
7165 0 : isolate->clear_pending_exception();
7166 :
7167 0 : FATAL(
7168 : "Parser failed on:\n"
7169 : "\t%s\n"
7170 : "with error:\n"
7171 : "\t%s\n"
7172 : "However, we expected no error.",
7173 0 : source->ToCString().get(), message_string->ToCString().get());
7174 235 : }
7175 : }
7176 :
7177 : // And that parsing a script does not.
7178 : {
7179 235 : i::Handle<i::Script> script = factory->NewScript(source);
7180 235 : i::ParseInfo info(isolate, script);
7181 235 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7182 235 : isolate->clear_pending_exception();
7183 : }
7184 5 : }
7185 5 : }
7186 :
7187 28342 : TEST(NamespaceExportParsing) {
7188 : // clang-format off
7189 : const char* kSources[] = {
7190 : "export * as arguments from 'bar'",
7191 : "export * as await from 'bar'",
7192 : "export * as default from 'bar'",
7193 : "export * as enum from 'bar'",
7194 : "export * as foo from 'bar'",
7195 : "export * as for from 'bar'",
7196 : "export * as let from 'bar'",
7197 : "export * as static from 'bar'",
7198 : "export * as yield from 'bar'",
7199 5 : };
7200 : // clang-format on
7201 :
7202 5 : i::FLAG_harmony_namespace_exports = true;
7203 : i::Isolate* isolate = CcTest::i_isolate();
7204 : i::Factory* factory = isolate->factory();
7205 :
7206 5 : v8::HandleScope handles(CcTest::isolate());
7207 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7208 : v8::Context::Scope context_scope(context);
7209 :
7210 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7211 5 : 128 * 1024);
7212 :
7213 50 : for (unsigned i = 0; i < arraysize(kSources); ++i) {
7214 : i::Handle<i::String> source =
7215 45 : factory->NewStringFromAsciiChecked(kSources[i]);
7216 45 : i::Handle<i::Script> script = factory->NewScript(source);
7217 45 : i::ParseInfo info(isolate, script);
7218 : info.set_module();
7219 45 : CHECK(i::parsing::ParseProgram(&info, isolate));
7220 50 : }
7221 5 : }
7222 :
7223 28342 : TEST(ImportExportParsingErrors) {
7224 : // clang-format off
7225 : const char* kErrorSources[] = {
7226 : "export {",
7227 : "var a; export { a",
7228 : "var a; export { a,",
7229 : "var a; export { a, ;",
7230 : "var a; export { a as };",
7231 : "var a, b; export { a as , b};",
7232 : "export }",
7233 : "var foo, bar; export { foo bar };",
7234 : "export { foo };",
7235 : "export { , };",
7236 : "export default;",
7237 : "export default var x = 7;",
7238 : "export default let x = 7;",
7239 : "export default const x = 7;",
7240 : "export *;",
7241 : "export * from;",
7242 : "export { Q } from;",
7243 : "export default from 'module.js';",
7244 : "export { for }",
7245 : "export { for as foo }",
7246 : "export { arguments }",
7247 : "export { arguments as foo }",
7248 : "var a; export { a, a };",
7249 : "var a, b; export { a as b, b };",
7250 : "var a, b; export { a as c, b as c };",
7251 : "export default function f(){}; export default class C {};",
7252 : "export default function f(){}; var a; export { a as default };",
7253 : "export function() {}",
7254 : "export function*() {}",
7255 : "export class {}",
7256 : "export class extends C {}",
7257 :
7258 : "import from;",
7259 : "import from 'm.js';",
7260 : "import { };",
7261 : "import {;",
7262 : "import };",
7263 : "import { , };",
7264 : "import { , } from 'm.js';",
7265 : "import { a } from;",
7266 : "import { a } 'm.js';",
7267 : "import , from 'm.js';",
7268 : "import a , from 'm.js';",
7269 : "import a { b, c } from 'm.js';",
7270 : "import arguments from 'm.js';",
7271 : "import eval from 'm.js';",
7272 : "import { arguments } from 'm.js';",
7273 : "import { eval } from 'm.js';",
7274 : "import { a as arguments } from 'm.js';",
7275 : "import { for } from 'm.js';",
7276 : "import { y as yield } from 'm.js'",
7277 : "import { s as static } from 'm.js'",
7278 : "import { l as let } from 'm.js'",
7279 : "import { a as await } from 'm.js';",
7280 : "import { a as enum } from 'm.js';",
7281 : "import { x }, def from 'm.js';",
7282 : "import def, def2 from 'm.js';",
7283 : "import * as x, def from 'm.js';",
7284 : "import * as x, * as y from 'm.js';",
7285 : "import {x}, {y} from 'm.js';",
7286 : "import * as x, {y} from 'm.js';",
7287 :
7288 : "export *;",
7289 : "export * as;",
7290 : "export * as foo;",
7291 : "export * as foo from;",
7292 : "export * as foo from ';",
7293 : "export * as ,foo from 'bar'",
7294 5 : };
7295 : // clang-format on
7296 :
7297 : i::Isolate* isolate = CcTest::i_isolate();
7298 : i::Factory* factory = isolate->factory();
7299 :
7300 5 : v8::HandleScope handles(CcTest::isolate());
7301 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7302 : v8::Context::Scope context_scope(context);
7303 :
7304 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7305 5 : 128 * 1024);
7306 :
7307 335 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7308 : i::Handle<i::String> source =
7309 330 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7310 :
7311 330 : i::Handle<i::Script> script = factory->NewScript(source);
7312 330 : i::ParseInfo info(isolate, script);
7313 : info.set_module();
7314 330 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7315 330 : isolate->clear_pending_exception();
7316 335 : }
7317 5 : }
7318 :
7319 28342 : TEST(ModuleTopLevelFunctionDecl) {
7320 : // clang-format off
7321 : const char* kErrorSources[] = {
7322 : "function f() {} function f() {}",
7323 : "var f; function f() {}",
7324 : "function f() {} var f;",
7325 : "function* f() {} function* f() {}",
7326 : "var f; function* f() {}",
7327 : "function* f() {} var f;",
7328 : "function f() {} function* f() {}",
7329 : "function* f() {} function f() {}",
7330 5 : };
7331 : // clang-format on
7332 :
7333 : i::Isolate* isolate = CcTest::i_isolate();
7334 : i::Factory* factory = isolate->factory();
7335 :
7336 5 : v8::HandleScope handles(CcTest::isolate());
7337 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7338 : v8::Context::Scope context_scope(context);
7339 :
7340 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7341 5 : 128 * 1024);
7342 :
7343 45 : for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
7344 : i::Handle<i::String> source =
7345 40 : factory->NewStringFromAsciiChecked(kErrorSources[i]);
7346 :
7347 40 : i::Handle<i::Script> script = factory->NewScript(source);
7348 40 : i::ParseInfo info(isolate, script);
7349 : info.set_module();
7350 40 : CHECK(!i::parsing::ParseProgram(&info, isolate));
7351 40 : isolate->clear_pending_exception();
7352 45 : }
7353 5 : }
7354 :
7355 28342 : TEST(ModuleAwaitReserved) {
7356 : // clang-format off
7357 : const char* kErrorSources[] = {
7358 : "await;",
7359 : "await: ;",
7360 : "var await;",
7361 : "var [await] = [];",
7362 : "var { await } = {};",
7363 : "var { x: await } = {};",
7364 : "{ var await; }",
7365 : "let await;",
7366 : "let [await] = [];",
7367 : "let { await } = {};",
7368 : "let { x: await } = {};",
7369 : "{ let await; }",
7370 : "const await = null;",
7371 : "const [await] = [];",
7372 : "const { await } = {};",
7373 : "const { x: await } = {};",
7374 : "{ const await = null; }",
7375 : "function await() {}",
7376 : "function f(await) {}",
7377 : "function* await() {}",
7378 : "function* g(await) {}",
7379 : "(function await() {});",
7380 : "(function (await) {});",
7381 : "(function* await() {});",
7382 : "(function* (await) {});",
7383 : "(await) => {};",
7384 : "await => {};",
7385 : "class await {}",
7386 : "class C { constructor(await) {} }",
7387 : "class C { m(await) {} }",
7388 : "class C { static m(await) {} }",
7389 : "class C { *m(await) {} }",
7390 : "class C { static *m(await) {} }",
7391 : "(class await {})",
7392 : "(class { constructor(await) {} });",
7393 : "(class { m(await) {} });",
7394 : "(class { static m(await) {} });",
7395 : "(class { *m(await) {} });",
7396 : "(class { static *m(await) {} });",
7397 : "({ m(await) {} });",
7398 : "({ *m(await) {} });",
7399 : "({ set p(await) {} });",
7400 : "try {} catch (await) {}",
7401 : "try {} catch (await) {} finally {}",
7402 : nullptr
7403 5 : };
7404 : // clang-format on
7405 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7406 :
7407 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7408 5 : }
7409 :
7410 28342 : TEST(ModuleAwaitReservedPreParse) {
7411 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7412 5 : const char* error_data[] = {"function f() { var await = 0; }", nullptr};
7413 :
7414 : RunModuleParserSyncTest(context_data, error_data, kError);
7415 5 : }
7416 :
7417 28342 : TEST(ModuleAwaitPermitted) {
7418 : // clang-format off
7419 : const char* kValidSources[] = {
7420 : "({}).await;",
7421 : "({ await: null });",
7422 : "({ await() {} });",
7423 : "({ get await() {} });",
7424 : "({ set await(x) {} });",
7425 : "(class { await() {} });",
7426 : "(class { static await() {} });",
7427 : "(class { *await() {} });",
7428 : "(class { static *await() {} });",
7429 : nullptr
7430 5 : };
7431 : // clang-format on
7432 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7433 :
7434 : RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
7435 5 : }
7436 :
7437 28342 : TEST(EnumReserved) {
7438 : // clang-format off
7439 : const char* kErrorSources[] = {
7440 : "enum;",
7441 : "enum: ;",
7442 : "var enum;",
7443 : "var [enum] = [];",
7444 : "var { enum } = {};",
7445 : "var { x: enum } = {};",
7446 : "{ var enum; }",
7447 : "let enum;",
7448 : "let [enum] = [];",
7449 : "let { enum } = {};",
7450 : "let { x: enum } = {};",
7451 : "{ let enum; }",
7452 : "const enum = null;",
7453 : "const [enum] = [];",
7454 : "const { enum } = {};",
7455 : "const { x: enum } = {};",
7456 : "{ const enum = null; }",
7457 : "function enum() {}",
7458 : "function f(enum) {}",
7459 : "function* enum() {}",
7460 : "function* g(enum) {}",
7461 : "(function enum() {});",
7462 : "(function (enum) {});",
7463 : "(function* enum() {});",
7464 : "(function* (enum) {});",
7465 : "(enum) => {};",
7466 : "enum => {};",
7467 : "class enum {}",
7468 : "class C { constructor(enum) {} }",
7469 : "class C { m(enum) {} }",
7470 : "class C { static m(enum) {} }",
7471 : "class C { *m(enum) {} }",
7472 : "class C { static *m(enum) {} }",
7473 : "(class enum {})",
7474 : "(class { constructor(enum) {} });",
7475 : "(class { m(enum) {} });",
7476 : "(class { static m(enum) {} });",
7477 : "(class { *m(enum) {} });",
7478 : "(class { static *m(enum) {} });",
7479 : "({ m(enum) {} });",
7480 : "({ *m(enum) {} });",
7481 : "({ set p(enum) {} });",
7482 : "try {} catch (enum) {}",
7483 : "try {} catch (enum) {} finally {}",
7484 : nullptr
7485 5 : };
7486 : // clang-format on
7487 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
7488 :
7489 : RunModuleParserSyncTest(context_data, kErrorSources, kError);
7490 5 : }
7491 :
7492 85 : static void CheckEntry(const i::ModuleDescriptor::Entry* entry,
7493 : const char* export_name, const char* local_name,
7494 : const char* import_name, int module_request) {
7495 85 : CHECK_NOT_NULL(entry);
7496 85 : if (export_name == nullptr) {
7497 35 : CHECK_NULL(entry->export_name);
7498 : } else {
7499 50 : CHECK(entry->export_name->IsOneByteEqualTo(export_name));
7500 : }
7501 85 : if (local_name == nullptr) {
7502 15 : CHECK_NULL(entry->local_name);
7503 : } else {
7504 70 : CHECK(entry->local_name->IsOneByteEqualTo(local_name));
7505 : }
7506 85 : if (import_name == nullptr) {
7507 55 : CHECK_NULL(entry->import_name);
7508 : } else {
7509 30 : CHECK(entry->import_name->IsOneByteEqualTo(import_name));
7510 : }
7511 85 : CHECK_EQ(entry->module_request, module_request);
7512 85 : }
7513 :
7514 28342 : TEST(ModuleParsingInternals) {
7515 : i::Isolate* isolate = CcTest::i_isolate();
7516 : i::Factory* factory = isolate->factory();
7517 5 : v8::HandleScope handles(CcTest::isolate());
7518 5 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7519 : v8::Context::Scope context_scope(context);
7520 5 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7521 5 : 128 * 1024);
7522 :
7523 : static const char kSource[] =
7524 : "let x = 5;"
7525 : "export { x as y };"
7526 : "import { q as z } from 'm.js';"
7527 : "import n from 'n.js';"
7528 : "export { a as b } from 'm.js';"
7529 : "export * from 'p.js';"
7530 : "export var foo;"
7531 : "export function goo() {};"
7532 : "export let hoo;"
7533 : "export const joo = 42;"
7534 : "export default (function koo() {});"
7535 : "import 'q.js';"
7536 : "let nonexport = 42;"
7537 : "import {m as mm} from 'm.js';"
7538 : "import {aa} from 'm.js';"
7539 : "export {aa as bb, x};"
7540 : "import * as loo from 'bar.js';"
7541 : "import * as foob from 'bar.js';"
7542 : "export {foob};";
7543 5 : i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
7544 5 : i::Handle<i::Script> script = factory->NewScript(source);
7545 10 : i::ParseInfo info(isolate, script);
7546 : info.set_module();
7547 5 : CHECK(i::parsing::ParseProgram(&info, isolate));
7548 5 : CHECK(i::Compiler::Analyze(&info));
7549 5 : i::FunctionLiteral* func = info.literal();
7550 10 : i::ModuleScope* module_scope = func->scope()->AsModuleScope();
7551 15 : i::Scope* outer_scope = module_scope->outer_scope();
7552 5 : CHECK(outer_scope->is_script_scope());
7553 5 : CHECK_NULL(outer_scope->outer_scope());
7554 5 : CHECK(module_scope->is_module_scope());
7555 : const i::ModuleDescriptor::Entry* entry;
7556 : i::Declaration::List* declarations = module_scope->declarations();
7557 5 : CHECK_EQ(13, declarations->LengthForTest());
7558 :
7559 5 : CHECK(declarations->AtForTest(0)->var()->raw_name()->IsOneByteEqualTo("x"));
7560 10 : CHECK(declarations->AtForTest(0)->var()->mode() == i::VariableMode::kLet);
7561 5 : CHECK(declarations->AtForTest(0)->var()->binding_needs_init());
7562 5 : CHECK(declarations->AtForTest(0)->var()->location() ==
7563 : i::VariableLocation::MODULE);
7564 :
7565 5 : CHECK(declarations->AtForTest(1)->var()->raw_name()->IsOneByteEqualTo("z"));
7566 10 : CHECK(declarations->AtForTest(1)->var()->mode() == i::VariableMode::kConst);
7567 5 : CHECK(declarations->AtForTest(1)->var()->binding_needs_init());
7568 10 : CHECK(declarations->AtForTest(1)->var()->location() ==
7569 : i::VariableLocation::MODULE);
7570 :
7571 5 : CHECK(declarations->AtForTest(2)->var()->raw_name()->IsOneByteEqualTo("n"));
7572 10 : CHECK(declarations->AtForTest(2)->var()->mode() == i::VariableMode::kConst);
7573 5 : CHECK(declarations->AtForTest(2)->var()->binding_needs_init());
7574 10 : CHECK(declarations->AtForTest(2)->var()->location() ==
7575 : i::VariableLocation::MODULE);
7576 :
7577 5 : CHECK(declarations->AtForTest(3)->var()->raw_name()->IsOneByteEqualTo("foo"));
7578 10 : CHECK(declarations->AtForTest(3)->var()->mode() == i::VariableMode::kVar);
7579 5 : CHECK(!declarations->AtForTest(3)->var()->binding_needs_init());
7580 10 : CHECK(declarations->AtForTest(3)->var()->location() ==
7581 : i::VariableLocation::MODULE);
7582 :
7583 5 : CHECK(declarations->AtForTest(4)->var()->raw_name()->IsOneByteEqualTo("goo"));
7584 10 : CHECK(declarations->AtForTest(4)->var()->mode() == i::VariableMode::kLet);
7585 5 : CHECK(!declarations->AtForTest(4)->var()->binding_needs_init());
7586 10 : CHECK(declarations->AtForTest(4)->var()->location() ==
7587 : i::VariableLocation::MODULE);
7588 :
7589 5 : CHECK(declarations->AtForTest(5)->var()->raw_name()->IsOneByteEqualTo("hoo"));
7590 10 : CHECK(declarations->AtForTest(5)->var()->mode() == i::VariableMode::kLet);
7591 5 : CHECK(declarations->AtForTest(5)->var()->binding_needs_init());
7592 10 : CHECK(declarations->AtForTest(5)->var()->location() ==
7593 : i::VariableLocation::MODULE);
7594 :
7595 5 : CHECK(declarations->AtForTest(6)->var()->raw_name()->IsOneByteEqualTo("joo"));
7596 10 : CHECK(declarations->AtForTest(6)->var()->mode() == i::VariableMode::kConst);
7597 5 : CHECK(declarations->AtForTest(6)->var()->binding_needs_init());
7598 10 : CHECK(declarations->AtForTest(6)->var()->location() ==
7599 : i::VariableLocation::MODULE);
7600 :
7601 5 : CHECK(declarations->AtForTest(7)->var()->raw_name()->IsOneByteEqualTo(
7602 : "*default*"));
7603 10 : CHECK(declarations->AtForTest(7)->var()->mode() == i::VariableMode::kConst);
7604 5 : CHECK(declarations->AtForTest(7)->var()->binding_needs_init());
7605 10 : CHECK(declarations->AtForTest(7)->var()->location() ==
7606 : i::VariableLocation::MODULE);
7607 :
7608 5 : CHECK(declarations->AtForTest(8)->var()->raw_name()->IsOneByteEqualTo(
7609 : "nonexport"));
7610 5 : CHECK(!declarations->AtForTest(8)->var()->binding_needs_init());
7611 10 : CHECK(declarations->AtForTest(8)->var()->location() ==
7612 : i::VariableLocation::LOCAL);
7613 :
7614 5 : CHECK(declarations->AtForTest(9)->var()->raw_name()->IsOneByteEqualTo("mm"));
7615 10 : CHECK(declarations->AtForTest(9)->var()->mode() == i::VariableMode::kConst);
7616 5 : CHECK(declarations->AtForTest(9)->var()->binding_needs_init());
7617 10 : CHECK(declarations->AtForTest(9)->var()->location() ==
7618 : i::VariableLocation::MODULE);
7619 :
7620 5 : CHECK(declarations->AtForTest(10)->var()->raw_name()->IsOneByteEqualTo("aa"));
7621 10 : CHECK(declarations->AtForTest(10)->var()->mode() == i::VariableMode::kConst);
7622 5 : CHECK(declarations->AtForTest(10)->var()->binding_needs_init());
7623 10 : CHECK(declarations->AtForTest(10)->var()->location() ==
7624 : i::VariableLocation::MODULE);
7625 :
7626 5 : CHECK(
7627 : declarations->AtForTest(11)->var()->raw_name()->IsOneByteEqualTo("loo"));
7628 10 : CHECK(declarations->AtForTest(11)->var()->mode() == i::VariableMode::kConst);
7629 5 : CHECK(!declarations->AtForTest(11)->var()->binding_needs_init());
7630 10 : CHECK(declarations->AtForTest(11)->var()->location() !=
7631 : i::VariableLocation::MODULE);
7632 :
7633 5 : CHECK(
7634 : declarations->AtForTest(12)->var()->raw_name()->IsOneByteEqualTo("foob"));
7635 10 : CHECK(declarations->AtForTest(12)->var()->mode() == i::VariableMode::kConst);
7636 5 : CHECK(!declarations->AtForTest(12)->var()->binding_needs_init());
7637 10 : CHECK(declarations->AtForTest(12)->var()->location() ==
7638 : i::VariableLocation::MODULE);
7639 :
7640 : i::ModuleDescriptor* descriptor = module_scope->module();
7641 5 : CHECK_NOT_NULL(descriptor);
7642 :
7643 5 : CHECK_EQ(5u, descriptor->module_requests().size());
7644 35 : for (const auto& elem : descriptor->module_requests()) {
7645 25 : if (elem.first->IsOneByteEqualTo("m.js")) {
7646 5 : CHECK_EQ(0, elem.second.index);
7647 5 : CHECK_EQ(51, elem.second.position);
7648 20 : } else if (elem.first->IsOneByteEqualTo("n.js")) {
7649 5 : CHECK_EQ(1, elem.second.index);
7650 5 : CHECK_EQ(72, elem.second.position);
7651 15 : } else if (elem.first->IsOneByteEqualTo("p.js")) {
7652 5 : CHECK_EQ(2, elem.second.index);
7653 5 : CHECK_EQ(123, elem.second.position);
7654 10 : } else if (elem.first->IsOneByteEqualTo("q.js")) {
7655 5 : CHECK_EQ(3, elem.second.index);
7656 5 : CHECK_EQ(249, elem.second.position);
7657 5 : } else if (elem.first->IsOneByteEqualTo("bar.js")) {
7658 5 : CHECK_EQ(4, elem.second.index);
7659 5 : CHECK_EQ(370, elem.second.position);
7660 : } else {
7661 0 : UNREACHABLE();
7662 : }
7663 : }
7664 :
7665 10 : CHECK_EQ(3, descriptor->special_exports().size());
7666 5 : CheckEntry(descriptor->special_exports().at(0), "b", nullptr, "a", 0);
7667 5 : CheckEntry(descriptor->special_exports().at(1), nullptr, nullptr, nullptr, 2);
7668 : CheckEntry(descriptor->special_exports().at(2), "bb", nullptr, "aa",
7669 5 : 0); // !!!
7670 :
7671 5 : CHECK_EQ(8u, descriptor->regular_exports().size());
7672 : entry = descriptor->regular_exports()
7673 10 : .find(declarations->AtForTest(3)->var()->raw_name())
7674 5 : ->second;
7675 5 : CheckEntry(entry, "foo", "foo", nullptr, -1);
7676 : entry = descriptor->regular_exports()
7677 10 : .find(declarations->AtForTest(4)->var()->raw_name())
7678 5 : ->second;
7679 5 : CheckEntry(entry, "goo", "goo", nullptr, -1);
7680 : entry = descriptor->regular_exports()
7681 10 : .find(declarations->AtForTest(5)->var()->raw_name())
7682 5 : ->second;
7683 5 : CheckEntry(entry, "hoo", "hoo", nullptr, -1);
7684 : entry = descriptor->regular_exports()
7685 10 : .find(declarations->AtForTest(6)->var()->raw_name())
7686 5 : ->second;
7687 5 : CheckEntry(entry, "joo", "joo", nullptr, -1);
7688 : entry = descriptor->regular_exports()
7689 10 : .find(declarations->AtForTest(7)->var()->raw_name())
7690 5 : ->second;
7691 5 : CheckEntry(entry, "default", "*default*", nullptr, -1);
7692 : entry = descriptor->regular_exports()
7693 10 : .find(declarations->AtForTest(12)->var()->raw_name())
7694 5 : ->second;
7695 5 : CheckEntry(entry, "foob", "foob", nullptr, -1);
7696 : // TODO(neis): The next lines are terrible. Find a better way.
7697 5 : auto name_x = declarations->AtForTest(0)->var()->raw_name();
7698 5 : CHECK_EQ(2u, descriptor->regular_exports().count(name_x));
7699 : auto it = descriptor->regular_exports().equal_range(name_x).first;
7700 5 : entry = it->second;
7701 5 : if (entry->export_name->IsOneByteEqualTo("y")) {
7702 5 : CheckEntry(entry, "y", "x", nullptr, -1);
7703 5 : entry = (++it)->second;
7704 5 : CheckEntry(entry, "x", "x", nullptr, -1);
7705 : } else {
7706 0 : CheckEntry(entry, "x", "x", nullptr, -1);
7707 0 : entry = (++it)->second;
7708 0 : CheckEntry(entry, "y", "x", nullptr, -1);
7709 : }
7710 :
7711 10 : CHECK_EQ(2, descriptor->namespace_imports().size());
7712 5 : CheckEntry(descriptor->namespace_imports().at(0), nullptr, "loo", nullptr, 4);
7713 : CheckEntry(descriptor->namespace_imports().at(1), nullptr, "foob", nullptr,
7714 5 : 4);
7715 :
7716 5 : CHECK_EQ(4u, descriptor->regular_imports().size());
7717 : entry = descriptor->regular_imports()
7718 10 : .find(declarations->AtForTest(1)->var()->raw_name())
7719 5 : ->second;
7720 5 : CheckEntry(entry, nullptr, "z", "q", 0);
7721 : entry = descriptor->regular_imports()
7722 10 : .find(declarations->AtForTest(2)->var()->raw_name())
7723 5 : ->second;
7724 5 : CheckEntry(entry, nullptr, "n", "default", 1);
7725 : entry = descriptor->regular_imports()
7726 10 : .find(declarations->AtForTest(9)->var()->raw_name())
7727 5 : ->second;
7728 5 : CheckEntry(entry, nullptr, "mm", "m", 0);
7729 : entry = descriptor->regular_imports()
7730 10 : .find(declarations->AtForTest(10)->var()->raw_name())
7731 5 : ->second;
7732 10 : CheckEntry(entry, nullptr, "aa", "aa", 0);
7733 5 : }
7734 :
7735 :
7736 28342 : TEST(DuplicateProtoError) {
7737 : const char* context_data[][2] = {
7738 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7739 : const char* error_data[] = {"__proto__: {}, __proto__: {}",
7740 : "__proto__: {}, \"__proto__\": {}",
7741 : "__proto__: {}, \"__\x70roto__\": {}",
7742 5 : "__proto__: {}, a: 1, __proto__: {}", nullptr};
7743 :
7744 5 : RunParserSyncTest(context_data, error_data, kError);
7745 5 : }
7746 :
7747 :
7748 28342 : TEST(DuplicateProtoNoError) {
7749 : const char* context_data[][2] = {
7750 5 : {"({", "});"}, {"'use strict'; ({", "});"}, {nullptr, nullptr}};
7751 : const char* error_data[] = {
7752 : "__proto__: {}, ['__proto__']: {}", "__proto__: {}, __proto__() {}",
7753 : "__proto__: {}, get __proto__() {}", "__proto__: {}, set __proto__(v) {}",
7754 5 : "__proto__: {}, __proto__", nullptr};
7755 :
7756 5 : RunParserSyncTest(context_data, error_data, kSuccess);
7757 5 : }
7758 :
7759 :
7760 28342 : TEST(DeclarationsError) {
7761 : const char* context_data[][2] = {{"'use strict'; if (true)", ""},
7762 : {"'use strict'; if (false) {} else", ""},
7763 : {"'use strict'; while (false)", ""},
7764 : {"'use strict'; for (;;)", ""},
7765 : {"'use strict'; for (x in y)", ""},
7766 : {"'use strict'; do ", " while (false)"},
7767 5 : {nullptr, nullptr}};
7768 :
7769 : const char* statement_data[] = {"let x = 1;", "const x = 1;", "class C {}",
7770 5 : nullptr};
7771 :
7772 5 : RunParserSyncTest(context_data, statement_data, kError);
7773 5 : }
7774 :
7775 :
7776 20 : void TestLanguageMode(const char* source,
7777 : i::LanguageMode expected_language_mode) {
7778 : i::Isolate* isolate = CcTest::i_isolate();
7779 : i::Factory* factory = isolate->factory();
7780 20 : v8::HandleScope handles(CcTest::isolate());
7781 20 : v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
7782 : v8::Context::Scope context_scope(context);
7783 20 : isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
7784 20 : 128 * 1024);
7785 :
7786 : i::Handle<i::Script> script =
7787 20 : factory->NewScript(factory->NewStringFromAsciiChecked(source));
7788 40 : i::ParseInfo info(isolate, script);
7789 20 : i::parsing::ParseProgram(&info, isolate);
7790 20 : CHECK_NOT_NULL(info.literal());
7791 40 : CHECK_EQ(expected_language_mode, info.literal()->language_mode());
7792 20 : }
7793 :
7794 :
7795 28342 : TEST(LanguageModeDirectives) {
7796 5 : TestLanguageMode("\"use nothing\"", i::LanguageMode::kSloppy);
7797 5 : TestLanguageMode("\"use strict\"", i::LanguageMode::kStrict);
7798 :
7799 5 : TestLanguageMode("var x = 1; \"use strict\"", i::LanguageMode::kSloppy);
7800 :
7801 : TestLanguageMode("\"use some future directive\"; \"use strict\";",
7802 5 : i::LanguageMode::kStrict);
7803 5 : }
7804 :
7805 :
7806 28342 : TEST(PropertyNameEvalArguments) {
7807 5 : const char* context_data[][2] = {{"'use strict';", ""}, {nullptr, nullptr}};
7808 :
7809 : const char* statement_data[] = {"({eval: 1})",
7810 : "({arguments: 1})",
7811 : "({eval() {}})",
7812 : "({arguments() {}})",
7813 : "({*eval() {}})",
7814 : "({*arguments() {}})",
7815 : "({get eval() {}})",
7816 : "({get arguments() {}})",
7817 : "({set eval(_) {}})",
7818 : "({set arguments(_) {}})",
7819 :
7820 : "class C {eval() {}}",
7821 : "class C {arguments() {}}",
7822 : "class C {*eval() {}}",
7823 : "class C {*arguments() {}}",
7824 : "class C {get eval() {}}",
7825 : "class C {get arguments() {}}",
7826 : "class C {set eval(_) {}}",
7827 : "class C {set arguments(_) {}}",
7828 :
7829 : "class C {static eval() {}}",
7830 : "class C {static arguments() {}}",
7831 : "class C {static *eval() {}}",
7832 : "class C {static *arguments() {}}",
7833 : "class C {static get eval() {}}",
7834 : "class C {static get arguments() {}}",
7835 : "class C {static set eval(_) {}}",
7836 : "class C {static set arguments(_) {}}",
7837 :
7838 5 : nullptr};
7839 :
7840 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
7841 5 : }
7842 :
7843 :
7844 28342 : TEST(FunctionLiteralDuplicateParameters) {
7845 : const char* strict_context_data[][2] = {
7846 : {"'use strict';(function(", "){})();"},
7847 : {"(function(", ") { 'use strict'; })();"},
7848 : {"'use strict'; function fn(", ") {}; fn();"},
7849 : {"function fn(", ") { 'use strict'; }; fn();"},
7850 5 : {nullptr, nullptr}};
7851 :
7852 : const char* sloppy_context_data[][2] = {{"(function(", "){})();"},
7853 : {"(function(", ") {})();"},
7854 : {"function fn(", ") {}; fn();"},
7855 : {"function fn(", ") {}; fn();"},
7856 5 : {nullptr, nullptr}};
7857 :
7858 : const char* data[] = {
7859 : "a, a",
7860 : "a, a, a",
7861 : "b, a, a",
7862 : "a, b, c, c",
7863 : "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
7864 5 : nullptr};
7865 :
7866 5 : RunParserSyncTest(strict_context_data, data, kError);
7867 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
7868 5 : }
7869 :
7870 :
7871 28342 : TEST(ArrowFunctionASIErrors) {
7872 : const char* context_data[][2] = {
7873 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
7874 :
7875 : const char* data[] = {"(a\n=> a)(1)",
7876 : "(a/*\n*/=> a)(1)",
7877 : "((a)\n=> a)(1)",
7878 : "((a)/*\n*/=> a)(1)",
7879 : "((a, b)\n=> a + b)(1, 2)",
7880 : "((a, b)/*\n*/=> a + b)(1, 2)",
7881 5 : nullptr};
7882 5 : RunParserSyncTest(context_data, data, kError);
7883 5 : }
7884 :
7885 28342 : TEST(ObjectSpreadPositiveTests) {
7886 : // clang-format off
7887 : const char* context_data[][2] = {
7888 : {"x = ", ""},
7889 : {"'use strict'; x = ", ""},
7890 5 : {nullptr, nullptr}};
7891 :
7892 : // clang-format off
7893 : const char* data[] = {
7894 : "{ ...y }",
7895 : "{ a: 1, ...y }",
7896 : "{ b: 1, ...y }",
7897 : "{ y, ...y}",
7898 : "{ ...z = y}",
7899 : "{ ...y, y }",
7900 : "{ ...y, ...y}",
7901 : "{ a: 1, ...y, b: 1}",
7902 : "{ ...y, b: 1}",
7903 : "{ ...1}",
7904 : "{ ...null}",
7905 : "{ ...undefined}",
7906 : "{ ...1 in {}}",
7907 : "{ ...[]}",
7908 : "{ ...async function() { }}",
7909 : "{ ...async () => { }}",
7910 : "{ ...new Foo()}",
7911 5 : nullptr};
7912 : // clang-format on
7913 :
7914 5 : RunParserSyncTest(context_data, data, kSuccess);
7915 5 : }
7916 :
7917 28342 : TEST(ObjectSpreadNegativeTests) {
7918 : const char* context_data[][2] = {
7919 5 : {"x = ", ""}, {"'use strict'; x = ", ""}, {nullptr, nullptr}};
7920 :
7921 : // clang-format off
7922 : const char* data[] = {
7923 : "{ ...var z = y}",
7924 : "{ ...var}",
7925 : "{ ...foo bar}",
7926 : "{* ...foo}",
7927 : "{get ...foo}",
7928 : "{set ...foo}",
7929 : "{async ...foo}",
7930 5 : nullptr};
7931 :
7932 5 : RunParserSyncTest(context_data, data, kError);
7933 5 : }
7934 :
7935 28342 : TEST(TemplateEscapesPositiveTests) {
7936 : // clang-format off
7937 : const char* context_data[][2] = {
7938 : {"", ""},
7939 : {"'use strict';", ""},
7940 5 : {nullptr, nullptr}};
7941 :
7942 : // clang-format off
7943 : const char* data[] = {
7944 : "tag`\\08`",
7945 : "tag`\\01`",
7946 : "tag`\\01${0}right`",
7947 : "tag`left${0}\\01`",
7948 : "tag`left${0}\\01${1}right`",
7949 : "tag`\\1`",
7950 : "tag`\\1${0}right`",
7951 : "tag`left${0}\\1`",
7952 : "tag`left${0}\\1${1}right`",
7953 : "tag`\\xg`",
7954 : "tag`\\xg${0}right`",
7955 : "tag`left${0}\\xg`",
7956 : "tag`left${0}\\xg${1}right`",
7957 : "tag`\\xAg`",
7958 : "tag`\\xAg${0}right`",
7959 : "tag`left${0}\\xAg`",
7960 : "tag`left${0}\\xAg${1}right`",
7961 : "tag`\\u0`",
7962 : "tag`\\u0${0}right`",
7963 : "tag`left${0}\\u0`",
7964 : "tag`left${0}\\u0${1}right`",
7965 : "tag`\\u0g`",
7966 : "tag`\\u0g${0}right`",
7967 : "tag`left${0}\\u0g`",
7968 : "tag`left${0}\\u0g${1}right`",
7969 : "tag`\\u00g`",
7970 : "tag`\\u00g${0}right`",
7971 : "tag`left${0}\\u00g`",
7972 : "tag`left${0}\\u00g${1}right`",
7973 : "tag`\\u000g`",
7974 : "tag`\\u000g${0}right`",
7975 : "tag`left${0}\\u000g`",
7976 : "tag`left${0}\\u000g${1}right`",
7977 : "tag`\\u{}`",
7978 : "tag`\\u{}${0}right`",
7979 : "tag`left${0}\\u{}`",
7980 : "tag`left${0}\\u{}${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{g}`",
7986 : "tag`\\u{g}${0}right`",
7987 : "tag`left${0}\\u{g}`",
7988 : "tag`left${0}\\u{g}${1}right`",
7989 : "tag`\\u{0`",
7990 : "tag`\\u{0${0}right`",
7991 : "tag`left${0}\\u{0`",
7992 : "tag`left${0}\\u{0${1}right`",
7993 : "tag`\\u{\\u{0}`",
7994 : "tag`\\u{\\u{0}${0}right`",
7995 : "tag`left${0}\\u{\\u{0}`",
7996 : "tag`left${0}\\u{\\u{0}${1}right`",
7997 : "tag`\\u{110000}`",
7998 : "tag`\\u{110000}${0}right`",
7999 : "tag`left${0}\\u{110000}`",
8000 : "tag`left${0}\\u{110000}${1}right`",
8001 : "tag` ${tag`\\u`}`",
8002 : "tag` ``\\u`",
8003 : "tag`\\u`` `",
8004 : "tag`\\u``\\u`",
8005 : "` ${tag`\\u`}`",
8006 : "` ``\\u`",
8007 5 : nullptr};
8008 : // clang-format on
8009 :
8010 5 : RunParserSyncTest(context_data, data, kSuccess);
8011 5 : }
8012 :
8013 28342 : TEST(TemplateEscapesNegativeTests) {
8014 : // clang-format off
8015 : const char* context_data[][2] = {
8016 : {"", ""},
8017 : {"'use strict';", ""},
8018 5 : {nullptr, nullptr}};
8019 :
8020 : // clang-format off
8021 : const char* data[] = {
8022 : "`\\08`",
8023 : "`\\01`",
8024 : "`\\01${0}right`",
8025 : "`left${0}\\01`",
8026 : "`left${0}\\01${1}right`",
8027 : "`\\1`",
8028 : "`\\1${0}right`",
8029 : "`left${0}\\1`",
8030 : "`left${0}\\1${1}right`",
8031 : "`\\xg`",
8032 : "`\\xg${0}right`",
8033 : "`left${0}\\xg`",
8034 : "`left${0}\\xg${1}right`",
8035 : "`\\xAg`",
8036 : "`\\xAg${0}right`",
8037 : "`left${0}\\xAg`",
8038 : "`left${0}\\xAg${1}right`",
8039 : "`\\u0`",
8040 : "`\\u0${0}right`",
8041 : "`left${0}\\u0`",
8042 : "`left${0}\\u0${1}right`",
8043 : "`\\u0g`",
8044 : "`\\u0g${0}right`",
8045 : "`left${0}\\u0g`",
8046 : "`left${0}\\u0g${1}right`",
8047 : "`\\u00g`",
8048 : "`\\u00g${0}right`",
8049 : "`left${0}\\u00g`",
8050 : "`left${0}\\u00g${1}right`",
8051 : "`\\u000g`",
8052 : "`\\u000g${0}right`",
8053 : "`left${0}\\u000g`",
8054 : "`left${0}\\u000g${1}right`",
8055 : "`\\u{}`",
8056 : "`\\u{}${0}right`",
8057 : "`left${0}\\u{}`",
8058 : "`left${0}\\u{}${1}right`",
8059 : "`\\u{-0}`",
8060 : "`\\u{-0}${0}right`",
8061 : "`left${0}\\u{-0}`",
8062 : "`left${0}\\u{-0}${1}right`",
8063 : "`\\u{g}`",
8064 : "`\\u{g}${0}right`",
8065 : "`left${0}\\u{g}`",
8066 : "`left${0}\\u{g}${1}right`",
8067 : "`\\u{0`",
8068 : "`\\u{0${0}right`",
8069 : "`left${0}\\u{0`",
8070 : "`left${0}\\u{0${1}right`",
8071 : "`\\u{\\u{0}`",
8072 : "`\\u{\\u{0}${0}right`",
8073 : "`left${0}\\u{\\u{0}`",
8074 : "`left${0}\\u{\\u{0}${1}right`",
8075 : "`\\u{110000}`",
8076 : "`\\u{110000}${0}right`",
8077 : "`left${0}\\u{110000}`",
8078 : "`left${0}\\u{110000}${1}right`",
8079 : "`\\1``\\2`",
8080 : "tag` ${`\\u`}`",
8081 : "`\\u```",
8082 5 : nullptr};
8083 : // clang-format on
8084 :
8085 5 : RunParserSyncTest(context_data, data, kError);
8086 5 : }
8087 :
8088 28342 : TEST(DestructuringPositiveTests) {
8089 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8090 : {"var ", " = {};"},
8091 : {"'use strict'; const ", " = {};"},
8092 : {"function f(", ") {}"},
8093 : {"function f(argument1, ", ") {}"},
8094 : {"var f = (", ") => {};"},
8095 : {"var f = (argument1,", ") => {};"},
8096 : {"try {} catch(", ") {}"},
8097 5 : {nullptr, nullptr}};
8098 :
8099 : // clang-format off
8100 : const char* data[] = {
8101 : "a",
8102 : "{ x : y }",
8103 : "{ x : y = 1 }",
8104 : "{ get, set }",
8105 : "{ get = 1, set = 2 }",
8106 : "[a]",
8107 : "[a = 1]",
8108 : "[a,b,c]",
8109 : "[a, b = 42, c]",
8110 : "{ x : x, y : y }",
8111 : "{ x : x = 1, y : y }",
8112 : "{ x : x, y : y = 42 }",
8113 : "[]",
8114 : "{}",
8115 : "[{x:x, y:y}, [a,b,c]]",
8116 : "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
8117 : "{x}",
8118 : "{x, y}",
8119 : "{x = 42, y = 15}",
8120 : "[a,,b]",
8121 : "{42 : x}",
8122 : "{42 : x = 42}",
8123 : "{42e-2 : x}",
8124 : "{42e-2 : x = 42}",
8125 : "{x : y, x : z}",
8126 : "{'hi' : x}",
8127 : "{'hi' : x = 42}",
8128 : "{var: x}",
8129 : "{var: x = 42}",
8130 : "{[x] : z}",
8131 : "{[1+1] : z}",
8132 : "{[foo()] : z}",
8133 : "{}",
8134 : "[...rest]",
8135 : "[a,b,...rest]",
8136 : "[a,,...rest]",
8137 : "{ __proto__: x, __proto__: y}",
8138 : "{arguments: x}",
8139 : "{eval: x}",
8140 : "{ x : y, ...z }",
8141 : "{ x : y = 1, ...z }",
8142 : "{ x : x, y : y, ...z }",
8143 : "{ x : x = 1, y : y, ...z }",
8144 : "{ x : x, y : y = 42, ...z }",
8145 : "[{x:x, y:y, ...z}, [a,b,c]]",
8146 : "[{x:x = 1, y:y = 2, ...z}, [a = 3, b = 4, c = 5]]",
8147 : "{...x}",
8148 : "{x, ...y}",
8149 : "{x = 42, y = 15, ...z}",
8150 : "{42 : x = 42, ...y}",
8151 : "{'hi' : x, ...z}",
8152 : "{'hi' : x = 42, ...z}",
8153 : "{var: x = 42, ...z}",
8154 : "{[x] : z, ...y}",
8155 : "{[1+1] : z, ...x}",
8156 : "{arguments: x, ...z}",
8157 : "{ __proto__: x, __proto__: y, ...z}",
8158 : nullptr
8159 5 : };
8160 :
8161 : // clang-format on
8162 5 : RunParserSyncTest(context_data, data, kSuccess);
8163 :
8164 : // v8:5201
8165 : {
8166 : // clang-format off
8167 : const char* sloppy_context_data[][2] = {
8168 : {"var ", " = {};"},
8169 : {"function f(", ") {}"},
8170 : {"function f(argument1, ", ") {}"},
8171 : {"var f = (", ") => {};"},
8172 : {"var f = (argument1,", ") => {};"},
8173 : {"try {} catch(", ") {}"},
8174 : {nullptr, nullptr}
8175 5 : };
8176 :
8177 : const char* data[] = {
8178 : "{arguments}",
8179 : "{eval}",
8180 : "{x: arguments}",
8181 : "{x: eval}",
8182 : "{arguments = false}",
8183 : "{eval = false}",
8184 : "{...arguments}",
8185 : "{...eval}",
8186 : nullptr
8187 5 : };
8188 : // clang-format on
8189 5 : RunParserSyncTest(sloppy_context_data, data, kSuccess);
8190 : }
8191 5 : }
8192 :
8193 :
8194 28342 : TEST(DestructuringNegativeTests) {
8195 : { // All modes.
8196 : const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
8197 : {"var ", " = {};"},
8198 : {"'use strict'; const ", " = {};"},
8199 : {"function f(", ") {}"},
8200 : {"function f(argument1, ", ") {}"},
8201 : {"var f = (", ") => {};"},
8202 : {"var f = ", " => {};"},
8203 : {"var f = (argument1,", ") => {};"},
8204 : {"try {} catch(", ") {}"},
8205 5 : {nullptr, nullptr}};
8206 :
8207 : // clang-format off
8208 : const char* data[] = {
8209 : "a++",
8210 : "++a",
8211 : "delete a",
8212 : "void a",
8213 : "typeof a",
8214 : "--a",
8215 : "+a",
8216 : "-a",
8217 : "~a",
8218 : "!a",
8219 : "{ x : y++ }",
8220 : "[a++]",
8221 : "(x => y)",
8222 : "(async x => y)",
8223 : "((x, z) => y)",
8224 : "(async (x, z) => y)",
8225 : "a[i]", "a()",
8226 : "a.b",
8227 : "new a",
8228 : "a + a",
8229 : "a - a",
8230 : "a * a",
8231 : "a / a",
8232 : "a == a",
8233 : "a != a",
8234 : "a > a",
8235 : "a < a",
8236 : "a <<< a",
8237 : "a >>> a",
8238 : "function a() {}",
8239 : "function* a() {}",
8240 : "async function a() {}",
8241 : "a`bcd`",
8242 : "this",
8243 : "null",
8244 : "true",
8245 : "false",
8246 : "1",
8247 : "'abc'",
8248 : "/abc/",
8249 : "`abc`",
8250 : "class {}",
8251 : "{+2 : x}",
8252 : "{-2 : x}",
8253 : "var",
8254 : "[var]",
8255 : "{x : {y : var}}",
8256 : "{x : x = a+}",
8257 : "{x : x = (a+)}",
8258 : "{x : x += a}",
8259 : "{m() {} = 0}",
8260 : "{[1+1]}",
8261 : "[...rest, x]",
8262 : "[a,b,...rest, x]",
8263 : "[a,,...rest, x]",
8264 : "[...rest,]",
8265 : "[a,b,...rest,]",
8266 : "[a,,...rest,]",
8267 : "[...rest,...rest1]",
8268 : "[a,b,...rest,...rest1]",
8269 : "[a,,..rest,...rest1]",
8270 : "[x, y, ...z = 1]",
8271 : "[...z = 1]",
8272 : "[x, y, ...[z] = [1]]",
8273 : "[...[z] = [1]]",
8274 : "{ x : 3 }",
8275 : "{ x : 'foo' }",
8276 : "{ x : /foo/ }",
8277 : "{ x : `foo` }",
8278 : "{ get a() {} }",
8279 : "{ set a() {} }",
8280 : "{ method() {} }",
8281 : "{ *method() {} }",
8282 : "...a++",
8283 : "...++a",
8284 : "...typeof a",
8285 : "...[a++]",
8286 : "...(x => y)",
8287 : "{ ...x, }",
8288 : "{ ...x, y }",
8289 : "{ y, ...x, y }",
8290 : "{ ...x, ...y }",
8291 : "{ ...x, ...x }",
8292 : "{ ...x, ...x = {} }",
8293 : "{ ...x, ...x = ...x }",
8294 : "{ ...x, ...x = ...{ x } }",
8295 : "{ ,, ...x }",
8296 : "{ ...get a() {} }",
8297 : "{ ...set a() {} }",
8298 : "{ ...method() {} }",
8299 : "{ ...function() {} }",
8300 : "{ ...*method() {} }",
8301 : "{...{x} }",
8302 : "{...[x] }",
8303 : "{...{ x = 5 } }",
8304 : "{...[ x = 5 ] }",
8305 : "{...x.f }",
8306 : "{...x[0] }",
8307 : "async function* a() {}",
8308 : nullptr
8309 5 : };
8310 :
8311 : // clang-format on
8312 5 : RunParserSyncTest(context_data, data, kError);
8313 : }
8314 :
8315 : { // All modes.
8316 : const char* context_data[][2] = {
8317 : {"'use strict'; let ", " = {};"}, {"var ", " = {};"},
8318 : {"'use strict'; const ", " = {};"}, {"function f(", ") {}"},
8319 : {"function f(argument1, ", ") {}"}, {"var f = (", ") => {};"},
8320 5 : {"var f = (argument1,", ") => {};"}, {nullptr, nullptr}};
8321 :
8322 : // clang-format off
8323 : const char* data[] = {
8324 : "x => x",
8325 : "() => x",
8326 5 : nullptr};
8327 : // clang-format on
8328 5 : RunParserSyncTest(context_data, data, kError);
8329 : }
8330 :
8331 : { // Strict mode.
8332 : const char* context_data[][2] = {
8333 : {"'use strict'; var ", " = {};"},
8334 : {"'use strict'; let ", " = {};"},
8335 : {"'use strict'; const ", " = {};"},
8336 : {"'use strict'; function f(", ") {}"},
8337 : {"'use strict'; function f(argument1, ", ") {}"},
8338 5 : {nullptr, nullptr}};
8339 :
8340 : // clang-format off
8341 : const char* data[] = {
8342 : "[arguments]",
8343 : "[eval]",
8344 : "{ a : arguments }",
8345 : "{ a : eval }",
8346 : "[public]",
8347 : "{ x : private }",
8348 : "{ x : arguments }",
8349 : "{ x : eval }",
8350 : "{ arguments }",
8351 : "{ eval }",
8352 : "{ arguments = false }"
8353 : "{ eval = false }",
8354 : "{ ...eval }",
8355 : "{ ...arguments }",
8356 5 : nullptr};
8357 :
8358 : // clang-format on
8359 5 : RunParserSyncTest(context_data, data, kError);
8360 : }
8361 :
8362 : { // 'yield' in generators.
8363 : const char* context_data[][2] = {
8364 : {"function*() { var ", " = {};"},
8365 : {"function*() { 'use strict'; let ", " = {};"},
8366 : {"function*() { 'use strict'; const ", " = {};"},
8367 5 : {nullptr, nullptr}};
8368 :
8369 : // clang-format off
8370 : const char* data[] = {
8371 : "yield",
8372 : "[yield]",
8373 : "{ x : yield }",
8374 5 : nullptr};
8375 : // clang-format on
8376 5 : RunParserSyncTest(context_data, data, kError);
8377 : }
8378 :
8379 : { // Declaration-specific errors
8380 : const char* context_data[][2] = {{"'use strict'; var ", ""},
8381 : {"'use strict'; let ", ""},
8382 : {"'use strict'; const ", ""},
8383 : {"'use strict'; for (var ", ";;) {}"},
8384 : {"'use strict'; for (let ", ";;) {}"},
8385 : {"'use strict'; for (const ", ";;) {}"},
8386 : {"var ", ""},
8387 : {"let ", ""},
8388 : {"const ", ""},
8389 : {"for (var ", ";;) {}"},
8390 : {"for (let ", ";;) {}"},
8391 : {"for (const ", ";;) {}"},
8392 5 : {nullptr, nullptr}};
8393 :
8394 : // clang-format off
8395 : const char* data[] = {
8396 : "{ a }",
8397 : "[ a ]",
8398 : "{ ...a }",
8399 : nullptr
8400 5 : };
8401 : // clang-format on
8402 5 : RunParserSyncTest(context_data, data, kError);
8403 : }
8404 5 : }
8405 :
8406 28342 : TEST(ObjectRestNegativeTestSlow) {
8407 : // clang-format off
8408 : const char* context_data[][2] = {
8409 : {"var { ", " } = { a: 1};"},
8410 : { nullptr, nullptr }
8411 5 : };
8412 :
8413 : using v8::internal::Code;
8414 : std::string statement;
8415 327675 : for (int i = 0; i < Code::kMaxArguments; ++i) {
8416 983010 : statement += std::to_string(i) + " : " + "x, ";
8417 : }
8418 : statement += "...y";
8419 :
8420 : const char* statement_data[] = {
8421 : statement.c_str(),
8422 : nullptr
8423 10 : };
8424 :
8425 : // clang-format on
8426 : // The test is quite slow, so run it with a reduced set of flags.
8427 : static const ParserFlag flags[] = {kAllowLazy};
8428 : RunParserSyncTest(context_data, statement_data, kError, nullptr, 0, flags,
8429 5 : arraysize(flags));
8430 5 : }
8431 :
8432 28342 : TEST(DestructuringAssignmentPositiveTests) {
8433 : const char* context_data[][2] = {
8434 : {"'use strict'; let x, y, z; (", " = {});"},
8435 : {"var x, y, z; (", " = {});"},
8436 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8437 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8438 : {"var x, y, z; for (x in ", " = {});"},
8439 : {"var x, y, z; for (x of ", " = {});"},
8440 : {"var x, y, z; for (", " in {});"},
8441 : {"var x, y, z; for (", " of {});"},
8442 : {"'use strict'; var x, y, z; for (", " in {});"},
8443 : {"'use strict'; var x, y, z; for (", " of {});"},
8444 : {"var x, y, z; m(['a']) ? ", " = {} : rhs"},
8445 : {"var x, y, z; m(['b']) ? lhs : ", " = {}"},
8446 : {"'use strict'; var x, y, z; m(['a']) ? ", " = {} : rhs"},
8447 : {"'use strict'; var x, y, z; m(['b']) ? lhs : ", " = {}"},
8448 5 : {nullptr, nullptr}};
8449 :
8450 : const char* mixed_assignments_context_data[][2] = {
8451 : {"'use strict'; let x, y, z; (", " = z = {});"},
8452 : {"var x, y, z; (", " = z = {});"},
8453 : {"'use strict'; let x, y, z; (x = ", " = z = {});"},
8454 : {"var x, y, z; (x = ", " = z = {});"},
8455 : {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
8456 : {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
8457 : {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
8458 : {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
8459 : {"var x, y, z; for (x in ", " = z = {});"},
8460 : {"var x, y, z; for (x in x = ", " = z = {});"},
8461 : {"var x, y, z; for (x of ", " = z = {});"},
8462 : {"var x, y, z; for (x of x = ", " = z = {});"},
8463 5 : {nullptr, nullptr}};
8464 :
8465 : // clang-format off
8466 : const char* data[] = {
8467 : "x",
8468 :
8469 : "{ x : y }",
8470 : "{ x : foo().y }",
8471 : "{ x : foo()[y] }",
8472 : "{ x : y.z }",
8473 : "{ x : y[z] }",
8474 : "{ x : { y } }",
8475 : "{ x : { foo: y } }",
8476 : "{ x : { foo: foo().y } }",
8477 : "{ x : { foo: foo()[y] } }",
8478 : "{ x : { foo: y.z } }",
8479 : "{ x : { foo: y[z] } }",
8480 : "{ x : [ y ] }",
8481 : "{ x : [ foo().y ] }",
8482 : "{ x : [ foo()[y] ] }",
8483 : "{ x : [ y.z ] }",
8484 : "{ x : [ y[z] ] }",
8485 :
8486 : "{ x : y = 10 }",
8487 : "{ x : foo().y = 10 }",
8488 : "{ x : foo()[y] = 10 }",
8489 : "{ x : y.z = 10 }",
8490 : "{ x : y[z] = 10 }",
8491 : "{ x : { y = 10 } = {} }",
8492 : "{ x : { foo: y = 10 } = {} }",
8493 : "{ x : { foo: foo().y = 10 } = {} }",
8494 : "{ x : { foo: foo()[y] = 10 } = {} }",
8495 : "{ x : { foo: y.z = 10 } = {} }",
8496 : "{ x : { foo: y[z] = 10 } = {} }",
8497 : "{ x : [ y = 10 ] = {} }",
8498 : "{ x : [ foo().y = 10 ] = {} }",
8499 : "{ x : [ foo()[y] = 10 ] = {} }",
8500 : "{ x : [ y.z = 10 ] = {} }",
8501 : "{ x : [ y[z] = 10 ] = {} }",
8502 : "{ z : { __proto__: x, __proto__: y } = z }"
8503 :
8504 : "[ x ]",
8505 : "[ foo().x ]",
8506 : "[ foo()[x] ]",
8507 : "[ x.y ]",
8508 : "[ x[y] ]",
8509 : "[ { x } ]",
8510 : "[ { x : y } ]",
8511 : "[ { x : foo().y } ]",
8512 : "[ { x : foo()[y] } ]",
8513 : "[ { x : x.y } ]",
8514 : "[ { x : x[y] } ]",
8515 : "[ [ x ] ]",
8516 : "[ [ foo().x ] ]",
8517 : "[ [ foo()[x] ] ]",
8518 : "[ [ x.y ] ]",
8519 : "[ [ x[y] ] ]",
8520 :
8521 : "[ x = 10 ]",
8522 : "[ foo().x = 10 ]",
8523 : "[ foo()[x] = 10 ]",
8524 : "[ x.y = 10 ]",
8525 : "[ x[y] = 10 ]",
8526 : "[ { x = 10 } = {} ]",
8527 : "[ { x : y = 10 } = {} ]",
8528 : "[ { x : foo().y = 10 } = {} ]",
8529 : "[ { x : foo()[y] = 10 } = {} ]",
8530 : "[ { x : x.y = 10 } = {} ]",
8531 : "[ { x : x[y] = 10 } = {} ]",
8532 : "[ [ x = 10 ] = {} ]",
8533 : "[ [ foo().x = 10 ] = {} ]",
8534 : "[ [ foo()[x] = 10 ] = {} ]",
8535 : "[ [ x.y = 10 ] = {} ]",
8536 : "[ [ x[y] = 10 ] = {} ]",
8537 : "{ x : y = 1 }",
8538 : "{ x }",
8539 : "{ x, y, z }",
8540 : "{ x = 1, y: z, z: y }",
8541 : "{x = 42, y = 15}",
8542 : "[x]",
8543 : "[x = 1]",
8544 : "[x,y,z]",
8545 : "[x, y = 42, z]",
8546 : "{ x : x, y : y }",
8547 : "{ x : x = 1, y : y }",
8548 : "{ x : x, y : y = 42 }",
8549 : "[]",
8550 : "{}",
8551 : "[{x:x, y:y}, [,x,z,]]",
8552 : "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
8553 : "[x,,y]",
8554 : "[(x),,(y)]",
8555 : "[(x)]",
8556 : "{42 : x}",
8557 : "{42 : x = 42}",
8558 : "{42e-2 : x}",
8559 : "{42e-2 : x = 42}",
8560 : "{'hi' : x}",
8561 : "{'hi' : x = 42}",
8562 : "{var: x}",
8563 : "{var: x = 42}",
8564 : "{var: (x) = 42}",
8565 : "{[x] : z}",
8566 : "{[1+1] : z}",
8567 : "{[1+1] : (z)}",
8568 : "{[foo()] : z}",
8569 : "{[foo()] : (z)}",
8570 : "{[foo()] : foo().bar}",
8571 : "{[foo()] : foo()['bar']}",
8572 : "{[foo()] : this.bar}",
8573 : "{[foo()] : this['bar']}",
8574 : "{[foo()] : 'foo'.bar}",
8575 : "{[foo()] : 'foo'['bar']}",
8576 : "[...x]",
8577 : "[x,y,...z]",
8578 : "[x,,...z]",
8579 : "{ x: y }",
8580 : "[x, y]",
8581 : "[((x, y) => z).x]",
8582 : "{x: ((y, z) => z).x}",
8583 : "[((x, y) => z)['x']]",
8584 : "{x: ((y, z) => z)['x']}",
8585 :
8586 : "{x: { y = 10 } }",
8587 : "[(({ x } = { x: 1 }) => x).a]",
8588 :
8589 : "{ ...d.x }",
8590 : "{ ...c[0]}",
8591 :
8592 : // v8:4662
8593 : "{ x: (y) }",
8594 : "{ x: (y) = [] }",
8595 : "{ x: (foo.bar) }",
8596 : "{ x: (foo['bar']) }",
8597 : "[ ...(a) ]",
8598 : "[ ...(foo['bar']) ]",
8599 : "[ ...(foo.bar) ]",
8600 : "[ (y) ]",
8601 : "[ (foo.bar) ]",
8602 : "[ (foo['bar']) ]",
8603 :
8604 5 : nullptr};
8605 : // clang-format on
8606 5 : RunParserSyncTest(context_data, data, kSuccess);
8607 :
8608 5 : RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
8609 :
8610 : const char* empty_context_data[][2] = {
8611 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8612 :
8613 : // CoverInitializedName ambiguity handling in various contexts
8614 : const char* ambiguity_data[] = {
8615 : "var foo = { x = 10 } = {};",
8616 : "var foo = { q } = { x = 10 } = {};",
8617 : "var foo; foo = { x = 10 } = {};",
8618 : "var foo; foo = { q } = { x = 10 } = {};",
8619 : "var x; ({ x = 10 } = {});",
8620 : "var q, x; ({ q } = { x = 10 } = {});",
8621 : "var x; [{ x = 10 } = {}]",
8622 : "var x; (true ? { x = true } = {} : { x = false } = {})",
8623 : "var q, x; (q, { x = 10 } = {});",
8624 : "var { x = 10 } = { x = 20 } = {};",
8625 : "var { __proto__: x, __proto__: y } = {}",
8626 : "({ __proto__: x, __proto__: y } = {})",
8627 : "var { x = 10 } = (o = { x = 20 } = {});",
8628 : "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
8629 : nullptr,
8630 5 : };
8631 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
8632 5 : }
8633 :
8634 :
8635 28342 : TEST(DestructuringAssignmentNegativeTests) {
8636 : const char* context_data[][2] = {
8637 : {"'use strict'; let x, y, z; (", " = {});"},
8638 : {"var x, y, z; (", " = {});"},
8639 : {"'use strict'; let x, y, z; for (x in ", " = {});"},
8640 : {"'use strict'; let x, y, z; for (x of ", " = {});"},
8641 : {"var x, y, z; for (x in ", " = {});"},
8642 : {"var x, y, z; for (x of ", " = {});"},
8643 5 : {nullptr, nullptr}};
8644 :
8645 : // clang-format off
8646 : const char* data[] = {
8647 : "{ x : ++y }",
8648 : "{ x : y * 2 }",
8649 : "{ get x() {} }",
8650 : "{ set x() {} }",
8651 : "{ x: y() }",
8652 : "{ this }",
8653 : "{ x: this }",
8654 : "{ x: this = 1 }",
8655 : "{ super }",
8656 : "{ x: super }",
8657 : "{ x: super = 1 }",
8658 : "{ new.target }",
8659 : "{ x: new.target }",
8660 : "{ x: new.target = 1 }",
8661 : "{ import.meta }",
8662 : "{ x: import.meta }",
8663 : "{ x: import.meta = 1 }",
8664 : "[x--]",
8665 : "[--x = 1]",
8666 : "[x()]",
8667 : "[this]",
8668 : "[this = 1]",
8669 : "[new.target]",
8670 : "[new.target = 1]",
8671 : "[import.meta]",
8672 : "[import.meta = 1]",
8673 : "[super]",
8674 : "[super = 1]",
8675 : "[function f() {}]",
8676 : "[async function f() {}]",
8677 : "[function* f() {}]",
8678 : "[50]",
8679 : "[(50)]",
8680 : "[(function() {})]",
8681 : "[(async function() {})]",
8682 : "[(function*() {})]",
8683 : "[(foo())]",
8684 : "{ x: 50 }",
8685 : "{ x: (50) }",
8686 : "['str']",
8687 : "{ x: 'str' }",
8688 : "{ x: ('str') }",
8689 : "{ x: (foo()) }",
8690 : "{ x: function() {} }",
8691 : "{ x: async function() {} }",
8692 : "{ x: function*() {} }",
8693 : "{ x: (function() {}) }",
8694 : "{ x: (async function() {}) }",
8695 : "{ x: (function*() {}) }",
8696 : "{ x: y } = 'str'",
8697 : "[x, y] = 'str'",
8698 : "[(x,y) => z]",
8699 : "[async(x,y) => z]",
8700 : "[async x => z]",
8701 : "{x: (y) => z}",
8702 : "{x: (y,w) => z}",
8703 : "{x: async (y) => z}",
8704 : "{x: async (y,w) => z}",
8705 : "[x, ...y, z]",
8706 : "[...x,]",
8707 : "[x, y, ...z = 1]",
8708 : "[...z = 1]",
8709 : "[x, y, ...[z] = [1]]",
8710 : "[...[z] = [1]]",
8711 :
8712 : "[...++x]",
8713 : "[...x--]",
8714 : "[...!x]",
8715 : "[...x + y]",
8716 :
8717 : // v8:4657
8718 : "({ x: x4, x: (x+=1e4) })",
8719 : "(({ x: x4, x: (x+=1e4) }))",
8720 : "({ x: x4, x: (x+=1e4) } = {})",
8721 : "(({ x: x4, x: (x+=1e4) } = {}))",
8722 : "(({ x: x4, x: (x+=1e4) }) = {})",
8723 : "({ x: y } = {})",
8724 : "(({ x: y } = {}))",
8725 : "(({ x: y }) = {})",
8726 : "([a])",
8727 : "(([a]))",
8728 : "([a] = [])",
8729 : "(([a] = []))",
8730 : "(([a]) = [])",
8731 :
8732 : // v8:4662
8733 : "{ x: ([y]) }",
8734 : "{ x: ([y] = []) }",
8735 : "{ x: ({y}) }",
8736 : "{ x: ({y} = {}) }",
8737 : "{ x: (++y) }",
8738 : "[ (...[a]) ]",
8739 : "[ ...([a]) ]",
8740 : "[ ...([a] = [])",
8741 : "[ ...[ ( [ a ] ) ] ]",
8742 : "[ ([a]) ]",
8743 : "[ (...[a]) ]",
8744 : "[ ([a] = []) ]",
8745 : "[ (++y) ]",
8746 : "[ ...(++y) ]",
8747 :
8748 : "[ x += x ]",
8749 : "{ foo: x += x }",
8750 :
8751 5 : nullptr};
8752 : // clang-format on
8753 5 : RunParserSyncTest(context_data, data, kError);
8754 :
8755 : const char* empty_context_data[][2] = {
8756 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8757 :
8758 : // CoverInitializedName ambiguity handling in various contexts
8759 : const char* ambiguity_data[] = {
8760 : "var foo = { x = 10 };", "var foo = { q } = { x = 10 };",
8761 : "var foo; foo = { x = 10 };", "var foo; foo = { q } = { x = 10 };",
8762 : "var x; ({ x = 10 });", "var q, x; ({ q } = { x = 10 });",
8763 : "var x; [{ x = 10 }]", "var x; (true ? { x = true } : { x = false })",
8764 : "var q, x; (q, { x = 10 });", "var { x = 10 } = { x = 20 };",
8765 : "var { x = 10 } = (o = { x = 20 });",
8766 : "var x; (({ x = 10 } = { x = 20 }) => x)({})",
8767 :
8768 : // Not ambiguous, but uses same context data
8769 : "switch([window %= []] = []) { default: }",
8770 :
8771 : nullptr,
8772 5 : };
8773 5 : RunParserSyncTest(empty_context_data, ambiguity_data, kError);
8774 :
8775 : // Strict mode errors
8776 : const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
8777 : {"'use strict'; for (", " of {}) {}"},
8778 : {"'use strict'; for (", " in {}) {}"},
8779 5 : {nullptr, nullptr}};
8780 : const char* strict_data[] = {
8781 : "{ eval }", "{ arguments }", "{ foo: eval }", "{ foo: arguments }",
8782 : "{ eval = 0 }", "{ arguments = 0 }", "{ foo: eval = 0 }",
8783 : "{ foo: arguments = 0 }", "[ eval ]", "[ arguments ]", "[ eval = 0 ]",
8784 : "[ arguments = 0 ]",
8785 :
8786 : // v8:4662
8787 : "{ x: (eval) }", "{ x: (arguments) }", "{ x: (eval = 0) }",
8788 : "{ x: (arguments = 0) }", "{ x: (eval) = 0 }", "{ x: (arguments) = 0 }",
8789 : "[ (eval) ]", "[ (arguments) ]", "[ (eval = 0) ]", "[ (arguments = 0) ]",
8790 : "[ (eval) = 0 ]", "[ (arguments) = 0 ]", "[ ...(eval) ]",
8791 : "[ ...(arguments) ]", "[ ...(eval = 0) ]", "[ ...(arguments = 0) ]",
8792 : "[ ...(eval) = 0 ]", "[ ...(arguments) = 0 ]",
8793 :
8794 5 : nullptr};
8795 5 : RunParserSyncTest(strict_context_data, strict_data, kError);
8796 5 : }
8797 :
8798 :
8799 28342 : TEST(DestructuringDisallowPatternsInForVarIn) {
8800 : const char* context_data[][2] = {
8801 5 : {"", ""}, {"function f() {", "}"}, {nullptr, nullptr}};
8802 : // clang-format off
8803 : const char* error_data[] = {
8804 : "for (let x = {} in null);",
8805 : "for (let x = {} of null);",
8806 5 : nullptr};
8807 : // clang-format on
8808 5 : RunParserSyncTest(context_data, error_data, kError);
8809 :
8810 : // clang-format off
8811 : const char* success_data[] = {
8812 : "for (var x = {} in null);",
8813 5 : nullptr};
8814 : // clang-format on
8815 5 : RunParserSyncTest(context_data, success_data, kSuccess);
8816 5 : }
8817 :
8818 :
8819 28342 : TEST(DestructuringDuplicateParams) {
8820 : const char* context_data[][2] = {{"'use strict';", ""},
8821 : {"function outer() { 'use strict';", "}"},
8822 5 : {nullptr, nullptr}};
8823 :
8824 :
8825 : // clang-format off
8826 : const char* error_data[] = {
8827 : "function f(x,x){}",
8828 : "function f(x, {x : x}){}",
8829 : "function f(x, {x}){}",
8830 : "function f({x,x}) {}",
8831 : "function f([x,x]) {}",
8832 : "function f(x, [y,{z:x}]) {}",
8833 : "function f([x,{y:x}]) {}",
8834 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8835 : "function f(x, x, {a}) {}",
8836 5 : nullptr};
8837 : // clang-format on
8838 5 : RunParserSyncTest(context_data, error_data, kError);
8839 5 : }
8840 :
8841 :
8842 28342 : TEST(DestructuringDuplicateParamsSloppy) {
8843 : const char* context_data[][2] = {
8844 5 : {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
8845 :
8846 :
8847 : // clang-format off
8848 : const char* error_data[] = {
8849 : // non-simple parameter list causes duplicates to be errors in sloppy mode.
8850 : "function f(x, {x : x}){}",
8851 : "function f(x, {x}){}",
8852 : "function f({x,x}) {}",
8853 : "function f(x, x, {a}) {}",
8854 5 : nullptr};
8855 : // clang-format on
8856 5 : RunParserSyncTest(context_data, error_data, kError);
8857 5 : }
8858 :
8859 :
8860 28342 : TEST(DestructuringDisallowPatternsInSingleParamArrows) {
8861 : const char* context_data[][2] = {{"'use strict';", ""},
8862 : {"function outer() { 'use strict';", "}"},
8863 : {"", ""},
8864 : {"function outer() { ", "}"},
8865 5 : {nullptr, nullptr}};
8866 :
8867 : // clang-format off
8868 : const char* error_data[] = {
8869 : "var f = {x} => {};",
8870 : "var f = {x,y} => {};",
8871 5 : nullptr};
8872 : // clang-format on
8873 5 : RunParserSyncTest(context_data, error_data, kError);
8874 5 : }
8875 :
8876 :
8877 28342 : TEST(DefaultParametersYieldInInitializers) {
8878 : // clang-format off
8879 : const char* sloppy_function_context_data[][2] = {
8880 : {"(function f(", ") { });"},
8881 : {nullptr, nullptr}
8882 5 : };
8883 :
8884 : const char* strict_function_context_data[][2] = {
8885 : {"'use strict'; (function f(", ") { });"},
8886 : {nullptr, nullptr}
8887 5 : };
8888 :
8889 : const char* sloppy_arrow_context_data[][2] = {
8890 : {"((", ")=>{});"},
8891 : {nullptr, nullptr}
8892 5 : };
8893 :
8894 : const char* strict_arrow_context_data[][2] = {
8895 : {"'use strict'; ((", ")=>{});"},
8896 : {nullptr, nullptr}
8897 5 : };
8898 :
8899 : const char* generator_context_data[][2] = {
8900 : {"'use strict'; (function *g(", ") { });"},
8901 : {"(function *g(", ") { });"},
8902 : // Arrow function within generator has the same rules.
8903 : {"'use strict'; (function *g() { (", ") => {} });"},
8904 : {"(function *g() { (", ") => {} });"},
8905 : // And similarly for arrow functions in the parameter list.
8906 : {"'use strict'; (function *g(z = (", ") => {}) { });"},
8907 : {"(function *g(z = (", ") => {}) { });"},
8908 : {nullptr, nullptr}
8909 5 : };
8910 :
8911 : const char* parameter_data[] = {
8912 : "x=yield",
8913 : "x, y=yield",
8914 : "{x=yield}",
8915 : "[x=yield]",
8916 :
8917 : "x=(yield)",
8918 : "x, y=(yield)",
8919 : "{x=(yield)}",
8920 : "[x=(yield)]",
8921 :
8922 : "x=f(yield)",
8923 : "x, y=f(yield)",
8924 : "{x=f(yield)}",
8925 : "[x=f(yield)]",
8926 :
8927 : "{x}=yield",
8928 : "[x]=yield",
8929 :
8930 : "{x}=(yield)",
8931 : "[x]=(yield)",
8932 :
8933 : "{x}=f(yield)",
8934 : "[x]=f(yield)",
8935 : nullptr
8936 5 : };
8937 :
8938 : // Because classes are always in strict mode, these are always errors.
8939 : const char* always_error_param_data[] = {
8940 : "x = class extends (yield) { }",
8941 : "x = class extends f(yield) { }",
8942 : "x = class extends (null, yield) { }",
8943 : "x = class extends (a ? null : yield) { }",
8944 : "[x] = [class extends (a ? null : yield) { }]",
8945 : "[x = class extends (a ? null : yield) { }]",
8946 : "[x = class extends (a ? null : yield) { }] = [null]",
8947 : "x = class { [yield]() { } }",
8948 : "x = class { static [yield]() { } }",
8949 : "x = class { [(yield, 1)]() { } }",
8950 : "x = class { [y = (yield, 1)]() { } }",
8951 : nullptr
8952 5 : };
8953 : // clang-format on
8954 :
8955 5 : RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
8956 5 : RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
8957 :
8958 5 : RunParserSyncTest(strict_function_context_data, parameter_data, kError);
8959 5 : RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
8960 :
8961 5 : RunParserSyncTest(generator_context_data, parameter_data, kError);
8962 5 : RunParserSyncTest(generator_context_data, always_error_param_data, kError);
8963 5 : }
8964 :
8965 28342 : TEST(SpreadArray) {
8966 : const char* context_data[][2] = {
8967 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8968 :
8969 : // clang-format off
8970 : const char* data[] = {
8971 : "[...a]",
8972 : "[a, ...b]",
8973 : "[...a,]",
8974 : "[...a, ,]",
8975 : "[, ...a]",
8976 : "[...a, ...b]",
8977 : "[...a, , ...b]",
8978 : "[...[...a]]",
8979 : "[, ...a]",
8980 : "[, , ...a]",
8981 5 : nullptr};
8982 : // clang-format on
8983 5 : RunParserSyncTest(context_data, data, kSuccess);
8984 5 : }
8985 :
8986 :
8987 28342 : TEST(SpreadArrayError) {
8988 : const char* context_data[][2] = {
8989 5 : {"'use strict';", ""}, {"", ""}, {nullptr, nullptr}};
8990 :
8991 : // clang-format off
8992 : const char* data[] = {
8993 : "[...]",
8994 : "[a, ...]",
8995 : "[..., ]",
8996 : "[..., ...]",
8997 : "[ (...a)]",
8998 5 : nullptr};
8999 : // clang-format on
9000 5 : RunParserSyncTest(context_data, data, kError);
9001 5 : }
9002 :
9003 :
9004 28342 : TEST(NewTarget) {
9005 : // clang-format off
9006 : const char* good_context_data[][2] = {
9007 : {"function f() {", "}"},
9008 : {"'use strict'; function f() {", "}"},
9009 : {"var f = function() {", "}"},
9010 : {"'use strict'; var f = function() {", "}"},
9011 : {"({m: function() {", "}})"},
9012 : {"'use strict'; ({m: function() {", "}})"},
9013 : {"({m() {", "}})"},
9014 : {"'use strict'; ({m() {", "}})"},
9015 : {"({get x() {", "}})"},
9016 : {"'use strict'; ({get x() {", "}})"},
9017 : {"({set x(_) {", "}})"},
9018 : {"'use strict'; ({set x(_) {", "}})"},
9019 : {"class C {m() {", "}}"},
9020 : {"class C {get x() {", "}}"},
9021 : {"class C {set x(_) {", "}}"},
9022 : {nullptr}
9023 5 : };
9024 :
9025 : const char* bad_context_data[][2] = {
9026 : {"", ""},
9027 : {"'use strict';", ""},
9028 : {nullptr}
9029 5 : };
9030 :
9031 : const char* data[] = {
9032 : "new.target",
9033 : "{ new.target }",
9034 : "() => { new.target }",
9035 : "() => new.target",
9036 : "if (1) { new.target }",
9037 : "if (1) {} else { new.target }",
9038 : "while (0) { new.target }",
9039 : "do { new.target } while (0)",
9040 : nullptr
9041 5 : };
9042 :
9043 : // clang-format on
9044 :
9045 5 : RunParserSyncTest(good_context_data, data, kSuccess);
9046 5 : RunParserSyncTest(bad_context_data, data, kError);
9047 5 : }
9048 :
9049 28342 : TEST(ImportMetaSuccess) {
9050 : // clang-format off
9051 : const char* context_data[][2] = {
9052 : {"", ""},
9053 : {"'use strict';", ""},
9054 : {"function f() {", "}"},
9055 : {"'use strict'; function f() {", "}"},
9056 : {"var f = function() {", "}"},
9057 : {"'use strict'; var f = function() {", "}"},
9058 : {"({m: function() {", "}})"},
9059 : {"'use strict'; ({m: function() {", "}})"},
9060 : {"({m() {", "}})"},
9061 : {"'use strict'; ({m() {", "}})"},
9062 : {"({get x() {", "}})"},
9063 : {"'use strict'; ({get x() {", "}})"},
9064 : {"({set x(_) {", "}})"},
9065 : {"'use strict'; ({set x(_) {", "}})"},
9066 : {"class C {m() {", "}}"},
9067 : {"class C {get x() {", "}}"},
9068 : {"class C {set x(_) {", "}}"},
9069 : {nullptr}
9070 5 : };
9071 :
9072 : const char* data[] = {
9073 : "import.meta",
9074 : "() => { import.meta }",
9075 : "() => import.meta",
9076 : "if (1) { import.meta }",
9077 : "if (1) {} else { import.meta }",
9078 : "while (0) { import.meta }",
9079 : "do { import.meta } while (0)",
9080 : "import.meta.url",
9081 : "import.meta[0]",
9082 : "import.meta.couldBeMutable = true",
9083 : "import.meta()",
9084 : "new import.meta.MagicClass",
9085 : "new import.meta",
9086 : "t = [...import.meta]",
9087 : "f = {...import.meta}",
9088 : "delete import.meta",
9089 : nullptr
9090 5 : };
9091 :
9092 : // clang-format on
9093 :
9094 : // Making sure the same *wouldn't* parse without the flags
9095 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9096 : nullptr, 0, true, true);
9097 :
9098 : static const ParserFlag flags[] = {
9099 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9100 : };
9101 : // 2.1.1 Static Semantics: Early Errors
9102 : // ImportMeta
9103 : // * It is an early Syntax Error if Module is not the syntactic goal symbol.
9104 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9105 5 : arraysize(flags));
9106 : // Making sure the same wouldn't parse without the flags either
9107 5 : RunParserSyncTest(context_data, data, kError);
9108 :
9109 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, flags,
9110 : arraysize(flags));
9111 5 : }
9112 :
9113 28342 : TEST(ImportMetaFailure) {
9114 : // clang-format off
9115 : const char* context_data[][2] = {
9116 : {"var ", ""},
9117 : {"let ", ""},
9118 : {"const ", ""},
9119 : {"var [", "] = [1]"},
9120 : {"([", "] = [1])"},
9121 : {"({", "} = {1})"},
9122 : {"var {", " = 1} = 1"},
9123 : {"for (var ", " of [1]) {}"},
9124 : {"(", ") => {}"},
9125 : {"let f = ", " => {}"},
9126 : {nullptr}
9127 5 : };
9128 :
9129 : const char* data[] = {
9130 : "import.meta",
9131 : nullptr
9132 5 : };
9133 :
9134 : // clang-format on
9135 :
9136 : static const ParserFlag flags[] = {
9137 : kAllowHarmonyImportMeta, kAllowHarmonyDynamicImport,
9138 : };
9139 :
9140 : RunParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9141 5 : arraysize(flags));
9142 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, flags,
9143 : arraysize(flags));
9144 :
9145 : RunModuleParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
9146 : nullptr, 0, true, true);
9147 5 : RunParserSyncTest(context_data, data, kError);
9148 5 : }
9149 :
9150 28342 : TEST(ConstSloppy) {
9151 : // clang-format off
9152 : const char* context_data[][2] = {
9153 : {"", ""},
9154 : {"{", "}"},
9155 : {nullptr, nullptr}
9156 5 : };
9157 :
9158 : const char* data[] = {
9159 : "const x = 1",
9160 : "for (const x = 1; x < 1; x++) {}",
9161 : "for (const x in {}) {}",
9162 : "for (const x of []) {}",
9163 : nullptr
9164 5 : };
9165 : // clang-format on
9166 5 : RunParserSyncTest(context_data, data, kSuccess);
9167 5 : }
9168 :
9169 :
9170 28342 : TEST(LetSloppy) {
9171 : // clang-format off
9172 : const char* context_data[][2] = {
9173 : {"", ""},
9174 : {"'use strict';", ""},
9175 : {"{", "}"},
9176 : {nullptr, nullptr}
9177 5 : };
9178 :
9179 : const char* data[] = {
9180 : "let x",
9181 : "let x = 1",
9182 : "for (let x = 1; x < 1; x++) {}",
9183 : "for (let x in {}) {}",
9184 : "for (let x of []) {}",
9185 : nullptr
9186 5 : };
9187 : // clang-format on
9188 :
9189 5 : RunParserSyncTest(context_data, data, kSuccess);
9190 5 : }
9191 :
9192 :
9193 28342 : TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
9194 : // TC39 deemed "use strict" directives to be an error when occurring in the
9195 : // body of a function with non-simple parameter list, on 29/7/2015.
9196 : // https://goo.gl/ueA7Ln
9197 : const char* context_data[][2] = {
9198 : {"function f(", ") { 'use strict'; }"},
9199 : {"function* g(", ") { 'use strict'; }"},
9200 : {"class c { foo(", ") { 'use strict' }"},
9201 : {"var a = (", ") => { 'use strict'; }"},
9202 : {"var o = { m(", ") { 'use strict'; }"},
9203 : {"var o = { *gm(", ") { 'use strict'; }"},
9204 : {"var c = { m(", ") { 'use strict'; }"},
9205 : {"var c = { *gm(", ") { 'use strict'; }"},
9206 :
9207 : {"'use strict'; function f(", ") { 'use strict'; }"},
9208 : {"'use strict'; function* g(", ") { 'use strict'; }"},
9209 : {"'use strict'; class c { foo(", ") { 'use strict' }"},
9210 : {"'use strict'; var a = (", ") => { 'use strict'; }"},
9211 : {"'use strict'; var o = { m(", ") { 'use strict'; }"},
9212 : {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
9213 : {"'use strict'; var c = { m(", ") { 'use strict'; }"},
9214 : {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
9215 :
9216 5 : {nullptr, nullptr}};
9217 :
9218 : const char* data[] = {
9219 : // TODO(@caitp): support formal parameter initializers
9220 : "{}",
9221 : "[]",
9222 : "[{}]",
9223 : "{a}",
9224 : "a, {b}",
9225 : "a, b, {c, d, e}",
9226 : "initializer = true",
9227 : "a, b, c = 1",
9228 : "...args",
9229 : "a, b, ...rest",
9230 : "[a, b, ...rest]",
9231 : "{ bindingPattern = {} }",
9232 : "{ initializedBindingPattern } = { initializedBindingPattern: true }",
9233 5 : nullptr};
9234 :
9235 5 : RunParserSyncTest(context_data, data, kError);
9236 5 : }
9237 :
9238 :
9239 28342 : TEST(LetSloppyOnly) {
9240 : // clang-format off
9241 : const char* context_data[][2] = {
9242 : {"", ""},
9243 : {"{", "}"},
9244 : {"(function() {", "})()"},
9245 : {nullptr, nullptr}
9246 5 : };
9247 :
9248 : const char* data[] = {
9249 : "let",
9250 : "let = 1",
9251 : "for (let = 1; let < 1; let++) {}",
9252 : "for (let in {}) {}",
9253 : "for (var let = 1; let < 1; let++) {}",
9254 : "for (var let in {}) {}",
9255 : "for (var [let] = 1; let < 1; let++) {}",
9256 : "for (var [let] in {}) {}",
9257 : "var let",
9258 : "var [let] = []",
9259 : nullptr
9260 5 : };
9261 : // clang-format on
9262 :
9263 5 : RunParserSyncTest(context_data, data, kSuccess);
9264 :
9265 : // Some things should be rejected even in sloppy mode
9266 : // This addresses BUG(v8:4403).
9267 :
9268 : // clang-format off
9269 : const char* fail_data[] = {
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 : "let [let] = 1",
9279 : "for (let [let] = 1; let < 1; let++) {}",
9280 : "for (let [let] in {}) {}",
9281 : "for (let [let] of []) {}",
9282 : "const [let] = 1",
9283 : "for (const [let] = 1; let < 1; let++) {}",
9284 : "for (const [let] in {}) {}",
9285 : "for (const [let] of []) {}",
9286 :
9287 : // Sprinkle in the escaped version too.
9288 : "let l\\u0065t = 1",
9289 : "const l\\u0065t = 1",
9290 : "let [l\\u0065t] = 1",
9291 : "const [l\\u0065t] = 1",
9292 : "for (let l\\u0065t in {}) {}",
9293 : nullptr
9294 5 : };
9295 : // clang-format on
9296 :
9297 5 : RunParserSyncTest(context_data, fail_data, kError);
9298 5 : }
9299 :
9300 :
9301 28342 : TEST(EscapedKeywords) {
9302 : // clang-format off
9303 : const char* sloppy_context_data[][2] = {
9304 : {"", ""},
9305 : {nullptr, nullptr}
9306 5 : };
9307 :
9308 : const char* strict_context_data[][2] = {
9309 : {"'use strict';", ""},
9310 : {nullptr, nullptr}
9311 5 : };
9312 :
9313 : const char* fail_data[] = {
9314 : "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
9315 : "cl\\u0061ss Foo {}",
9316 : "var x = cl\\u0061ss {}",
9317 : "\\u0063onst foo = 1;",
9318 : "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
9319 : "d\\u0065bugger;",
9320 : "d\\u0065lete this.a;",
9321 : "\\u0063o { } while(0)",
9322 : "if (d\\u006f { true }) {}",
9323 : "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
9324 : "e\\u0078port var foo;",
9325 : "try { } catch (e) {} f\\u0069nally { }",
9326 : "f\\u006fr (var i = 0; i < 10; ++i);",
9327 : "f\\u0075nction fn() {}",
9328 : "var f = f\\u0075nction() {}",
9329 : "\\u0069f (true) { }",
9330 : "\\u0069mport blah from './foo.js';",
9331 : "n\\u0065w function f() {}",
9332 : "(function() { r\\u0065turn; })()",
9333 : "class C extends function() {} { constructor() { sup\\u0065r() } }",
9334 : "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
9335 : "sw\\u0069tch (this.a) {}",
9336 : "var x = th\\u0069s;",
9337 : "th\\u0069s.a = 1;",
9338 : "thr\\u006fw 'boo';",
9339 : "t\\u0072y { true } catch (e) {}",
9340 : "var x = typ\\u0065of 'blah'",
9341 : "v\\u0061r a = true",
9342 : "var v\\u0061r = true",
9343 : "(function() { return v\\u006fid 0; })()",
9344 : "wh\\u0069le (true) { }",
9345 : "w\\u0069th (this.scope) { }",
9346 : "(function*() { y\\u0069eld 1; })()",
9347 : "(function*() { var y\\u0069eld = 1; })()",
9348 :
9349 : "var \\u0065num = 1;",
9350 : "var { \\u0065num } = {}",
9351 : "(\\u0065num = 1);",
9352 :
9353 : // Null / Boolean literals
9354 : "(x === n\\u0075ll);",
9355 : "var x = n\\u0075ll;",
9356 : "var n\\u0075ll = 1;",
9357 : "var { n\\u0075ll } = { 1 };",
9358 : "n\\u0075ll = 1;",
9359 : "(x === tr\\u0075e);",
9360 : "var x = tr\\u0075e;",
9361 : "var tr\\u0075e = 1;",
9362 : "var { tr\\u0075e } = {};",
9363 : "tr\\u0075e = 1;",
9364 : "(x === f\\u0061lse);",
9365 : "var x = f\\u0061lse;",
9366 : "var f\\u0061lse = 1;",
9367 : "var { f\\u0061lse } = {};",
9368 : "f\\u0061lse = 1;",
9369 :
9370 : // TODO(caitp): consistent error messages for labeled statements and
9371 : // expressions
9372 : "switch (this.a) { c\\u0061se 6: break; }",
9373 : "try { } c\\u0061tch (e) {}",
9374 : "switch (this.a) { d\\u0065fault: break; }",
9375 : "class C \\u0065xtends function B() {} {}",
9376 : "for (var a i\\u006e this) {}",
9377 : "if ('foo' \\u0069n this) {}",
9378 : "if (this \\u0069nstanceof Array) {}",
9379 : "(n\\u0065w function f() {})",
9380 : "(typ\\u0065of 123)",
9381 : "(v\\u006fid 0)",
9382 : "do { ; } wh\\u0069le (true) { }",
9383 : "(function*() { return (n++, y\\u0069eld 1); })()",
9384 : "class C { st\\u0061tic bar() {} }",
9385 : "class C { st\\u0061tic *bar() {} }",
9386 : "class C { st\\u0061tic get bar() {} }",
9387 : "class C { st\\u0061tic set bar() {} }",
9388 :
9389 : // TODO(adamk): These should not be errors in sloppy mode.
9390 : "(y\\u0069eld);",
9391 : "var y\\u0069eld = 1;",
9392 : "var { y\\u0069eld } = {};",
9393 : nullptr
9394 5 : };
9395 : // clang-format on
9396 :
9397 5 : RunParserSyncTest(sloppy_context_data, fail_data, kError);
9398 5 : RunParserSyncTest(strict_context_data, fail_data, kError);
9399 : RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
9400 :
9401 : // clang-format off
9402 : const char* let_data[] = {
9403 : "var l\\u0065t = 1;",
9404 : "l\\u0065t = 1;",
9405 : "(l\\u0065t === 1);",
9406 : nullptr
9407 5 : };
9408 : // clang-format on
9409 :
9410 5 : RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
9411 5 : RunParserSyncTest(strict_context_data, let_data, kError);
9412 :
9413 : // Non-errors in sloppy mode
9414 : const char* valid_data[] = {"(\\u0069mplements = 1);",
9415 : "var impl\\u0065ments = 1;",
9416 : "var { impl\\u0065ments } = {};",
9417 : "(\\u0069nterface = 1);",
9418 : "var int\\u0065rface = 1;",
9419 : "var { int\\u0065rface } = {};",
9420 : "(p\\u0061ckage = 1);",
9421 : "var packa\\u0067e = 1;",
9422 : "var { packa\\u0067e } = {};",
9423 : "(p\\u0072ivate = 1);",
9424 : "var p\\u0072ivate;",
9425 : "var { p\\u0072ivate } = {};",
9426 : "(prot\\u0065cted);",
9427 : "var prot\\u0065cted = 1;",
9428 : "var { prot\\u0065cted } = {};",
9429 : "(publ\\u0069c);",
9430 : "var publ\\u0069c = 1;",
9431 : "var { publ\\u0069c } = {};",
9432 : "(st\\u0061tic);",
9433 : "var st\\u0061tic = 1;",
9434 : "var { st\\u0061tic } = {};",
9435 5 : nullptr};
9436 5 : RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
9437 5 : RunParserSyncTest(strict_context_data, valid_data, kError);
9438 : RunModuleParserSyncTest(strict_context_data, valid_data, kError);
9439 5 : }
9440 :
9441 :
9442 28342 : TEST(MiscSyntaxErrors) {
9443 : // clang-format off
9444 : const char* context_data[][2] = {
9445 : { "'use strict'", "" },
9446 : { "", "" },
9447 : { nullptr, nullptr }
9448 5 : };
9449 : const char* error_data[] = {
9450 : "for (();;) {}",
9451 :
9452 : // crbug.com/582626
9453 : "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
9454 : nullptr
9455 5 : };
9456 : // clang-format on
9457 :
9458 5 : RunParserSyncTest(context_data, error_data, kError);
9459 5 : }
9460 :
9461 :
9462 28342 : TEST(EscapeSequenceErrors) {
9463 : // clang-format off
9464 : const char* context_data[][2] = {
9465 : { "'", "'" },
9466 : { "\"", "\"" },
9467 : { "`", "`" },
9468 : { "`${'", "'}`" },
9469 : { "`${\"", "\"}`" },
9470 : { "`${`", "`}`" },
9471 : { nullptr, nullptr }
9472 5 : };
9473 : const char* error_data[] = {
9474 : "\\uABCG",
9475 : "\\u{ZZ}",
9476 : "\\u{FFZ}",
9477 : "\\u{FFFFFFFFFF }",
9478 : "\\u{110000}",
9479 : "\\u{110000",
9480 : "\\u{FFFD }",
9481 : "\\xZF",
9482 : nullptr
9483 5 : };
9484 : // clang-format on
9485 :
9486 5 : RunParserSyncTest(context_data, error_data, kError);
9487 5 : }
9488 :
9489 28342 : TEST(NewTargetErrors) {
9490 : // clang-format off
9491 : const char* context_data[][2] = {
9492 : { "'use strict'", "" },
9493 : { "", "" },
9494 : { nullptr, nullptr }
9495 5 : };
9496 : const char* error_data[] = {
9497 : "var x = new.target",
9498 : "function f() { return new.t\\u0061rget; }",
9499 : nullptr
9500 5 : };
9501 : // clang-format on
9502 5 : RunParserSyncTest(context_data, error_data, kError);
9503 5 : }
9504 :
9505 28342 : TEST(FunctionDeclarationError) {
9506 : // clang-format off
9507 : const char* strict_context[][2] = {
9508 : { "'use strict';", "" },
9509 : { "'use strict'; { ", "}" },
9510 : {"(function() { 'use strict';", "})()"},
9511 : {"(function() { 'use strict'; {", "} })()"},
9512 : { nullptr, nullptr }
9513 5 : };
9514 : const char* sloppy_context[][2] = {
9515 : { "", "" },
9516 : { "{", "}" },
9517 : {"(function() {", "})()"},
9518 : {"(function() { {", "} })()"},
9519 : { nullptr, nullptr }
9520 5 : };
9521 : // Invalid in all contexts
9522 : const char* error_data[] = {
9523 : "try function foo() {} catch (e) {}",
9524 : "do function foo() {} while (0);",
9525 : "for (;false;) function foo() {}",
9526 : "for (var i = 0; i < 1; i++) function f() { };",
9527 : "for (var x in {a: 1}) function f() { };",
9528 : "for (var x in {}) function f() { };",
9529 : "for (var x in {}) function foo() {}",
9530 : "for (x in {a: 1}) function f() { };",
9531 : "for (x in {}) function f() { };",
9532 : "var x; for (x in {}) function foo() {}",
9533 : "with ({}) function f() { };",
9534 : "do label: function foo() {} while (0);",
9535 : "for (;false;) label: function foo() {}",
9536 : "for (var i = 0; i < 1; i++) label: function f() { };",
9537 : "for (var x in {a: 1}) label: function f() { };",
9538 : "for (var x in {}) label: function f() { };",
9539 : "for (var x in {}) label: function foo() {}",
9540 : "for (x in {a: 1}) label: function f() { };",
9541 : "for (x in {}) label: function f() { };",
9542 : "var x; for (x in {}) label: function foo() {}",
9543 : "with ({}) label: function f() { };",
9544 : "if (true) label: function f() {}",
9545 : "if (true) {} else label: function f() {}",
9546 : "if (true) function* f() { }",
9547 : "label: function* f() { }",
9548 : "if (true) async function f() { }",
9549 : "label: async function f() { }",
9550 : "if (true) async function* f() { }",
9551 : "label: async function* f() { }",
9552 : nullptr
9553 5 : };
9554 : // Valid only in sloppy mode.
9555 : const char* sloppy_data[] = {
9556 : "if (true) function foo() {}",
9557 : "if (false) {} else function f() { };",
9558 : "label: function f() { }",
9559 : "label: if (true) function f() { }",
9560 : "label: if (true) {} else function f() { }",
9561 : "label: label2: function f() { }",
9562 : nullptr
9563 5 : };
9564 : // clang-format on
9565 :
9566 : // Nothing parses in strict mode without a SyntaxError
9567 5 : RunParserSyncTest(strict_context, error_data, kError);
9568 5 : RunParserSyncTest(strict_context, sloppy_data, kError);
9569 :
9570 : // In sloppy mode, sloppy_data is successful
9571 5 : RunParserSyncTest(sloppy_context, error_data, kError);
9572 5 : RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
9573 5 : }
9574 :
9575 28342 : TEST(ExponentiationOperator) {
9576 : // clang-format off
9577 : const char* context_data[][2] = {
9578 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9579 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9580 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9581 : { nullptr, nullptr }
9582 5 : };
9583 : const char* data[] = {
9584 : "(delete O.p) ** 10",
9585 : "(delete x) ** 10",
9586 : "(~O.p) ** 10",
9587 : "(~x) ** 10",
9588 : "(!O.p) ** 10",
9589 : "(!x) ** 10",
9590 : "(+O.p) ** 10",
9591 : "(+x) ** 10",
9592 : "(-O.p) ** 10",
9593 : "(-x) ** 10",
9594 : "(typeof O.p) ** 10",
9595 : "(typeof x) ** 10",
9596 : "(void 0) ** 10",
9597 : "(void O.p) ** 10",
9598 : "(void x) ** 10",
9599 : "++O.p ** 10",
9600 : "++x ** 10",
9601 : "--O.p ** 10",
9602 : "--x ** 10",
9603 : "O.p++ ** 10",
9604 : "x++ ** 10",
9605 : "O.p-- ** 10",
9606 : "x-- ** 10",
9607 : nullptr
9608 5 : };
9609 : // clang-format on
9610 :
9611 5 : RunParserSyncTest(context_data, data, kSuccess);
9612 5 : }
9613 :
9614 28342 : TEST(ExponentiationOperatorErrors) {
9615 : // clang-format off
9616 : const char* context_data[][2] = {
9617 : { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
9618 : { "var O = { p: 1 }, x = 10; ; (", ")" },
9619 : { "var O = { p: 1 }, x = 10; foo(", ")" },
9620 : { nullptr, nullptr }
9621 5 : };
9622 : const char* error_data[] = {
9623 : "delete O.p ** 10",
9624 : "delete x ** 10",
9625 : "~O.p ** 10",
9626 : "~x ** 10",
9627 : "!O.p ** 10",
9628 : "!x ** 10",
9629 : "+O.p ** 10",
9630 : "+x ** 10",
9631 : "-O.p ** 10",
9632 : "-x ** 10",
9633 : "typeof O.p ** 10",
9634 : "typeof x ** 10",
9635 : "void ** 10",
9636 : "void O.p ** 10",
9637 : "void x ** 10",
9638 : "++delete O.p ** 10",
9639 : "--delete O.p ** 10",
9640 : "++~O.p ** 10",
9641 : "++~x ** 10",
9642 : "--!O.p ** 10",
9643 : "--!x ** 10",
9644 : "++-O.p ** 10",
9645 : "++-x ** 10",
9646 : "--+O.p ** 10",
9647 : "--+x ** 10",
9648 : "[ x ] **= [ 2 ]",
9649 : "[ x **= 2 ] = [ 2 ]",
9650 : "{ x } **= { x: 2 }",
9651 : "{ x: x **= 2 ] = { x: 2 }",
9652 : // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
9653 : // "Array() **= 10",
9654 : nullptr
9655 5 : };
9656 : // clang-format on
9657 :
9658 5 : RunParserSyncTest(context_data, error_data, kError);
9659 5 : }
9660 :
9661 28342 : TEST(AsyncAwait) {
9662 : // clang-format off
9663 : const char* context_data[][2] = {
9664 : { "'use strict';", "" },
9665 : { "", "" },
9666 : { nullptr, nullptr }
9667 5 : };
9668 :
9669 : const char* data[] = {
9670 : "var asyncFn = async function() { await 1; };",
9671 : "var asyncFn = async function withName() { await 1; };",
9672 : "var asyncFn = async () => await 'test';",
9673 : "var asyncFn = async x => await x + 'test';",
9674 : "async function asyncFn() { await 1; }",
9675 : "var O = { async method() { await 1; } }",
9676 : "var O = { async ['meth' + 'od']() { await 1; } }",
9677 : "var O = { async 'method'() { await 1; } }",
9678 : "var O = { async 0() { await 1; } }",
9679 : "async function await() {}",
9680 :
9681 : "var asyncFn = async({ foo = 1 }) => foo;",
9682 : "var asyncFn = async({ foo = 1 } = {}) => foo;",
9683 :
9684 : "function* g() { var f = async(yield); }",
9685 : "function* g() { var f = async(x = yield); }",
9686 :
9687 : // v8:7817 assert that `await` is still allowed in the body of an arrow fn
9688 : // within formal parameters
9689 : "async(a = a => { var await = 1; return 1; }) => a()",
9690 : "async(a = await => 1); async(a) => 1",
9691 : "(async(a = await => 1), async(a) => 1)",
9692 : "async(a = await => 1, b = async() => 1);",
9693 :
9694 : nullptr
9695 5 : };
9696 : // clang-format on
9697 :
9698 5 : RunParserSyncTest(context_data, data, kSuccess);
9699 :
9700 : // clang-format off
9701 : const char* async_body_context_data[][2] = {
9702 : { "async function f() {", "}" },
9703 : { "var f = async function() {", "}" },
9704 : { "var f = async() => {", "}" },
9705 : { "var O = { async method() {", "} }" },
9706 : { "'use strict'; async function f() {", "}" },
9707 : { "'use strict'; var f = async function() {", "}" },
9708 : { "'use strict'; var f = async() => {", "}" },
9709 : { "'use strict'; var O = { async method() {", "} }" },
9710 : { nullptr, nullptr }
9711 5 : };
9712 :
9713 : const char* body_context_data[][2] = {
9714 : { "function f() {", "}" },
9715 : { "function* g() {", "}" },
9716 : { "var f = function() {", "}" },
9717 : { "var g = function*() {", "}" },
9718 : { "var O = { method() {", "} }" },
9719 : { "var O = { *method() {", "} }" },
9720 : { "var f = () => {", "}" },
9721 : { "'use strict'; function f() {", "}" },
9722 : { "'use strict'; function* g() {", "}" },
9723 : { "'use strict'; var f = function() {", "}" },
9724 : { "'use strict'; var g = function*() {", "}" },
9725 : { "'use strict'; var O = { method() {", "} }" },
9726 : { "'use strict'; var O = { *method() {", "} }" },
9727 : { "'use strict'; var f = () => {", "}" },
9728 : { nullptr, nullptr }
9729 5 : };
9730 :
9731 : const char* body_data[] = {
9732 : "var async = 1; return async;",
9733 : "let async = 1; return async;",
9734 : "const async = 1; return async;",
9735 : "function async() {} return async();",
9736 : "var async = async => async; return async();",
9737 : "function foo() { var await = 1; return await; }",
9738 : "function foo(await) { return await; }",
9739 : "function* foo() { var await = 1; return await; }",
9740 : "function* foo(await) { return await; }",
9741 : "var f = () => { var await = 1; return await; }",
9742 : "var O = { method() { var await = 1; return await; } };",
9743 : "var O = { method(await) { return await; } };",
9744 : "var O = { *method() { var await = 1; return await; } };",
9745 : "var O = { *method(await) { return await; } };",
9746 : "var asyncFn = async function*() {}",
9747 : "async function* f() {}",
9748 : "var O = { async *method() {} };",
9749 :
9750 : "(function await() {})",
9751 : nullptr
9752 5 : };
9753 : // clang-format on
9754 :
9755 5 : RunParserSyncTest(async_body_context_data, body_data, kSuccess);
9756 5 : RunParserSyncTest(body_context_data, body_data, kSuccess);
9757 5 : }
9758 :
9759 28342 : TEST(AsyncAwaitErrors) {
9760 : // clang-format off
9761 : const char* context_data[][2] = {
9762 : { "'use strict';", "" },
9763 : { "", "" },
9764 : { nullptr, nullptr }
9765 5 : };
9766 :
9767 : const char* strict_context_data[][2] = {
9768 : { "'use strict';", "" },
9769 : { nullptr, nullptr }
9770 5 : };
9771 :
9772 : const char* error_data[] = {
9773 : "var asyncFn = async function await() {};",
9774 : "var asyncFn = async () => var await = 'test';",
9775 : "var asyncFn = async await => await + 'test';",
9776 : "var asyncFn = async function(await) {};",
9777 : "var asyncFn = async (await) => 'test';",
9778 : "async function f(await) {}",
9779 :
9780 : "var O = { async method(a, a) {} }",
9781 : "var O = { async ['meth' + 'od'](a, a) {} }",
9782 : "var O = { async 'method'(a, a) {} }",
9783 : "var O = { async 0(a, a) {} }",
9784 :
9785 : "var f = async() => await;",
9786 :
9787 : "var O = { *async method() {} };",
9788 : "var O = { async method*() {} };",
9789 :
9790 : "var asyncFn = async function(x = await 1) { return x; }",
9791 : "async function f(x = await 1) { return x; }",
9792 : "var f = async(x = await 1) => x;",
9793 : "var O = { async method(x = await 1) { return x; } };",
9794 :
9795 : "function* g() { var f = async yield => 1; }",
9796 : "function* g() { var f = async(yield) => 1; }",
9797 : "function* g() { var f = async(x = yield) => 1; }",
9798 : "function* g() { var f = async({x = yield}) => 1; }",
9799 :
9800 : "class C { async constructor() {} }",
9801 : "class C {}; class C2 extends C { async constructor() {} }",
9802 : "class C { static async prototype() {} }",
9803 : "class C {}; class C2 extends C { static async prototype() {} }",
9804 :
9805 : "var f = async() => ((async(x = await 1) => x)();",
9806 :
9807 : // Henrique Ferreiro's bug (tm)
9808 : "(async function foo1() { } foo2 => 1)",
9809 : "(async function foo3() { } () => 1)",
9810 : "(async function foo4() { } => 1)",
9811 : "(async function() { } foo5 => 1)",
9812 : "(async function() { } () => 1)",
9813 : "(async function() { } => 1)",
9814 : "(async.foo6 => 1)",
9815 : "(async.foo7 foo8 => 1)",
9816 : "(async.foo9 () => 1)",
9817 : "(async().foo10 => 1)",
9818 : "(async().foo11 foo12 => 1)",
9819 : "(async().foo13 () => 1)",
9820 : "(async['foo14'] => 1)",
9821 : "(async['foo15'] foo16 => 1)",
9822 : "(async['foo17'] () => 1)",
9823 : "(async()['foo18'] => 1)",
9824 : "(async()['foo19'] foo20 => 1)",
9825 : "(async()['foo21'] () => 1)",
9826 : "(async`foo22` => 1)",
9827 : "(async`foo23` foo24 => 1)",
9828 : "(async`foo25` () => 1)",
9829 : "(async`foo26`.bar27 => 1)",
9830 : "(async`foo28`.bar29 foo30 => 1)",
9831 : "(async`foo31`.bar32 () => 1)",
9832 :
9833 : // v8:5148 assert that errors are still thrown for calls that may have been
9834 : // async functions
9835 : "async({ foo33 = 1 })",
9836 :
9837 : "async(...a = b) => b",
9838 : "async(...a,) => b",
9839 : "async(...a, b) => b",
9840 :
9841 : // v8:7817 assert that `await` is an invalid identifier in arrow formal
9842 : // parameters nested within an async arrow function
9843 : "async(a = await => 1) => a",
9844 : "async(a = (await) => 1) => a",
9845 : "async(a = (...await) => 1) => a",
9846 : nullptr
9847 5 : };
9848 :
9849 : const char* strict_error_data[] = {
9850 : "var O = { async method(eval) {} }",
9851 : "var O = { async ['meth' + 'od'](eval) {} }",
9852 : "var O = { async 'method'(eval) {} }",
9853 : "var O = { async 0(eval) {} }",
9854 :
9855 : "var O = { async method(arguments) {} }",
9856 : "var O = { async ['meth' + 'od'](arguments) {} }",
9857 : "var O = { async 'method'(arguments) {} }",
9858 : "var O = { async 0(arguments) {} }",
9859 :
9860 : "var O = { async method(dupe, dupe) {} }",
9861 :
9862 : // TODO(caitp): preparser needs to report duplicate parameter errors, too.
9863 : // "var f = async(dupe, dupe) => {}",
9864 :
9865 : nullptr
9866 5 : };
9867 :
9868 5 : RunParserSyncTest(context_data, error_data, kError);
9869 5 : RunParserSyncTest(strict_context_data, strict_error_data, kError);
9870 :
9871 : // clang-format off
9872 : const char* async_body_context_data[][2] = {
9873 : { "async function f() {", "}" },
9874 : { "var f = async function() {", "}" },
9875 : { "var f = async() => {", "}" },
9876 : { "var O = { async method() {", "} }" },
9877 : { "'use strict'; async function f() {", "}" },
9878 : { "'use strict'; var f = async function() {", "}" },
9879 : { "'use strict'; var f = async() => {", "}" },
9880 : { "'use strict'; var O = { async method() {", "} }" },
9881 : { nullptr, nullptr }
9882 5 : };
9883 :
9884 : const char* async_body_error_data[] = {
9885 : "var await = 1;",
9886 : "var { await } = 1;",
9887 : "var [ await ] = 1;",
9888 : "return async (await) => {};",
9889 : "var O = { async [await](a, a) {} }",
9890 : "await;",
9891 :
9892 : "function await() {}",
9893 :
9894 : "var f = await => 42;",
9895 : "var f = (await) => 42;",
9896 : "var f = (await, a) => 42;",
9897 : "var f = (...await) => 42;",
9898 :
9899 : "var e = (await);",
9900 : "var e = (await, f);",
9901 : "var e = (await = 42)",
9902 :
9903 : "var e = [await];",
9904 : "var e = {await};",
9905 :
9906 : nullptr
9907 5 : };
9908 : // clang-format on
9909 :
9910 5 : RunParserSyncTest(async_body_context_data, async_body_error_data, kError);
9911 5 : }
9912 :
9913 28342 : TEST(Regress7173) {
9914 : // Await expression is an invalid destructuring target, and should not crash
9915 :
9916 : // clang-format off
9917 : const char* error_context_data[][2] = {
9918 : { "'use strict'; async function f() {", "}" },
9919 : { "async function f() {", "}" },
9920 : { "'use strict'; function f() {", "}" },
9921 : { "function f() {", "}" },
9922 : { "let f = async() => {", "}" },
9923 : { "let f = () => {", "}" },
9924 : { "'use strict'; async function* f() {", "}" },
9925 : { "async function* f() {", "}" },
9926 : { "'use strict'; function* f() {", "}" },
9927 : { "function* f() {", "}" },
9928 : { nullptr, nullptr }
9929 5 : };
9930 :
9931 : const char* error_data[] = {
9932 : "var [await f] = [];",
9933 : "let [await f] = [];",
9934 : "const [await f] = [];",
9935 :
9936 : "var [...await f] = [];",
9937 : "let [...await f] = [];",
9938 : "const [...await f] = [];",
9939 :
9940 : "var { await f } = {};",
9941 : "let { await f } = {};",
9942 : "const { await f } = {};",
9943 :
9944 : "var { ...await f } = {};",
9945 : "let { ...await f } = {};",
9946 : "const { ...await f } = {};",
9947 :
9948 : "var { f: await f } = {};",
9949 : "let { f: await f } = {};",
9950 : "const { f: await f } = {};"
9951 :
9952 : "var { f: ...await f } = {};",
9953 : "let { f: ...await f } = {};",
9954 : "const { f: ...await f } = {};"
9955 :
9956 : "var { [f]: await f } = {};",
9957 : "let { [f]: await f } = {};",
9958 : "const { [f]: await f } = {};",
9959 :
9960 : "var { [f]: ...await f } = {};",
9961 : "let { [f]: ...await f } = {};",
9962 : "const { [f]: ...await f } = {};",
9963 :
9964 : nullptr
9965 5 : };
9966 : // clang-format on
9967 :
9968 5 : RunParserSyncTest(error_context_data, error_data, kError);
9969 5 : }
9970 :
9971 28342 : TEST(AsyncAwaitFormalParameters) {
9972 : // clang-format off
9973 : const char* context_for_formal_parameters[][2] = {
9974 : { "async function f(", ") {}" },
9975 : { "var f = async function f(", ") {}" },
9976 : { "var f = async(", ") => {}" },
9977 : { "'use strict'; async function f(", ") {}" },
9978 : { "'use strict'; var f = async function f(", ") {}" },
9979 : { "'use strict'; var f = async(", ") => {}" },
9980 : { nullptr, nullptr }
9981 5 : };
9982 :
9983 : const char* good_formal_parameters[] = {
9984 : "x = function await() {}",
9985 : "x = function *await() {}",
9986 : "x = function() { let await = 0; }",
9987 : "x = () => { let await = 0; }",
9988 : nullptr
9989 5 : };
9990 :
9991 : const char* bad_formal_parameters[] = {
9992 : "{ await }",
9993 : "{ await = 1 }",
9994 : "{ await } = {}",
9995 : "{ await = 1 } = {}",
9996 : "[await]",
9997 : "[await] = []",
9998 : "[await = 1]",
9999 : "[await = 1] = []",
10000 : "...await",
10001 : "await",
10002 : "await = 1",
10003 : "...[await]",
10004 : "x = await",
10005 :
10006 : // v8:5190
10007 : "1) => 1",
10008 : "'str') => 1",
10009 : "/foo/) => 1",
10010 : "{ foo = async(1) => 1 }) => 1",
10011 : "{ foo = async(a) => 1 })",
10012 :
10013 : "x = async(await)",
10014 : "x = { [await]: 1 }",
10015 : "x = class extends (await) { }",
10016 : "x = class { static [await]() {} }",
10017 : "{ x = await }",
10018 :
10019 : // v8:6714
10020 : "x = class await {}",
10021 : "x = 1 ? class await {} : 0",
10022 : "x = async function await() {}",
10023 :
10024 : "x = y[await]",
10025 : "x = `${await}`",
10026 : "x = y()[await]",
10027 :
10028 : nullptr
10029 5 : };
10030 : // clang-format on
10031 :
10032 : RunParserSyncTest(context_for_formal_parameters, good_formal_parameters,
10033 5 : kSuccess);
10034 :
10035 : RunParserSyncTest(context_for_formal_parameters, bad_formal_parameters,
10036 5 : kError);
10037 5 : }
10038 :
10039 28342 : TEST(AsyncAwaitModule) {
10040 : // clang-format off
10041 : const char* context_data[][2] = {
10042 : { "", "" },
10043 : { nullptr, nullptr }
10044 5 : };
10045 :
10046 : const char* data[] = {
10047 : "export default async function() { await 1; }",
10048 : "export default async function async() { await 1; }",
10049 : "export async function async() { await 1; }",
10050 : nullptr
10051 5 : };
10052 : // clang-format on
10053 :
10054 : RunModuleParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
10055 : nullptr, 0, false);
10056 5 : }
10057 :
10058 28342 : TEST(AsyncAwaitModuleErrors) {
10059 : // clang-format off
10060 : const char* context_data[][2] = {
10061 : { "", "" },
10062 : { nullptr, nullptr }
10063 5 : };
10064 :
10065 : const char* error_data[] = {
10066 : "export default (async function await() {})",
10067 : "export default async function await() {}",
10068 : "export async function await() {}",
10069 : "export async function() {}",
10070 : "export async",
10071 : "export async\nfunction async() { await 1; }",
10072 : nullptr
10073 5 : };
10074 : // clang-format on
10075 :
10076 : RunModuleParserSyncTest(context_data, error_data, kError, nullptr, 0, nullptr,
10077 : 0, nullptr, 0, false);
10078 5 : }
10079 :
10080 28342 : TEST(RestrictiveForInErrors) {
10081 : // clang-format off
10082 : const char* strict_context_data[][2] = {
10083 : { "'use strict'", "" },
10084 : { nullptr, nullptr }
10085 5 : };
10086 : const char* sloppy_context_data[][2] = {
10087 : { "", "" },
10088 : { nullptr, nullptr }
10089 5 : };
10090 : const char* error_data[] = {
10091 : "for (const x = 0 in {});",
10092 : "for (let x = 0 in {});",
10093 : nullptr
10094 5 : };
10095 : const char* sloppy_data[] = {
10096 : "for (var x = 0 in {});",
10097 : nullptr
10098 5 : };
10099 : // clang-format on
10100 :
10101 5 : RunParserSyncTest(strict_context_data, error_data, kError);
10102 5 : RunParserSyncTest(strict_context_data, sloppy_data, kError);
10103 5 : RunParserSyncTest(sloppy_context_data, error_data, kError);
10104 5 : RunParserSyncTest(sloppy_context_data, sloppy_data, kSuccess);
10105 5 : }
10106 :
10107 28342 : TEST(NoDuplicateGeneratorsInBlock) {
10108 : const char* block_context_data[][2] = {
10109 : {"'use strict'; {", "}"},
10110 : {"{", "}"},
10111 : {"(function() { {", "} })()"},
10112 : {"(function() {'use strict'; {", "} })()"},
10113 5 : {nullptr, nullptr}};
10114 : const char* top_level_context_data[][2] = {
10115 : {"'use strict';", ""},
10116 : {"", ""},
10117 : {"(function() {", "})()"},
10118 : {"(function() {'use strict';", "})()"},
10119 5 : {nullptr, nullptr}};
10120 : const char* error_data[] = {"function* x() {} function* x() {}",
10121 : "function x() {} function* x() {}",
10122 5 : "function* x() {} function x() {}", nullptr};
10123 : // The preparser doesn't enforce the restriction, so turn it off.
10124 : bool test_preparser = false;
10125 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10126 5 : 0, nullptr, 0, false, test_preparser);
10127 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10128 5 : }
10129 :
10130 28342 : TEST(NoDuplicateAsyncFunctionInBlock) {
10131 : const char* block_context_data[][2] = {
10132 : {"'use strict'; {", "}"},
10133 : {"{", "}"},
10134 : {"(function() { {", "} })()"},
10135 : {"(function() {'use strict'; {", "} })()"},
10136 5 : {nullptr, nullptr}};
10137 : const char* top_level_context_data[][2] = {
10138 : {"'use strict';", ""},
10139 : {"", ""},
10140 : {"(function() {", "})()"},
10141 : {"(function() {'use strict';", "})()"},
10142 5 : {nullptr, nullptr}};
10143 : const char* error_data[] = {"async function x() {} async function x() {}",
10144 : "function x() {} async function x() {}",
10145 : "async function x() {} function x() {}",
10146 : "function* x() {} async function x() {}",
10147 : "function* x() {} async function x() {}",
10148 : "async function x() {} function* x() {}",
10149 : "function* x() {} async function x() {}",
10150 5 : nullptr};
10151 : // The preparser doesn't enforce the restriction, so turn it off.
10152 : bool test_preparser = false;
10153 : RunParserSyncTest(block_context_data, error_data, kError, nullptr, 0, nullptr,
10154 5 : 0, nullptr, 0, false, test_preparser);
10155 5 : RunParserSyncTest(top_level_context_data, error_data, kSuccess);
10156 5 : }
10157 :
10158 28342 : TEST(TrailingCommasInParameters) {
10159 : // clang-format off
10160 : const char* context_data[][2] = {
10161 : { "", "" },
10162 : { "'use strict';", "" },
10163 : { "function foo() {", "}" },
10164 : { "function foo() {'use strict';", "}" },
10165 : { nullptr, nullptr }
10166 5 : };
10167 :
10168 : const char* data[] = {
10169 : " function a(b,) {}",
10170 : " function* a(b,) {}",
10171 : "(function a(b,) {});",
10172 : "(function* a(b,) {});",
10173 : "(function (b,) {});",
10174 : "(function* (b,) {});",
10175 : " function a(b,c,d,) {}",
10176 : " function* a(b,c,d,) {}",
10177 : "(function a(b,c,d,) {});",
10178 : "(function* a(b,c,d,) {});",
10179 : "(function (b,c,d,) {});",
10180 : "(function* (b,c,d,) {});",
10181 : "(b,) => {};",
10182 : "(b,c,d,) => {};",
10183 : "a(1,);",
10184 : "a(1,2,3,);",
10185 : "a(...[],);",
10186 : "a(1, 2, ...[],);",
10187 : "a(...[], 2, ...[],);",
10188 : nullptr
10189 5 : };
10190 : // clang-format on
10191 :
10192 5 : RunParserSyncTest(context_data, data, kSuccess);
10193 5 : }
10194 :
10195 28342 : TEST(TrailingCommasInParametersErrors) {
10196 : // clang-format off
10197 : const char* context_data[][2] = {
10198 : { "", "" },
10199 : { "'use strict';", "" },
10200 : { "function foo() {", "}" },
10201 : { "function foo() {'use strict';", "}" },
10202 : { nullptr, nullptr }
10203 5 : };
10204 :
10205 : const char* data[] = {
10206 : // too many trailing commas
10207 : " function a(b,,) {}",
10208 : " function* a(b,,) {}",
10209 : "(function a(b,,) {});",
10210 : "(function* a(b,,) {});",
10211 : "(function (b,,) {});",
10212 : "(function* (b,,) {});",
10213 : " function a(b,c,d,,) {}",
10214 : " function* a(b,c,d,,) {}",
10215 : "(function a(b,c,d,,) {});",
10216 : "(function* a(b,c,d,,) {});",
10217 : "(function (b,c,d,,) {});",
10218 : "(function* (b,c,d,,) {});",
10219 : "(b,,) => {};",
10220 : "(b,c,d,,) => {};",
10221 : "a(1,,);",
10222 : "a(1,2,3,,);",
10223 : // only a trailing comma and no parameters
10224 : " function a1(,) {}",
10225 : " function* a2(,) {}",
10226 : "(function a3(,) {});",
10227 : "(function* a4(,) {});",
10228 : "(function (,) {});",
10229 : "(function* (,) {});",
10230 : "(,) => {};",
10231 : "a1(,);",
10232 : // no trailing commas after rest parameter declaration
10233 : " function a(...b,) {}",
10234 : " function* a(...b,) {}",
10235 : "(function a(...b,) {});",
10236 : "(function* a(...b,) {});",
10237 : "(function (...b,) {});",
10238 : "(function* (...b,) {});",
10239 : " function a(b, c, ...d,) {}",
10240 : " function* a(b, c, ...d,) {}",
10241 : "(function a(b, c, ...d,) {});",
10242 : "(function* a(b, c, ...d,) {});",
10243 : "(function (b, c, ...d,) {});",
10244 : "(function* (b, c, ...d,) {});",
10245 : "(...b,) => {};",
10246 : "(b, c, ...d,) => {};",
10247 : // parenthesized trailing comma without arrow is still an error
10248 : "(,);",
10249 : "(a,);",
10250 : "(a,b,c,);",
10251 : nullptr
10252 5 : };
10253 : // clang-format on
10254 :
10255 5 : RunParserSyncTest(context_data, data, kError);
10256 5 : }
10257 :
10258 28342 : TEST(ArgumentsRedeclaration) {
10259 : {
10260 : // clang-format off
10261 : const char* context_data[][2] = {
10262 : { "function f(", ") {}" },
10263 : { nullptr, nullptr }
10264 5 : };
10265 : const char* success_data[] = {
10266 : "{arguments}",
10267 : "{arguments = false}",
10268 : "arg1, arguments",
10269 : "arg1, ...arguments",
10270 : nullptr
10271 5 : };
10272 : // clang-format on
10273 5 : RunParserSyncTest(context_data, success_data, kSuccess);
10274 : }
10275 :
10276 : {
10277 : // clang-format off
10278 : const char* context_data[][2] = {
10279 : { "function f() {", "}" },
10280 : { nullptr, nullptr }
10281 5 : };
10282 : const char* data[] = {
10283 : "const arguments = 1",
10284 : "let arguments",
10285 : "var arguments",
10286 : nullptr
10287 5 : };
10288 : // clang-format on
10289 5 : RunParserSyncTest(context_data, data, kSuccess);
10290 : }
10291 5 : }
10292 :
10293 :
10294 : // Test that lazily parsed inner functions don't result in overly pessimistic
10295 : // context allocations.
10296 28342 : TEST(NoPessimisticContextAllocation) {
10297 : i::Isolate* isolate = CcTest::i_isolate();
10298 : i::Factory* factory = isolate->factory();
10299 : i::HandleScope scope(isolate);
10300 10 : LocalContext env;
10301 :
10302 : const char* prefix = "(function outer() { var my_var; ";
10303 : const char* suffix = " })();";
10304 5 : int prefix_len = Utf8LengthHelper(prefix);
10305 5 : int suffix_len = Utf8LengthHelper(suffix);
10306 :
10307 : // Test both normal inner functions and inner arrow functions.
10308 : const char* inner_functions[] = {"function inner(%s) { %s }",
10309 5 : "(%s) => { %s }"};
10310 :
10311 : struct {
10312 : const char* params;
10313 : const char* source;
10314 : bool ctxt_allocate;
10315 : } inners[] = {
10316 : // Context allocating because we need to:
10317 : {"", "my_var;", true},
10318 : {"", "if (true) { let my_var; } my_var;", true},
10319 : {"", "eval('foo');", true},
10320 : {"", "function inner2() { my_var; }", true},
10321 : {"", "function inner2() { eval('foo'); }", true},
10322 : {"", "var {my_var : a} = {my_var};", true},
10323 : {"", "let {my_var : a} = {my_var};", true},
10324 : {"", "const {my_var : a} = {my_var};", true},
10325 : {"", "var [a, b = my_var] = [1, 2];", true},
10326 : {"", "var [a, b = my_var] = [1, 2]; my_var;", true},
10327 : {"", "let [a, b = my_var] = [1, 2];", true},
10328 : {"", "let [a, b = my_var] = [1, 2]; my_var;", true},
10329 : {"", "const [a, b = my_var] = [1, 2];", true},
10330 : {"", "const [a, b = my_var] = [1, 2]; my_var;", true},
10331 : {"", "var {a = my_var} = {}", true},
10332 : {"", "var {a: b = my_var} = {}", true},
10333 : {"", "let {a = my_var} = {}", true},
10334 : {"", "let {a: b = my_var} = {}", true},
10335 : {"", "const {a = my_var} = {}", true},
10336 : {"", "const {a: b = my_var} = {}", true},
10337 : {"a = my_var", "", true},
10338 : {"a = my_var", "let my_var;", true},
10339 : {"", "function inner2(a = my_var) { }", true},
10340 : {"", "(a = my_var) => { }", true},
10341 : {"{a} = {a: my_var}", "", true},
10342 : {"", "function inner2({a} = {a: my_var}) { }", true},
10343 : {"", "({a} = {a: my_var}) => { }", true},
10344 : {"[a] = [my_var]", "", true},
10345 : {"", "function inner2([a] = [my_var]) { }", true},
10346 : {"", "([a] = [my_var]) => { }", true},
10347 : {"", "function inner2(a = eval('')) { }", true},
10348 : {"", "(a = eval('')) => { }", true},
10349 : {"", "try { } catch (my_var) { } my_var;", true},
10350 : {"", "for (my_var in {}) { my_var; }", true},
10351 : {"", "for (my_var in {}) { }", true},
10352 : {"", "for (my_var of []) { my_var; }", true},
10353 : {"", "for (my_var of []) { }", true},
10354 : {"", "for ([a, my_var, b] in {}) { my_var; }", true},
10355 : {"", "for ([a, my_var, b] of []) { my_var; }", true},
10356 : {"", "for ({x: my_var} in {}) { my_var; }", true},
10357 : {"", "for ({x: my_var} of []) { my_var; }", true},
10358 : {"", "for ({my_var} in {}) { my_var; }", true},
10359 : {"", "for ({my_var} of []) { my_var; }", true},
10360 : {"", "for ({y, x: my_var} in {}) { my_var; }", true},
10361 : {"", "for ({y, x: my_var} of []) { my_var; }", true},
10362 : {"", "for ({a, my_var} in {}) { my_var; }", true},
10363 : {"", "for ({a, 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 [a, my_var, b] in {}) { } my_var;", true},
10367 : {"", "for (let [a, my_var, b] of []) { } my_var;", true},
10368 : {"", "for (let {x: my_var} in {}) { } my_var;", true},
10369 : {"", "for (let {x: my_var} of []) { } my_var;", true},
10370 : {"", "for (let {my_var} in {}) { } my_var;", true},
10371 : {"", "for (let {my_var} of []) { } my_var;", true},
10372 : {"", "for (let {y, x: my_var} in {}) { } my_var;", true},
10373 : {"", "for (let {y, x: my_var} of []) { } my_var;", true},
10374 : {"", "for (let {a, my_var} in {}) { } my_var;", true},
10375 : {"", "for (let {a, my_var} of []) { } my_var;", true},
10376 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { } my_var;", true},
10377 : {"", "'use strict'; if (true) { function my_var() {} } my_var;", true},
10378 : {"",
10379 : "'use strict'; function inner2() { if (true) { function my_var() {} } "
10380 : "my_var; }",
10381 : true},
10382 : {"",
10383 : "function inner2() { 'use strict'; if (true) { function my_var() {} } "
10384 : "my_var; }",
10385 : true},
10386 : {"",
10387 : "() => { 'use strict'; if (true) { function my_var() {} } my_var; }",
10388 : true},
10389 : {"",
10390 : "if (true) { let my_var; if (true) { function my_var() {} } } my_var;",
10391 : true},
10392 : {"", "function inner2(a = my_var) {}", true},
10393 : {"", "function inner2(a = my_var) { let my_var; }", true},
10394 : {"", "(a = my_var) => {}", true},
10395 : {"", "(a = my_var) => { let my_var; }", true},
10396 : // No pessimistic context allocation:
10397 : {"", "var my_var; my_var;", false},
10398 : {"", "var my_var;", false},
10399 : {"", "var my_var = 0;", false},
10400 : {"", "if (true) { var my_var; } my_var;", false},
10401 : {"", "let my_var; my_var;", false},
10402 : {"", "let my_var;", false},
10403 : {"", "let my_var = 0;", false},
10404 : {"", "const my_var = 0; my_var;", false},
10405 : {"", "const my_var = 0;", false},
10406 : {"", "var [a, my_var] = [1, 2]; my_var;", false},
10407 : {"", "let [a, my_var] = [1, 2]; my_var;", false},
10408 : {"", "const [a, my_var] = [1, 2]; my_var;", false},
10409 : {"", "var {a: my_var} = {a: 3}; my_var;", false},
10410 : {"", "let {a: my_var} = {a: 3}; my_var;", false},
10411 : {"", "const {a: my_var} = {a: 3}; my_var;", false},
10412 : {"", "var {my_var} = {my_var: 3}; my_var;", false},
10413 : {"", "let {my_var} = {my_var: 3}; my_var;", false},
10414 : {"", "const {my_var} = {my_var: 3}; my_var;", false},
10415 : {"my_var", "my_var;", false},
10416 : {"my_var", "", false},
10417 : {"my_var = 5", "my_var;", false},
10418 : {"my_var = 5", "", false},
10419 : {"...my_var", "my_var;", false},
10420 : {"...my_var", "", false},
10421 : {"[a, my_var, b]", "my_var;", false},
10422 : {"[a, my_var, b]", "", false},
10423 : {"[a, my_var, b] = [1, 2, 3]", "my_var;", false},
10424 : {"[a, my_var, b] = [1, 2, 3]", "", false},
10425 : {"{x: my_var}", "my_var;", false},
10426 : {"{x: my_var}", "", false},
10427 : {"{x: my_var} = {x: 0}", "my_var;", false},
10428 : {"{x: my_var} = {x: 0}", "", false},
10429 : {"{my_var}", "my_var;", false},
10430 : {"{my_var}", "", false},
10431 : {"{my_var} = {my_var: 0}", "my_var;", false},
10432 : {"{my_var} = {my_var: 0}", "", false},
10433 : {"", "function inner2(my_var) { my_var; }", false},
10434 : {"", "function inner2(my_var) { }", false},
10435 : {"", "function inner2(my_var = 5) { my_var; }", false},
10436 : {"", "function inner2(my_var = 5) { }", false},
10437 : {"", "function inner2(...my_var) { my_var; }", false},
10438 : {"", "function inner2(...my_var) { }", false},
10439 : {"", "function inner2([a, my_var, b]) { my_var; }", false},
10440 : {"", "function inner2([a, my_var, b]) { }", false},
10441 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { my_var; }", false},
10442 : {"", "function inner2([a, my_var, b] = [1, 2, 3]) { }", false},
10443 : {"", "function inner2({x: my_var}) { my_var; }", false},
10444 : {"", "function inner2({x: my_var}) { }", false},
10445 : {"", "function inner2({x: my_var} = {x: 0}) { my_var; }", false},
10446 : {"", "function inner2({x: my_var} = {x: 0}) { }", false},
10447 : {"", "function inner2({my_var}) { my_var; }", false},
10448 : {"", "function inner2({my_var}) { }", false},
10449 : {"", "function inner2({my_var} = {my_var: 8}) { my_var; } ", false},
10450 : {"", "function inner2({my_var} = {my_var: 8}) { }", false},
10451 : {"", "my_var => my_var;", false},
10452 : {"", "my_var => { }", false},
10453 : {"", "(my_var = 5) => my_var;", false},
10454 : {"", "(my_var = 5) => { }", false},
10455 : {"", "(...my_var) => my_var;", false},
10456 : {"", "(...my_var) => { }", false},
10457 : {"", "([a, my_var, b]) => my_var;", false},
10458 : {"", "([a, my_var, b]) => { }", false},
10459 : {"", "([a, my_var, b] = [1, 2, 3]) => my_var;", false},
10460 : {"", "([a, my_var, b] = [1, 2, 3]) => { }", false},
10461 : {"", "({x: my_var}) => my_var;", false},
10462 : {"", "({x: my_var}) => { }", false},
10463 : {"", "({x: my_var} = {x: 0}) => my_var;", false},
10464 : {"", "({x: my_var} = {x: 0}) => { }", false},
10465 : {"", "({my_var}) => my_var;", false},
10466 : {"", "({my_var}) => { }", false},
10467 : {"", "({my_var} = {my_var: 5}) => my_var;", false},
10468 : {"", "({my_var} = {my_var: 5}) => { }", false},
10469 : {"", "({a, my_var}) => my_var;", false},
10470 : {"", "({a, my_var}) => { }", false},
10471 : {"", "({a, my_var} = {a: 0, my_var: 5}) => my_var;", false},
10472 : {"", "({a, my_var} = {a: 0, my_var: 5}) => { }", false},
10473 : {"", "({y, x: my_var}) => my_var;", false},
10474 : {"", "({y, x: my_var}) => { }", false},
10475 : {"", "({y, x: my_var} = {y: 0, x: 0}) => my_var;", false},
10476 : {"", "({y, x: my_var} = {y: 0, x: 0}) => { }", false},
10477 : {"", "try { } catch (my_var) { my_var; }", false},
10478 : {"", "try { } catch ([a, my_var, b]) { my_var; }", false},
10479 : {"", "try { } catch ({x: my_var}) { my_var; }", false},
10480 : {"", "try { } catch ({y, x: my_var}) { my_var; }", false},
10481 : {"", "try { } catch ({my_var}) { my_var; }", false},
10482 : {"", "for (let my_var in {}) { my_var; }", false},
10483 : {"", "for (let my_var in {}) { }", false},
10484 : {"", "for (let my_var of []) { my_var; }", false},
10485 : {"", "for (let my_var of []) { }", false},
10486 : {"", "for (let [a, my_var, b] in {}) { my_var; }", false},
10487 : {"", "for (let [a, my_var, b] of []) { my_var; }", false},
10488 : {"", "for (let {x: my_var} in {}) { my_var; }", false},
10489 : {"", "for (let {x: my_var} of []) { my_var; }", false},
10490 : {"", "for (let {my_var} in {}) { my_var; }", false},
10491 : {"", "for (let {my_var} of []) { my_var; }", false},
10492 : {"", "for (let {y, x: my_var} in {}) { my_var; }", false},
10493 : {"", "for (let {y, x: my_var} of []) { my_var; }", false},
10494 : {"", "for (let {a, my_var} in {}) { my_var; }", false},
10495 : {"", "for (let {a, my_var} of []) { my_var; }", false},
10496 : {"", "for (var my_var in {}) { my_var; }", false},
10497 : {"", "for (var my_var in {}) { }", false},
10498 : {"", "for (var my_var of []) { my_var; }", false},
10499 : {"", "for (var my_var of []) { }", false},
10500 : {"", "for (var [a, my_var, b] in {}) { my_var; }", false},
10501 : {"", "for (var [a, my_var, b] of []) { my_var; }", false},
10502 : {"", "for (var {x: my_var} in {}) { my_var; }", false},
10503 : {"", "for (var {x: 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 {y, x: my_var} in {}) { my_var; }", false},
10507 : {"", "for (var {y, x: my_var} of []) { my_var; }", false},
10508 : {"", "for (var {a, my_var} in {}) { my_var; }", false},
10509 : {"", "for (var {a, 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 [a, my_var, b] in {}) { } my_var;", false},
10513 : {"", "for (var [a, my_var, b] of []) { } my_var;", false},
10514 : {"", "for (var {x: my_var} in {}) { } my_var;", false},
10515 : {"", "for (var {x: my_var} of []) { } my_var;", false},
10516 : {"", "for (var {my_var} in {}) { } my_var;", false},
10517 : {"", "for (var {my_var} of []) { } my_var;", false},
10518 : {"", "for (var {y, x: my_var} in {}) { } my_var;", false},
10519 : {"", "for (var {y, x: my_var} of []) { } my_var;", false},
10520 : {"", "for (var {a, my_var} in {}) { } my_var;", false},
10521 : {"", "for (var {a, my_var} of []) { } my_var;", false},
10522 : {"", "for (let my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10523 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { my_var; }", false},
10524 : {"", "for (var my_var = 0; my_var < 1; ++my_var) { } my_var; ", false},
10525 : {"", "for (let a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10526 : false},
10527 : {"", "for (var a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }",
10528 : false},
10529 : {"", "class my_var {}; my_var; ", false},
10530 : {"", "function my_var() {} my_var;", false},
10531 : {"", "if (true) { function my_var() {} } my_var;", false},
10532 : {"", "function inner2() { if (true) { function my_var() {} } my_var; }",
10533 : false},
10534 : {"", "() => { if (true) { function my_var() {} } my_var; }", false},
10535 : {"",
10536 : "if (true) { var my_var; if (true) { function my_var() {} } } my_var;",
10537 : false},
10538 5 : };
10539 :
10540 15 : for (unsigned inner_ix = 0; inner_ix < arraysize(inner_functions);
10541 : ++inner_ix) {
10542 10 : const char* inner_function = inner_functions[inner_ix];
10543 10 : int inner_function_len = Utf8LengthHelper(inner_function) - 4;
10544 :
10545 2060 : for (unsigned i = 0; i < arraysize(inners); ++i) {
10546 2050 : int params_len = Utf8LengthHelper(inners[i].params);
10547 2050 : int source_len = Utf8LengthHelper(inners[i].source);
10548 2050 : int len = prefix_len + inner_function_len + params_len + source_len +
10549 2050 : suffix_len;
10550 :
10551 2050 : i::ScopedVector<char> program(len + 1);
10552 2050 : i::SNPrintF(program, "%s", prefix);
10553 : i::SNPrintF(program + prefix_len, inner_function, inners[i].params,
10554 4100 : inners[i].source);
10555 : i::SNPrintF(
10556 2050 : program + prefix_len + inner_function_len + params_len + source_len,
10557 4100 : "%s", suffix);
10558 :
10559 : i::Handle<i::String> source =
10560 2050 : factory->InternalizeUtf8String(program.start());
10561 4100 : source->PrintOn(stdout);
10562 : printf("\n");
10563 :
10564 2050 : i::Handle<i::Script> script = factory->NewScript(source);
10565 4100 : i::ParseInfo info(isolate, script);
10566 :
10567 2050 : CHECK(i::parsing::ParseProgram(&info, isolate));
10568 2050 : CHECK(i::Compiler::Analyze(&info));
10569 2050 : CHECK_NOT_NULL(info.literal());
10570 :
10571 2050 : i::Scope* scope = info.literal()->scope()->inner_scope();
10572 : DCHECK_NOT_NULL(scope);
10573 : DCHECK_NULL(scope->sibling());
10574 : DCHECK(scope->is_function_scope());
10575 : const i::AstRawString* var_name =
10576 2050 : info.ast_value_factory()->GetOneByteString("my_var");
10577 : i::Variable* var = scope->LookupForTesting(var_name);
10578 2050 : CHECK_EQ(inners[i].ctxt_allocate,
10579 : i::ScopeTestHelper::MustAllocateInContext(var));
10580 : }
10581 : }
10582 5 : }
10583 :
10584 28342 : TEST(EscapedStrictReservedWord) {
10585 : // Test that identifiers which are both escaped and only reserved in the
10586 : // strict mode are accepted in non-strict mode.
10587 5 : const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
10588 :
10589 : const char* statement_data[] = {"if (true) l\\u0065t: ;",
10590 : "function l\\u0065t() { }",
10591 : "(function l\\u0065t() { })",
10592 : "async function l\\u0065t() { }",
10593 : "(async function l\\u0065t() { })",
10594 : "l\\u0065t => 42",
10595 : "async l\\u0065t => 42",
10596 : "function packag\\u0065() {}",
10597 : "function impl\\u0065ments() {}",
10598 : "function privat\\u0065() {}",
10599 5 : nullptr};
10600 :
10601 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
10602 5 : }
10603 :
10604 28342 : TEST(ForAwaitOf) {
10605 : // clang-format off
10606 : const char* context_data[][2] = {
10607 : { "async function f() { for await ", " ; }" },
10608 : { "async function f() { for await ", " { } }" },
10609 : { "async function * f() { for await ", " { } }" },
10610 : { "async function f() { 'use strict'; for await ", " ; }" },
10611 : { "async function f() { 'use strict'; for await ", " { } }" },
10612 : { "async function * f() { 'use strict'; for await ", " { } }" },
10613 : { "async function f() { for\nawait ", " ; }" },
10614 : { "async function f() { for\nawait ", " { } }" },
10615 : { "async function * f() { for\nawait ", " { } }" },
10616 : { "async function f() { 'use strict'; for\nawait ", " ; }" },
10617 : { "async function f() { 'use strict'; for\nawait ", " { } }" },
10618 : { "async function * f() { 'use strict'; for\nawait ", " { } }" },
10619 : { "async function f() { for await\n", " ; }" },
10620 : { "async function f() { for await\n", " { } }" },
10621 : { "async function * f() { for await\n", " { } }" },
10622 : { "async function f() { 'use strict'; for await\n", " ; }" },
10623 : { "async function f() { 'use strict'; for await\n", " { } }" },
10624 : { "async function * f() { 'use strict'; for await\n", " { } }" },
10625 : { nullptr, nullptr }
10626 5 : };
10627 :
10628 : const char* context_data2[][2] = {
10629 : { "async function f() { let a; for await ", " ; }" },
10630 : { "async function f() { let a; for await ", " { } }" },
10631 : { "async function * f() { let a; for await ", " { } }" },
10632 : { "async function f() { 'use strict'; let a; for await ", " ; }" },
10633 : { "async function f() { 'use strict'; let a; for await ", " { } }" },
10634 : { "async function * f() { 'use strict'; let a; for await ", " { } }" },
10635 : { "async function f() { let a; for\nawait ", " ; }" },
10636 : { "async function f() { let a; for\nawait ", " { } }" },
10637 : { "async function * f() { let a; for\nawait ", " { } }" },
10638 : { "async function f() { 'use strict'; let a; for\nawait ", " ; }" },
10639 : { "async function f() { 'use strict'; let a; for\nawait ", " { } }" },
10640 : { "async function * f() { 'use strict'; let a; for\nawait ", " { } }" },
10641 : { "async function f() { let a; for await\n", " ; }" },
10642 : { "async function f() { let a; for await\n", " { } }" },
10643 : { "async function * f() { let a; for await\n", " { } }" },
10644 : { "async function f() { 'use strict'; let a; for await\n", " ; }" },
10645 : { "async function f() { 'use strict'; let a; for await\n", " { } }" },
10646 : { "async function * f() { 'use strict'; let a; for await\n", " { } }" },
10647 : { nullptr, nullptr }
10648 5 : };
10649 :
10650 : const char* expr_data[] = {
10651 : // Primary Expressions
10652 : "(a of [])",
10653 : "(a.b of [])",
10654 : "([a] of [])",
10655 : "([a = 1] of [])",
10656 : "([a = 1, ...b] of [])",
10657 : "({a} of [])",
10658 : "({a: a} of [])",
10659 : "({'a': a} of [])",
10660 : "({\"a\": a} of [])",
10661 : "({[Symbol.iterator]: a} of [])",
10662 : "({0: a} of [])",
10663 : "({a = 1} of [])",
10664 : "({a: a = 1} of [])",
10665 : "({'a': a = 1} of [])",
10666 : "({\"a\": a = 1} of [])",
10667 : "({[Symbol.iterator]: a = 1} of [])",
10668 : "({0: a = 1} of [])",
10669 : nullptr
10670 5 : };
10671 :
10672 : const char* var_data[] = {
10673 : // VarDeclarations
10674 : "(var a of [])",
10675 : "(var [a] of [])",
10676 : "(var [a = 1] of [])",
10677 : "(var [a = 1, ...b] of [])",
10678 : "(var {a} of [])",
10679 : "(var {a: a} of [])",
10680 : "(var {'a': a} of [])",
10681 : "(var {\"a\": a} of [])",
10682 : "(var {[Symbol.iterator]: a} of [])",
10683 : "(var {0: a} of [])",
10684 : "(var {a = 1} of [])",
10685 : "(var {a: a = 1} of [])",
10686 : "(var {'a': a = 1} of [])",
10687 : "(var {\"a\": a = 1} of [])",
10688 : "(var {[Symbol.iterator]: a = 1} of [])",
10689 : "(var {0: a = 1} of [])",
10690 : nullptr
10691 5 : };
10692 :
10693 : const char* lexical_data[] = {
10694 : // LexicalDeclartions
10695 : "(let a of [])",
10696 : "(let [a] of [])",
10697 : "(let [a = 1] of [])",
10698 : "(let [a = 1, ...b] of [])",
10699 : "(let {a} of [])",
10700 : "(let {a: a} of [])",
10701 : "(let {'a': a} of [])",
10702 : "(let {\"a\": a} of [])",
10703 : "(let {[Symbol.iterator]: a} of [])",
10704 : "(let {0: a} of [])",
10705 : "(let {a = 1} of [])",
10706 : "(let {a: a = 1} of [])",
10707 : "(let {'a': a = 1} of [])",
10708 : "(let {\"a\": a = 1} of [])",
10709 : "(let {[Symbol.iterator]: a = 1} of [])",
10710 : "(let {0: a = 1} of [])",
10711 :
10712 : "(const a of [])",
10713 : "(const [a] of [])",
10714 : "(const [a = 1] of [])",
10715 : "(const [a = 1, ...b] of [])",
10716 : "(const {a} of [])",
10717 : "(const {a: a} of [])",
10718 : "(const {'a': a} of [])",
10719 : "(const {\"a\": a} of [])",
10720 : "(const {[Symbol.iterator]: a} of [])",
10721 : "(const {0: a} of [])",
10722 : "(const {a = 1} of [])",
10723 : "(const {a: a = 1} of [])",
10724 : "(const {'a': a = 1} of [])",
10725 : "(const {\"a\": a = 1} of [])",
10726 : "(const {[Symbol.iterator]: a = 1} of [])",
10727 : "(const {0: a = 1} of [])",
10728 : nullptr
10729 5 : };
10730 : // clang-format on
10731 5 : RunParserSyncTest(context_data, expr_data, kSuccess);
10732 5 : RunParserSyncTest(context_data2, expr_data, kSuccess);
10733 :
10734 5 : RunParserSyncTest(context_data, var_data, kSuccess);
10735 : // TODO(marja): PreParser doesn't report early errors.
10736 : // (https://bugs.chromium.org/p/v8/issues/detail?id=2728)
10737 : // RunParserSyncTest(context_data2, var_data, kError, nullptr, 0,
10738 : // always_flags,
10739 : // arraysize(always_flags));
10740 :
10741 5 : RunParserSyncTest(context_data, lexical_data, kSuccess);
10742 5 : RunParserSyncTest(context_data2, lexical_data, kSuccess);
10743 5 : }
10744 :
10745 28342 : TEST(ForAwaitOfErrors) {
10746 : // clang-format off
10747 : const char* context_data[][2] = {
10748 : { "async function f() { for await ", " ; }" },
10749 : { "async function f() { for await ", " { } }" },
10750 : { "async function f() { 'use strict'; for await ", " ; }" },
10751 : { "async function f() { 'use strict'; for await ", " { } }" },
10752 : { "async function * f() { for await ", " ; }" },
10753 : { "async function * f() { for await ", " { } }" },
10754 : { "async function * f() { 'use strict'; for await ", " ; }" },
10755 : { "async function * f() { 'use strict'; for await ", " { } }" },
10756 : { nullptr, nullptr }
10757 5 : };
10758 :
10759 : const char* data[] = {
10760 : // Primary Expressions
10761 : "(a = 1 of [])",
10762 : "(a = 1) of [])",
10763 : "(a.b = 1 of [])",
10764 : "((a.b = 1) of [])",
10765 : "([a] = 1 of [])",
10766 : "(([a] = 1) of [])",
10767 : "([a = 1] = 1 of [])",
10768 : "(([a = 1] = 1) of [])",
10769 : "([a = 1 = 1, ...b] = 1 of [])",
10770 : "(([a = 1 = 1, ...b] = 1) of [])",
10771 : "({a} = 1 of [])",
10772 : "(({a} = 1) of [])",
10773 : "({a: a} = 1 of [])",
10774 : "(({a: a} = 1) of [])",
10775 : "({'a': a} = 1 of [])",
10776 : "(({'a': a} = 1) of [])",
10777 : "({\"a\": a} = 1 of [])",
10778 : "(({\"a\": a} = 1) of [])",
10779 : "({[Symbol.iterator]: a} = 1 of [])",
10780 : "(({[Symbol.iterator]: a} = 1) of [])",
10781 : "({0: a} = 1 of [])",
10782 : "(({0: a} = 1) of [])",
10783 : "({a = 1} = 1 of [])",
10784 : "(({a = 1} = 1) of [])",
10785 : "({a: a = 1} = 1 of [])",
10786 : "(({a: a = 1} = 1) of [])",
10787 : "({'a': a = 1} = 1 of [])",
10788 : "(({'a': a = 1} = 1) of [])",
10789 : "({\"a\": a = 1} = 1 of [])",
10790 : "(({\"a\": a = 1} = 1) of [])",
10791 : "({[Symbol.iterator]: a = 1} = 1 of [])",
10792 : "(({[Symbol.iterator]: a = 1} = 1) of [])",
10793 : "({0: a = 1} = 1 of [])",
10794 : "(({0: a = 1} = 1) of [])",
10795 : "(function a() {} of [])",
10796 : "([1] of [])",
10797 : "({a: 1} of [])"
10798 :
10799 : // VarDeclarations
10800 : "(var a = 1 of [])",
10801 : "(var a, b of [])",
10802 : "(var [a] = 1 of [])",
10803 : "(var [a], b of [])",
10804 : "(var [a = 1] = 1 of [])",
10805 : "(var [a = 1], b of [])",
10806 : "(var [a = 1 = 1, ...b] of [])",
10807 : "(var [a = 1, ...b], c of [])",
10808 : "(var {a} = 1 of [])",
10809 : "(var {a}, b of [])",
10810 : "(var {a: a} = 1 of [])",
10811 : "(var {a: a}, b of [])",
10812 : "(var {'a': a} = 1 of [])",
10813 : "(var {'a': a}, b of [])",
10814 : "(var {\"a\": a} = 1 of [])",
10815 : "(var {\"a\": a}, b of [])",
10816 : "(var {[Symbol.iterator]: a} = 1 of [])",
10817 : "(var {[Symbol.iterator]: a}, b of [])",
10818 : "(var {0: a} = 1 of [])",
10819 : "(var {0: a}, b of [])",
10820 : "(var {a = 1} = 1 of [])",
10821 : "(var {a = 1}, b of [])",
10822 : "(var {a: a = 1} = 1 of [])",
10823 : "(var {a: a = 1}, b of [])",
10824 : "(var {'a': a = 1} = 1 of [])",
10825 : "(var {'a': a = 1}, b of [])",
10826 : "(var {\"a\": a = 1} = 1 of [])",
10827 : "(var {\"a\": a = 1}, b of [])",
10828 : "(var {[Symbol.iterator]: a = 1} = 1 of [])",
10829 : "(var {[Symbol.iterator]: a = 1}, b of [])",
10830 : "(var {0: a = 1} = 1 of [])",
10831 : "(var {0: a = 1}, b of [])",
10832 :
10833 : // LexicalDeclartions
10834 : "(let a = 1 of [])",
10835 : "(let a, b of [])",
10836 : "(let [a] = 1 of [])",
10837 : "(let [a], b of [])",
10838 : "(let [a = 1] = 1 of [])",
10839 : "(let [a = 1], b of [])",
10840 : "(let [a = 1, ...b] = 1 of [])",
10841 : "(let [a = 1, ...b], c of [])",
10842 : "(let {a} = 1 of [])",
10843 : "(let {a}, b of [])",
10844 : "(let {a: a} = 1 of [])",
10845 : "(let {a: a}, b of [])",
10846 : "(let {'a': a} = 1 of [])",
10847 : "(let {'a': a}, b of [])",
10848 : "(let {\"a\": a} = 1 of [])",
10849 : "(let {\"a\": a}, b of [])",
10850 : "(let {[Symbol.iterator]: a} = 1 of [])",
10851 : "(let {[Symbol.iterator]: a}, b of [])",
10852 : "(let {0: a} = 1 of [])",
10853 : "(let {0: a}, b of [])",
10854 : "(let {a = 1} = 1 of [])",
10855 : "(let {a = 1}, b of [])",
10856 : "(let {a: a = 1} = 1 of [])",
10857 : "(let {a: a = 1}, b of [])",
10858 : "(let {'a': a = 1} = 1 of [])",
10859 : "(let {'a': a = 1}, b of [])",
10860 : "(let {\"a\": a = 1} = 1 of [])",
10861 : "(let {\"a\": a = 1}, b of [])",
10862 : "(let {[Symbol.iterator]: a = 1} = 1 of [])",
10863 : "(let {[Symbol.iterator]: a = 1}, b of [])",
10864 : "(let {0: a = 1} = 1 of [])",
10865 : "(let {0: a = 1}, b of [])",
10866 :
10867 : "(const a = 1 of [])",
10868 : "(const a, b of [])",
10869 : "(const [a] = 1 of [])",
10870 : "(const [a], b of [])",
10871 : "(const [a = 1] = 1 of [])",
10872 : "(const [a = 1], b of [])",
10873 : "(const [a = 1, ...b] = 1 of [])",
10874 : "(const [a = 1, ...b], b of [])",
10875 : "(const {a} = 1 of [])",
10876 : "(const {a}, b of [])",
10877 : "(const {a: a} = 1 of [])",
10878 : "(const {a: a}, b of [])",
10879 : "(const {'a': a} = 1 of [])",
10880 : "(const {'a': a}, b of [])",
10881 : "(const {\"a\": a} = 1 of [])",
10882 : "(const {\"a\": a}, b of [])",
10883 : "(const {[Symbol.iterator]: a} = 1 of [])",
10884 : "(const {[Symbol.iterator]: a}, b of [])",
10885 : "(const {0: a} = 1 of [])",
10886 : "(const {0: a}, b of [])",
10887 : "(const {a = 1} = 1 of [])",
10888 : "(const {a = 1}, b of [])",
10889 : "(const {a: a = 1} = 1 of [])",
10890 : "(const {a: a = 1}, b of [])",
10891 : "(const {'a': a = 1} = 1 of [])",
10892 : "(const {'a': a = 1}, b of [])",
10893 : "(const {\"a\": a = 1} = 1 of [])",
10894 : "(const {\"a\": a = 1}, b of [])",
10895 : "(const {[Symbol.iterator]: a = 1} = 1 of [])",
10896 : "(const {[Symbol.iterator]: a = 1}, b of [])",
10897 : "(const {0: a = 1} = 1 of [])",
10898 : "(const {0: a = 1}, b of [])",
10899 :
10900 : nullptr
10901 5 : };
10902 : // clang-format on
10903 5 : RunParserSyncTest(context_data, data, kError);
10904 5 : }
10905 :
10906 28342 : TEST(ForAwaitOfFunctionDeclaration) {
10907 : // clang-format off
10908 : const char* context_data[][2] = {
10909 : { "async function f() {", "}" },
10910 : { "async function f() { 'use strict'; ", "}" },
10911 : { nullptr, nullptr }
10912 5 : };
10913 :
10914 : const char* data[] = {
10915 : "for await (x of []) function d() {};",
10916 : "for await (x of []) function d() {}; return d;",
10917 : "for await (x of []) function* g() {};",
10918 : "for await (x of []) function* g() {}; return g;",
10919 : // TODO(caitp): handle async function declarations in ParseScopedStatement.
10920 : // "for await (x of []) async function a() {};",
10921 : // "for await (x of []) async function a() {}; return a;",
10922 : nullptr
10923 5 : };
10924 :
10925 : // clang-format on
10926 5 : RunParserSyncTest(context_data, data, kError);
10927 5 : }
10928 :
10929 28342 : TEST(AsyncGenerator) {
10930 : // clang-format off
10931 : const char* context_data[][2] = {
10932 : { "async function * gen() {", "}" },
10933 : { "(async function * gen() {", "})" },
10934 : { "(async function * () {", "})" },
10935 : { "({ async * gen () {", "} })" },
10936 : { nullptr, nullptr }
10937 5 : };
10938 :
10939 : const char* statement_data[] = {
10940 : // An async generator without a body is valid.
10941 : ""
10942 : // Valid yield expressions inside generators.
10943 : "yield 2;",
10944 : "yield * 2;",
10945 : "yield * \n 2;",
10946 : "yield yield 1;",
10947 : "yield * yield * 1;",
10948 : "yield 3 + (yield 4);",
10949 : "yield * 3 + (yield * 4);",
10950 : "(yield * 3) + (yield * 4);",
10951 : "yield 3; yield 4;",
10952 : "yield * 3; yield * 4;",
10953 : "(function (yield) { })",
10954 : "(function yield() { })",
10955 : "(function (await) { })",
10956 : "(function await() { })",
10957 : "yield { yield: 12 }",
10958 : "yield /* comment */ { yield: 12 }",
10959 : "yield * \n { yield: 12 }",
10960 : "yield /* comment */ * \n { yield: 12 }",
10961 : // You can return in an async generator.
10962 : "yield 1; return",
10963 : "yield * 1; return",
10964 : "yield 1; return 37",
10965 : "yield * 1; return 37",
10966 : "yield 1; return 37; yield 'dead';",
10967 : "yield * 1; return 37; yield * 'dead';",
10968 : // Yield/Await are still a valid key in object literals.
10969 : "({ yield: 1 })",
10970 : "({ get yield() { } })",
10971 : "({ await: 1 })",
10972 : "({ get await() { } })",
10973 : // And in assignment pattern computed properties
10974 : "({ [yield]: x } = { })",
10975 : "({ [await 1]: x } = { })",
10976 : // Yield without RHS.
10977 : "yield;",
10978 : "yield",
10979 : "yield\n",
10980 : "yield /* comment */"
10981 : "yield // comment\n"
10982 : "(yield)",
10983 : "[yield]",
10984 : "{yield}",
10985 : "yield, yield",
10986 : "yield; yield",
10987 : "(yield) ? yield : yield",
10988 : "(yield) \n ? yield : yield",
10989 : // If there is a newline before the next token, we don't look for RHS.
10990 : "yield\nfor (;;) {}",
10991 : "x = class extends (yield) {}",
10992 : "x = class extends f(yield) {}",
10993 : "x = class extends (null, yield) { }",
10994 : "x = class extends (a ? null : yield) { }",
10995 : "x = class extends (await 10) {}",
10996 : "x = class extends f(await 10) {}",
10997 : "x = class extends (null, await 10) { }",
10998 : "x = class extends (a ? null : await 10) { }",
10999 :
11000 : // More tests featuring AwaitExpressions
11001 : "await 10",
11002 : "await 10; return",
11003 : "await 10; return 20",
11004 : "await 10; return 20; yield 'dead'",
11005 : "await (yield 10)",
11006 : "await (yield 10); return",
11007 : "await (yield 10); return 20",
11008 : "await (yield 10); return 20; yield 'dead'",
11009 : "yield await 10",
11010 : "yield await 10; return",
11011 : "yield await 10; return 20",
11012 : "yield await 10; return 20; yield 'dead'",
11013 : "await /* comment */ 10",
11014 : "await // comment\n 10",
11015 : "yield await /* comment\n */ 10",
11016 : "yield await // comment\n 10",
11017 : "await (yield /* comment */)",
11018 : "await (yield // comment\n)",
11019 : nullptr
11020 5 : };
11021 : // clang-format on
11022 :
11023 5 : RunParserSyncTest(context_data, statement_data, kSuccess);
11024 5 : }
11025 :
11026 28342 : TEST(AsyncGeneratorErrors) {
11027 : // clang-format off
11028 : const char* context_data[][2] = {
11029 : { "async function * gen() {", "}" },
11030 : { "\"use strict\"; async function * gen() {", "}" },
11031 : { nullptr, nullptr }
11032 5 : };
11033 :
11034 : const char* statement_data[] = {
11035 : // Invalid yield expressions inside generators.
11036 : "var yield;",
11037 : "var await;",
11038 : "var foo, yield;",
11039 : "var foo, await;",
11040 : "try { } catch (yield) { }",
11041 : "try { } catch (await) { }",
11042 : "function yield() { }",
11043 : "function await() { }",
11044 : // The name of the NFE is bound in the generator, which does not permit
11045 : // yield or await to be identifiers.
11046 : "(async function * yield() { })",
11047 : "(async function * await() { })",
11048 : // Yield and Await aren't valid as a formal parameter for generators.
11049 : "async function * foo(yield) { }",
11050 : "(async function * foo(yield) { })",
11051 : "async function * foo(await) { }",
11052 : "(async function * foo(await) { })",
11053 : "yield = 1;",
11054 : "await = 1;",
11055 : "var foo = yield = 1;",
11056 : "var foo = await = 1;",
11057 : "++yield;",
11058 : "++await;",
11059 : "yield++;",
11060 : "await++;",
11061 : "yield *",
11062 : "(yield *)",
11063 : // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
11064 : // is invalid.
11065 : "yield 3 + yield 4;",
11066 : "yield: 34",
11067 : "yield ? 1 : 2",
11068 : // Parses as yield (/ yield): invalid.
11069 : "yield / yield",
11070 : "+ yield",
11071 : "+ yield 3",
11072 : // Invalid (no newline allowed between yield and *).
11073 : "yield\n*3",
11074 : // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
11075 : // object literal, and yield is not a valid label).
11076 : "yield\n{yield: 42}",
11077 : "yield /* comment */\n {yield: 42}",
11078 : "yield //comment\n {yield: 42}",
11079 : // Destructuring binding and assignment are both disallowed
11080 : "var [yield] = [42];",
11081 : "var [await] = [42];",
11082 : "var {foo: yield} = {a: 42};",
11083 : "var {foo: await} = {a: 42};",
11084 : "[yield] = [42];",
11085 : "[await] = [42];",
11086 : "({a: yield} = {a: 42});",
11087 : "({a: await} = {a: 42});",
11088 : // Also disallow full yield/await expressions on LHS
11089 : "var [yield 24] = [42];",
11090 : "var [await 24] = [42];",
11091 : "var {foo: yield 24} = {a: 42};",
11092 : "var {foo: await 24} = {a: 42};",
11093 : "[yield 24] = [42];",
11094 : "[await 24] = [42];",
11095 : "({a: yield 24} = {a: 42});",
11096 : "({a: await 24} = {a: 42});",
11097 : "for (yield 'x' in {});",
11098 : "for (await 'x' in {});",
11099 : "for (yield 'x' of {});",
11100 : "for (await 'x' of {});",
11101 : "for (yield 'x' in {} in {});",
11102 : "for (await 'x' in {} in {});",
11103 : "for (yield 'x' in {} of {});",
11104 : "for (await 'x' in {} of {});",
11105 : "class C extends yield { }",
11106 : "class C extends await { }",
11107 : nullptr
11108 5 : };
11109 : // clang-format on
11110 :
11111 5 : RunParserSyncTest(context_data, statement_data, kError);
11112 5 : }
11113 :
11114 28342 : TEST(LexicalLoopVariable) {
11115 : i::Isolate* isolate = CcTest::i_isolate();
11116 : i::HandleScope scope(isolate);
11117 10 : LocalContext env;
11118 : typedef std::function<void(const i::ParseInfo& info, i::DeclarationScope*)>
11119 : TestCB;
11120 50 : auto TestProgram = [isolate](const char* program, TestCB test) {
11121 50 : i::Factory* const factory = isolate->factory();
11122 : i::Handle<i::String> source =
11123 100 : factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
11124 50 : i::Handle<i::Script> script = factory->NewScript(source);
11125 50 : i::ParseInfo info(isolate, script);
11126 :
11127 : info.set_allow_lazy_parsing(false);
11128 50 : CHECK(i::parsing::ParseProgram(&info, isolate));
11129 50 : CHECK(i::Rewriter::Rewrite(&info));
11130 50 : CHECK(i::DeclarationScope::Analyze(&info));
11131 50 : i::DeclarationScope::AllocateScopeInfos(&info, isolate);
11132 50 : CHECK_NOT_NULL(info.literal());
11133 :
11134 50 : i::DeclarationScope* script_scope = info.literal()->scope();
11135 50 : CHECK(script_scope->is_script_scope());
11136 :
11137 50 : test(info, script_scope);
11138 55 : };
11139 :
11140 : // Check `let` loop variables is a stack local when not captured by
11141 : // an eval or closure within the area of the loop body.
11142 : const char* local_bindings[] = {
11143 : "function loop() {"
11144 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11145 : " }"
11146 : " eval('0');"
11147 : "}",
11148 :
11149 : "function loop() {"
11150 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11151 : " }"
11152 : " function foo() {}"
11153 : " foo();"
11154 : "}",
11155 5 : };
11156 15 : for (const char* source : local_bindings) {
11157 10 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11158 20 : i::Scope* fn = s->inner_scope();
11159 10 : CHECK(fn->is_function_scope());
11160 :
11161 25 : i::Scope* loop_block = fn->inner_scope();
11162 10 : if (loop_block->is_function_scope()) loop_block = loop_block->sibling();
11163 10 : CHECK(loop_block->is_block_scope());
11164 :
11165 : const i::AstRawString* var_name =
11166 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11167 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11168 10 : CHECK_NOT_NULL(loop_var);
11169 10 : CHECK(loop_var->IsStackLocal());
11170 10 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11171 10 : CHECK_NULL(loop_block->inner_scope());
11172 30 : });
11173 : }
11174 :
11175 : // Check `let` loop variable is not a stack local, and is duplicated in the
11176 : // loop body to ensure capturing can work correctly.
11177 : // In this version of the test, the inner loop block's duplicate `loop_var`
11178 : // binding is not captured, and is a local.
11179 : const char* context_bindings1[] = {
11180 : "function loop() {"
11181 : " for (let loop_var = eval('0'); loop_var < 10; ++loop_var) {"
11182 : " }"
11183 : "}",
11184 :
11185 : "function loop() {"
11186 : " for (let loop_var = (() => (loop_var, 0))(); loop_var < 10;"
11187 : " ++loop_var) {"
11188 : " }"
11189 5 : "}"};
11190 15 : for (const char* source : context_bindings1) {
11191 10 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11192 20 : i::Scope* fn = s->inner_scope();
11193 10 : CHECK(fn->is_function_scope());
11194 :
11195 30 : i::Scope* loop_block = fn->inner_scope();
11196 10 : CHECK(loop_block->is_block_scope());
11197 :
11198 : const i::AstRawString* var_name =
11199 10 : info.ast_value_factory()->GetOneByteString("loop_var");
11200 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11201 10 : CHECK_NOT_NULL(loop_var);
11202 10 : CHECK(loop_var->IsContextSlot());
11203 10 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11204 :
11205 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11206 10 : CHECK_NE(loop_var, loop_var2);
11207 10 : CHECK(loop_var2->IsStackLocal());
11208 10 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
11209 30 : });
11210 : }
11211 :
11212 : // Check `let` loop variable is not a stack local, and is duplicated in the
11213 : // loop body to ensure capturing can work correctly.
11214 : // In this version of the test, the inner loop block's duplicate `loop_var`
11215 : // binding is captured, and must be context allocated.
11216 : const char* context_bindings2[] = {
11217 : "function loop() {"
11218 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11219 : " eval('0');"
11220 : " }"
11221 : "}",
11222 :
11223 : "function loop() {"
11224 : " for (let loop_var = 0; loop_var < eval('10'); ++loop_var) {"
11225 : " }"
11226 : "}",
11227 :
11228 : "function loop() {"
11229 : " for (let loop_var = 0; loop_var < 10; eval('++loop_var')) {"
11230 : " }"
11231 : "}",
11232 5 : };
11233 :
11234 20 : for (const char* source : context_bindings2) {
11235 15 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11236 30 : i::Scope* fn = s->inner_scope();
11237 15 : CHECK(fn->is_function_scope());
11238 :
11239 45 : i::Scope* loop_block = fn->inner_scope();
11240 15 : CHECK(loop_block->is_block_scope());
11241 :
11242 : const i::AstRawString* var_name =
11243 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11244 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11245 15 : CHECK_NOT_NULL(loop_var);
11246 15 : CHECK(loop_var->IsContextSlot());
11247 15 : CHECK_EQ(loop_block->ContextLocalCount(), 1);
11248 :
11249 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11250 15 : CHECK_NE(loop_var, loop_var2);
11251 15 : CHECK(loop_var2->IsContextSlot());
11252 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11253 45 : });
11254 : }
11255 :
11256 : // Similar to the above, but the first block scope's variables are not
11257 : // captured due to the closure occurring in a nested scope.
11258 : const char* context_bindings3[] = {
11259 : "function loop() {"
11260 : " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
11261 : " (() => loop_var)();"
11262 : " }"
11263 : "}",
11264 :
11265 : "function loop() {"
11266 : " for (let loop_var = 0; loop_var < (() => (loop_var, 10))();"
11267 : " ++loop_var) {"
11268 : " }"
11269 : "}",
11270 :
11271 : "function loop() {"
11272 : " for (let loop_var = 0; loop_var < 10; (() => ++loop_var)()) {"
11273 : " }"
11274 : "}",
11275 5 : };
11276 :
11277 20 : for (const char* source : context_bindings3) {
11278 15 : TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
11279 30 : i::Scope* fn = s->inner_scope();
11280 15 : CHECK(fn->is_function_scope());
11281 :
11282 45 : i::Scope* loop_block = fn->inner_scope();
11283 15 : CHECK(loop_block->is_block_scope());
11284 :
11285 : const i::AstRawString* var_name =
11286 15 : info.ast_value_factory()->GetOneByteString("loop_var");
11287 : i::Variable* loop_var = loop_block->LookupLocal(var_name);
11288 15 : CHECK_NOT_NULL(loop_var);
11289 15 : CHECK(loop_var->IsStackLocal());
11290 15 : CHECK_EQ(loop_block->ContextLocalCount(), 0);
11291 :
11292 : i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
11293 15 : CHECK_NE(loop_var, loop_var2);
11294 15 : CHECK(loop_var2->IsContextSlot());
11295 15 : CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
11296 45 : });
11297 : }
11298 5 : }
11299 :
11300 28342 : TEST(PrivateNamesSyntaxError) {
11301 : i::Isolate* isolate = CcTest::i_isolate();
11302 : i::HandleScope scope(isolate);
11303 10 : LocalContext env;
11304 :
11305 155 : auto test = [isolate](const char* program, bool is_lazy) {
11306 155 : i::FLAG_harmony_private_fields = true;
11307 155 : i::Factory* const factory = isolate->factory();
11308 : i::Handle<i::String> source =
11309 310 : factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
11310 155 : i::Handle<i::Script> script = factory->NewScript(source);
11311 155 : i::ParseInfo info(isolate, script);
11312 :
11313 : info.set_allow_lazy_parsing(is_lazy);
11314 155 : CHECK(i::parsing::ParseProgram(&info, isolate));
11315 155 : CHECK(i::Rewriter::Rewrite(&info));
11316 155 : CHECK(!i::DeclarationScope::Analyze(&info));
11317 310 : return info.pending_error_handler()->has_pending_error();
11318 160 : };
11319 :
11320 : const char* data[] = {
11321 : "class A {"
11322 : " foo() { return this.#bar; }"
11323 : "}",
11324 :
11325 : "let A = class {"
11326 : " foo() { return this.#bar; }"
11327 : "}",
11328 :
11329 : "class A {"
11330 : " #foo; "
11331 : " bar() { return this.#baz; }"
11332 : "}",
11333 :
11334 : "let A = class {"
11335 : " #foo; "
11336 : " bar() { return this.#baz; }"
11337 : "}",
11338 :
11339 : "class A {"
11340 : " bar() {"
11341 : " class D { #baz = 1; };"
11342 : " return this.#baz;"
11343 : " }"
11344 : "}",
11345 :
11346 : "let A = class {"
11347 : " bar() {"
11348 : " class D { #baz = 1; };"
11349 : " return this.#baz;"
11350 : " }"
11351 : "}",
11352 :
11353 : "a.#bar",
11354 :
11355 : "class Foo {};"
11356 : "Foo.#bar;",
11357 :
11358 : "let Foo = class {};"
11359 : "Foo.#bar;",
11360 :
11361 : "class Foo {};"
11362 : "(new Foo).#bar;",
11363 :
11364 : "let Foo = class {};"
11365 : "(new Foo).#bar;",
11366 :
11367 : "class Foo { #bar; };"
11368 : "(new Foo).#bar;",
11369 :
11370 : "let Foo = class { #bar; };"
11371 : "(new Foo).#bar;",
11372 :
11373 : "function t(){"
11374 : " class Foo { getA() { return this.#foo; } }"
11375 : "}",
11376 :
11377 : "function t(){"
11378 : " return class { getA() { return this.#foo; } }"
11379 : "}",
11380 5 : };
11381 :
11382 : // TODO(gsathya): The preparser does not track unresolved
11383 : // variables in top level function which fails this test.
11384 : // https://bugs.chromium.org/p/v8/issues/detail?id=7468
11385 : const char* parser_data[] = {
11386 : "function t() {"
11387 : " return this.#foo;"
11388 : "}",
11389 5 : };
11390 :
11391 80 : for (const char* source : data) {
11392 75 : CHECK(test(source, true));
11393 75 : CHECK(test(source, false));
11394 : }
11395 :
11396 10 : for (const char* source : parser_data) {
11397 5 : CHECK(test(source, false));
11398 : }
11399 5 : }
11400 :
11401 28342 : TEST(HashbangSyntax) {
11402 : const char* context_data[][2] = {
11403 5 : {"#!\n", ""}, {"#!---IGNORED---\n", ""}, {nullptr, nullptr}};
11404 :
11405 5 : const char* data[] = {"function\nFN\n(\n)\n {\n}\nFN();", nullptr};
11406 :
11407 5 : i::FLAG_harmony_hashbang = true;
11408 5 : RunParserSyncTest(context_data, data, kSuccess);
11409 : RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0,
11410 5 : nullptr, 0, true);
11411 :
11412 5 : i::FLAG_harmony_hashbang = false;
11413 5 : RunParserSyncTest(context_data, data, kError);
11414 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0, nullptr,
11415 5 : 0, true);
11416 5 : }
11417 :
11418 28342 : TEST(HashbangSyntaxErrors) {
11419 5 : const char* file_context_data[][2] = {{"", ""}, {nullptr, nullptr}};
11420 : const char* other_context_data[][2] = {{"/**/", ""},
11421 : {"//---\n", ""},
11422 : {";", ""},
11423 : {"function fn() {", "}"},
11424 : {"function* fn() {", "}"},
11425 : {"async function fn() {", "}"},
11426 : {"async function* fn() {", "}"},
11427 : {"() => {", "}"},
11428 : {"() => ", ""},
11429 : {"function fn(a = ", ") {}"},
11430 : {"function* fn(a = ", ") {}"},
11431 : {"async function fn(a = ", ") {}"},
11432 : {"async function* fn(a = ", ") {}"},
11433 : {"(a = ", ") => {}"},
11434 : {"(a = ", ") => a"},
11435 : {"class k {", "}"},
11436 : {"[", "]"},
11437 : {"{", "}"},
11438 : {"({", "})"},
11439 5 : {nullptr, nullptr}};
11440 :
11441 : const char* invalid_hashbang_data[] = {// Encoded characters are not allowed
11442 : "#\\u0021\n"
11443 : "\\u0023!\n",
11444 : "\\u0023\\u0021\n",
11445 :
11446 : "\n#!---IGNORED---\n",
11447 5 : " #!---IGNORED---\n", nullptr};
11448 5 : const char* hashbang_data[] = {"#!\n", "#!---IGNORED---\n", nullptr};
11449 :
11450 15 : auto SyntaxErrorTest = [](const char* context_data[][2], const char* data[]) {
11451 15 : i::FLAG_harmony_hashbang = true;
11452 15 : RunParserSyncTest(context_data, data, kError);
11453 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11454 15 : nullptr, 0, true);
11455 :
11456 15 : i::FLAG_harmony_hashbang = false;
11457 15 : RunParserSyncTest(context_data, data, kError);
11458 : RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0,
11459 15 : nullptr, 0, true);
11460 15 : };
11461 :
11462 5 : SyntaxErrorTest(file_context_data, invalid_hashbang_data);
11463 5 : SyntaxErrorTest(other_context_data, invalid_hashbang_data);
11464 5 : SyntaxErrorTest(other_context_data, hashbang_data);
11465 5 : }
11466 :
11467 : } // namespace test_parsing
11468 : } // namespace internal
11469 85011 : } // namespace v8
|