blob: ab1fc765991cf6206ce13ca35d03be3441940628 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blockd0582a62009-12-15 09:54:21 +00002// 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
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080028#include <stdio.h>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029#include <stdlib.h>
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080030#include <string.h>
Steve Blockd0582a62009-12-15 09:54:21 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/v8.h"
Steve Blockd0582a62009-12-15 09:54:21 +000033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034#include "src/ast/ast.h"
35#include "src/ast/ast-numbering.h"
36#include "src/ast/ast-value-factory.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037#include "src/compiler.h"
38#include "src/execution.h"
39#include "src/isolate.h"
40#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041#include "src/parsing/parser.h"
42#include "src/parsing/preparser.h"
43#include "src/parsing/rewriter.h"
44#include "src/parsing/scanner-character-streams.h"
45#include "src/parsing/token.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046#include "src/utils.h"
47
48#include "test/cctest/cctest.h"
Steve Blockd0582a62009-12-15 09:54:21 +000049
Ben Murdoch69a99ed2011-11-30 16:03:39 +000050TEST(ScanKeywords) {
Steve Blockd0582a62009-12-15 09:54:21 +000051 struct KeywordToken {
52 const char* keyword;
53 i::Token::Value token;
54 };
55
56 static const KeywordToken keywords[] = {
57#define KEYWORD(t, s, d) { s, i::Token::t },
Ben Murdoch69a99ed2011-11-30 16:03:39 +000058 TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
Steve Blockd0582a62009-12-15 09:54:21 +000059#undef KEYWORD
60 { NULL, i::Token::IDENTIFIER }
61 };
62
Steve Blockd0582a62009-12-15 09:54:21 +000063 KeywordToken key_token;
Ben Murdoch69a99ed2011-11-30 16:03:39 +000064 i::UnicodeCache unicode_cache;
65 i::byte buffer[32];
Steve Blockd0582a62009-12-15 09:54:21 +000066 for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +000067 const i::byte* keyword =
68 reinterpret_cast<const i::byte*>(key_token.keyword);
69 int length = i::StrLength(key_token.keyword);
70 CHECK(static_cast<int>(sizeof(buffer)) >= length);
71 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010072 i::Utf8ToUtf16CharacterStream stream(keyword, length);
73 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000074 scanner.Initialize(&stream);
75 CHECK_EQ(key_token.token, scanner.Next());
76 CHECK_EQ(i::Token::EOS, scanner.Next());
Steve Blockd0582a62009-12-15 09:54:21 +000077 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000078 // Removing characters will make keyword matching fail.
79 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010080 i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
81 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000082 scanner.Initialize(&stream);
83 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
84 CHECK_EQ(i::Token::EOS, scanner.Next());
Steve Blockd0582a62009-12-15 09:54:21 +000085 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000086 // Adding characters will make keyword matching fail.
87 static const char chars_to_append[] = { 'z', '0', '_' };
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
89 i::MemMove(buffer, keyword, length);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000090 buffer[length] = chars_to_append[j];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010091 i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
92 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000093 scanner.Initialize(&stream);
94 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
95 CHECK_EQ(i::Token::EOS, scanner.Next());
96 }
97 // Replacing characters will make keyword matching fail.
98 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 i::MemMove(buffer, keyword, length);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000100 buffer[length - 1] = '_';
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100101 i::Utf8ToUtf16CharacterStream stream(buffer, length);
102 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000103 scanner.Initialize(&stream);
104 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
105 CHECK_EQ(i::Token::EOS, scanner.Next());
106 }
Steve Blockd0582a62009-12-15 09:54:21 +0000107 }
Steve Blockd0582a62009-12-15 09:54:21 +0000108}
109
Iain Merrick9ac36c92010-09-13 15:29:50 +0100110
111TEST(ScanHTMLEndComments) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000112 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 v8::Isolate* isolate = CcTest::isolate();
114 v8::HandleScope handles(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000115
Iain Merrick9ac36c92010-09-13 15:29:50 +0100116 // Regression test. See:
117 // http://code.google.com/p/chromium/issues/detail?id=53548
118 // Tests that --> is correctly interpreted as comment-to-end-of-line if there
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000119 // is only whitespace before it on the line (with comments considered as
120 // whitespace, even a multiline-comment containing a newline).
121 // This was not the case if it occurred before the first real token
Iain Merrick9ac36c92010-09-13 15:29:50 +0100122 // in the input.
123 const char* tests[] = {
124 // Before first real token.
125 "--> is eol-comment\nvar y = 37;\n",
126 "\n --> is eol-comment\nvar y = 37;\n",
127 "/* precomment */ --> is eol-comment\nvar y = 37;\n",
128 "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
129 // After first real token.
130 "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
131 "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
132 NULL
133 };
134
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000135 const char* fail_tests[] = {
136 "x --> is eol-comment\nvar y = 37;\n",
137 "\"\\n\" --> is eol-comment\nvar y = 37;\n",
138 "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
139 "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
140 "var x = 42; --> is eol-comment\nvar y = 37;\n",
141 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
142 NULL
143 };
144
Iain Merrick9ac36c92010-09-13 15:29:50 +0100145 // Parser/Scanner needs a stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 CcTest::i_isolate()->stack_guard()->SetStackLimit(
147 i::GetCurrentStackPosition() - 128 * 1024);
148 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100149 for (int i = 0; tests[i]; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 const i::byte* source =
151 reinterpret_cast<const i::byte*>(tests[i]);
152 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
153 i::CompleteParserRecorder log;
154 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
155 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100156 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 i::AstValueFactory ast_value_factory(
158 &zone, CcTest::i_isolate()->heap()->HashSeed());
159 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
160 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 preparser.set_allow_lazy(true);
162 i::PreParser::PreParseResult result = preparser.PreParseProgram();
163 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
164 CHECK(!log.HasError());
Iain Merrick9ac36c92010-09-13 15:29:50 +0100165 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000166
167 for (int i = 0; fail_tests[i]; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 const i::byte* source =
169 reinterpret_cast<const i::byte*>(fail_tests[i]);
170 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
171 i::CompleteParserRecorder log;
172 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
173 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100174 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 i::AstValueFactory ast_value_factory(
176 &zone, CcTest::i_isolate()->heap()->HashSeed());
177 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
178 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 preparser.set_allow_lazy(true);
180 i::PreParser::PreParseResult result = preparser.PreParseProgram();
181 // Even in the case of a syntax error, kPreParseSuccess is returned.
182 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
183 CHECK(log.HasError());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000184 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100185}
186
187
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188class ScriptResource : public v8::String::ExternalOneByteStringResource {
Iain Merrick9ac36c92010-09-13 15:29:50 +0100189 public:
190 ScriptResource(const char* data, size_t length)
191 : data_(data), length_(length) { }
192
193 const char* data() const { return data_; }
194 size_t length() const { return length_; }
195
196 private:
197 const char* data_;
198 size_t length_;
199};
200
201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202TEST(UsingCachedData) {
Ben Murdochda12d292016-06-02 14:46:10 +0100203 // Producing cached parser data while parsing eagerly is not supported.
204 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 v8::Isolate* isolate = CcTest::isolate();
207 v8::HandleScope handles(isolate);
208 v8::Local<v8::Context> context = v8::Context::New(isolate);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100209 v8::Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 CcTest::i_isolate()->stack_guard()->SetStackLimit(
211 i::GetCurrentStackPosition() - 128 * 1024);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100212
213 // Source containing functions that might be lazily compiled and all types
214 // of symbols (string, propertyName, regexp).
215 const char* source =
216 "var x = 42;"
217 "function foo(a) { return function nolazy(b) { return a + b; } }"
218 "function bar(a) { if (a) return function lazy(b) { return b; } }"
219 "var z = {'string': 'string literal', bareword: 'propertyName', "
220 " 42: 'number literal', for: 'keyword as propertyName', "
221 " f\\u006fr: 'keyword propertyname with escape'};"
222 "var v = /RegExp Literal/;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 "var w = /RegExp Literal\\u0020With Escape/gi;"
Iain Merrick9ac36c92010-09-13 15:29:50 +0100224 "var y = { get getter() { return 42; }, "
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 " set setter(v) { this.value = v; }};"
226 "var f = a => function (b) { return a + b; };"
227 "var g = a => b => a + b;";
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100228 int source_length = i::StrLength(source);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 // ScriptResource will be deleted when the corresponding String is GCd.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 v8::ScriptCompiler::Source script_source(
232 v8::String::NewExternalOneByte(isolate,
233 new ScriptResource(source, source_length))
234 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 i::FLAG_min_preparse_length = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
237 v8::ScriptCompiler::kProduceParserCache)
238 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 CHECK(script_source.GetCachedData());
240
241 // Compile the script again, using the cached data.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100242 bool lazy_flag = i::FLAG_lazy;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 i::FLAG_lazy = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
245 v8::ScriptCompiler::kConsumeParserCache)
246 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 i::FLAG_lazy = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 v8::ScriptCompiler::CompileUnboundScript(
249 isolate, &script_source, v8::ScriptCompiler::kConsumeParserCache)
250 .ToLocalChecked();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100251 i::FLAG_lazy = lazy_flag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252}
Iain Merrick9ac36c92010-09-13 15:29:50 +0100253
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255TEST(PreparseFunctionDataIsUsed) {
Ben Murdochda12d292016-06-02 14:46:10 +0100256 // Producing cached parser data while parsing eagerly is not supported.
257 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
258
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 // This tests that we actually do use the function data generated by the
260 // preparser.
261
262 // Make preparsing work for short scripts.
263 i::FLAG_min_preparse_length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264
265 v8::Isolate* isolate = CcTest::isolate();
266 v8::HandleScope handles(isolate);
267 v8::Local<v8::Context> context = v8::Context::New(isolate);
268 v8::Context::Scope context_scope(context);
269 CcTest::i_isolate()->stack_guard()->SetStackLimit(
270 i::GetCurrentStackPosition() - 128 * 1024);
271
272 const char* good_code[] = {
273 "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
274 "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
275 };
276
277 // Insert a syntax error inside the lazy function.
278 const char* bad_code[] = {
279 "function this_is_lazy() { if ( } function foo() { return 25; } foo();",
280 "var this_is_lazy = () => { if ( }; var foo = () => 25; foo();",
281 };
282
283 for (unsigned i = 0; i < arraysize(good_code); i++) {
284 v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &good_source,
286 v8::ScriptCompiler::kProduceParserCache)
287 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288
289 const v8::ScriptCompiler::CachedData* cached_data =
290 good_source.GetCachedData();
291 CHECK(cached_data->data != NULL);
292 CHECK_GT(cached_data->length, 0);
293
294 // Now compile the erroneous code with the good preparse data. If the
295 // preparse data is used, the lazy function is skipped and it should
296 // compile fine.
297 v8::ScriptCompiler::Source bad_source(
298 v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
299 cached_data->data, cached_data->length));
300 v8::Local<v8::Value> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 CompileRun(isolate->GetCurrentContext(), &bad_source,
302 v8::ScriptCompiler::kConsumeParserCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 CHECK_EQ(25, result->Int32Value(isolate->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100306}
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800307
308
309TEST(StandAlonePreParser) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000310 v8::V8::Initialize();
311
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 CcTest::i_isolate()->stack_guard()->SetStackLimit(
313 i::GetCurrentStackPosition() - 128 * 1024);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800314
315 const char* programs[] = {
316 "{label: 42}",
317 "var x = 42;",
318 "function foo(x, y) { return x + y; }",
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000319 "%ArgleBargle(glop);",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800320 "var x = new new Function('this.x = 42');",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 "var f = (x, y) => x + y;",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800322 NULL
323 };
324
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800326 for (int i = 0; programs[i]; i++) {
327 const char* program = programs[i];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100328 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100329 reinterpret_cast<const i::byte*>(program),
330 static_cast<unsigned>(strlen(program)));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800331 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100333 scanner.Initialize(&stream);
334
Ben Murdochda12d292016-06-02 14:46:10 +0100335 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 i::AstValueFactory ast_value_factory(
337 &zone, CcTest::i_isolate()->heap()->HashSeed());
338 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
339 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 preparser.set_allow_lazy(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 preparser.set_allow_natives(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 i::PreParser::PreParseResult result = preparser.PreParseProgram();
343 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
344 CHECK(!log.HasError());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800345 }
346}
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800347
348
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100349TEST(StandAlonePreParserNoNatives) {
350 v8::V8::Initialize();
351
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 CcTest::i_isolate()->stack_guard()->SetStackLimit(
353 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354
355 const char* programs[] = {
356 "%ArgleBargle(glop);",
357 "var x = %_IsSmi(42);",
358 NULL
359 };
360
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 for (int i = 0; programs[i]; i++) {
363 const char* program = programs[i];
364 i::Utf8ToUtf16CharacterStream stream(
365 reinterpret_cast<const i::byte*>(program),
366 static_cast<unsigned>(strlen(program)));
367 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100369 scanner.Initialize(&stream);
370
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 // Preparser defaults to disallowing natives syntax.
Ben Murdochda12d292016-06-02 14:46:10 +0100372 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 i::AstValueFactory ast_value_factory(
374 &zone, CcTest::i_isolate()->heap()->HashSeed());
375 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
376 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 preparser.set_allow_lazy(true);
378 i::PreParser::PreParseResult result = preparser.PreParseProgram();
379 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
380 CHECK(log.HasError());
381 }
382}
383
384
385TEST(PreparsingObjectLiterals) {
386 // Regression test for a bug where the symbol stream produced by PreParser
387 // didn't match what Parser wanted to consume.
388 v8::Isolate* isolate = CcTest::isolate();
389 v8::HandleScope handles(isolate);
390 v8::Local<v8::Context> context = v8::Context::New(isolate);
391 v8::Context::Scope context_scope(context);
392 CcTest::i_isolate()->stack_guard()->SetStackLimit(
393 i::GetCurrentStackPosition() - 128 * 1024);
394
395 {
396 const char* source = "var myo = {if: \"foo\"}; myo.if;";
397 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
398 CHECK(result->IsString());
399 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 }
402
403 {
404 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
405 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
406 CHECK(result->IsString());
407 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 }
410
411 {
412 const char* source = "var myo = {1: \"foo\"}; myo[1];";
413 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
414 CHECK(result->IsString());
415 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100417 }
418}
419
420
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800421TEST(RegressChromium62639) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000422 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
426 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800427
428 const char* program = "var x = 'something';\n"
429 "escape: function() {}";
430 // Fails parsing expecting an identifier after "function".
431 // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
432 // and then used the invalid currently scanned literal. This always
433 // failed in debug mode, and sometimes crashed in release mode.
434
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100435 i::Utf8ToUtf16CharacterStream stream(
436 reinterpret_cast<const i::byte*>(program),
437 static_cast<unsigned>(strlen(program)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 i::CompleteParserRecorder log;
439 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
440 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100441 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 i::AstValueFactory ast_value_factory(&zone,
443 CcTest::i_isolate()->heap()->HashSeed());
444 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 CcTest::i_isolate()->stack_guard()->real_climit());
446 preparser.set_allow_lazy(true);
447 i::PreParser::PreParseResult result = preparser.PreParseProgram();
448 // Even in the case of a syntax error, kPreParseSuccess is returned.
449 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
450 CHECK(log.HasError());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800451}
452
453
454TEST(Regress928) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000455 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 i::Isolate* isolate = CcTest::i_isolate();
457 i::Factory* factory = isolate->factory();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000458
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800459 // Preparsing didn't consider the catch clause of a try statement
460 // as with-content, which made it assume that a function inside
461 // the block could be lazily compiled, and an extra, unexpected,
462 // entry was added to the data.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
464 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800465
466 const char* program =
467 "try { } catch (e) { var foo = function () { /* first */ } }"
468 "var bar = function () { /* second */ }";
469
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 v8::HandleScope handles(CcTest::isolate());
471 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
472 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
473 i::CompleteParserRecorder log;
474 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
475 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100476 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 i::AstValueFactory ast_value_factory(&zone,
478 CcTest::i_isolate()->heap()->HashSeed());
479 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 CcTest::i_isolate()->stack_guard()->real_climit());
481 preparser.set_allow_lazy(true);
482 i::PreParser::PreParseResult result = preparser.PreParseProgram();
483 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
484 i::ScriptData* sd = log.GetScriptData();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400485 i::ParseData* pd = i::ParseData::FromCachedData(sd);
486 pd->Initialize();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800487
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100488 int first_function =
489 static_cast<int>(strstr(program, "function") - program);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100490 int first_lbrace = first_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800491 CHECK_EQ('{', program[first_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400492 i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800493 CHECK(!entry1.is_valid());
494
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100495 int second_function =
496 static_cast<int>(strstr(program + first_lbrace, "function") - program);
497 int second_lbrace =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100498 second_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800499 CHECK_EQ('{', program[second_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500 i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800501 CHECK(entry2.is_valid());
502 CHECK_EQ('}', program[entry2.end_pos() - 1]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 delete pd;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800505}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100506
507
508TEST(PreParseOverflow) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000509 v8::V8::Initialize();
510
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 CcTest::i_isolate()->stack_guard()->SetStackLimit(
512 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
514 size_t kProgramSize = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 v8::base::SmartArrayPointer<char> program(
516 i::NewArray<char>(kProgramSize + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 memset(program.get(), '(', kProgramSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100518 program[kProgramSize] = '\0';
519
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100522 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 reinterpret_cast<const i::byte*>(program.get()),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100524 static_cast<unsigned>(kProgramSize));
525 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100527 scanner.Initialize(&stream);
528
Ben Murdochda12d292016-06-02 14:46:10 +0100529 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 i::AstValueFactory ast_value_factory(&zone,
531 CcTest::i_isolate()->heap()->HashSeed());
532 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
533 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 preparser.set_allow_lazy(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 i::PreParser::PreParseResult result = preparser.PreParseProgram();
536 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537}
538
539
540class TestExternalResource: public v8::String::ExternalStringResource {
541 public:
542 explicit TestExternalResource(uint16_t* data, int length)
543 : data_(data), length_(static_cast<size_t>(length)) { }
544
545 ~TestExternalResource() { }
546
547 const uint16_t* data() const {
548 return data_;
549 }
550
551 size_t length() const {
552 return length_;
553 }
554 private:
555 uint16_t* data_;
556 size_t length_;
557};
558
559
560#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
561
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562void TestCharacterStream(const char* one_byte_source, unsigned length,
563 unsigned start = 0, unsigned end = 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100564 if (end == 0) end = length;
565 unsigned sub_length = end - start;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 i::Isolate* isolate = CcTest::i_isolate();
567 i::Factory* factory = isolate->factory();
568 i::HandleScope test_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 v8::base::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100570 for (unsigned i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100572 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 i::Vector<const char> one_byte_vector(one_byte_source,
574 static_cast<int>(length));
575 i::Handle<i::String> one_byte_string =
576 factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
577 TestExternalResource resource(uc16_buffer.get(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100578 i::Handle<i::String> uc16_string(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100580
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100581 i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100582 i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
584 end);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100585 i::Utf8ToUtf16CharacterStream utf8_stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 reinterpret_cast<const i::byte*>(one_byte_source), end);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 utf8_stream.SeekForward(start);
588
589 unsigned i = start;
590 while (i < end) {
591 // Read streams one char at a time
592 CHECK_EQU(i, uc16_stream.pos());
593 CHECK_EQU(i, string_stream.pos());
594 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100596 int32_t c1 = uc16_stream.Advance();
597 int32_t c2 = string_stream.Advance();
598 int32_t c3 = utf8_stream.Advance();
599 i++;
600 CHECK_EQ(c0, c1);
601 CHECK_EQ(c0, c2);
602 CHECK_EQ(c0, c3);
603 CHECK_EQU(i, uc16_stream.pos());
604 CHECK_EQU(i, string_stream.pos());
605 CHECK_EQU(i, utf8_stream.pos());
606 }
607 while (i > start + sub_length / 4) {
608 // Pushback, re-read, pushback again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 int32_t c0 = one_byte_source[i - 1];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100610 CHECK_EQU(i, uc16_stream.pos());
611 CHECK_EQU(i, string_stream.pos());
612 CHECK_EQU(i, utf8_stream.pos());
613 uc16_stream.PushBack(c0);
614 string_stream.PushBack(c0);
615 utf8_stream.PushBack(c0);
616 i--;
617 CHECK_EQU(i, uc16_stream.pos());
618 CHECK_EQU(i, string_stream.pos());
619 CHECK_EQU(i, utf8_stream.pos());
620 int32_t c1 = uc16_stream.Advance();
621 int32_t c2 = string_stream.Advance();
622 int32_t c3 = utf8_stream.Advance();
623 i++;
624 CHECK_EQU(i, uc16_stream.pos());
625 CHECK_EQU(i, string_stream.pos());
626 CHECK_EQU(i, utf8_stream.pos());
627 CHECK_EQ(c0, c1);
628 CHECK_EQ(c0, c2);
629 CHECK_EQ(c0, c3);
630 uc16_stream.PushBack(c0);
631 string_stream.PushBack(c0);
632 utf8_stream.PushBack(c0);
633 i--;
634 CHECK_EQU(i, uc16_stream.pos());
635 CHECK_EQU(i, string_stream.pos());
636 CHECK_EQU(i, utf8_stream.pos());
637 }
638 unsigned halfway = start + sub_length / 2;
639 uc16_stream.SeekForward(halfway - i);
640 string_stream.SeekForward(halfway - i);
641 utf8_stream.SeekForward(halfway - i);
642 i = halfway;
643 CHECK_EQU(i, uc16_stream.pos());
644 CHECK_EQU(i, string_stream.pos());
645 CHECK_EQU(i, utf8_stream.pos());
646
647 while (i < end) {
648 // Read streams one char at a time
649 CHECK_EQU(i, uc16_stream.pos());
650 CHECK_EQU(i, string_stream.pos());
651 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653 int32_t c1 = uc16_stream.Advance();
654 int32_t c2 = string_stream.Advance();
655 int32_t c3 = utf8_stream.Advance();
656 i++;
657 CHECK_EQ(c0, c1);
658 CHECK_EQ(c0, c2);
659 CHECK_EQ(c0, c3);
660 CHECK_EQU(i, uc16_stream.pos());
661 CHECK_EQU(i, string_stream.pos());
662 CHECK_EQU(i, utf8_stream.pos());
663 }
664
665 int32_t c1 = uc16_stream.Advance();
666 int32_t c2 = string_stream.Advance();
667 int32_t c3 = utf8_stream.Advance();
668 CHECK_LT(c1, 0);
669 CHECK_LT(c2, 0);
670 CHECK_LT(c3, 0);
671}
672
673
674TEST(CharacterStreams) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675 v8::Isolate* isolate = CcTest::isolate();
676 v8::HandleScope handles(isolate);
677 v8::Local<v8::Context> context = v8::Context::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 v8::Context::Scope context_scope(context);
679
680 TestCharacterStream("abc\0\n\r\x7f", 7);
681 static const unsigned kBigStringSize = 4096;
682 char buffer[kBigStringSize + 1];
683 for (unsigned i = 0; i < kBigStringSize; i++) {
684 buffer[i] = static_cast<char>(i & 0x7f);
685 }
686 TestCharacterStream(buffer, kBigStringSize);
687
688 TestCharacterStream(buffer, kBigStringSize, 576, 3298);
689
690 TestCharacterStream("\0", 1);
691 TestCharacterStream("", 0);
692}
693
694
695TEST(Utf8CharacterStream) {
696 static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
697 static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
698
699 static const int kAllUtf8CharsSize =
700 (unibrow::Utf8::kMaxOneByteChar + 1) +
701 (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
702 (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
703 static const unsigned kAllUtf8CharsSizeU =
704 static_cast<unsigned>(kAllUtf8CharsSize);
705
706 char buffer[kAllUtf8CharsSizeU];
707 unsigned cursor = 0;
708 for (int i = 0; i <= kMaxUC16Char; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 cursor += unibrow::Utf8::Encode(buffer + cursor, i,
710 unibrow::Utf16::kNoPreviousCharacter, true);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 CHECK(cursor == kAllUtf8CharsSizeU);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100713
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100714 i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
715 kAllUtf8CharsSizeU);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 int32_t bad = unibrow::Utf8::kBadChar;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717 for (int i = 0; i <= kMaxUC16Char; i++) {
718 CHECK_EQU(i, stream.pos());
719 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 if (i >= 0xd800 && i <= 0xdfff) {
721 CHECK_EQ(bad, c);
722 } else {
723 CHECK_EQ(i, c);
724 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100725 CHECK_EQU(i + 1, stream.pos());
726 }
727 for (int i = kMaxUC16Char; i >= 0; i--) {
728 CHECK_EQU(i + 1, stream.pos());
729 stream.PushBack(i);
730 CHECK_EQU(i, stream.pos());
731 }
732 int i = 0;
733 while (stream.pos() < kMaxUC16CharU) {
734 CHECK_EQU(i, stream.pos());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 int progress = static_cast<int>(stream.SeekForward(12));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 i += progress;
737 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 if (i >= 0xd800 && i <= 0xdfff) {
739 CHECK_EQ(bad, c);
740 } else if (i <= kMaxUC16Char) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100741 CHECK_EQ(i, c);
742 } else {
743 CHECK_EQ(-1, c);
744 }
745 i += 1;
746 CHECK_EQU(i, stream.pos());
747 }
748}
749
750#undef CHECK_EQU
751
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100752void TestStreamScanner(i::Utf16CharacterStream* stream,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 i::Token::Value* expected_tokens,
754 int skip_pos = 0, // Zero means not skipping.
755 int skip_to = 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +0100757 scanner.Initialize(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758
759 int i = 0;
760 do {
761 i::Token::Value expected = expected_tokens[i];
762 i::Token::Value actual = scanner.Next();
763 CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
764 if (scanner.location().end_pos == skip_pos) {
765 scanner.SeekForward(skip_to);
766 }
767 i++;
768 } while (expected_tokens[i] != i::Token::ILLEGAL);
769}
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772TEST(StreamScanner) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000773 v8::V8::Initialize();
774
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100776 i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
777 static_cast<unsigned>(strlen(str1)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778 i::Token::Value expectations1[] = {
779 i::Token::LBRACE,
780 i::Token::IDENTIFIER,
781 i::Token::IDENTIFIER,
782 i::Token::FOR,
783 i::Token::COLON,
784 i::Token::MUL,
785 i::Token::DIV,
786 i::Token::LT,
787 i::Token::SUB,
788 i::Token::IDENTIFIER,
789 i::Token::EOS,
790 i::Token::ILLEGAL
791 };
792 TestStreamScanner(&stream1, expectations1, 0, 0);
793
794 const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100795 i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
796 static_cast<unsigned>(strlen(str2)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100797 i::Token::Value expectations2[] = {
798 i::Token::CASE,
799 i::Token::DEFAULT,
800 i::Token::CONST,
801 i::Token::LBRACE,
802 // Skipped part here
803 i::Token::RBRACE,
804 i::Token::DO,
805 i::Token::EOS,
806 i::Token::ILLEGAL
807 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 CHECK_EQ('{', str2[19]);
809 CHECK_EQ('}', str2[37]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100810 TestStreamScanner(&stream2, expectations2, 20, 37);
811
812 const char* str3 = "{}}}}";
813 i::Token::Value expectations3[] = {
814 i::Token::LBRACE,
815 i::Token::RBRACE,
816 i::Token::RBRACE,
817 i::Token::RBRACE,
818 i::Token::RBRACE,
819 i::Token::EOS,
820 i::Token::ILLEGAL
821 };
822 // Skip zero-four RBRACEs.
823 for (int i = 0; i <= 4; i++) {
824 expectations3[6 - i] = i::Token::ILLEGAL;
825 expectations3[5 - i] = i::Token::EOS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100826 i::Utf8ToUtf16CharacterStream stream3(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100827 reinterpret_cast<const i::byte*>(str3),
828 static_cast<unsigned>(strlen(str3)));
829 TestStreamScanner(&stream3, expectations3, 1, 1 + i);
830 }
831}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100832
833
834void TestScanRegExp(const char* re_source, const char* expected) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100835 i::Utf8ToUtf16CharacterStream stream(
Ben Murdoch086aeea2011-05-13 15:57:08 +0100836 reinterpret_cast<const i::byte*>(re_source),
837 static_cast<unsigned>(strlen(re_source)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 i::HandleScope scope(CcTest::i_isolate());
839 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100840 scanner.Initialize(&stream);
841
842 i::Token::Value start = scanner.peek();
843 CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
844 CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
845 scanner.Next(); // Current token is now the regexp literal.
Ben Murdochda12d292016-06-02 14:46:10 +0100846 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 i::AstValueFactory ast_value_factory(&zone,
848 CcTest::i_isolate()->heap()->HashSeed());
849 ast_value_factory.Internalize(CcTest::i_isolate());
850 i::Handle<i::String> val =
851 scanner.CurrentSymbol(&ast_value_factory)->string();
852 i::DisallowHeapAllocation no_alloc;
853 i::String::FlatContent content = val->GetFlatContent();
854 CHECK(content.IsOneByte());
855 i::Vector<const uint8_t> actual = content.ToOneByteVector();
Ben Murdoch086aeea2011-05-13 15:57:08 +0100856 for (int i = 0; i < actual.length(); i++) {
857 CHECK_NE('\0', expected[i]);
858 CHECK_EQ(expected[i], actual[i]);
859 }
860}
861
862
863TEST(RegExpScanning) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000864 v8::V8::Initialize();
865
Ben Murdoch086aeea2011-05-13 15:57:08 +0100866 // RegExp token with added garbage at the end. The scanner should only
867 // scan the RegExp until the terminating slash just before "flipperwald".
868 TestScanRegExp("/b/flipperwald", "b");
869 // Incomplete escape sequences doesn't hide the terminating slash.
870 TestScanRegExp("/\\x/flipperwald", "\\x");
871 TestScanRegExp("/\\u/flipperwald", "\\u");
872 TestScanRegExp("/\\u1/flipperwald", "\\u1");
873 TestScanRegExp("/\\u12/flipperwald", "\\u12");
874 TestScanRegExp("/\\u123/flipperwald", "\\u123");
875 TestScanRegExp("/\\c/flipperwald", "\\c");
876 TestScanRegExp("/\\c//flipperwald", "\\c");
877 // Slashes inside character classes are not terminating.
878 TestScanRegExp("/[/]/flipperwald", "[/]");
879 TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
880 // Incomplete escape sequences inside a character class doesn't hide
881 // the end of the character class.
882 TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
883 TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
884 TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
885 TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
886 TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
887 TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
888 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
889 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
890 // Escaped ']'s wont end the character class.
891 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
892 // Escaped slashes are not terminating.
893 TestScanRegExp("/\\//flipperwald", "\\/");
894 // Starting with '=' works too.
895 TestScanRegExp("/=/", "=");
896 TestScanRegExp("/=?/", "=?");
897}
Ben Murdoch692be652012-01-10 18:47:50 +0000898
899
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100900static int Utf8LengthHelper(const char* s) {
901 int len = i::StrLength(s);
902 int character_length = len;
903 for (int i = 0; i < len; i++) {
904 unsigned char c = s[i];
905 int input_offset = 0;
906 int output_adjust = 0;
907 if (c > 0x7f) {
908 if (c < 0xc0) continue;
909 if (c >= 0xf0) {
910 if (c >= 0xf8) {
911 // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
912 // byte.
913 continue; // Handle first UTF-8 byte.
914 }
915 if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
916 // This 4 byte sequence could have been coded as a 3 byte sequence.
917 // Record a single kBadChar for the first byte and continue.
918 continue;
919 }
920 input_offset = 3;
921 // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
922 character_length -= 2;
923 } else if (c >= 0xe0) {
924 if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
925 // This 3 byte sequence could have been coded as a 2 byte sequence.
926 // Record a single kBadChar for the first byte and continue.
927 continue;
928 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 if (c == 0xed) {
930 unsigned char d = s[i + 1];
931 if ((d < 0x80) || (d > 0x9f)) {
932 // This 3 byte sequence is part of a surrogate pair which is not
933 // supported by UTF-8. Record a single kBadChar for the first byte
934 // and continue.
935 continue;
936 }
937 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100938 input_offset = 2;
939 // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
940 output_adjust = 2;
941 } else {
942 if ((c & 0x1e) == 0) {
943 // This 2 byte sequence could have been coded as a 1 byte sequence.
944 // Record a single kBadChar for the first byte and continue.
945 continue;
946 }
947 input_offset = 1;
948 // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
949 output_adjust = 1;
950 }
951 bool bad = false;
952 for (int j = 1; j <= input_offset; j++) {
953 if ((s[i + j] & 0xc0) != 0x80) {
954 // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
955 // which is a single UTF-16 code unit.
956 bad = true;
957 break;
958 }
959 }
960 if (!bad) {
961 i += input_offset;
962 character_length -= output_adjust;
963 }
964 }
965 }
966 return character_length;
967}
968
969
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400970TEST(ScopeUsesArgumentsSuperThis) {
971 static const struct {
972 const char* prefix;
973 const char* suffix;
974 } surroundings[] = {
975 { "function f() {", "}" },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 { "var f = () => {", "};" },
977 { "class C { constructor() {", "} }" },
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400978 };
979
980 enum Expected {
981 NONE = 0,
982 ARGUMENTS = 1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 SUPER_PROPERTY = 1 << 1,
984 THIS = 1 << 2,
985 EVAL = 1 << 4
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 };
987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 // clang-format off
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 static const struct {
990 const char* body;
991 int expected;
992 } source_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 {"", NONE},
994 {"return this", THIS},
995 {"return arguments", ARGUMENTS},
996 {"return super.x", SUPER_PROPERTY},
997 {"return arguments[0]", ARGUMENTS},
998 {"return this + arguments[0]", ARGUMENTS | THIS},
999 {"return this + arguments[0] + super.x",
1000 ARGUMENTS | SUPER_PROPERTY | THIS},
1001 {"return x => this + x", THIS},
1002 {"return x => super.f() + x", SUPER_PROPERTY},
1003 {"this.foo = 42;", THIS},
1004 {"this.foo();", THIS},
1005 {"if (foo()) { this.f() }", THIS},
1006 {"if (foo()) { super.f() }", SUPER_PROPERTY},
1007 {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
1008 {"while (true) { this.f() }", THIS},
1009 {"while (true) { super.f() }", SUPER_PROPERTY},
1010 {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
1011 // Multiple nesting levels must work as well.
1012 {"while (true) { while (true) { while (true) return this } }", THIS},
1013 {"while (true) { while (true) { while (true) return super.f() } }",
1014 SUPER_PROPERTY},
1015 {"if (1) { return () => { while (true) new this() } }", THIS},
1016 {"return function (x) { return this + x }", NONE},
1017 {"return { m(x) { return super.m() + x } }", NONE},
1018 {"var x = function () { this.foo = 42 };", NONE},
1019 {"var x = { m() { super.foo = 42 } };", NONE},
1020 {"if (1) { return function () { while (true) new this() } }", NONE},
1021 {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1022 {"return function (x) { return () => this }", NONE},
1023 {"return { m(x) { return () => super.m() } }", NONE},
1024 // Flags must be correctly set when using block scoping.
1025 {"\"use strict\"; while (true) { let x; this, arguments; }",
1026 THIS},
1027 {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1028 SUPER_PROPERTY | THIS},
1029 {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
1030 {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
1031 {"\"use strict\"; if (1) {"
1032 " let x; return { m() { return this + super.m() + arguments } }"
1033 "}",
1034 NONE},
1035 {"eval(42)", EVAL},
1036 {"if (1) { eval(42) }", EVAL},
1037 {"eval('super.x')", EVAL},
1038 {"eval('this.x')", EVAL},
1039 {"eval('arguments')", EVAL},
1040 };
1041 // clang-format on
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042
1043 i::Isolate* isolate = CcTest::i_isolate();
1044 i::Factory* factory = isolate->factory();
1045
1046 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001048 v8::Context::Scope context_scope(context);
1049
1050 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1051 128 * 1024);
1052
1053 for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1054 for (unsigned i = 0; i < arraysize(source_data); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 // Super property is only allowed in constructor and method.
1056 if (((source_data[i].expected & SUPER_PROPERTY) ||
1057 (source_data[i].expected == NONE)) && j != 2) {
1058 continue;
1059 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001060 int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1061 i::StrLength(surroundings[j].suffix) +
1062 i::StrLength(source_data[i].body);
1063 i::ScopedVector<char> program(kProgramByteSize + 1);
1064 i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1065 source_data[i].body, surroundings[j].suffix);
1066 i::Handle<i::String> source =
1067 factory->NewStringFromUtf8(i::CStrVector(program.start()))
1068 .ToHandleChecked();
1069 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001070 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071 i::ParseInfo info(&zone, script);
1072 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 info.set_global();
1074 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001075 CHECK(i::Rewriter::Rewrite(&info));
1076 CHECK(i::Scope::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 CHECK(info.literal() != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 i::Scope* script_scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001080 CHECK(script_scope->is_script_scope());
1081 CHECK_EQ(1, script_scope->inner_scopes()->length());
1082
1083 i::Scope* scope = script_scope->inner_scopes()->at(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 // Adjust for constructor scope.
1085 if (j == 2) {
1086 CHECK_EQ(1, scope->inner_scopes()->length());
1087 scope = scope->inner_scopes()->at(0);
1088 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001089 CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
1090 scope->uses_arguments());
1091 CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1092 scope->uses_super_property());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 if ((source_data[i].expected & THIS) != 0) {
1094 // Currently the is_used() flag is conservative; all variables in a
1095 // script scope are marked as used.
1096 CHECK(
1097 scope->Lookup(info.ast_value_factory()->this_string())->is_used());
1098 }
1099 CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001100 }
1101 }
1102}
1103
1104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105static void CheckParsesToNumber(const char* source, bool with_dot) {
1106 v8::V8::Initialize();
1107 HandleAndZoneScope handles;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001109 i::Isolate* isolate = CcTest::i_isolate();
1110 i::Factory* factory = isolate->factory();
1111
1112 std::string full_source = "function f() { return ";
1113 full_source += source;
1114 full_source += "; }";
1115
1116 i::Handle<i::String> source_code =
1117 factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1118 .ToHandleChecked();
1119
1120 i::Handle<i::Script> script = factory->NewScript(source_code);
1121
1122 i::ParseInfo info(handles.main_zone(), script);
1123 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001124 info.set_global();
1125 info.set_lazy(false);
1126 info.set_allow_lazy_parsing(false);
1127 info.set_toplevel(true);
1128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001129 CHECK(i::Compiler::ParseAndAnalyze(&info));
1130
1131 CHECK(info.scope()->declarations()->length() == 1);
1132 i::FunctionLiteral* fun =
1133 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
1134 CHECK(fun->body()->length() == 1);
1135 CHECK(fun->body()->at(0)->IsReturnStatement());
1136 i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1137 i::Literal* lit = ret->expression()->AsLiteral();
1138 if (lit != NULL) {
1139 const i::AstValue* val = lit->raw_value();
1140 CHECK(with_dot == val->ContainsDot());
1141 } else if (with_dot) {
1142 i::BinaryOperation* bin = ret->expression()->AsBinaryOperation();
1143 CHECK(bin != NULL);
1144 CHECK_EQ(i::Token::MUL, bin->op());
1145 i::Literal* rlit = bin->right()->AsLiteral();
1146 const i::AstValue* val = rlit->raw_value();
1147 CHECK(with_dot == val->ContainsDot());
1148 CHECK_EQ(1.0, val->AsNumber());
1149 }
1150}
1151
1152
1153TEST(ParseNumbers) {
1154 CheckParsesToNumber("1.", true);
1155 CheckParsesToNumber("1.34", true);
1156 CheckParsesToNumber("134", false);
1157 CheckParsesToNumber("134e44", false);
1158 CheckParsesToNumber("134.e44", true);
1159 CheckParsesToNumber("134.44e44", true);
1160 CheckParsesToNumber(".44", true);
1161
1162 CheckParsesToNumber("-1.", true);
1163 CheckParsesToNumber("-1.0", true);
1164 CheckParsesToNumber("-1.34", true);
1165 CheckParsesToNumber("-134", false);
1166 CheckParsesToNumber("-134e44", false);
1167 CheckParsesToNumber("-134.e44", true);
1168 CheckParsesToNumber("-134.44e44", true);
1169 CheckParsesToNumber("-.44", true);
1170
1171 CheckParsesToNumber("+x", true);
1172}
1173
1174
1175TEST(ScopePositions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001176 // Test the parser for correctly setting the start and end positions
1177 // of a scope. We check the scope positions of exactly one scope
1178 // nested in the global scope of a program. 'inner source' is the
1179 // source code that determines the part of the source belonging
1180 // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1181 // parts of the source that belong to the global scope.
1182 struct SourceData {
1183 const char* outer_prefix;
1184 const char* inner_source;
1185 const char* outer_suffix;
1186 i::ScopeType scope_type;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 i::LanguageMode language_mode;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001188 };
1189
1190 const SourceData source_data[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
1192 { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001193 { " with ({}) ", "{\n"
1194 " block;\n"
1195 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 " more;", i::WITH_SCOPE, i::SLOPPY },
1197 { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001198 { " with ({}) ", "statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001200 { " with ({})\n"
1201 " ", "statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001203 { " try {} catch ", "(e) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001205 { " try {} catch ", "(e) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001207 { " try {} catch ", "(e) {\n"
1208 " block;\n"
1209 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 " more;", i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001211 { " try {} catch ", "(e) { block; }", " finally { block; } more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001212 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001213 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214 " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001215 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001217 { " start;\n"
1218 " ", "{\n"
1219 " let block;\n"
1220 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001222 { " start;\n"
1223 " function fun", "(a,b) { infunction; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001225 { " start;\n"
1226 " function fun", "(a,b) {\n"
1227 " infunction;\n"
1228 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 " more;", i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 { " start;\n", "(a,b) => a + b", "; more;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001231 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001232 { " start;\n", "(a,b) => { return a+b; }", "\nmore;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234 { " start;\n"
1235 " (function fun", "(a,b) { infunction; }", ")();",
1236 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001237 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001239 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001240 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001241 { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
1242 " block;\n"
1243 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001245 { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001247 { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001248 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001249 { " for ", "(let x = 1 ; x < 10; ++ x)\n"
1250 " statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001252 { " for ", "(let x in {}) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001254 { " for ", "(let x in {}) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001256 { " for ", "(let x in {}) {\n"
1257 " block;\n"
1258 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001260 { " for ", "(let x in {}) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001262 { " for ", "(let x in {}) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001264 { " for ", "(let x in {})\n"
1265 " statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001267 // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1268 // the preparser off in terms of byte offsets.
1269 // 6 byte encoding.
1270 { " 'foo\355\240\201\355\260\211';\n"
1271 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001273 // 4 byte encoding.
1274 { " 'foo\360\220\220\212';\n"
1275 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001277 // 3 byte encoding of \u0fff.
1278 { " 'foo\340\277\277';\n"
1279 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001281 // Broken 6 byte encoding with missing last byte.
1282 { " 'foo\355\240\201\355\211';\n"
1283 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001285 // Broken 3 byte encoding of \u0fff with missing last byte.
1286 { " 'foo\340\277';\n"
1287 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001288 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001289 // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1290 { " 'foo\340';\n"
1291 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001293 // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1294 { " 'foo\340\203\277';\n"
1295 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001297 // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1298 { " 'foo\340\201\277';\n"
1299 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001301 // Unpaired lead surrogate.
1302 { " 'foo\355\240\201';\n"
1303 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001304 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001305 // Unpaired lead surrogate where following code point is a 3 byte sequence.
1306 { " 'foo\355\240\201\340\277\277';\n"
1307 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001308 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001309 // Unpaired lead surrogate where following code point is a 4 byte encoding
1310 // of a trail surrogate.
1311 { " 'foo\355\240\201\360\215\260\211';\n"
1312 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001313 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001314 // Unpaired trail surrogate.
1315 { " 'foo\355\260\211';\n"
1316 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001318 // 2 byte encoding of \u00ff.
1319 { " 'foo\303\277';\n"
1320 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001322 // Broken 2 byte encoding of \u00ff with missing last byte.
1323 { " 'foo\303';\n"
1324 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001326 // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1327 { " 'foo\301\277';\n"
1328 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001330 // Illegal 5 byte encoding.
1331 { " 'foo\370\277\277\277\277';\n"
1332 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001334 // Illegal 6 byte encoding.
1335 { " 'foo\374\277\277\277\277\277';\n"
1336 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001338 // Illegal 0xfe byte
1339 { " 'foo\376\277\277\277\277\277\277';\n"
1340 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001342 // Illegal 0xff byte
1343 { " 'foo\377\277\277\277\277\277\277\277';\n"
1344 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001346 { " 'foo';\n"
1347 " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001349 { " 'foo';\n"
1350 " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 i::FUNCTION_SCOPE, i::SLOPPY },
1352 { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001353 };
1354
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 i::Isolate* isolate = CcTest::i_isolate();
1356 i::Factory* factory = isolate->factory();
1357
1358 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001360 v8::Context::Scope context_scope(context);
1361
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1363 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001364
1365 for (int i = 0; source_data[i].outer_prefix; i++) {
1366 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1367 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1368 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1369 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1370 int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1371 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1372 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1373 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 i::ScopedVector<char> program(kProgramByteSize + 1);
1375 i::SNPrintF(program, "%s%s%s",
1376 source_data[i].outer_prefix,
1377 source_data[i].inner_source,
1378 source_data[i].outer_suffix);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001379
1380 // Parse program source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 i::Handle<i::String> source = factory->NewStringFromUtf8(
1382 i::CStrVector(program.start())).ToHandleChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001383 CHECK_EQ(source->length(), kProgramSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001385 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 i::ParseInfo info(&zone, script);
1387 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 parser.set_allow_lazy(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001389 info.set_global();
1390 info.set_language_mode(source_data[i].language_mode);
1391 parser.Parse(&info);
1392 CHECK(info.literal() != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001393
1394 // Check scope types and positions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395 i::Scope* scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001396 CHECK(scope->is_script_scope());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001397 CHECK_EQ(scope->start_position(), 0);
1398 CHECK_EQ(scope->end_position(), kProgramSize);
1399 CHECK_EQ(scope->inner_scopes()->length(), 1);
1400
1401 i::Scope* inner_scope = scope->inner_scopes()->at(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402 CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001403 CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1404 // The end position of a token is one position after the last
1405 // character belonging to that token.
1406 CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1407 }
1408}
1409
1410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411TEST(DiscardFunctionBody) {
1412 // Test that inner function bodies are discarded if possible.
1413 // See comments in ParseFunctionLiteral in parser.cc.
1414 const char* discard_sources[] = {
1415 "(function f() { function g() { var a; } })();",
1416 "(function f() { function g() { { function h() { } } } })();",
1417 /* TODO(conradw): In future it may be possible to apply this optimisation
1418 * to these productions.
1419 "(function f() { 0, function g() { var a; } })();",
1420 "(function f() { 0, { g() { var a; } } })();",
1421 "(function f() { 0, class c { g() { var a; } } })();", */
1422 NULL};
1423
1424 i::Isolate* isolate = CcTest::i_isolate();
1425 i::Factory* factory = isolate->factory();
1426 v8::HandleScope handles(CcTest::isolate());
1427 i::FunctionLiteral* function;
1428
1429 for (int i = 0; discard_sources[i]; i++) {
1430 const char* source = discard_sources[i];
1431 i::Handle<i::String> source_code =
1432 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
1433 i::Handle<i::Script> script = factory->NewScript(source_code);
Ben Murdochda12d292016-06-02 14:46:10 +01001434 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 i::ParseInfo info(&zone, script);
1436 info.set_allow_lazy_parsing();
1437 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 parser.Parse(&info);
1439 function = info.literal();
1440 CHECK_NOT_NULL(function);
1441 CHECK_NOT_NULL(function->body());
1442 CHECK_EQ(1, function->body()->length());
1443 i::FunctionLiteral* inner =
1444 function->body()->first()->AsExpressionStatement()->expression()->
1445 AsCall()->expression()->AsFunctionLiteral();
1446 i::Scope* inner_scope = inner->scope();
1447 i::FunctionLiteral* fun = nullptr;
1448 if (inner_scope->declarations()->length() > 1) {
1449 fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun();
1450 } else {
1451 // TODO(conradw): This path won't be hit until the other test cases can be
1452 // uncommented.
1453 UNREACHABLE();
1454 CHECK_NOT_NULL(inner->body());
1455 CHECK_GE(2, inner->body()->length());
1456 i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
1457 expression()->AsBinaryOperation()->right();
1458 if (exp->IsFunctionLiteral()) {
1459 fun = exp->AsFunctionLiteral();
1460 } else if (exp->IsObjectLiteral()) {
1461 fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
1462 AsFunctionLiteral();
1463 } else {
1464 fun = exp->AsClassLiteral()->properties()->at(0)->value()->
1465 AsFunctionLiteral();
1466 }
1467 }
1468 CHECK_NULL(fun->body());
1469 }
1470}
1471
1472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473const char* ReadString(unsigned* start) {
1474 int length = start[0];
1475 char* result = i::NewArray<char>(length + 1);
1476 for (int i = 0; i < length; i++) {
1477 result[i] = start[i + 1];
1478 }
1479 result[length] = '\0';
1480 return result;
1481}
1482
1483
1484i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
1485 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486 int message = data[i::PreparseDataConstants::kMessageTemplatePos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001488 i::Handle<i::Object> arg_object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001489 if (arg_count == 1) {
1490 // Position after text found by skipping past length field and
1491 // length field content words.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001492 const char* arg =
1493 ReadString(&data[i::PreparseDataConstants::kMessageArgPos]);
1494 arg_object = v8::Utils::OpenHandle(*v8_str(arg));
1495 i::DeleteArray(arg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 } else {
1497 CHECK_EQ(0, arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 arg_object = isolate->factory()->undefined_value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 }
1500
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501 data.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001502 return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503}
1504
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001505enum ParserFlag {
1506 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001507 kAllowNatives,
Ben Murdochda12d292016-06-02 14:46:10 +01001508 kAllowHarmonyFunctionSent,
1509 kAllowHarmonyRestrictiveDeclarations,
Ben Murdochc5610432016-08-08 18:44:38 +01001510 kAllowHarmonyExponentiationOperator,
1511 kAllowHarmonyForIn,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001512 kAllowHarmonyAsyncAwait,
1513 kAllowHarmonyRestrictiveGenerators,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514};
1515
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516enum ParserSyncTestResult {
1517 kSuccessOrError,
1518 kSuccess,
1519 kError
1520};
1521
1522template <typename Traits>
1523void SetParserFlags(i::ParserBase<Traits>* parser,
1524 i::EnumSet<ParserFlag> flags) {
1525 parser->set_allow_lazy(flags.Contains(kAllowLazy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001526 parser->set_allow_natives(flags.Contains(kAllowNatives));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001527 parser->set_allow_harmony_function_sent(
1528 flags.Contains(kAllowHarmonyFunctionSent));
Ben Murdochda12d292016-06-02 14:46:10 +01001529 parser->set_allow_harmony_restrictive_declarations(
1530 flags.Contains(kAllowHarmonyRestrictiveDeclarations));
1531 parser->set_allow_harmony_exponentiation_operator(
1532 flags.Contains(kAllowHarmonyExponentiationOperator));
Ben Murdochc5610432016-08-08 18:44:38 +01001533 parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn));
1534 parser->set_allow_harmony_async_await(
1535 flags.Contains(kAllowHarmonyAsyncAwait));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001536 parser->set_allow_harmony_restrictive_generators(
1537 flags.Contains(kAllowHarmonyRestrictiveGenerators));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001538}
1539
1540
1541void TestParserSyncWithFlags(i::Handle<i::String> source,
1542 i::EnumSet<ParserFlag> flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543 ParserSyncTestResult result,
Ben Murdochc5610432016-08-08 18:44:38 +01001544 bool is_module = false,
1545 bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546 i::Isolate* isolate = CcTest::i_isolate();
1547 i::Factory* factory = isolate->factory();
1548
1549 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001550 int preparser_materialized_literals = -1;
1551 int parser_materialized_literals = -2;
Ben Murdoch692be652012-01-10 18:47:50 +00001552
1553 // Preparse the data.
1554 i::CompleteParserRecorder log;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001555 if (test_preparser) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 i::Scanner scanner(isolate->unicode_cache());
1557 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
Ben Murdochda12d292016-06-02 14:46:10 +01001558 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 i::AstValueFactory ast_value_factory(
1560 &zone, CcTest::i_isolate()->heap()->HashSeed());
1561 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
1562 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001563 SetParserFlags(&preparser, flags);
1564 scanner.Initialize(&stream);
Ben Murdochc5610432016-08-08 18:44:38 +01001565 i::PreParser::PreParseResult result =
1566 preparser.PreParseProgram(&preparser_materialized_literals, is_module);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1568 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 bool preparse_error = log.HasError();
Ben Murdoch692be652012-01-10 18:47:50 +00001570
1571 // Parse the data
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572 i::FunctionLiteral* function;
1573 {
1574 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001575 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 i::ParseInfo info(&zone, script);
1577 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001578 SetParserFlags(&parser, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001579 if (is_module) {
1580 info.set_module();
1581 } else {
1582 info.set_global();
1583 }
1584 parser.Parse(&info);
1585 function = info.literal();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001586 if (function) {
1587 parser_materialized_literals = function->materialized_literal_count();
1588 }
Ben Murdoch692be652012-01-10 18:47:50 +00001589 }
1590
1591 // Check that preparsing fails iff parsing fails.
Ben Murdoch692be652012-01-10 18:47:50 +00001592 if (function == NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 // Extract exception from the parser.
1594 CHECK(isolate->has_pending_exception());
1595 i::Handle<i::JSObject> exception_handle(
1596 i::JSObject::cast(isolate->pending_exception()));
Ben Murdochda12d292016-06-02 14:46:10 +01001597 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
1598 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1599 .ToHandleChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001600
1601 if (result == kSuccess) {
1602 v8::base::OS::Print(
1603 "Parser failed on:\n"
1604 "\t%s\n"
1605 "with error:\n"
1606 "\t%s\n"
1607 "However, we expected no error.",
1608 source->ToCString().get(), message_string->ToCString().get());
1609 CHECK(false);
1610 }
1611
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 if (test_preparser && !preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 v8::base::OS::Print(
1614 "Parser failed on:\n"
1615 "\t%s\n"
1616 "with error:\n"
1617 "\t%s\n"
1618 "However, the preparser succeeded",
1619 source->ToCString().get(), message_string->ToCString().get());
1620 CHECK(false);
1621 }
1622 // Check that preparser and parser produce the same error.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623 if (test_preparser) {
1624 i::Handle<i::String> preparser_message =
1625 FormatMessage(log.ErrorMessageData());
1626 if (!i::String::Equals(message_string, preparser_message)) {
1627 v8::base::OS::Print(
1628 "Expected parser and preparser to produce the same error on:\n"
1629 "\t%s\n"
1630 "However, found the following error messages\n"
1631 "\tparser: %s\n"
1632 "\tpreparser: %s\n",
1633 source->ToCString().get(), message_string->ToCString().get(),
1634 preparser_message->ToCString().get());
1635 CHECK(false);
1636 }
Ben Murdoch692be652012-01-10 18:47:50 +00001637 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001638 } else if (test_preparser && preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639 v8::base::OS::Print(
1640 "Preparser failed on:\n"
1641 "\t%s\n"
1642 "with error:\n"
1643 "\t%s\n"
1644 "However, the parser succeeded",
1645 source->ToCString().get(),
1646 FormatMessage(log.ErrorMessageData())->ToCString().get());
1647 CHECK(false);
1648 } else if (result == kError) {
1649 v8::base::OS::Print(
1650 "Expected error on:\n"
1651 "\t%s\n"
1652 "However, parser and preparser succeeded",
1653 source->ToCString().get());
1654 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 } else if (test_preparser &&
1656 preparser_materialized_literals != parser_materialized_literals) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001657 v8::base::OS::Print(
1658 "Preparser materialized literals (%d) differ from Parser materialized "
1659 "literals (%d) on:\n"
1660 "\t%s\n"
1661 "However, parser and preparser succeeded",
1662 preparser_materialized_literals, parser_materialized_literals,
1663 source->ToCString().get());
1664 CHECK(false);
Ben Murdoch692be652012-01-10 18:47:50 +00001665 }
1666}
1667
1668
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669void TestParserSync(const char* source, const ParserFlag* varying_flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670 size_t varying_flags_length,
1671 ParserSyncTestResult result = kSuccessOrError,
1672 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001673 size_t always_true_flags_length = 0,
1674 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 size_t always_false_flags_length = 0,
Ben Murdochc5610432016-08-08 18:44:38 +01001676 bool is_module = false, bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677 i::Handle<i::String> str =
1678 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1679 for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1680 i::EnumSet<ParserFlag> flags;
1681 for (size_t flag_index = 0; flag_index < varying_flags_length;
1682 ++flag_index) {
1683 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1684 }
1685 for (size_t flag_index = 0; flag_index < always_true_flags_length;
1686 ++flag_index) {
1687 flags.Add(always_true_flags[flag_index]);
1688 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001689 for (size_t flag_index = 0; flag_index < always_false_flags_length;
1690 ++flag_index) {
1691 flags.Remove(always_false_flags[flag_index]);
1692 }
Ben Murdochc5610432016-08-08 18:44:38 +01001693 TestParserSyncWithFlags(str, flags, result, is_module, test_preparser);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001694 }
1695}
1696
1697
Ben Murdoch692be652012-01-10 18:47:50 +00001698TEST(ParserSync) {
1699 const char* context_data[][2] = {
1700 { "", "" },
1701 { "{", "}" },
1702 { "if (true) ", " else {}" },
1703 { "if (true) {} else ", "" },
1704 { "if (true) ", "" },
1705 { "do ", " while (false)" },
1706 { "while (false) ", "" },
1707 { "for (;;) ", "" },
1708 { "with ({})", "" },
1709 { "switch (12) { case 12: ", "}" },
1710 { "switch (12) { default: ", "}" },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001711 { "switch (12) { ", "case 12: }" },
Ben Murdoch692be652012-01-10 18:47:50 +00001712 { "label2: ", "" },
1713 { NULL, NULL }
1714 };
1715
1716 const char* statement_data[] = {
1717 "{}",
1718 "var x",
1719 "var x = 1",
1720 "const x",
1721 "const x = 1",
1722 ";",
1723 "12",
1724 "if (false) {} else ;",
1725 "if (false) {} else {}",
1726 "if (false) {} else 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001727 "if (false) ;",
Ben Murdoch692be652012-01-10 18:47:50 +00001728 "if (false) {}",
1729 "if (false) 12",
1730 "do {} while (false)",
1731 "for (;;) ;",
1732 "for (;;) {}",
1733 "for (;;) 12",
1734 "continue",
1735 "continue label",
1736 "continue\nlabel",
1737 "break",
1738 "break label",
1739 "break\nlabel",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001740 // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1741 // "return",
1742 // "return 12",
1743 // "return\n12",
Ben Murdoch692be652012-01-10 18:47:50 +00001744 "with ({}) ;",
1745 "with ({}) {}",
1746 "with ({}) 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001747 "switch ({}) { default: }",
1748 "label3: ",
Ben Murdoch692be652012-01-10 18:47:50 +00001749 "throw",
1750 "throw 12",
1751 "throw\n12",
1752 "try {} catch(e) {}",
1753 "try {} finally {}",
1754 "try {} catch(e) {} finally {}",
1755 "debugger",
1756 NULL
1757 };
1758
1759 const char* termination_data[] = {
1760 "",
1761 ";",
1762 "\n",
1763 ";\n",
1764 "\n;",
1765 NULL
1766 };
1767
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001769 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch692be652012-01-10 18:47:50 +00001770 v8::Context::Scope context_scope(context);
1771
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1773 i::GetCurrentStackPosition() - 128 * 1024);
1774
Ben Murdoch692be652012-01-10 18:47:50 +00001775 for (int i = 0; context_data[i][0] != NULL; ++i) {
1776 for (int j = 0; statement_data[j] != NULL; ++j) {
1777 for (int k = 0; termination_data[k] != NULL; ++k) {
1778 int kPrefixLen = i::StrLength(context_data[i][0]);
1779 int kStatementLen = i::StrLength(statement_data[j]);
1780 int kTerminationLen = i::StrLength(termination_data[k]);
1781 int kSuffixLen = i::StrLength(context_data[i][1]);
1782 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1783 + kSuffixLen + i::StrLength("label: for (;;) { }");
1784
1785 // Plug the source code pieces together.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 i::ScopedVector<char> program(kProgramSize + 1);
1787 int length = i::SNPrintF(program,
Ben Murdoch692be652012-01-10 18:47:50 +00001788 "label: for (;;) { %s%s%s%s }",
1789 context_data[i][0],
1790 statement_data[j],
1791 termination_data[k],
1792 context_data[i][1]);
1793 CHECK(length == kProgramSize);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001794 TestParserSync(program.start(), NULL, 0);
Ben Murdoch692be652012-01-10 18:47:50 +00001795 }
1796 }
1797 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001798
1799 // Neither Harmony numeric literals nor our natives syntax have any
1800 // interaction with the flags above, so test these separately to reduce
1801 // the combinatorial explosion.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001802 TestParserSync("0o1234", NULL, 0);
1803 TestParserSync("0b1011", NULL, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001805 static const ParserFlag flags3[] = { kAllowNatives };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001806 TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1807}
1808
1809
1810TEST(StrictOctal) {
1811 // Test that syntax error caused by octal literal is reported correctly as
1812 // such (issue 2220).
1813 v8::V8::Initialize();
1814 v8::HandleScope scope(CcTest::isolate());
1815 v8::Context::Scope context_scope(
1816 v8::Context::New(CcTest::isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001818 const char* script =
1819 "\"use strict\"; \n"
1820 "a = function() { \n"
1821 " b = function() { \n"
1822 " 01; \n"
1823 " }; \n"
1824 "}; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825 v8_compile(v8_str(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001826 CHECK(try_catch.HasCaught());
1827 v8::String::Utf8Value exception(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001828 CHECK_EQ(0,
1829 strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1830 *exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001831}
1832
1833
1834void RunParserSyncTest(const char* context_data[][2],
1835 const char* statement_data[],
1836 ParserSyncTestResult result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001837 const ParserFlag* flags = NULL, int flags_len = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001838 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001839 int always_true_len = 0,
1840 const ParserFlag* always_false_flags = NULL,
Ben Murdochc5610432016-08-08 18:44:38 +01001841 int always_false_len = 0, bool is_module = false,
1842 bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001844 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 v8::Context::Scope context_scope(context);
1846
1847 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1848 i::GetCurrentStackPosition() - 128 * 1024);
1849
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001850 // Experimental feature flags should not go here; pass the flags as
1851 // always_true_flags if the test needs them.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001852 static const ParserFlag default_flags[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001853 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001854 kAllowNatives,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001855 };
1856 ParserFlag* generated_flags = NULL;
1857 if (flags == NULL) {
1858 flags = default_flags;
1859 flags_len = arraysize(default_flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001860 if (always_true_flags != NULL || always_false_flags != NULL) {
1861 // Remove always_true/false_flags from default_flags (if present).
1862 CHECK((always_true_flags != NULL) == (always_true_len > 0));
1863 CHECK((always_false_flags != NULL) == (always_false_len > 0));
1864 generated_flags = new ParserFlag[flags_len + always_true_len];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 int flag_index = 0;
1866 for (int i = 0; i < flags_len; ++i) {
1867 bool use_flag = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001868 for (int j = 0; use_flag && j < always_true_len; ++j) {
1869 if (flags[i] == always_true_flags[j]) use_flag = false;
1870 }
1871 for (int j = 0; use_flag && j < always_false_len; ++j) {
1872 if (flags[i] == always_false_flags[j]) use_flag = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 }
1874 if (use_flag) generated_flags[flag_index++] = flags[i];
1875 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 flags_len = flag_index;
1877 flags = generated_flags;
1878 }
1879 }
1880 for (int i = 0; context_data[i][0] != NULL; ++i) {
1881 for (int j = 0; statement_data[j] != NULL; ++j) {
1882 int kPrefixLen = i::StrLength(context_data[i][0]);
1883 int kStatementLen = i::StrLength(statement_data[j]);
1884 int kSuffixLen = i::StrLength(context_data[i][1]);
1885 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1886
1887 // Plug the source code pieces together.
1888 i::ScopedVector<char> program(kProgramSize + 1);
1889 int length = i::SNPrintF(program,
1890 "%s%s%s",
1891 context_data[i][0],
1892 statement_data[j],
1893 context_data[i][1]);
1894 CHECK(length == kProgramSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001895 TestParserSync(program.start(), flags, flags_len, result,
1896 always_true_flags, always_true_len, always_false_flags,
Ben Murdochc5610432016-08-08 18:44:38 +01001897 always_false_len, is_module, test_preparser);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001898 }
1899 }
1900 delete[] generated_flags;
1901}
1902
1903
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001904void RunModuleParserSyncTest(const char* context_data[][2],
1905 const char* statement_data[],
1906 ParserSyncTestResult result,
1907 const ParserFlag* flags = NULL, int flags_len = 0,
1908 const ParserFlag* always_true_flags = NULL,
1909 int always_true_len = 0,
1910 const ParserFlag* always_false_flags = NULL,
Ben Murdochc5610432016-08-08 18:44:38 +01001911 int always_false_len = 0,
1912 bool test_preparser = true) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001913 RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1914 always_true_flags, always_true_len, always_false_flags,
Ben Murdochc5610432016-08-08 18:44:38 +01001915 always_false_len, true, test_preparser);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001916}
1917
1918
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001919TEST(ErrorsEvalAndArguments) {
1920 // Tests that both preparsing and parsing produce the right kind of errors for
1921 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1922 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1923 // isn't.
1924 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001925 {"\"use strict\";", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001926 {"var eval; function test_func() {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001927 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928
1929 const char* statement_data[] = {
1930 "var eval;",
1931 "var arguments",
1932 "var foo, eval;",
1933 "var foo, arguments;",
1934 "try { } catch (eval) { }",
1935 "try { } catch (arguments) { }",
1936 "function eval() { }",
1937 "function arguments() { }",
1938 "function foo(eval) { }",
1939 "function foo(arguments) { }",
1940 "function foo(bar, eval) { }",
1941 "function foo(bar, arguments) { }",
1942 "(eval) => { }",
1943 "(arguments) => { }",
1944 "(foo, eval) => { }",
1945 "(foo, arguments) => { }",
1946 "eval = 1;",
1947 "arguments = 1;",
1948 "var foo = eval = 1;",
1949 "var foo = arguments = 1;",
1950 "++eval;",
1951 "++arguments;",
1952 "eval++;",
1953 "arguments++;",
1954 NULL
1955 };
1956
Ben Murdochda12d292016-06-02 14:46:10 +01001957 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001958}
1959
1960
1961TEST(NoErrorsEvalAndArgumentsSloppy) {
1962 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1963 // identifiers when needed.
1964 const char* context_data[][2] = {
1965 { "", "" },
1966 { "function test_func() {", "}"},
1967 { NULL, NULL }
1968 };
1969
1970 const char* statement_data[] = {
1971 "var eval;",
1972 "var arguments",
1973 "var foo, eval;",
1974 "var foo, arguments;",
1975 "try { } catch (eval) { }",
1976 "try { } catch (arguments) { }",
1977 "function eval() { }",
1978 "function arguments() { }",
1979 "function foo(eval) { }",
1980 "function foo(arguments) { }",
1981 "function foo(bar, eval) { }",
1982 "function foo(bar, arguments) { }",
1983 "eval = 1;",
1984 "arguments = 1;",
1985 "var foo = eval = 1;",
1986 "var foo = arguments = 1;",
1987 "++eval;",
1988 "++arguments;",
1989 "eval++;",
1990 "arguments++;",
1991 NULL
1992 };
1993
1994 RunParserSyncTest(context_data, statement_data, kSuccess);
1995}
1996
1997
1998TEST(NoErrorsEvalAndArgumentsStrict) {
1999 const char* context_data[][2] = {
2000 { "\"use strict\";", "" },
2001 { "function test_func() { \"use strict\";", "}" },
2002 { "() => { \"use strict\"; ", "}" },
2003 { NULL, NULL }
2004 };
2005
2006 const char* statement_data[] = {
2007 "eval;",
2008 "arguments;",
2009 "var foo = eval;",
2010 "var foo = arguments;",
2011 "var foo = { eval: 1 };",
2012 "var foo = { arguments: 1 };",
2013 "var foo = { }; foo.eval = {};",
2014 "var foo = { }; foo.arguments = {};",
2015 NULL
2016 };
2017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002018 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002019}
2020
Ben Murdochc5610432016-08-08 18:44:38 +01002021#define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2022 V(implements) \
2023 V(interface) \
2024 V(package) \
2025 V(private) \
2026 V(protected) \
2027 V(public) \
2028 V(static) \
2029 V(yield)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002030
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002031#define FUTURE_STRICT_RESERVED_WORDS(V) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002032 V(let) \
Ben Murdochc5610432016-08-08 18:44:38 +01002033 FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002034
Ben Murdochc5610432016-08-08 18:44:38 +01002035#define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2036 V(implements) \
2037 V(static) \
2038 V(yield)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002039
2040#define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002041 V(let) \
Ben Murdochc5610432016-08-08 18:44:38 +01002042 LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002043
2044#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2045 "var " #NAME ";", \
2046 "var foo, " #NAME ";", \
2047 "try { } catch (" #NAME ") { }", \
2048 "function " #NAME "() { }", \
2049 "(function " #NAME "() { })", \
2050 "function foo(" #NAME ") { }", \
2051 "function foo(bar, " #NAME ") { }", \
2052 #NAME " = 1;", \
2053 #NAME " += 1;", \
2054 "var foo = " #NAME " = 1;", \
2055 "++" #NAME ";", \
2056 #NAME " ++;",
2057
Ben Murdochc5610432016-08-08 18:44:38 +01002058// clang-format off
2059#define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
2060 "let " #NAME ";", \
2061 "for (let " #NAME "; false; ) {}", \
2062 "for (let " #NAME " in {}) {}", \
2063 "for (let " #NAME " of []) {}", \
2064 "const " #NAME " = null;", \
2065 "for (const " #NAME " = null; false; ) {}", \
2066 "for (const " #NAME " in {}) {}", \
2067 "for (const " #NAME " of []) {}",
2068// clang-format on
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002069
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002070TEST(ErrorsFutureStrictReservedWords) {
2071 // Tests that both preparsing and parsing produce the right kind of errors for
2072 // using future strict reserved words as identifiers. Without the strict mode,
2073 // it's ok to use future strict reserved words as identifiers. With the strict
2074 // mode, it isn't.
Ben Murdochc5610432016-08-08 18:44:38 +01002075 const char* strict_contexts[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002076 {"function test_func() {\"use strict\"; ", "}"},
2077 {"() => { \"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002078 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002079
Ben Murdochc5610432016-08-08 18:44:38 +01002080 // clang-format off
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002081 const char* statement_data[] {
2082 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochc5610432016-08-08 18:44:38 +01002083 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002084 NULL
2085 };
Ben Murdochc5610432016-08-08 18:44:38 +01002086 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087
Ben Murdochc5610432016-08-08 18:44:38 +01002088 RunParserSyncTest(strict_contexts, statement_data, kError);
2089
2090 // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
2091 //
2092 // > LexicalDeclaration : LetOrConst BindingList ;
2093 // >
2094 // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
2095 const char* non_strict_contexts[][2] = {{"", ""},
2096 {"function test_func() {", "}"},
2097 {"() => {", "}"},
2098 {NULL, NULL}};
2099 const char* invalid_statements[] = {FUTURE_STRICT_RESERVED_LEX_BINDINGS("let")
2100 NULL};
2101
2102 RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103}
2104
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002105#undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2106
2107
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002108TEST(NoErrorsFutureStrictReservedWords) {
2109 const char* context_data[][2] = {
2110 { "", "" },
2111 { "function test_func() {", "}"},
2112 { "() => {", "}" },
2113 { NULL, NULL }
2114 };
2115
Ben Murdochc5610432016-08-08 18:44:38 +01002116 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002117 const char* statement_data[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002118 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochc5610432016-08-08 18:44:38 +01002119 FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002120 NULL
2121 };
Ben Murdochc5610432016-08-08 18:44:38 +01002122 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002124 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002125}
2126
2127
2128TEST(ErrorsReservedWords) {
2129 // Tests that both preparsing and parsing produce the right kind of errors for
2130 // using future reserved words as identifiers. These tests don't depend on the
2131 // strict mode.
2132 const char* context_data[][2] = {
2133 { "", "" },
2134 { "\"use strict\";", "" },
2135 { "var eval; function test_func() {", "}"},
2136 { "var eval; function test_func() {\"use strict\"; ", "}"},
2137 { "var eval; () => {", "}"},
2138 { "var eval; () => {\"use strict\"; ", "}"},
2139 { NULL, NULL }
2140 };
2141
2142 const char* statement_data[] = {
2143 "var super;",
2144 "var foo, super;",
2145 "try { } catch (super) { }",
2146 "function super() { }",
2147 "function foo(super) { }",
2148 "function foo(bar, super) { }",
2149 "(super) => { }",
2150 "(bar, super) => { }",
2151 "super = 1;",
2152 "var foo = super = 1;",
2153 "++super;",
2154 "super++;",
2155 "function foo super",
2156 NULL
2157 };
2158
2159 RunParserSyncTest(context_data, statement_data, kError);
2160}
2161
2162
2163TEST(NoErrorsLetSloppyAllModes) {
2164 // In sloppy mode, it's okay to use "let" as identifier.
2165 const char* context_data[][2] = {
2166 { "", "" },
2167 { "function f() {", "}" },
2168 { "(function f() {", "})" },
2169 { NULL, NULL }
2170 };
2171
2172 const char* statement_data[] = {
2173 "var let;",
2174 "var foo, let;",
2175 "try { } catch (let) { }",
2176 "function let() { }",
2177 "(function let() { })",
2178 "function foo(let) { }",
2179 "function foo(bar, let) { }",
2180 "let = 1;",
2181 "var foo = let = 1;",
2182 "let * 2;",
2183 "++let;",
2184 "let++;",
2185 "let: 34",
2186 "function let(let) { let: let(let + let(0)); }",
2187 "({ let: 1 })",
2188 "({ get let() { 1 } })",
2189 "let(100)",
2190 NULL
2191 };
2192
2193 RunParserSyncTest(context_data, statement_data, kSuccess);
2194}
2195
2196
2197TEST(NoErrorsYieldSloppyAllModes) {
2198 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2199 // generator (see other test).
2200 const char* context_data[][2] = {
2201 { "", "" },
2202 { "function not_gen() {", "}" },
2203 { "(function not_gen() {", "})" },
2204 { NULL, NULL }
2205 };
2206
2207 const char* statement_data[] = {
2208 "var yield;",
2209 "var foo, yield;",
2210 "try { } catch (yield) { }",
2211 "function yield() { }",
2212 "(function yield() { })",
2213 "function foo(yield) { }",
2214 "function foo(bar, yield) { }",
2215 "yield = 1;",
2216 "var foo = yield = 1;",
2217 "yield * 2;",
2218 "++yield;",
2219 "yield++;",
2220 "yield: 34",
2221 "function yield(yield) { yield: yield (yield + yield(0)); }",
2222 "({ yield: 1 })",
2223 "({ get yield() { 1 } })",
2224 "yield(100)",
2225 "yield[100]",
2226 NULL
2227 };
2228
2229 RunParserSyncTest(context_data, statement_data, kSuccess);
2230}
2231
2232
2233TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2234 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2235 // generator (see next test).
2236 const char* context_data[][2] = {
2237 { "", "" },
2238 { "function not_gen() {", "}" },
2239 { "function * gen() { function not_gen() {", "} }" },
2240 { "(function not_gen() {", "})" },
2241 { "(function * gen() { (function not_gen() {", "}) })" },
2242 { NULL, NULL }
2243 };
2244
2245 const char* statement_data[] = {
2246 "var yield;",
2247 "var foo, yield;",
2248 "try { } catch (yield) { }",
2249 "function yield() { }",
2250 "(function yield() { })",
2251 "function foo(yield) { }",
2252 "function foo(bar, yield) { }",
2253 "function * yield() { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002254 "yield = 1;",
2255 "var foo = yield = 1;",
2256 "yield * 2;",
2257 "++yield;",
2258 "yield++;",
2259 "yield: 34",
2260 "function yield(yield) { yield: yield (yield + yield(0)); }",
2261 "({ yield: 1 })",
2262 "({ get yield() { 1 } })",
2263 "yield(100)",
2264 "yield[100]",
2265 NULL
2266 };
2267
2268 RunParserSyncTest(context_data, statement_data, kSuccess);
2269}
2270
2271
2272TEST(ErrorsYieldStrict) {
2273 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002274 {"\"use strict\";", ""},
2275 {"\"use strict\"; function not_gen() {", "}"},
2276 {"function test_func() {\"use strict\"; ", "}"},
2277 {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2278 {"\"use strict\"; (function not_gen() {", "})"},
2279 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2280 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002281 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002282
2283 const char* statement_data[] = {
2284 "var yield;",
2285 "var foo, yield;",
2286 "try { } catch (yield) { }",
2287 "function yield() { }",
2288 "(function yield() { })",
2289 "function foo(yield) { }",
2290 "function foo(bar, yield) { }",
2291 "function * yield() { }",
2292 "(function * yield() { })",
2293 "yield = 1;",
2294 "var foo = yield = 1;",
2295 "++yield;",
2296 "yield++;",
2297 "yield: 34;",
2298 NULL
2299 };
2300
Ben Murdochda12d292016-06-02 14:46:10 +01002301 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002302}
2303
2304
2305TEST(ErrorsYieldSloppy) {
2306 const char* context_data[][2] = {
2307 { "", "" },
2308 { "function not_gen() {", "}" },
2309 { "(function not_gen() {", "})" },
2310 { NULL, NULL }
2311 };
2312
2313 const char* statement_data[] = {
2314 "(function * yield() { })",
2315 NULL
2316 };
2317
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002318 RunParserSyncTest(context_data, statement_data, kError);
2319}
2320
2321
2322TEST(NoErrorsGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002323 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002324 const char* context_data[][2] = {
2325 { "function * gen() {", "}" },
2326 { "(function * gen() {", "})" },
2327 { "(function * () {", "})" },
2328 { NULL, NULL }
2329 };
2330
2331 const char* statement_data[] = {
2332 // A generator without a body is valid.
2333 ""
2334 // Valid yield expressions inside generators.
2335 "yield 2;",
2336 "yield * 2;",
2337 "yield * \n 2;",
2338 "yield yield 1;",
2339 "yield * yield * 1;",
2340 "yield 3 + (yield 4);",
2341 "yield * 3 + (yield * 4);",
2342 "(yield * 3) + (yield * 4);",
2343 "yield 3; yield 4;",
2344 "yield * 3; yield * 4;",
2345 "(function (yield) { })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002346 "(function yield() { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 "yield { yield: 12 }",
2348 "yield /* comment */ { yield: 12 }",
2349 "yield * \n { yield: 12 }",
2350 "yield /* comment */ * \n { yield: 12 }",
2351 // You can return in a generator.
2352 "yield 1; return",
2353 "yield * 1; return",
2354 "yield 1; return 37",
2355 "yield * 1; return 37",
2356 "yield 1; return 37; yield 'dead';",
2357 "yield * 1; return 37; yield * 'dead';",
2358 // Yield is still a valid key in object literals.
2359 "({ yield: 1 })",
2360 "({ get yield() { } })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002361 // And in assignment pattern computed properties
2362 "({ [yield]: x } = { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002363 // Yield without RHS.
2364 "yield;",
2365 "yield",
2366 "yield\n",
2367 "yield /* comment */"
2368 "yield // comment\n"
2369 "(yield)",
2370 "[yield]",
2371 "{yield}",
2372 "yield, yield",
2373 "yield; yield",
2374 "(yield) ? yield : yield",
2375 "(yield) \n ? yield : yield",
2376 // If there is a newline before the next token, we don't look for RHS.
2377 "yield\nfor (;;) {}",
Ben Murdochda12d292016-06-02 14:46:10 +01002378 "x = class extends (yield) {}",
2379 "x = class extends f(yield) {}",
2380 "x = class extends (null, yield) { }",
2381 "x = class extends (a ? null : yield) { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002382 NULL
2383 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002384 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002385
Ben Murdochc5610432016-08-08 18:44:38 +01002386 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002387}
2388
2389
2390TEST(ErrorsYieldGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002391 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002392 const char* context_data[][2] = {
2393 { "function * gen() {", "}" },
2394 { "\"use strict\"; function * gen() {", "}" },
2395 { NULL, NULL }
2396 };
2397
2398 const char* statement_data[] = {
2399 // Invalid yield expressions inside generators.
2400 "var yield;",
2401 "var foo, yield;",
2402 "try { } catch (yield) { }",
2403 "function yield() { }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002404 // The name of the NFE is bound in the generator, which does not permit
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002405 // yield to be an identifier.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002406 "(function * yield() { })",
2407 // Yield isn't valid as a formal parameter for generators.
2408 "function * foo(yield) { }",
2409 "(function * foo(yield) { })",
2410 "yield = 1;",
2411 "var foo = yield = 1;",
2412 "++yield;",
2413 "yield++;",
2414 "yield *",
2415 "(yield *)",
2416 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2417 // is invalid.
2418 "yield 3 + yield 4;",
2419 "yield: 34",
2420 "yield ? 1 : 2",
2421 // Parses as yield (/ yield): invalid.
2422 "yield / yield",
2423 "+ yield",
2424 "+ yield 3",
2425 // Invalid (no newline allowed between yield and *).
2426 "yield\n*3",
2427 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2428 // object literal, and yield is not a valid label).
2429 "yield\n{yield: 42}",
2430 "yield /* comment */\n {yield: 42}",
2431 "yield //comment\n {yield: 42}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 // Destructuring binding and assignment are both disallowed
2433 "var [yield] = [42];",
2434 "var {foo: yield} = {a: 42};",
2435 "[yield] = [42];",
2436 "({a: yield} = {a: 42});",
2437 // Also disallow full yield expressions on LHS
2438 "var [yield 24] = [42];",
2439 "var {foo: yield 24} = {a: 42};",
2440 "[yield 24] = [42];",
2441 "({a: yield 24} = {a: 42});",
Ben Murdochc5610432016-08-08 18:44:38 +01002442 "for (yield 'x' in {});",
2443 "for (yield 'x' of {});",
2444 "for (yield 'x' in {} in {});",
2445 "for (yield 'x' in {} of {});",
Ben Murdochda12d292016-06-02 14:46:10 +01002446 "class C extends yield { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002447 NULL
2448 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002449 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450
2451 RunParserSyncTest(context_data, statement_data, kError);
2452}
2453
2454
2455TEST(ErrorsNameOfStrictFunction) {
2456 // Tests that illegal tokens as names of a strict function produce the correct
2457 // errors.
2458 const char* context_data[][2] = {
2459 { "function ", ""},
2460 { "\"use strict\"; function", ""},
2461 { "function * ", ""},
2462 { "\"use strict\"; function * ", ""},
2463 { NULL, NULL }
2464 };
2465
2466 const char* statement_data[] = {
2467 "eval() {\"use strict\";}",
2468 "arguments() {\"use strict\";}",
2469 "interface() {\"use strict\";}",
2470 "yield() {\"use strict\";}",
2471 // Future reserved words are always illegal
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002472 "super() { }",
2473 "super() {\"use strict\";}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474 NULL
2475 };
2476
Ben Murdochda12d292016-06-02 14:46:10 +01002477 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478}
2479
2480
2481TEST(NoErrorsNameOfStrictFunction) {
2482 const char* context_data[][2] = {
2483 { "function ", ""},
2484 { NULL, NULL }
2485 };
2486
2487 const char* statement_data[] = {
2488 "eval() { }",
2489 "arguments() { }",
2490 "interface() { }",
2491 "yield() { }",
2492 NULL
2493 };
2494
2495 RunParserSyncTest(context_data, statement_data, kSuccess);
2496}
2497
2498
2499TEST(NoErrorsNameOfStrictGenerator) {
2500 const char* context_data[][2] = {
2501 { "function * ", ""},
2502 { NULL, NULL }
2503 };
2504
2505 const char* statement_data[] = {
2506 "eval() { }",
2507 "arguments() { }",
2508 "interface() { }",
2509 "yield() { }",
2510 NULL
2511 };
2512
2513 RunParserSyncTest(context_data, statement_data, kSuccess);
2514}
2515
2516
2517TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2518 // Using future reserved words as labels is always an error.
2519 const char* context_data[][2] = {
2520 { "", ""},
2521 { "function test_func() {", "}" },
2522 { "() => {", "}" },
2523 { NULL, NULL }
2524 };
2525
2526 const char* statement_data[] = {
2527 "super: while(true) { break super; }",
2528 NULL
2529 };
2530
2531 RunParserSyncTest(context_data, statement_data, kError);
2532}
2533
2534
2535TEST(ErrorsIllegalWordsAsLabelsStrict) {
2536 // Tests that illegal tokens as labels produce the correct errors.
2537 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002538 {"\"use strict\";", ""},
2539 {"function test_func() {\"use strict\"; ", "}"},
2540 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002542
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002543#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544 const char* statement_data[] = {
2545 "super: while(true) { break super; }",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002546 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002547 NULL
2548 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002549#undef LABELLED_WHILE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002550
Ben Murdochda12d292016-06-02 14:46:10 +01002551 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002552}
2553
2554
2555TEST(NoErrorsIllegalWordsAsLabels) {
2556 // Using eval and arguments as labels is legal even in strict mode.
2557 const char* context_data[][2] = {
2558 { "", ""},
2559 { "function test_func() {", "}" },
2560 { "() => {", "}" },
2561 { "\"use strict\";", "" },
2562 { "\"use strict\"; function test_func() {", "}" },
2563 { "\"use strict\"; () => {", "}" },
2564 { NULL, NULL }
2565 };
2566
2567 const char* statement_data[] = {
2568 "mylabel: while(true) { break mylabel; }",
2569 "eval: while(true) { break eval; }",
2570 "arguments: while(true) { break arguments; }",
2571 NULL
2572 };
2573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002574 RunParserSyncTest(context_data, statement_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002575}
2576
2577
2578TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2579 const char* context_data[][2] = {
2580 { "", ""},
2581 { "function test_func() {", "}" },
2582 { "() => {", "}" },
2583 { NULL, NULL }
2584 };
2585
2586#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2587 const char* statement_data[] {
2588 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2589 NULL
2590 };
2591#undef LABELLED_WHILE
2592
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002593 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002594}
2595
2596
2597TEST(ErrorsParenthesizedLabels) {
2598 // Parenthesized identifiers shouldn't be recognized as labels.
2599 const char* context_data[][2] = {
2600 { "", ""},
2601 { "function test_func() {", "}" },
2602 { "() => {", "}" },
2603 { NULL, NULL }
2604 };
2605
2606 const char* statement_data[] = {
2607 "(mylabel): while(true) { break mylabel; }",
2608 NULL
2609 };
2610
2611 RunParserSyncTest(context_data, statement_data, kError);
2612}
2613
2614
2615TEST(NoErrorsParenthesizedDirectivePrologue) {
2616 // Parenthesized directive prologue shouldn't be recognized.
2617 const char* context_data[][2] = {
2618 { "", ""},
2619 { NULL, NULL }
2620 };
2621
2622 const char* statement_data[] = {
2623 "(\"use strict\"); var eval;",
2624 NULL
2625 };
2626
Ben Murdochda12d292016-06-02 14:46:10 +01002627 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002628}
2629
2630
2631TEST(ErrorsNotAnIdentifierName) {
2632 const char* context_data[][2] = {
2633 { "", ""},
2634 { "\"use strict\";", ""},
2635 { NULL, NULL }
2636 };
2637
2638 const char* statement_data[] = {
2639 "var foo = {}; foo.{;",
2640 "var foo = {}; foo.};",
2641 "var foo = {}; foo.=;",
2642 "var foo = {}; foo.888;",
2643 "var foo = {}; foo.-;",
2644 "var foo = {}; foo.--;",
2645 NULL
2646 };
2647
2648 RunParserSyncTest(context_data, statement_data, kError);
2649}
2650
2651
2652TEST(NoErrorsIdentifierNames) {
2653 // Keywords etc. are valid as property names.
2654 const char* context_data[][2] = {
2655 { "", ""},
2656 { "\"use strict\";", ""},
2657 { NULL, NULL }
2658 };
2659
2660 const char* statement_data[] = {
2661 "var foo = {}; foo.if;",
2662 "var foo = {}; foo.yield;",
2663 "var foo = {}; foo.super;",
2664 "var foo = {}; foo.interface;",
2665 "var foo = {}; foo.eval;",
2666 "var foo = {}; foo.arguments;",
2667 NULL
2668 };
2669
2670 RunParserSyncTest(context_data, statement_data, kSuccess);
2671}
2672
2673
2674TEST(DontRegressPreParserDataSizes) {
2675 // These tests make sure that Parser doesn't start producing less "preparse
2676 // data" (data which the embedder can cache).
2677 v8::V8::Initialize();
2678 v8::Isolate* isolate = CcTest::isolate();
2679 v8::HandleScope handles(isolate);
2680
2681 CcTest::i_isolate()->stack_guard()->SetStackLimit(
2682 i::GetCurrentStackPosition() - 128 * 1024);
2683
2684 struct TestCase {
2685 const char* program;
2686 int functions;
2687 } test_cases[] = {
2688 // No functions.
2689 {"var x = 42;", 0},
2690 // Functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002691 {"function foo() {}", 1},
2692 {"function foo() {} function bar() {}", 2},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002693 // Getter / setter functions are recorded as functions if they're on the top
2694 // level.
2695 {"var x = {get foo(){} };", 1},
2696 // Functions insize lazy functions are not recorded.
2697 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2698 {"function lazy() { var x = {get foo(){} } }", 1},
2699 {NULL, 0}
2700 };
2701
2702 for (int i = 0; test_cases[i].program; i++) {
2703 const char* program = test_cases[i].program;
2704 i::Factory* factory = CcTest::i_isolate()->factory();
2705 i::Handle<i::String> source =
2706 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2707 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01002708 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002709 i::ParseInfo info(&zone, script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002710 i::ScriptData* sd = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002711 info.set_cached_data(&sd);
2712 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
2713 info.set_allow_lazy_parsing();
2714 i::Parser::ParseStatic(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002715 i::ParseData* pd = i::ParseData::FromCachedData(sd);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002716
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002717 if (pd->FunctionCount() != test_cases[i].functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002718 v8::base::OS::Print(
2719 "Expected preparse data for program:\n"
2720 "\t%s\n"
2721 "to contain %d functions, however, received %d functions.\n",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002722 program, test_cases[i].functions, pd->FunctionCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002723 CHECK(false);
2724 }
2725 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002726 delete pd;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002727 }
2728}
2729
2730
2731TEST(FunctionDeclaresItselfStrict) {
2732 // Tests that we produce the right kinds of errors when a function declares
2733 // itself strict (we cannot produce there errors as soon as we see the
2734 // offending identifiers, because we don't know at that point whether the
2735 // function is strict or not).
2736 const char* context_data[][2] = {
2737 {"function eval() {", "}"},
2738 {"function arguments() {", "}"},
2739 {"function yield() {", "}"},
2740 {"function interface() {", "}"},
2741 {"function foo(eval) {", "}"},
2742 {"function foo(arguments) {", "}"},
2743 {"function foo(yield) {", "}"},
2744 {"function foo(interface) {", "}"},
2745 {"function foo(bar, eval) {", "}"},
2746 {"function foo(bar, arguments) {", "}"},
2747 {"function foo(bar, yield) {", "}"},
2748 {"function foo(bar, interface) {", "}"},
2749 {"function foo(bar, bar) {", "}"},
2750 { NULL, NULL }
2751 };
2752
2753 const char* strict_statement_data[] = {
2754 "\"use strict\";",
2755 NULL
2756 };
2757
2758 const char* non_strict_statement_data[] = {
2759 ";",
2760 NULL
2761 };
2762
Ben Murdochda12d292016-06-02 14:46:10 +01002763 RunParserSyncTest(context_data, strict_statement_data, kError);
2764 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002765}
2766
2767
2768TEST(ErrorsTryWithoutCatchOrFinally) {
2769 const char* context_data[][2] = {
2770 {"", ""},
2771 { NULL, NULL }
2772 };
2773
2774 const char* statement_data[] = {
2775 "try { }",
2776 "try { } foo();",
2777 "try { } catch (e) foo();",
2778 "try { } catch { }",
2779 "try { } finally foo();",
2780 NULL
2781 };
2782
2783 RunParserSyncTest(context_data, statement_data, kError);
2784}
2785
2786
2787TEST(NoErrorsTryCatchFinally) {
2788 const char* context_data[][2] = {
2789 {"", ""},
2790 { NULL, NULL }
2791 };
2792
2793 const char* statement_data[] = {
2794 "try { } catch (e) { }",
2795 "try { } catch (e) { } finally { }",
2796 "try { } finally { }",
2797 NULL
2798 };
2799
2800 RunParserSyncTest(context_data, statement_data, kSuccess);
2801}
2802
2803
2804TEST(ErrorsRegexpLiteral) {
2805 const char* context_data[][2] = {
2806 {"var r = ", ""},
2807 { NULL, NULL }
2808 };
2809
2810 const char* statement_data[] = {
2811 "/unterminated",
2812 NULL
2813 };
2814
2815 RunParserSyncTest(context_data, statement_data, kError);
2816}
2817
2818
2819TEST(NoErrorsRegexpLiteral) {
2820 const char* context_data[][2] = {
2821 {"var r = ", ""},
2822 { NULL, NULL }
2823 };
2824
2825 const char* statement_data[] = {
2826 "/foo/",
2827 "/foo/g",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002828 NULL
2829 };
2830
2831 RunParserSyncTest(context_data, statement_data, kSuccess);
2832}
2833
2834
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002835TEST(NoErrorsNewExpression) {
2836 const char* context_data[][2] = {
2837 {"", ""},
2838 {"var f =", ""},
2839 { NULL, NULL }
2840 };
2841
2842 const char* statement_data[] = {
2843 "new foo",
2844 "new foo();",
2845 "new foo(1);",
2846 "new foo(1, 2);",
2847 // The first () will be processed as a part of the NewExpression and the
2848 // second () will be processed as part of LeftHandSideExpression.
2849 "new foo()();",
2850 // The first () will be processed as a part of the inner NewExpression and
2851 // the second () will be processed as a part of the outer NewExpression.
2852 "new new foo()();",
2853 "new foo.bar;",
2854 "new foo.bar();",
2855 "new foo.bar.baz;",
2856 "new foo.bar().baz;",
2857 "new foo[bar];",
2858 "new foo[bar]();",
2859 "new foo[bar][baz];",
2860 "new foo[bar]()[baz];",
2861 "new foo[bar].baz(baz)()[bar].baz;",
2862 "new \"foo\"", // Runtime error
2863 "new 1", // Runtime error
2864 // This even runs:
2865 "(new new Function(\"this.x = 1\")).x;",
2866 "new new Test_Two(String, 2).v(0123).length;",
2867 NULL
2868 };
2869
2870 RunParserSyncTest(context_data, statement_data, kSuccess);
2871}
2872
2873
2874TEST(ErrorsNewExpression) {
2875 const char* context_data[][2] = {
2876 {"", ""},
2877 {"var f =", ""},
2878 { NULL, NULL }
2879 };
2880
2881 const char* statement_data[] = {
2882 "new foo bar",
2883 "new ) foo",
2884 "new ++foo",
2885 "new foo ++",
2886 NULL
2887 };
2888
2889 RunParserSyncTest(context_data, statement_data, kError);
2890}
2891
2892
2893TEST(StrictObjectLiteralChecking) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002894 const char* context_data[][2] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002895 {"\"use strict\"; var myobject = {", "};"},
2896 {"\"use strict\"; var myobject = {", ",};"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002897 {"var myobject = {", "};"},
2898 {"var myobject = {", ",};"},
2899 { NULL, NULL }
2900 };
2901
2902 // These are only errors in strict mode.
2903 const char* statement_data[] = {
2904 "foo: 1, foo: 2",
2905 "\"foo\": 1, \"foo\": 2",
2906 "foo: 1, \"foo\": 2",
2907 "1: 1, 1: 2",
2908 "1: 1, \"1\": 2",
2909 "get: 1, get: 2", // Not a getter for real, just a property called get.
2910 "set: 1, set: 2", // Not a setter for real, just a property called set.
2911 NULL
2912 };
2913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002915}
2916
2917
2918TEST(ErrorsObjectLiteralChecking) {
2919 const char* context_data[][2] = {
2920 {"\"use strict\"; var myobject = {", "};"},
2921 {"var myobject = {", "};"},
2922 { NULL, NULL }
2923 };
2924
2925 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002926 ",",
2927 // Wrong number of parameters
2928 "get bar(x) {}",
2929 "get bar(x, y) {}",
2930 "set bar() {}",
2931 "set bar(x, y) {}",
2932 // Parsing FunctionLiteral for getter or setter fails
2933 "get foo( +",
2934 "get foo() \"error\"",
2935 NULL
2936 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002937
2938 RunParserSyncTest(context_data, statement_data, kError);
2939}
2940
2941
2942TEST(NoErrorsObjectLiteralChecking) {
2943 const char* context_data[][2] = {
2944 {"var myobject = {", "};"},
2945 {"var myobject = {", ",};"},
2946 {"\"use strict\"; var myobject = {", "};"},
2947 {"\"use strict\"; var myobject = {", ",};"},
2948 { NULL, NULL }
2949 };
2950
2951 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002952 "foo: 1, get foo() {}",
2953 "foo: 1, set foo(v) {}",
2954 "\"foo\": 1, get \"foo\"() {}",
2955 "\"foo\": 1, set \"foo\"(v) {}",
2956 "1: 1, get 1() {}",
2957 "1: 1, set 1(v) {}",
2958 "get foo() {}, get foo() {}",
2959 "set foo(_) {}, set foo(v) {}",
2960 "foo: 1, get \"foo\"() {}",
2961 "foo: 1, set \"foo\"(v) {}",
2962 "\"foo\": 1, get foo() {}",
2963 "\"foo\": 1, set foo(v) {}",
2964 "1: 1, get \"1\"() {}",
2965 "1: 1, set \"1\"(v) {}",
2966 "\"1\": 1, get 1() {}",
2967 "\"1\": 1, set 1(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002968 "foo: 1, bar: 2",
2969 "\"foo\": 1, \"bar\": 2",
2970 "1: 1, 2: 2",
2971 // Syntax: IdentifierName ':' AssignmentExpression
2972 "foo: bar = 5 + baz",
2973 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2974 "get foo() {}",
2975 "get \"foo\"() {}",
2976 "get 1() {}",
2977 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2978 // '{' FunctionBody '}'
2979 "set foo(v) {}",
2980 "set \"foo\"(v) {}",
2981 "set 1(v) {}",
2982 // Non-colliding getters and setters -> no errors
2983 "foo: 1, get bar() {}",
2984 "foo: 1, set bar(v) {}",
2985 "\"foo\": 1, get \"bar\"() {}",
2986 "\"foo\": 1, set \"bar\"(v) {}",
2987 "1: 1, get 2() {}",
2988 "1: 1, set 2(v) {}",
2989 "get: 1, get foo() {}",
2990 "set: 1, set foo(_) {}",
2991 // Keywords, future reserved and strict future reserved are also allowed as
2992 // property names.
2993 "if: 4",
2994 "interface: 5",
2995 "super: 6",
2996 "eval: 7",
2997 "arguments: 8",
2998 NULL
2999 };
3000
3001 RunParserSyncTest(context_data, statement_data, kSuccess);
3002}
3003
3004
3005TEST(TooManyArguments) {
3006 const char* context_data[][2] = {
3007 {"foo(", "0)"},
3008 { NULL, NULL }
3009 };
3010
3011 using v8::internal::Code;
3012 char statement[Code::kMaxArguments * 2 + 1];
3013 for (int i = 0; i < Code::kMaxArguments; ++i) {
3014 statement[2 * i] = '0';
3015 statement[2 * i + 1] = ',';
3016 }
3017 statement[Code::kMaxArguments * 2] = 0;
3018
3019 const char* statement_data[] = {
3020 statement,
3021 NULL
3022 };
3023
3024 // The test is quite slow, so run it with a reduced set of flags.
3025 static const ParserFlag empty_flags[] = {kAllowLazy};
3026 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
3027}
3028
3029
3030TEST(StrictDelete) {
3031 // "delete <Identifier>" is not allowed in strict mode.
3032 const char* strict_context_data[][2] = {
3033 {"\"use strict\"; ", ""},
3034 { NULL, NULL }
3035 };
3036
3037 const char* sloppy_context_data[][2] = {
3038 {"", ""},
3039 { NULL, NULL }
3040 };
3041
3042 // These are errors in the strict mode.
3043 const char* sloppy_statement_data[] = {
3044 "delete foo;",
3045 "delete foo + 1;",
3046 "delete (foo);",
3047 "delete eval;",
3048 "delete interface;",
3049 NULL
3050 };
3051
3052 // These are always OK
3053 const char* good_statement_data[] = {
3054 "delete this;",
3055 "delete 1;",
3056 "delete 1 + 2;",
3057 "delete foo();",
3058 "delete foo.bar;",
3059 "delete foo[bar];",
3060 "delete foo--;",
3061 "delete --foo;",
3062 "delete new foo();",
3063 "delete new foo(bar);",
3064 NULL
3065 };
3066
3067 // These are always errors
3068 const char* bad_statement_data[] = {
3069 "delete if;",
3070 NULL
3071 };
3072
Ben Murdochda12d292016-06-02 14:46:10 +01003073 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
3074 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003075
Ben Murdochda12d292016-06-02 14:46:10 +01003076 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
3077 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003078
Ben Murdochda12d292016-06-02 14:46:10 +01003079 RunParserSyncTest(strict_context_data, bad_statement_data, kError);
3080 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003081}
3082
3083
3084TEST(NoErrorsDeclsInCase) {
3085 const char* context_data[][2] = {
3086 {"'use strict'; switch(x) { case 1:", "}"},
3087 {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3088 {"'use strict'; switch(x) { case 1: case 2:", "}"},
3089 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3090 {"'use strict'; switch(x) { default:", "}"},
3091 {"function foo() {'use strict'; switch(x) { default:", "}}"},
3092 {"'use strict'; switch(x) { case 1: default:", "}"},
3093 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3094 { nullptr, nullptr }
3095 };
3096
3097 const char* statement_data[] = {
3098 "function f() { }",
3099 "class C { }",
3100 "class C extends Q {}",
3101 "function f() { } class C {}",
3102 "function f() { }; class C {}",
3103 "class C {}; function f() {}",
3104 nullptr
3105 };
3106
3107 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003108}
3109
3110
3111TEST(InvalidLeftHandSide) {
3112 const char* assignment_context_data[][2] = {
3113 {"", " = 1;"},
3114 {"\"use strict\"; ", " = 1;"},
3115 { NULL, NULL }
3116 };
3117
3118 const char* prefix_context_data[][2] = {
3119 {"++", ";"},
3120 {"\"use strict\"; ++", ";"},
3121 {NULL, NULL},
3122 };
3123
3124 const char* postfix_context_data[][2] = {
3125 {"", "++;"},
3126 {"\"use strict\"; ", "++;"},
3127 { NULL, NULL }
3128 };
3129
3130 // Good left hand sides for assigment or prefix / postfix operations.
3131 const char* good_statement_data[] = {
3132 "foo",
3133 "foo.bar",
3134 "foo[bar]",
3135 "foo()[bar]",
3136 "foo().bar",
3137 "this.foo",
3138 "this[foo]",
3139 "new foo()[bar]",
3140 "new foo().bar",
3141 "foo()",
3142 "foo(bar)",
3143 "foo[bar]()",
3144 "foo.bar()",
3145 "this()",
3146 "this.foo()",
3147 "this[foo].bar()",
3148 "this.foo[foo].bar(this)(bar)[foo]()",
3149 NULL
3150 };
3151
3152 // Bad left hand sides for assigment or prefix / postfix operations.
3153 const char* bad_statement_data_common[] = {
3154 "2",
3155 "new foo",
3156 "new foo()",
3157 "null",
3158 "if", // Unexpected token
3159 "{x: 1}", // Unexpected token
3160 "this",
3161 "\"bar\"",
3162 "(foo + bar)",
3163 "new new foo()[bar]", // means: new (new foo()[bar])
3164 "new new foo().bar", // means: new (new foo()[bar])
3165 NULL
3166 };
3167
3168 // These are not okay for assignment, but okay for prefix / postix.
3169 const char* bad_statement_data_for_assignment[] = {
3170 "++foo",
3171 "foo++",
3172 "foo + bar",
3173 NULL
3174 };
3175
3176 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3177 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3178 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3179 kError);
3180
3181 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3182 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3183
3184 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3185 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3186}
3187
3188
3189TEST(FuncNameInferrerBasic) {
3190 // Tests that function names are inferred properly.
3191 i::FLAG_allow_natives_syntax = true;
3192 v8::Isolate* isolate = CcTest::isolate();
3193 v8::HandleScope scope(isolate);
3194 LocalContext env;
3195 CompileRun("var foo1 = function() {}; "
3196 "var foo2 = function foo3() {}; "
3197 "function not_ctor() { "
3198 " var foo4 = function() {}; "
3199 " return %FunctionGetInferredName(foo4); "
3200 "} "
3201 "function Ctor() { "
3202 " var foo5 = function() {}; "
3203 " return %FunctionGetInferredName(foo5); "
3204 "} "
3205 "var obj1 = { foo6: function() {} }; "
3206 "var obj2 = { 'foo7': function() {} }; "
3207 "var obj3 = {}; "
3208 "obj3[1] = function() {}; "
3209 "var obj4 = {}; "
3210 "obj4[1] = function foo8() {}; "
3211 "var obj5 = {}; "
3212 "obj5['foo9'] = function() {}; "
3213 "var obj6 = { obj7 : { foo10: function() {} } };");
3214 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3215 // foo2 is not unnamed -> its name is not inferred.
3216 ExpectString("%FunctionGetInferredName(foo2)", "");
3217 ExpectString("not_ctor()", "foo4");
3218 ExpectString("Ctor()", "Ctor.foo5");
3219 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3220 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3221 ExpectString("%FunctionGetInferredName(obj3[1])",
3222 "obj3.(anonymous function)");
3223 ExpectString("%FunctionGetInferredName(obj4[1])", "");
3224 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3225 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3226}
3227
3228
3229TEST(FuncNameInferrerTwoByte) {
3230 // Tests function name inferring in cases where some parts of the inferred
3231 // function name are two-byte strings.
3232 i::FLAG_allow_natives_syntax = true;
3233 v8::Isolate* isolate = CcTest::isolate();
3234 v8::HandleScope scope(isolate);
3235 LocalContext env;
3236 uint16_t* two_byte_source = AsciiToTwoByteString(
3237 "var obj1 = { oXj2 : { foo1: function() {} } }; "
3238 "%FunctionGetInferredName(obj1.oXj2.foo1)");
3239 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3240 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3241 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3242 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003243 v8::String::NewFromTwoByte(isolate, two_byte_source,
3244 v8::NewStringType::kNormal)
3245 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003246 v8::Local<v8::Value> result = CompileRun(source);
3247 CHECK(result->IsString());
3248 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003249 v8::String::NewFromTwoByte(isolate, two_byte_name,
3250 v8::NewStringType::kNormal)
3251 .ToLocalChecked();
3252 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003253 i::DeleteArray(two_byte_source);
3254 i::DeleteArray(two_byte_name);
3255}
3256
3257
3258TEST(FuncNameInferrerEscaped) {
3259 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3260 // character as a unicode escape.
3261 i::FLAG_allow_natives_syntax = true;
3262 v8::Isolate* isolate = CcTest::isolate();
3263 v8::HandleScope scope(isolate);
3264 LocalContext env;
3265 uint16_t* two_byte_source = AsciiToTwoByteString(
3266 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3267 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3268 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3269 // Fix to correspond to the non-ASCII name in two_byte_source.
3270 two_byte_name[6] = 0x010d;
3271 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003272 v8::String::NewFromTwoByte(isolate, two_byte_source,
3273 v8::NewStringType::kNormal)
3274 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003275 v8::Local<v8::Value> result = CompileRun(source);
3276 CHECK(result->IsString());
3277 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003278 v8::String::NewFromTwoByte(isolate, two_byte_name,
3279 v8::NewStringType::kNormal)
3280 .ToLocalChecked();
3281 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003282 i::DeleteArray(two_byte_source);
3283 i::DeleteArray(two_byte_name);
3284}
3285
3286
3287TEST(RegressionLazyFunctionWithErrorWithArg) {
Ben Murdochda12d292016-06-02 14:46:10 +01003288 // Test only applies when lazy parsing.
3289 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
3290
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003291 // The bug occurred when a lazy function had an error which requires a
3292 // parameter (such as "unknown label" here). The error message was processed
3293 // before the AstValueFactory containing the error message string was
3294 // internalized.
3295 v8::Isolate* isolate = CcTest::isolate();
3296 v8::HandleScope scope(isolate);
3297 LocalContext env;
3298 i::FLAG_lazy = true;
3299 i::FLAG_min_preparse_length = 0;
3300 CompileRun("function this_is_lazy() {\n"
3301 " break p;\n"
3302 "}\n"
3303 "this_is_lazy();\n");
3304}
3305
3306
3307TEST(SerializationOfMaybeAssignmentFlag) {
3308 i::Isolate* isolate = CcTest::i_isolate();
3309 i::Factory* factory = isolate->factory();
3310 i::HandleScope scope(isolate);
3311 LocalContext env;
3312
3313 const char* src =
3314 "function h() {"
3315 " var result = [];"
3316 " function f() {"
3317 " result.push(2);"
3318 " }"
3319 " function assertResult(r) {"
3320 " f();"
3321 " result = [];"
3322 " }"
3323 " assertResult([2]);"
3324 " assertResult([2]);"
3325 " return f;"
3326 "};"
3327 "h();";
3328
3329 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3330 i::SNPrintF(program, "%s", src);
3331 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3332 source->PrintOn(stdout);
3333 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003334 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003335 v8::Local<v8::Value> v = CompileRun(src);
3336 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3337 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3338 i::Context* context = f->context();
3339 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3340 avf.Internalize(isolate);
3341 const i::AstRawString* name = avf.GetOneByteString("result");
3342 i::Handle<i::String> str = name->string();
3343 CHECK(str->IsInternalizedString());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003344 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003345 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003346 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003347 i::Scope* s =
3348 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3349 CHECK(s != script_scope);
3350 CHECK(name != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351
3352 // Get result from h's function context (that is f's context)
3353 i::Variable* var = s->Lookup(name);
3354
3355 CHECK(var != NULL);
3356 // Maybe assigned should survive deserialization
3357 CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3358 // TODO(sigurds) Figure out if is_used should survive context serialization.
3359}
3360
3361
3362TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3363 i::Isolate* isolate = CcTest::i_isolate();
3364 i::Factory* factory = isolate->factory();
3365 i::HandleScope scope(isolate);
3366 LocalContext env;
3367
3368
3369 const char* src =
3370 "function f(x) {"
3371 " var a = arguments;"
3372 " function g(i) {"
3373 " ++a[0];"
3374 " };"
3375 " return g;"
3376 " }"
3377 "f(0);";
3378
3379 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3380 i::SNPrintF(program, "%s", src);
3381 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3382 source->PrintOn(stdout);
3383 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003384 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003385 v8::Local<v8::Value> v = CompileRun(src);
3386 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3387 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3388 i::Context* context = f->context();
3389 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3390 avf.Internalize(isolate);
3391
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003392 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003393 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003394 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003395 i::Scope* s =
3396 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3397 CHECK(s != script_scope);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003398 const i::AstRawString* name_x = avf.GetOneByteString("x");
3399
3400 // Get result from f's function context (that is g's outer context)
3401 i::Variable* var_x = s->Lookup(name_x);
3402 CHECK(var_x != NULL);
3403 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3404}
3405
3406
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003407TEST(InnerAssignment) {
3408 i::Isolate* isolate = CcTest::i_isolate();
3409 i::Factory* factory = isolate->factory();
3410 i::HandleScope scope(isolate);
3411 LocalContext env;
3412
3413 const char* prefix = "function f() {";
3414 const char* midfix = " function g() {";
3415 const char* suffix = "}}";
3416 struct { const char* source; bool assigned; bool strict; } outers[] = {
3417 // Actual assignments.
3418 { "var x; var x = 5;", true, false },
3419 { "var x; { var x = 5; }", true, false },
3420 { "'use strict'; let x; x = 6;", true, true },
3421 { "var x = 5; function x() {}", true, false },
3422 // Actual non-assignments.
3423 { "var x;", false, false },
3424 { "var x = 5;", false, false },
3425 { "'use strict'; let x;", false, true },
3426 { "'use strict'; let x = 6;", false, true },
3427 { "'use strict'; var x = 0; { let x = 6; }", false, true },
3428 { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3429 { "'use strict'; let x = 0; { let x = 6; }", false, true },
3430 { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3431 { "var x; try {} catch (x) { x = 5; }", false, false },
3432 { "function x() {}", false, false },
3433 // Eval approximation.
3434 { "var x; eval('');", true, false },
3435 { "eval(''); var x;", true, false },
3436 { "'use strict'; let x; eval('');", true, true },
3437 { "'use strict'; eval(''); let x;", true, true },
3438 // Non-assignments not recognized, because the analysis is approximative.
3439 { "var x; var x;", true, false },
3440 { "var x = 5; var x;", true, false },
3441 { "var x; { var x; }", true, false },
3442 { "var x; function x() {}", true, false },
3443 { "function x() {}; var x;", true, false },
3444 { "var x; try {} catch (x) { var x = 5; }", true, false },
3445 };
3446 struct { const char* source; bool assigned; bool with; } inners[] = {
3447 // Actual assignments.
3448 { "x = 1;", true, false },
3449 { "x++;", true, false },
3450 { "++x;", true, false },
3451 { "x--;", true, false },
3452 { "--x;", true, false },
3453 { "{ x = 1; }", true, false },
3454 { "'use strict'; { let x; }; x = 0;", true, false },
3455 { "'use strict'; { const x = 1; }; x = 0;", true, false },
3456 { "'use strict'; { function x() {} }; x = 0;", true, false },
3457 { "with ({}) { x = 1; }", true, true },
3458 { "eval('');", true, false },
3459 { "'use strict'; { let y; eval('') }", true, false },
3460 { "function h() { x = 0; }", true, false },
3461 { "(function() { x = 0; })", true, false },
3462 { "(function() { x = 0; })", true, false },
3463 { "with ({}) (function() { x = 0; })", true, true },
3464 // Actual non-assignments.
3465 { "", false, false },
3466 { "x;", false, false },
3467 { "var x;", false, false },
3468 { "var x = 8;", false, false },
3469 { "var x; x = 8;", false, false },
3470 { "'use strict'; let x;", false, false },
3471 { "'use strict'; let x = 8;", false, false },
3472 { "'use strict'; let x; x = 8;", false, false },
3473 { "'use strict'; const x = 8;", false, false },
3474 { "function x() {}", false, false },
3475 { "function x() { x = 0; }", false, false },
3476 { "function h(x) { x = 0; }", false, false },
3477 { "'use strict'; { let x; x = 0; }", false, false },
3478 { "{ var x; }; x = 0;", false, false },
3479 { "with ({}) {}", false, true },
3480 { "var x; { with ({}) { x = 1; } }", false, true },
3481 { "try {} catch(x) { x = 0; }", false, false },
3482 { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3483 // Eval approximation.
3484 { "eval('');", true, false },
3485 { "function h() { eval(''); }", true, false },
3486 { "(function() { eval(''); })", true, false },
3487 // Shadowing not recognized because of eval approximation.
3488 { "var x; eval('');", true, false },
3489 { "'use strict'; let x; eval('');", true, false },
3490 { "try {} catch(x) { eval(''); }", true, false },
3491 { "function x() { eval(''); }", true, false },
3492 { "(function(x) { eval(''); })", true, false },
3493 };
3494
3495 // Used to trigger lazy compilation of function
3496 int comment_len = 2048;
3497 i::ScopedVector<char> comment(comment_len + 1);
3498 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3499 int prefix_len = Utf8LengthHelper(prefix);
3500 int midfix_len = Utf8LengthHelper(midfix);
3501 int suffix_len = Utf8LengthHelper(suffix);
3502 for (unsigned i = 0; i < arraysize(outers); ++i) {
3503 const char* outer = outers[i].source;
3504 int outer_len = Utf8LengthHelper(outer);
3505 for (unsigned j = 0; j < arraysize(inners); ++j) {
3506 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3507 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3508 if (outers[i].strict && inners[j].with) continue;
3509 const char* inner = inners[j].source;
3510 int inner_len = Utf8LengthHelper(inner);
3511
3512 int outer_comment_len = outer_lazy ? comment_len : 0;
3513 int inner_comment_len = inner_lazy ? comment_len : 0;
3514 const char* outer_comment = outer_lazy ? comment.start() : "";
3515 const char* inner_comment = inner_lazy ? comment.start() : "";
3516 int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3517 inner_comment_len + inner_len + suffix_len;
3518 i::ScopedVector<char> program(len + 1);
3519
3520 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3521 midfix, inner_comment, inner, suffix);
3522 i::Handle<i::String> source =
3523 factory->InternalizeUtf8String(program.start());
3524 source->PrintOn(stdout);
3525 printf("\n");
3526
3527 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01003528 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003529 i::ParseInfo info(&zone, script);
3530 i::Parser parser(&info);
3531 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003532 CHECK(i::Compiler::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003533 CHECK(info.literal() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003535 i::Scope* scope = info.literal()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003536 CHECK_EQ(scope->inner_scopes()->length(), 1);
3537 i::Scope* inner_scope = scope->inner_scopes()->at(0);
3538 const i::AstRawString* var_name =
3539 info.ast_value_factory()->GetOneByteString("x");
3540 i::Variable* var = inner_scope->Lookup(var_name);
3541 bool expected = outers[i].assigned || inners[j].assigned;
3542 CHECK(var != NULL);
3543 CHECK(var->is_used() || !expected);
3544 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3545 }
3546 }
3547 }
3548 }
3549}
3550
3551namespace {
3552
3553int* global_use_counts = NULL;
3554
3555void MockUseCounterCallback(v8::Isolate* isolate,
3556 v8::Isolate::UseCounterFeature feature) {
3557 ++global_use_counts[feature];
3558}
3559
3560}
3561
3562
3563TEST(UseAsmUseCount) {
3564 i::Isolate* isolate = CcTest::i_isolate();
3565 i::HandleScope scope(isolate);
3566 LocalContext env;
3567 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3568 global_use_counts = use_counts;
3569 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3570 CompileRun("\"use asm\";\n"
3571 "var foo = 1;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003572 "function bar() { \"use asm\"; var baz = 1; }");
Ben Murdoch61f157c2016-09-16 13:49:30 +01003573 CHECK_LT(0, use_counts[v8::Isolate::kUseAsm]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003574}
3575
3576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003577TEST(StrictModeUseCount) {
3578 i::Isolate* isolate = CcTest::i_isolate();
3579 i::HandleScope scope(isolate);
3580 LocalContext env;
3581 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3582 global_use_counts = use_counts;
3583 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3584 CompileRun(
3585 "\"use strict\";\n"
3586 "function bar() { var baz = 1; }"); // strict mode inherits
3587 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3588 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
3589}
3590
3591
3592TEST(SloppyModeUseCount) {
3593 i::Isolate* isolate = CcTest::i_isolate();
3594 i::HandleScope scope(isolate);
3595 LocalContext env;
3596 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3597 global_use_counts = use_counts;
3598 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3599 CompileRun("function bar() { var baz = 1; }");
3600 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3601 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
3602}
3603
3604
3605TEST(BothModesUseCount) {
3606 i::Isolate* isolate = CcTest::i_isolate();
3607 i::HandleScope scope(isolate);
3608 LocalContext env;
3609 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3610 global_use_counts = use_counts;
3611 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3612 CompileRun("function bar() { 'use strict'; var baz = 1; }");
3613 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3614 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3615}
3616
3617
3618TEST(ErrorsArrowFormalParameters) {
3619 const char* context_data[][2] = {
3620 { "()", "=>{}" },
3621 { "()", "=>{};" },
3622 { "var x = ()", "=>{}" },
3623 { "var x = ()", "=>{};" },
3624
3625 { "a", "=>{}" },
3626 { "a", "=>{};" },
3627 { "var x = a", "=>{}" },
3628 { "var x = a", "=>{};" },
3629
3630 { "(a)", "=>{}" },
3631 { "(a)", "=>{};" },
3632 { "var x = (a)", "=>{}" },
3633 { "var x = (a)", "=>{};" },
3634
3635 { "(...a)", "=>{}" },
3636 { "(...a)", "=>{};" },
3637 { "var x = (...a)", "=>{}" },
3638 { "var x = (...a)", "=>{};" },
3639
3640 { "(a,b)", "=>{}" },
3641 { "(a,b)", "=>{};" },
3642 { "var x = (a,b)", "=>{}" },
3643 { "var x = (a,b)", "=>{};" },
3644
3645 { "(a,...b)", "=>{}" },
3646 { "(a,...b)", "=>{};" },
3647 { "var x = (a,...b)", "=>{}" },
3648 { "var x = (a,...b)", "=>{};" },
3649
3650 { nullptr, nullptr }
3651 };
3652 const char* assignment_expression_suffix_data[] = {
3653 "?c:d=>{}",
3654 "=c=>{}",
3655 "()",
3656 "(c)",
3657 "[1]",
3658 "[c]",
3659 ".c",
3660 "-c",
3661 "+c",
3662 "c++",
3663 "`c`",
3664 "`${c}`",
3665 "`template-head${c}`",
3666 "`${c}template-tail`",
3667 "`template-head${c}template-tail`",
3668 "`${c}template-tail`",
3669 nullptr
3670 };
3671
3672 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003673}
3674
3675
3676TEST(ErrorsArrowFunctions) {
3677 // Tests that parser and preparser generate the same kind of errors
3678 // on invalid arrow function syntax.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003679
3680 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003681 const char* context_data[][2] = {
3682 {"", ";"},
3683 {"v = ", ";"},
3684 {"bar ? (", ") : baz;"},
3685 {"bar ? baz : (", ");"},
3686 {"bar[", "];"},
3687 {"bar, ", ";"},
3688 {"", ", bar;"},
3689 {NULL, NULL}
3690 };
3691
3692 const char* statement_data[] = {
3693 "=> 0",
3694 "=>",
3695 "() =>",
3696 "=> {}",
3697 ") => {}",
3698 ", => {}",
3699 "(,) => {}",
3700 "return => {}",
3701 "() => {'value': 42}",
3702
3703 // Check that the early return introduced in ParsePrimaryExpression
3704 // does not accept stray closing parentheses.
3705 ")",
3706 ") => 0",
3707 "foo[()]",
3708 "()",
3709
3710 // Parameter lists with extra parens should be recognized as errors.
3711 "(()) => 0",
3712 "((x)) => 0",
3713 "((x, y)) => 0",
3714 "(x, (y)) => 0",
3715 "((x, y, z)) => 0",
3716 "(x, (y, z)) => 0",
3717 "((x, y), z) => 0",
3718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003719 // Arrow function formal parameters are parsed as StrictFormalParameters,
3720 // which confusingly only implies that there are no duplicates. Words
3721 // reserved in strict mode, and eval or arguments, are indeed valid in
3722 // sloppy mode.
3723 "eval => { 'use strict'; 0 }",
3724 "arguments => { 'use strict'; 0 }",
3725 "yield => { 'use strict'; 0 }",
3726 "interface => { 'use strict'; 0 }",
3727 "(eval) => { 'use strict'; 0 }",
3728 "(arguments) => { 'use strict'; 0 }",
3729 "(yield) => { 'use strict'; 0 }",
3730 "(interface) => { 'use strict'; 0 }",
3731 "(eval, bar) => { 'use strict'; 0 }",
3732 "(bar, eval) => { 'use strict'; 0 }",
3733 "(bar, arguments) => { 'use strict'; 0 }",
3734 "(bar, yield) => { 'use strict'; 0 }",
3735 "(bar, interface) => { 'use strict'; 0 }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003736 // TODO(aperez): Detecting duplicates does not work in PreParser.
3737 // "(bar, bar) => {}",
3738
3739 // The parameter list is parsed as an expression, but only
3740 // a comma-separated list of identifier is valid.
3741 "32 => {}",
3742 "(32) => {}",
3743 "(a, 32) => {}",
3744 "if => {}",
3745 "(if) => {}",
3746 "(a, if) => {}",
3747 "a + b => {}",
3748 "(a + b) => {}",
3749 "(a + b, c) => {}",
3750 "(a, b - c) => {}",
3751 "\"a\" => {}",
3752 "(\"a\") => {}",
3753 "(\"a\", b) => {}",
3754 "(a, \"b\") => {}",
3755 "-a => {}",
3756 "(-a) => {}",
3757 "(-a, b) => {}",
3758 "(a, -b) => {}",
3759 "{} => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003760 "a++ => {}",
3761 "(a++) => {}",
3762 "(a++, b) => {}",
3763 "(a, b++) => {}",
3764 "[] => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003765 "(foo ? bar : baz) => {}",
3766 "(a, foo ? bar : baz) => {}",
3767 "(foo ? bar : baz, a) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003768 "(a.b, c) => {}",
3769 "(c, a.b) => {}",
3770 "(a['b'], c) => {}",
3771 "(c, a['b']) => {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01003772
3773 // crbug.com/582626
3774 "(...rest - a) => b",
3775 "(a, ...b - 10) => b",
3776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003777 NULL
3778 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01003779 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003780
3781 // The test is quite slow, so run it with a reduced set of flags.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003782 static const ParserFlag flags[] = {kAllowLazy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003783 RunParserSyncTest(context_data, statement_data, kError, flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003784 arraysize(flags));
3785
3786 // In a context where a concise arrow body is parsed with [~In] variant,
3787 // ensure that an error is reported in both full parser and preparser.
3788 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3789 {nullptr, nullptr}};
3790 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
3791 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
3792 arraysize(flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003793}
3794
3795
3796TEST(NoErrorsArrowFunctions) {
3797 // Tests that parser and preparser accept valid arrow functions syntax.
Ben Murdochda12d292016-06-02 14:46:10 +01003798 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003799 const char* context_data[][2] = {
3800 {"", ";"},
3801 {"bar ? (", ") : baz;"},
3802 {"bar ? baz : (", ");"},
3803 {"bar, ", ";"},
3804 {"", ", bar;"},
3805 {NULL, NULL}
3806 };
3807
3808 const char* statement_data[] = {
3809 "() => {}",
3810 "() => { return 42 }",
3811 "x => { return x; }",
3812 "(x) => { return x; }",
3813 "(x, y) => { return x + y; }",
3814 "(x, y, z) => { return x + y + z; }",
3815 "(x, y) => { x.a = y; }",
3816 "() => 42",
3817 "x => x",
3818 "x => x * x",
3819 "(x) => x",
3820 "(x) => x * x",
3821 "(x, y) => x + y",
3822 "(x, y, z) => x, y, z",
3823 "(x, y) => x.a = y",
3824 "() => ({'value': 42})",
3825 "x => y => x + y",
3826 "(x, y) => (u, v) => x*u + y*v",
3827 "(x, y) => z => z * (x + y)",
3828 "x => (y, z) => z * (x + y)",
3829
3830 // Those are comma-separated expressions, with arrow functions as items.
3831 // They stress the code for validating arrow function parameter lists.
3832 "a, b => 0",
3833 "a, b, (c, d) => 0",
3834 "(a, b, (c, d) => 0)",
3835 "(a, b) => 0, (c, d) => 1",
3836 "(a, b => {}, a => a + 1)",
3837 "((a, b) => {}, (a => a + 1))",
3838 "(a, (a, (b, c) => 0))",
3839
3840 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3841 "foo ? bar : baz => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003842
3843 // Arrows with non-simple parameters.
Ben Murdochda12d292016-06-02 14:46:10 +01003844 "({}) => {}",
3845 "(a, {}) => {}",
3846 "({}, a) => {}",
3847 "([]) => {}",
3848 "(a, []) => {}",
3849 "([], a) => {}",
3850 "(a = b) => {}",
3851 "(a = b, c) => {}",
3852 "(a, b = c) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003853 "({a}) => {}",
3854 "(x = 9) => {}",
3855 "(x, y = 9) => {}",
3856 "(x = 9, y) => {}",
3857 "(x, y = 9, z) => {}",
3858 "(x, y = 9, z = 8) => {}",
3859 "(...a) => {}",
3860 "(x, ...a) => {}",
3861 "(x = 9, ...a) => {}",
3862 "(x, y = 9, ...a) => {}",
3863 "(x, y = 9, {b}, z = 8, ...a) => {}",
Ben Murdochda12d292016-06-02 14:46:10 +01003864 "({a} = {}) => {}",
3865 "([x] = []) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003866 "({a = 42}) => {}",
3867 "([x = 0]) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003868 NULL
3869 };
Ben Murdochda12d292016-06-02 14:46:10 +01003870 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003871
Ben Murdochda12d292016-06-02 14:46:10 +01003872 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003873
3874 static const ParserFlag flags[] = {kAllowLazy};
3875 // In a context where a concise arrow body is parsed with [~In] variant,
3876 // ensure that nested expressions can still use the 'in' operator,
3877 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3878 {nullptr, nullptr}};
3879 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
3880 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
3881 arraysize(flags));
3882}
3883
3884
3885TEST(ArrowFunctionsSloppyParameterNames) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003886 const char* strict_context_data[][2] = {
3887 {"'use strict'; ", ";"},
3888 {"'use strict'; bar ? (", ") : baz;"},
3889 {"'use strict'; bar ? baz : (", ");"},
3890 {"'use strict'; bar, ", ";"},
3891 {"'use strict'; ", ", bar;"},
3892 {NULL, NULL}
3893 };
3894
3895 const char* sloppy_context_data[][2] = {
3896 {"", ";"},
3897 {"bar ? (", ") : baz;"},
3898 {"bar ? baz : (", ");"},
3899 {"bar, ", ";"},
3900 {"", ", bar;"},
3901 {NULL, NULL}
3902 };
3903
3904 const char* statement_data[] = {
3905 "eval => {}",
3906 "arguments => {}",
3907 "yield => {}",
3908 "interface => {}",
3909 "(eval) => {}",
3910 "(arguments) => {}",
3911 "(yield) => {}",
3912 "(interface) => {}",
3913 "(eval, bar) => {}",
3914 "(bar, eval) => {}",
3915 "(bar, arguments) => {}",
3916 "(bar, yield) => {}",
3917 "(bar, interface) => {}",
3918 "(interface, eval) => {}",
3919 "(interface, arguments) => {}",
3920 "(eval, interface) => {}",
3921 "(arguments, interface) => {}",
3922 NULL
3923 };
3924
Ben Murdochda12d292016-06-02 14:46:10 +01003925 RunParserSyncTest(strict_context_data, statement_data, kError);
3926 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003927}
3928
3929
3930TEST(ArrowFunctionsYieldParameterNameInGenerator) {
3931 const char* sloppy_function_context_data[][2] = {
3932 {"(function f() { (", "); });"},
3933 {NULL, NULL}
3934 };
3935
3936 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003937 {"(function f() {'use strict'; (", "); });"},
3938 {NULL, NULL}
3939 };
3940
3941 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003942 {"(function *g() {'use strict'; (", "); });"},
3943 {"(function *g() { (", "); });"},
3944 {NULL, NULL}
3945 };
3946
3947 const char* arrow_data[] = {
3948 "yield => {}",
3949 "(yield) => {}",
3950 "(a, yield) => {}",
3951 "(yield, a) => {}",
3952 "(yield, ...a) => {}",
3953 "(a, ...yield) => {}",
3954 "({yield}) => {}",
3955 "([yield]) => {}",
3956 NULL
3957 };
3958
Ben Murdochda12d292016-06-02 14:46:10 +01003959 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
3960 RunParserSyncTest(strict_function_context_data, arrow_data, kError);
3961 RunParserSyncTest(generator_context_data, arrow_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003962}
3963
3964
3965TEST(SuperNoErrors) {
3966 // Tests that parser and preparser accept 'super' keyword in right places.
3967 const char* context_data[][2] = {
3968 {"class C { m() { ", "; } }"},
3969 {"class C { m() { k = ", "; } }"},
3970 {"class C { m() { foo(", "); } }"},
3971 {"class C { m() { () => ", "; } }"},
3972 {NULL, NULL}
3973 };
3974
3975 const char* statement_data[] = {
3976 "super.x",
3977 "super[27]",
3978 "new super.x",
3979 "new super.x()",
3980 "new super[27]",
3981 "new super[27]()",
3982 "z.super", // Ok, property lookup.
3983 NULL
3984 };
3985
Ben Murdochc5610432016-08-08 18:44:38 +01003986 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003987}
3988
3989
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003990TEST(SuperErrors) {
3991 const char* context_data[][2] = {
3992 {"class C { m() { ", "; } }"},
3993 {"class C { m() { k = ", "; } }"},
3994 {"class C { m() { foo(", "); } }"},
3995 {"class C { m() { () => ", "; } }"},
3996 {NULL, NULL}
3997 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003999 const char* expression_data[] = {
4000 "super",
4001 "super = x",
4002 "y = super",
4003 "f(super)",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004004 "new super",
4005 "new super()",
4006 "new super(12, 45)",
4007 "new new super",
4008 "new new super()",
4009 "new new super()()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004010 NULL
4011 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004012
Ben Murdochc5610432016-08-08 18:44:38 +01004013 RunParserSyncTest(context_data, expression_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004014}
4015
4016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004017TEST(SuperCall) {
4018 const char* context_data[][2] = {{"", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004019 {NULL, NULL}};
4020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004021 const char* success_data[] = {
4022 "class C extends B { constructor() { super(); } }",
4023 "class C extends B { constructor() { () => super(); } }",
4024 NULL
4025 };
4026
Ben Murdochc5610432016-08-08 18:44:38 +01004027 RunParserSyncTest(context_data, success_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004028
4029 const char* error_data[] = {
4030 "class C { constructor() { super(); } }",
4031 "class C { method() { super(); } }",
4032 "class C { method() { () => super(); } }",
4033 "class C { *method() { super(); } }",
4034 "class C { get x() { super(); } }",
4035 "class C { set x(_) { super(); } }",
4036 "({ method() { super(); } })",
4037 "({ *method() { super(); } })",
4038 "({ get x() { super(); } })",
4039 "({ set x(_) { super(); } })",
4040 "({ f: function() { super(); } })",
4041 "(function() { super(); })",
4042 "var f = function() { super(); }",
4043 "({ f: function*() { super(); } })",
4044 "(function*() { super(); })",
4045 "var f = function*() { super(); }",
4046 NULL
4047 };
4048
Ben Murdochc5610432016-08-08 18:44:38 +01004049 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004050}
4051
4052
4053TEST(SuperNewNoErrors) {
4054 const char* context_data[][2] = {
4055 {"class C { constructor() { ", " } }"},
4056 {"class C { *method() { ", " } }"},
4057 {"class C { get x() { ", " } }"},
4058 {"class C { set x(_) { ", " } }"},
4059 {"({ method() { ", " } })"},
4060 {"({ *method() { ", " } })"},
4061 {"({ get x() { ", " } })"},
4062 {"({ set x(_) { ", " } })"},
4063 {NULL, NULL}
4064 };
4065
4066 const char* expression_data[] = {
4067 "new super.x;",
4068 "new super.x();",
4069 "() => new super.x;",
4070 "() => new super.x();",
4071 NULL
4072 };
4073
Ben Murdochc5610432016-08-08 18:44:38 +01004074 RunParserSyncTest(context_data, expression_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004075}
4076
4077
4078TEST(SuperNewErrors) {
4079 const char* context_data[][2] = {
4080 {"class C { method() { ", " } }"},
4081 {"class C { *method() { ", " } }"},
4082 {"class C { get x() { ", " } }"},
4083 {"class C { set x(_) { ", " } }"},
4084 {"({ method() { ", " } })"},
4085 {"({ *method() { ", " } })"},
4086 {"({ get x() { ", " } })"},
4087 {"({ set x(_) { ", " } })"},
4088 {"({ f: function() { ", " } })"},
4089 {"(function() { ", " })"},
4090 {"var f = function() { ", " }"},
4091 {"({ f: function*() { ", " } })"},
4092 {"(function*() { ", " })"},
4093 {"var f = function*() { ", " }"},
4094 {NULL, NULL}
4095 };
4096
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004097 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004098 "new super;",
4099 "new super();",
4100 "() => new super;",
4101 "() => new super();",
4102 NULL
4103 };
4104
Ben Murdochc5610432016-08-08 18:44:38 +01004105 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004106}
4107
4108
4109TEST(SuperErrorsNonMethods) {
4110 // super is only allowed in methods, accessors and constructors.
4111 const char* context_data[][2] = {
4112 {"", ";"},
4113 {"k = ", ";"},
4114 {"foo(", ");"},
4115 {"if (", ") {}"},
4116 {"if (true) {", "}"},
4117 {"if (false) {} else {", "}"},
4118 {"while (true) {", "}"},
4119 {"function f() {", "}"},
4120 {"class C extends (", ") {}"},
4121 {"class C { m() { function f() {", "} } }"},
4122 {"({ m() { function f() {", "} } })"},
4123 {NULL, NULL}
4124 };
4125
4126 const char* statement_data[] = {
4127 "super",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004128 "super = x",
4129 "y = super",
4130 "f(super)",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004131 "super.x",
4132 "super[27]",
4133 "super.x()",
4134 "super[27]()",
4135 "super()",
4136 "new super.x",
4137 "new super.x()",
4138 "new super[27]",
4139 "new super[27]()",
4140 NULL
4141 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004142
Ben Murdochc5610432016-08-08 18:44:38 +01004143 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004144}
4145
4146
4147TEST(NoErrorsMethodDefinition) {
4148 const char* context_data[][2] = {{"({", "});"},
4149 {"'use strict'; ({", "});"},
4150 {"({*", "});"},
4151 {"'use strict'; ({*", "});"},
4152 {NULL, NULL}};
4153
4154 const char* object_literal_body_data[] = {
4155 "m() {}",
4156 "m(x) { return x; }",
4157 "m(x, y) {}, n() {}",
4158 "set(x, y) {}",
4159 "get(x, y) {}",
4160 NULL
4161 };
4162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004163 RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004164}
4165
4166
4167TEST(MethodDefinitionNames) {
4168 const char* context_data[][2] = {{"({", "(x, y) {}});"},
4169 {"'use strict'; ({", "(x, y) {}});"},
4170 {"({*", "(x, y) {}});"},
4171 {"'use strict'; ({*", "(x, y) {}});"},
4172 {NULL, NULL}};
4173
4174 const char* name_data[] = {
4175 "m",
4176 "'m'",
4177 "\"m\"",
4178 "\"m n\"",
4179 "true",
4180 "false",
4181 "null",
4182 "0",
4183 "1.2",
4184 "1e1",
4185 "1E1",
4186 "1e+1",
4187 "1e-1",
4188
4189 // Keywords
4190 "async",
4191 "await",
4192 "break",
4193 "case",
4194 "catch",
4195 "class",
4196 "const",
4197 "continue",
4198 "debugger",
4199 "default",
4200 "delete",
4201 "do",
4202 "else",
4203 "enum",
4204 "export",
4205 "extends",
4206 "finally",
4207 "for",
4208 "function",
4209 "if",
4210 "implements",
4211 "import",
4212 "in",
4213 "instanceof",
4214 "interface",
4215 "let",
4216 "new",
4217 "package",
4218 "private",
4219 "protected",
4220 "public",
4221 "return",
4222 "static",
4223 "super",
4224 "switch",
4225 "this",
4226 "throw",
4227 "try",
4228 "typeof",
4229 "var",
4230 "void",
4231 "while",
4232 "with",
4233 "yield",
4234 NULL
4235 };
4236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004237 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004238}
4239
4240
4241TEST(MethodDefinitionStrictFormalParamereters) {
4242 const char* context_data[][2] = {{"({method(", "){}});"},
4243 {"'use strict'; ({method(", "){}});"},
4244 {"({*method(", "){}});"},
4245 {"'use strict'; ({*method(", "){}});"},
4246 {NULL, NULL}};
4247
4248 const char* params_data[] = {
4249 "x, x",
4250 "x, y, x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004251 "var",
4252 "const",
4253 NULL
4254 };
4255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004256 RunParserSyncTest(context_data, params_data, kError);
4257}
4258
4259
4260TEST(MethodDefinitionEvalArguments) {
4261 const char* strict_context_data[][2] =
4262 {{"'use strict'; ({method(", "){}});"},
4263 {"'use strict'; ({*method(", "){}});"},
4264 {NULL, NULL}};
4265 const char* sloppy_context_data[][2] =
4266 {{"({method(", "){}});"},
4267 {"({*method(", "){}});"},
4268 {NULL, NULL}};
4269
4270 const char* data[] = {
4271 "eval",
4272 "arguments",
4273 NULL};
4274
4275 // Fail in strict mode
4276 RunParserSyncTest(strict_context_data, data, kError);
4277
4278 // OK in sloppy mode
4279 RunParserSyncTest(sloppy_context_data, data, kSuccess);
4280}
4281
4282
4283TEST(MethodDefinitionDuplicateEvalArguments) {
4284 const char* context_data[][2] =
4285 {{"'use strict'; ({method(", "){}});"},
4286 {"'use strict'; ({*method(", "){}});"},
4287 {"({method(", "){}});"},
4288 {"({*method(", "){}});"},
4289 {NULL, NULL}};
4290
4291 const char* data[] = {
4292 "eval, eval",
4293 "eval, a, eval",
4294 "arguments, arguments",
4295 "arguments, a, arguments",
4296 NULL};
4297
4298 // In strict mode, the error is using "eval" or "arguments" as parameter names
4299 // In sloppy mode, the error is that eval / arguments are duplicated
4300 RunParserSyncTest(context_data, data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004301}
4302
4303
4304TEST(MethodDefinitionDuplicateProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004305 const char* context_data[][2] = {{"'use strict'; ({", "});"},
4306 {NULL, NULL}};
4307
4308 const char* params_data[] = {
4309 "x: 1, x() {}",
4310 "x() {}, x: 1",
4311 "x() {}, get x() {}",
4312 "x() {}, set x(_) {}",
4313 "x() {}, x() {}",
4314 "x() {}, y() {}, x() {}",
4315 "x() {}, \"x\"() {}",
4316 "x() {}, 'x'() {}",
4317 "0() {}, '0'() {}",
4318 "1.0() {}, 1: 1",
4319
4320 "x: 1, *x() {}",
4321 "*x() {}, x: 1",
4322 "*x() {}, get x() {}",
4323 "*x() {}, set x(_) {}",
4324 "*x() {}, *x() {}",
4325 "*x() {}, y() {}, *x() {}",
4326 "*x() {}, *\"x\"() {}",
4327 "*x() {}, *'x'() {}",
4328 "*0() {}, *'0'() {}",
4329 "*1.0() {}, 1: 1",
4330
4331 NULL
4332 };
4333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004334 RunParserSyncTest(context_data, params_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004335}
4336
4337
4338TEST(ClassExpressionNoErrors) {
4339 const char* context_data[][2] = {{"(", ");"},
4340 {"var C = ", ";"},
4341 {"bar, ", ";"},
4342 {NULL, NULL}};
4343 const char* class_data[] = {
4344 "class {}",
4345 "class name {}",
4346 "class extends F {}",
4347 "class name extends F {}",
4348 "class extends (F, G) {}",
4349 "class name extends (F, G) {}",
4350 "class extends class {} {}",
4351 "class name extends class {} {}",
4352 "class extends class base {} {}",
4353 "class name extends class base {} {}",
4354 NULL};
4355
Ben Murdochc5610432016-08-08 18:44:38 +01004356 RunParserSyncTest(context_data, class_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004357}
4358
4359
4360TEST(ClassDeclarationNoErrors) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004361 const char* context_data[][2] = {{"'use strict'; ", ""},
4362 {"'use strict'; {", "}"},
4363 {"'use strict'; if (true) {", "}"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004364 {NULL, NULL}};
4365 const char* statement_data[] = {
4366 "class name {}",
4367 "class name extends F {}",
4368 "class name extends (F, G) {}",
4369 "class name extends class {} {}",
4370 "class name extends class base {} {}",
4371 NULL};
4372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004373 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004374}
4375
4376
4377TEST(ClassBodyNoErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004378 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004379 // Tests that parser and preparser accept valid class syntax.
4380 const char* context_data[][2] = {{"(class {", "});"},
4381 {"(class extends Base {", "});"},
4382 {"class C {", "}"},
4383 {"class C extends Base {", "}"},
4384 {NULL, NULL}};
4385 const char* class_body_data[] = {
4386 ";",
4387 ";;",
4388 "m() {}",
4389 "m() {};",
4390 "; m() {}",
4391 "m() {}; n(x) {}",
4392 "get x() {}",
4393 "set x(v) {}",
4394 "get() {}",
4395 "set() {}",
4396 "*g() {}",
4397 "*g() {};",
4398 "; *g() {}",
4399 "*g() {}; *h(x) {}",
4400 "static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004401 "get static() {}",
4402 "set static(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004403 "static m() {}",
4404 "static get x() {}",
4405 "static set x(v) {}",
4406 "static get() {}",
4407 "static set() {}",
4408 "static static() {}",
4409 "static get static() {}",
4410 "static set static(v) {}",
4411 "*static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004412 "static *static() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004413 "*get() {}",
4414 "*set() {}",
4415 "static *g() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004416
4417 // Escaped 'static' should be allowed anywhere
4418 // static-as-PropertyName is.
4419 "st\\u0061tic() {}",
4420 "get st\\u0061tic() {}",
4421 "set st\\u0061tic(v) {}",
4422 "static st\\u0061tic() {}",
4423 "static get st\\u0061tic() {}",
4424 "static set st\\u0061tic(v) {}",
4425 "*st\\u0061tic() {}",
4426 "static *st\\u0061tic() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004427 NULL};
Ben Murdoch097c5b22016-05-18 11:27:45 +01004428 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004429
Ben Murdochc5610432016-08-08 18:44:38 +01004430 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004431}
4432
4433
4434TEST(ClassPropertyNameNoErrors) {
4435 const char* context_data[][2] = {{"(class {", "() {}});"},
4436 {"(class { get ", "() {}});"},
4437 {"(class { set ", "(v) {}});"},
4438 {"(class { static ", "() {}});"},
4439 {"(class { static get ", "() {}});"},
4440 {"(class { static set ", "(v) {}});"},
4441 {"(class { *", "() {}});"},
4442 {"(class { static *", "() {}});"},
4443 {"class C {", "() {}}"},
4444 {"class C { get ", "() {}}"},
4445 {"class C { set ", "(v) {}}"},
4446 {"class C { static ", "() {}}"},
4447 {"class C { static get ", "() {}}"},
4448 {"class C { static set ", "(v) {}}"},
4449 {"class C { *", "() {}}"},
4450 {"class C { static *", "() {}}"},
4451 {NULL, NULL}};
4452 const char* name_data[] = {
4453 "42",
4454 "42.5",
4455 "42e2",
4456 "42e+2",
4457 "42e-2",
4458 "null",
4459 "false",
4460 "true",
4461 "'str'",
4462 "\"str\"",
4463 "static",
4464 "get",
4465 "set",
4466 "var",
4467 "const",
4468 "let",
4469 "this",
4470 "class",
4471 "function",
4472 "yield",
4473 "if",
4474 "else",
4475 "for",
4476 "while",
4477 "do",
4478 "try",
4479 "catch",
4480 "finally",
4481 NULL};
4482
Ben Murdochc5610432016-08-08 18:44:38 +01004483 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004484}
4485
4486
4487TEST(ClassExpressionErrors) {
4488 const char* context_data[][2] = {{"(", ");"},
4489 {"var C = ", ";"},
4490 {"bar, ", ";"},
4491 {NULL, NULL}};
4492 const char* class_data[] = {
4493 "class",
4494 "class name",
4495 "class name extends",
4496 "class extends",
4497 "class {",
4498 "class { m }",
4499 "class { m; n }",
4500 "class { m: 1 }",
4501 "class { m(); n() }",
4502 "class { get m }",
4503 "class { get m() }",
4504 "class { get m() { }",
4505 "class { set m() {} }", // Missing required parameter.
4506 "class { m() {}, n() {} }", // No commas allowed.
4507 NULL};
4508
Ben Murdochc5610432016-08-08 18:44:38 +01004509 RunParserSyncTest(context_data, class_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004510}
4511
4512
4513TEST(ClassDeclarationErrors) {
4514 const char* context_data[][2] = {{"", ""},
4515 {"{", "}"},
4516 {"if (true) {", "}"},
4517 {NULL, NULL}};
4518 const char* class_data[] = {
4519 "class",
4520 "class name",
4521 "class name extends",
4522 "class extends",
4523 "class name {",
4524 "class name { m }",
4525 "class name { m; n }",
4526 "class name { m: 1 }",
4527 "class name { m(); n() }",
4528 "class name { get x }",
4529 "class name { get x() }",
4530 "class name { set x() {) }", // missing required param
4531 "class {}", // Name is required for declaration
4532 "class extends base {}",
4533 "class name { *",
4534 "class name { * }",
4535 "class name { *; }",
4536 "class name { *get x() {} }",
4537 "class name { *set x(_) {} }",
4538 "class name { *static m() {} }",
4539 NULL};
4540
Ben Murdochc5610432016-08-08 18:44:38 +01004541 RunParserSyncTest(context_data, class_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004542}
4543
4544
4545TEST(ClassNameErrors) {
4546 const char* context_data[][2] = {{"class ", "{}"},
4547 {"(class ", "{});"},
4548 {"'use strict'; class ", "{}"},
4549 {"'use strict'; (class ", "{});"},
4550 {NULL, NULL}};
4551 const char* class_name[] = {
4552 "arguments",
4553 "eval",
4554 "implements",
4555 "interface",
4556 "let",
4557 "package",
4558 "private",
4559 "protected",
4560 "public",
4561 "static",
4562 "var",
4563 "yield",
4564 NULL};
4565
Ben Murdochc5610432016-08-08 18:44:38 +01004566 RunParserSyncTest(context_data, class_name, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004567}
4568
4569
4570TEST(ClassGetterParamNameErrors) {
4571 const char* context_data[][2] = {
4572 {"class C { get name(", ") {} }"},
4573 {"(class { get name(", ") {} });"},
4574 {"'use strict'; class C { get name(", ") {} }"},
4575 {"'use strict'; (class { get name(", ") {} })"},
4576 {NULL, NULL}
4577 };
4578
4579 const char* class_name[] = {
4580 "arguments",
4581 "eval",
4582 "implements",
4583 "interface",
4584 "let",
4585 "package",
4586 "private",
4587 "protected",
4588 "public",
4589 "static",
4590 "var",
4591 "yield",
4592 NULL};
4593
Ben Murdochc5610432016-08-08 18:44:38 +01004594 RunParserSyncTest(context_data, class_name, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004595}
4596
4597
4598TEST(ClassStaticPrototypeErrors) {
4599 const char* context_data[][2] = {{"class C {", "}"},
4600 {"(class {", "});"},
4601 {NULL, NULL}};
4602
4603 const char* class_body_data[] = {
4604 "static prototype() {}",
4605 "static get prototype() {}",
4606 "static set prototype(_) {}",
4607 "static *prototype() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004608 "static 'prototype'() {}",
4609 "static *'prototype'() {}",
4610 "static prot\\u006ftype() {}",
4611 "static 'prot\\u006ftype'() {}",
4612 "static get 'prot\\u006ftype'() {}",
4613 "static set 'prot\\u006ftype'(_) {}",
4614 "static *'prot\\u006ftype'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004615 NULL};
4616
Ben Murdochc5610432016-08-08 18:44:38 +01004617 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004618}
4619
4620
4621TEST(ClassSpecialConstructorErrors) {
4622 const char* context_data[][2] = {{"class C {", "}"},
4623 {"(class {", "});"},
4624 {NULL, NULL}};
4625
4626 const char* class_body_data[] = {
4627 "get constructor() {}",
4628 "get constructor(_) {}",
4629 "*constructor() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004630 "get 'constructor'() {}",
4631 "*'constructor'() {}",
4632 "get c\\u006fnstructor() {}",
4633 "*c\\u006fnstructor() {}",
4634 "get 'c\\u006fnstructor'() {}",
4635 "get 'c\\u006fnstructor'(_) {}",
4636 "*'c\\u006fnstructor'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004637 NULL};
4638
Ben Murdochc5610432016-08-08 18:44:38 +01004639 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004640}
4641
4642
4643TEST(ClassConstructorNoErrors) {
4644 const char* context_data[][2] = {{"class C {", "}"},
4645 {"(class {", "});"},
4646 {NULL, NULL}};
4647
4648 const char* class_body_data[] = {
4649 "constructor() {}",
4650 "static constructor() {}",
4651 "static get constructor() {}",
4652 "static set constructor(_) {}",
4653 "static *constructor() {}",
4654 NULL};
4655
Ben Murdochc5610432016-08-08 18:44:38 +01004656 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004657}
4658
4659
4660TEST(ClassMultipleConstructorErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004661 const char* context_data[][2] = {{"class C {", "}"},
4662 {"(class {", "});"},
4663 {NULL, NULL}};
4664
4665 const char* class_body_data[] = {
4666 "constructor() {}; constructor() {}",
4667 NULL};
4668
Ben Murdochc5610432016-08-08 18:44:38 +01004669 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004670}
4671
4672
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004673TEST(ClassMultiplePropertyNamesNoErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004674 const char* context_data[][2] = {{"class C {", "}"},
4675 {"(class {", "});"},
4676 {NULL, NULL}};
4677
4678 const char* class_body_data[] = {
4679 "constructor() {}; static constructor() {}",
4680 "m() {}; static m() {}",
4681 "m() {}; m() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004682 "static m() {}; static m() {}",
4683 "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004684 NULL};
4685
Ben Murdochc5610432016-08-08 18:44:38 +01004686 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004687}
4688
4689
4690TEST(ClassesAreStrictErrors) {
4691 const char* context_data[][2] = {{"", ""},
4692 {"(", ");"},
4693 {NULL, NULL}};
4694
4695 const char* class_body_data[] = {
4696 "class C { method() { with ({}) {} } }",
4697 "class C extends function() { with ({}) {} } {}",
4698 "class C { *method() { with ({}) {} } }",
4699 NULL};
4700
Ben Murdochc5610432016-08-08 18:44:38 +01004701 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdoch692be652012-01-10 18:47:50 +00004702}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004703
4704
4705TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4706 const char* context_data[][2] = {{"({", "});"},
4707 {"'use strict'; ({", "});"},
4708 {NULL, NULL}};
4709
4710 const char* name_data[] = {
4711 "break",
4712 "case",
4713 "catch",
4714 "class",
4715 "const",
4716 "continue",
4717 "debugger",
4718 "default",
4719 "delete",
4720 "do",
4721 "else",
4722 "enum",
4723 "export",
4724 "extends",
4725 "false",
4726 "finally",
4727 "for",
4728 "function",
4729 "if",
4730 "import",
4731 "in",
4732 "instanceof",
4733 "new",
4734 "null",
4735 "return",
4736 "super",
4737 "switch",
4738 "this",
4739 "throw",
4740 "true",
4741 "try",
4742 "typeof",
4743 "var",
4744 "void",
4745 "while",
4746 "with",
4747 NULL
4748 };
4749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004750 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004751}
4752
4753
4754TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4755 const char* context_data[][2] = {{"({", "});"},
4756 {NULL, NULL}};
4757
4758 const char* name_data[] = {
4759 "implements",
4760 "interface",
4761 "let",
4762 "package",
4763 "private",
4764 "protected",
4765 "public",
4766 "static",
4767 "yield",
4768 NULL
4769 };
4770
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004771 RunParserSyncTest(context_data, name_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004772
4773 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4774 {NULL, NULL}};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004775 RunParserSyncTest(context_strict_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004776}
4777
4778
4779TEST(ObjectLiteralPropertyShorthandError) {
4780 const char* context_data[][2] = {{"({", "});"},
4781 {"'use strict'; ({", "});"},
4782 {NULL, NULL}};
4783
4784 const char* name_data[] = {
4785 "1",
4786 "1.2",
4787 "0",
4788 "0.1",
4789 "1.0",
4790 "1e1",
4791 "0x1",
4792 "\"s\"",
4793 "'s'",
4794 NULL
4795 };
4796
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004797 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004798}
4799
4800
4801TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4802 const char* context_data[][2] = {{"", ""},
4803 {NULL, NULL}};
4804
4805 const char* name_data[] = {
4806 "function* g() { ({yield}); }",
4807 NULL
4808 };
4809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004810 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004811}
4812
4813
4814TEST(ConstParsingInForIn) {
4815 const char* context_data[][2] = {{"'use strict';", ""},
4816 {"function foo(){ 'use strict';", "}"},
4817 {NULL, NULL}};
4818
4819 const char* data[] = {
4820 "for(const x = 1; ; ) {}",
4821 "for(const x = 1, y = 2;;){}",
4822 "for(const x in [1,2,3]) {}",
4823 "for(const x of [1,2,3]) {}",
4824 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004825 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004826}
4827
4828
Ben Murdoch097c5b22016-05-18 11:27:45 +01004829TEST(StatementParsingInForIn) {
4830 const char* context_data[][2] = {{"", ""},
4831 {"'use strict';", ""},
4832 {"function foo(){ 'use strict';", "}"},
4833 {NULL, NULL}};
4834
4835 const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
4836 "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
4837 NULL};
4838
Ben Murdochc5610432016-08-08 18:44:38 +01004839 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004840}
4841
4842
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004843TEST(ConstParsingInForInError) {
4844 const char* context_data[][2] = {{"'use strict';", ""},
4845 {"function foo(){ 'use strict';", "}"},
4846 {NULL, NULL}};
4847
4848 const char* data[] = {
4849 "for(const x,y = 1; ; ) {}",
4850 "for(const x = 4 in [1,2,3]) {}",
4851 "for(const x = 4, y in [1,2,3]) {}",
4852 "for(const x = 4 of [1,2,3]) {}",
4853 "for(const x = 4, y of [1,2,3]) {}",
4854 "for(const x = 1, y = 2 in []) {}",
4855 "for(const x,y in []) {}",
4856 "for(const x = 1, y = 2 of []) {}",
4857 "for(const x,y of []) {}",
4858 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004859 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
4860}
4861
4862
4863TEST(InitializedDeclarationsInStrictForInError) {
4864 const char* context_data[][2] = {{"'use strict';", ""},
4865 {"function foo(){ 'use strict';", "}"},
4866 {NULL, NULL}};
4867
4868 const char* data[] = {
4869 "for (var i = 1 in {}) {}",
4870 "for (var i = void 0 in [1, 2, 3]) {}",
4871 "for (let i = 1 in {}) {}",
4872 "for (let i = void 0 in [1, 2, 3]) {}",
4873 "for (const i = 1 in {}) {}",
4874 "for (const i = void 0 in [1, 2, 3]) {}",
4875 NULL};
4876 RunParserSyncTest(context_data, data, kError);
4877}
4878
4879
4880TEST(InitializedDeclarationsInStrictForOfError) {
4881 const char* context_data[][2] = {{"'use strict';", ""},
4882 {"function foo(){ 'use strict';", "}"},
4883 {NULL, NULL}};
4884
4885 const char* data[] = {
4886 "for (var i = 1 of {}) {}",
4887 "for (var i = void 0 of [1, 2, 3]) {}",
4888 "for (let i = 1 of {}) {}",
4889 "for (let i = void 0 of [1, 2, 3]) {}",
4890 "for (const i = 1 of {}) {}",
4891 "for (const i = void 0 of [1, 2, 3]) {}",
4892 NULL};
4893 RunParserSyncTest(context_data, data, kError);
4894}
4895
4896
4897TEST(InitializedDeclarationsInSloppyForInError) {
4898 const char* context_data[][2] = {{"", ""},
4899 {"function foo(){", "}"},
4900 {NULL, NULL}};
4901
4902 const char* data[] = {
4903 "for (var i = 1 in {}) {}",
4904 "for (var i = void 0 in [1, 2, 3]) {}",
4905 NULL};
4906 // TODO(caitp): This should be an error in sloppy mode.
4907 RunParserSyncTest(context_data, data, kSuccess);
4908}
4909
4910
4911TEST(InitializedDeclarationsInSloppyForOfError) {
4912 const char* context_data[][2] = {{"", ""},
4913 {"function foo(){", "}"},
4914 {NULL, NULL}};
4915
4916 const char* data[] = {
4917 "for (var i = 1 of {}) {}",
4918 "for (var i = void 0 of [1, 2, 3]) {}",
4919 NULL};
4920 RunParserSyncTest(context_data, data, kError);
4921}
4922
4923
4924TEST(ForInMultipleDeclarationsError) {
4925 const char* context_data[][2] = {{"", ""},
4926 {"function foo(){", "}"},
4927 {"'use strict';", ""},
4928 {"function foo(){ 'use strict';", "}"},
4929 {NULL, NULL}};
4930
4931 const char* data[] = {
4932 "for (var i, j in {}) {}",
4933 "for (var i, j in [1, 2, 3]) {}",
4934 "for (var i, j = 1 in {}) {}",
4935 "for (var i, j = void 0 in [1, 2, 3]) {}",
4936
4937 "for (let i, j in {}) {}",
4938 "for (let i, j in [1, 2, 3]) {}",
4939 "for (let i, j = 1 in {}) {}",
4940 "for (let i, j = void 0 in [1, 2, 3]) {}",
4941
4942 "for (const i, j in {}) {}",
4943 "for (const i, j in [1, 2, 3]) {}",
4944 "for (const i, j = 1 in {}) {}",
4945 "for (const i, j = void 0 in [1, 2, 3]) {}",
4946 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004947 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004948}
4949
4950
4951TEST(ForOfMultipleDeclarationsError) {
4952 const char* context_data[][2] = {{"", ""},
4953 {"function foo(){", "}"},
4954 {"'use strict';", ""},
4955 {"function foo(){ 'use strict';", "}"},
4956 {NULL, NULL}};
4957
4958 const char* data[] = {
4959 "for (var i, j of {}) {}",
4960 "for (var i, j of [1, 2, 3]) {}",
4961 "for (var i, j = 1 of {}) {}",
4962 "for (var i, j = void 0 of [1, 2, 3]) {}",
4963
4964 "for (let i, j of {}) {}",
4965 "for (let i, j of [1, 2, 3]) {}",
4966 "for (let i, j = 1 of {}) {}",
4967 "for (let i, j = void 0 of [1, 2, 3]) {}",
4968
4969 "for (const i, j of {}) {}",
4970 "for (const i, j of [1, 2, 3]) {}",
4971 "for (const i, j = 1 of {}) {}",
4972 "for (const i, j = void 0 of [1, 2, 3]) {}",
4973 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004974 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004975}
4976
4977
4978TEST(ForInNoDeclarationsError) {
4979 const char* context_data[][2] = {{"", ""},
4980 {"function foo(){", "}"},
4981 {"'use strict';", ""},
4982 {"function foo(){ 'use strict';", "}"},
4983 {NULL, NULL}};
4984
4985 const char* data[] = {
4986 "for (var in {}) {}",
4987 "for (const in {}) {}",
4988 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004989 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004990}
4991
4992
4993TEST(ForOfNoDeclarationsError) {
4994 const char* context_data[][2] = {{"", ""},
4995 {"function foo(){", "}"},
4996 {"'use strict';", ""},
4997 {"function foo(){ 'use strict';", "}"},
4998 {NULL, NULL}};
4999
5000 const char* data[] = {
5001 "for (var of [1, 2, 3]) {}",
5002 "for (const of [1, 2, 3]) {}",
5003 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005004 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005005}
5006
5007
Ben Murdoch097c5b22016-05-18 11:27:45 +01005008TEST(ForOfInOperator) {
5009 const char* context_data[][2] = {{"", ""},
5010 {"'use strict';", ""},
5011 {"function foo(){ 'use strict';", "}"},
5012 {NULL, NULL}};
5013
5014 const char* data[] = {
5015 "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
5016 "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
5017
Ben Murdochc5610432016-08-08 18:44:38 +01005018 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005019}
5020
5021
5022TEST(ForOfYieldIdentifier) {
5023 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5024
5025 const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
5026 "for(let x of yield) {}", "for(const x of yield) {}",
5027 NULL};
5028
Ben Murdochc5610432016-08-08 18:44:38 +01005029 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005030}
5031
5032
5033TEST(ForOfYieldExpression) {
5034 const char* context_data[][2] = {{"", ""},
5035 {"'use strict';", ""},
5036 {"function foo(){ 'use strict';", "}"},
5037 {NULL, NULL}};
5038
5039 const char* data[] = {"function* g() { for(x of yield) {} }",
5040 "function* g() { for(var x of yield) {} }",
5041 "function* g() { for(let x of yield) {} }",
5042 "function* g() { for(const x of yield) {} }", NULL};
5043
Ben Murdochc5610432016-08-08 18:44:38 +01005044 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005045}
5046
5047
5048TEST(ForOfExpressionError) {
5049 const char* context_data[][2] = {{"", ""},
5050 {"'use strict';", ""},
5051 {"function foo(){ 'use strict';", "}"},
5052 {NULL, NULL}};
5053
5054 const char* data[] = {
5055 "for(x of [], []) {}", "for(var x of [], []) {}",
5056 "for(let x of [], []) {}", "for(const x of [], []) {}",
5057
5058 // AssignmentExpression should be validated statically:
5059 "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
5060 "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
5061
Ben Murdochc5610432016-08-08 18:44:38 +01005062 RunParserSyncTest(context_data, data, kError);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005063}
5064
5065
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005066TEST(InvalidUnicodeEscapes) {
5067 const char* context_data[][2] = {{"", ""},
5068 {"'use strict';", ""},
5069 {NULL, NULL}};
5070 const char* data[] = {
5071 "var foob\\u123r = 0;",
5072 "var \\u123roo = 0;",
5073 "\"foob\\u123rr\"",
5074 // No escapes allowed in regexp flags
5075 "/regex/\\u0069g",
5076 "/regex/\\u006g",
5077 // Braces gone wrong
5078 "var foob\\u{c481r = 0;",
5079 "var foob\\uc481}r = 0;",
5080 "var \\u{0052oo = 0;",
5081 "var \\u0052}oo = 0;",
5082 "\"foob\\u{c481r\"",
5083 "var foob\\u{}ar = 0;",
5084 // Too high value for the unicode escape
5085 "\"\\u{110000}\"",
5086 // Not an unicode escape
5087 "var foob\\v1234r = 0;",
5088 "var foob\\U1234r = 0;",
5089 "var foob\\v{1234}r = 0;",
5090 "var foob\\U{1234}r = 0;",
5091 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005092 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005093}
5094
5095
5096TEST(UnicodeEscapes) {
5097 const char* context_data[][2] = {{"", ""},
5098 {"'use strict';", ""},
5099 {NULL, NULL}};
5100 const char* data[] = {
5101 // Identifier starting with escape
5102 "var \\u0052oo = 0;",
5103 "var \\u{0052}oo = 0;",
5104 "var \\u{52}oo = 0;",
5105 "var \\u{00000000052}oo = 0;",
5106 // Identifier with an escape but not starting with an escape
5107 "var foob\\uc481r = 0;",
5108 "var foob\\u{c481}r = 0;",
5109 // String with an escape
5110 "\"foob\\uc481r\"",
5111 "\"foob\\{uc481}r\"",
5112 // This character is a valid unicode character, representable as a surrogate
5113 // pair, not representable as 4 hex digits.
5114 "\"foo\\u{10e6d}\"",
5115 // Max value for the unicode escape
5116 "\"\\u{10ffff}\"",
5117 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005118 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005119}
5120
5121
5122TEST(ScanTemplateLiterals) {
5123 const char* context_data[][2] = {{"'use strict';", ""},
5124 {"function foo(){ 'use strict';"
5125 " var a, b, c; return ", "}"},
5126 {NULL, NULL}};
5127
5128 const char* data[] = {
5129 "``",
5130 "`no-subst-template`",
5131 "`template-head${a}`",
5132 "`${a}`",
5133 "`${a}template-tail`",
5134 "`template-head${a}template-tail`",
5135 "`${a}${b}${c}`",
5136 "`a${a}b${b}c${c}`",
5137 "`${a}a${b}b${c}c`",
5138 "`foo\n\nbar\r\nbaz`",
5139 "`foo\n\n${ bar }\r\nbaz`",
5140 "`foo${a /* comment */}`",
5141 "`foo${a // comment\n}`",
5142 "`foo${a \n}`",
5143 "`foo${a \r\n}`",
5144 "`foo${a \r}`",
5145 "`foo${/* comment */ a}`",
5146 "`foo${// comment\na}`",
5147 "`foo${\n a}`",
5148 "`foo${\r\n a}`",
5149 "`foo${\r a}`",
5150 "`foo${'a' in a}`",
5151 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005152 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005153}
5154
5155
5156TEST(ScanTaggedTemplateLiterals) {
5157 const char* context_data[][2] = {{"'use strict';", ""},
5158 {"function foo(){ 'use strict';"
5159 " function tag() {}"
5160 " var a, b, c; return ", "}"},
5161 {NULL, NULL}};
5162
5163 const char* data[] = {
5164 "tag ``",
5165 "tag `no-subst-template`",
5166 "tag`template-head${a}`",
5167 "tag `${a}`",
5168 "tag `${a}template-tail`",
5169 "tag `template-head${a}template-tail`",
5170 "tag\n`${a}${b}${c}`",
5171 "tag\r\n`a${a}b${b}c${c}`",
5172 "tag `${a}a${b}b${c}c`",
5173 "tag\t`foo\n\nbar\r\nbaz`",
5174 "tag\r`foo\n\n${ bar }\r\nbaz`",
5175 "tag`foo${a /* comment */}`",
5176 "tag`foo${a // comment\n}`",
5177 "tag`foo${a \n}`",
5178 "tag`foo${a \r\n}`",
5179 "tag`foo${a \r}`",
5180 "tag`foo${/* comment */ a}`",
5181 "tag`foo${// comment\na}`",
5182 "tag`foo${\n a}`",
5183 "tag`foo${\r\n a}`",
5184 "tag`foo${\r a}`",
5185 "tag`foo${'a' in a}`",
5186 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005187 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005188}
5189
5190
5191TEST(TemplateMaterializedLiterals) {
5192 const char* context_data[][2] = {
5193 {
5194 "'use strict';\n"
5195 "function tag() {}\n"
5196 "var a, b, c;\n"
5197 "(", ")"
5198 },
5199 {NULL, NULL}
5200 };
5201
5202 const char* data[] = {
5203 "tag``",
5204 "tag`a`",
5205 "tag`a${1}b`",
5206 "tag`a${1}b${2}c`",
5207 "``",
5208 "`a`",
5209 "`a${1}b`",
5210 "`a${1}b${2}c`",
5211 NULL
5212 };
5213
Ben Murdochc5610432016-08-08 18:44:38 +01005214 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005215}
5216
5217
5218TEST(ScanUnterminatedTemplateLiterals) {
5219 const char* context_data[][2] = {{"'use strict';", ""},
5220 {"function foo(){ 'use strict';"
5221 " var a, b, c; return ", "}"},
5222 {NULL, NULL}};
5223
5224 const char* data[] = {
5225 "`no-subst-template",
5226 "`template-head${a}",
5227 "`${a}template-tail",
5228 "`template-head${a}template-tail",
5229 "`${a}${b}${c}",
5230 "`a${a}b${b}c${c}",
5231 "`${a}a${b}b${c}c",
5232 "`foo\n\nbar\r\nbaz",
5233 "`foo\n\n${ bar }\r\nbaz",
5234 "`foo${a /* comment } */`",
5235 "`foo${a /* comment } `*/",
5236 "`foo${a // comment}`",
5237 "`foo${a \n`",
5238 "`foo${a \r\n`",
5239 "`foo${a \r`",
5240 "`foo${/* comment */ a`",
5241 "`foo${// commenta}`",
5242 "`foo${\n a`",
5243 "`foo${\r\n a`",
5244 "`foo${\r a`",
5245 "`foo${fn(}`",
5246 "`foo${1 if}`",
5247 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005248 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005249}
5250
5251
5252TEST(TemplateLiteralsIllegalTokens) {
5253 const char* context_data[][2] = {{"'use strict';", ""},
5254 {"function foo(){ 'use strict';"
5255 " var a, b, c; return ", "}"},
5256 {NULL, NULL}};
5257 const char* data[] = {
5258 "`hello\\x`",
5259 "`hello\\x${1}`",
5260 "`hello${1}\\x`",
5261 "`hello${1}\\x${2}`",
5262 "`hello\\x\n`",
5263 "`hello\\x\n${1}`",
5264 "`hello${1}\\x\n`",
5265 "`hello${1}\\x\n${2}`",
5266 NULL};
5267
Ben Murdochc5610432016-08-08 18:44:38 +01005268 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005269}
5270
5271
5272TEST(ParseRestParameters) {
5273 const char* context_data[][2] = {{"'use strict';(function(",
5274 "){ return args;})(1, [], /regexp/, 'str',"
5275 "function(){});"},
5276 {"(function(", "){ return args;})(1, [],"
5277 "/regexp/, 'str', function(){});"},
5278 {NULL, NULL}};
5279
5280 const char* data[] = {"...args",
5281 "a, ...args",
5282 "... args",
5283 "a, ... args",
5284 "...\targs",
5285 "a, ...\targs",
5286 "...\r\nargs",
5287 "a, ...\r\nargs",
5288 "...\rargs",
5289 "a, ...\rargs",
5290 "...\t\n\t\t\n args",
5291 "a, ... \n \n args",
5292 "...{ length, 0: a, 1: b}",
5293 "...{}",
5294 "...[a, b]",
5295 "...[]",
5296 "...[...[a, b, ...c]]",
5297 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01005298 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005299}
5300
5301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005302TEST(ParseRestParametersErrors) {
5303 const char* context_data[][2] = {{"'use strict';(function(",
5304 "){ return args;}(1, [], /regexp/, 'str',"
5305 "function(){});"},
5306 {"(function(", "){ return args;}(1, [],"
5307 "/regexp/, 'str', function(){});"},
5308 {NULL, NULL}};
5309
5310 const char* data[] = {
5311 "...args, b",
5312 "a, ...args, b",
5313 "...args, b",
5314 "a, ...args, b",
5315 "...args,\tb",
5316 "a,...args\t,b",
5317 "...args\r\n, b",
5318 "a, ... args,\r\nb",
5319 "...args\r,b",
5320 "a, ... args,\rb",
5321 "...args\t\n\t\t\n, b",
5322 "a, ... args, \n \n b",
5323 "a, a, ...args",
5324 "a,\ta, ...args",
5325 "a,\ra, ...args",
5326 "a,\na, ...args",
5327 NULL};
5328 RunParserSyncTest(context_data, data, kError);
5329}
5330
5331
5332TEST(RestParameterInSetterMethodError) {
5333 const char* context_data[][2] = {
5334 {"'use strict';({ set prop(", ") {} }).prop = 1;"},
5335 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
5336 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
5337 {"({ set prop(", ") {} }).prop = 1;"},
5338 {"(class { static set prop(", ") {} }).prop = 1;"},
5339 {"(new (class { set prop(", ") {} })).prop = 1;"},
5340 {nullptr, nullptr}};
5341 const char* data[] = {"...a", "...arguments", "...eval", nullptr};
5342
Ben Murdochc5610432016-08-08 18:44:38 +01005343 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005344}
5345
5346
5347TEST(RestParametersEvalArguments) {
Ben Murdochc5610432016-08-08 18:44:38 +01005348 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005349 const char* strict_context_data[][2] =
5350 {{"'use strict';(function(",
5351 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5352 {NULL, NULL}};
5353 const char* sloppy_context_data[][2] =
5354 {{"(function(",
5355 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5356 {NULL, NULL}};
5357
5358 const char* data[] = {
5359 "...eval",
5360 "eval, ...args",
5361 "...arguments",
Ben Murdochc5610432016-08-08 18:44:38 +01005362 // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
5363 // "arguments, ...args",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005364 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005365 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005366
5367 // Fail in strict mode
5368 RunParserSyncTest(strict_context_data, data, kError);
5369
5370 // OK in sloppy mode
5371 RunParserSyncTest(sloppy_context_data, data, kSuccess);
5372}
5373
5374
5375TEST(RestParametersDuplicateEvalArguments) {
5376 const char* context_data[][2] =
5377 {{"'use strict';(function(",
5378 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5379 {"(function(",
5380 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5381 {NULL, NULL}};
5382
5383 const char* data[] = {
5384 "eval, ...eval",
5385 "eval, eval, ...args",
5386 "arguments, ...arguments",
5387 "arguments, arguments, ...args",
5388 NULL};
5389
5390 // In strict mode, the error is using "eval" or "arguments" as parameter names
5391 // In sloppy mode, the error is that eval / arguments are duplicated
5392 RunParserSyncTest(context_data, data, kError);
5393}
5394
5395
5396TEST(SpreadCall) {
5397 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5398 {"function fn() {} fn(", ");"},
5399 {NULL, NULL}};
5400
5401 const char* data[] = {
5402 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
5403 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
5404 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
5405 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
5406 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
5407 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
5408
5409 RunParserSyncTest(context_data, data, kSuccess);
5410}
5411
5412
5413TEST(SpreadCallErrors) {
5414 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5415 {"function fn() {} fn(", ");"},
5416 {NULL, NULL}};
5417
5418 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
5419
5420 RunParserSyncTest(context_data, data, kError);
5421}
5422
5423
5424TEST(BadRestSpread) {
5425 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
5426 {"function fn() { ", "} fn();"},
5427 {NULL, NULL}};
5428 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];",
5429 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
5430 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}",
5431 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005432 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005433}
5434
5435
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005436TEST(LexicalScopingSloppyMode) {
5437 const char* context_data[][2] = {
5438 {"", ""},
5439 {"function f() {", "}"},
5440 {"{", "}"},
5441 {NULL, NULL}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005442
5443 const char* good_data[] = {
5444 "let = 1;",
5445 "for(let = 1;;){}",
5446 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005447 RunParserSyncTest(context_data, good_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005448}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005449
5450
5451TEST(ComputedPropertyName) {
5452 const char* context_data[][2] = {{"({[", "]: 1});"},
5453 {"({get [", "]() {}});"},
5454 {"({set [", "](_) {}});"},
5455 {"({[", "]() {}});"},
5456 {"({*[", "]() {}});"},
5457 {"(class {get [", "]() {}});"},
5458 {"(class {set [", "](_) {}});"},
5459 {"(class {[", "]() {}});"},
5460 {"(class {*[", "]() {}});"},
5461 {NULL, NULL}};
5462 const char* error_data[] = {
5463 "1, 2",
5464 "var name",
5465 NULL};
5466
Ben Murdochc5610432016-08-08 18:44:38 +01005467 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005468
5469 const char* name_data[] = {
5470 "1",
5471 "1 + 2",
5472 "'name'",
5473 "\"name\"",
5474 "[]",
5475 "{}",
5476 NULL};
5477
Ben Murdochc5610432016-08-08 18:44:38 +01005478 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005479}
5480
5481
5482TEST(ComputedPropertyNameShorthandError) {
5483 const char* context_data[][2] = {{"({", "});"},
5484 {NULL, NULL}};
5485 const char* error_data[] = {
5486 "a: 1, [2]",
5487 "[1], a: 1",
5488 NULL};
5489
Ben Murdochc5610432016-08-08 18:44:38 +01005490 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005491}
5492
5493
5494TEST(BasicImportExportParsing) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005495 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005496 const char* kSources[] = {
5497 "export let x = 0;",
5498 "export var y = 0;",
5499 "export const z = 0;",
5500 "export function func() { };",
5501 "export class C { };",
5502 "export { };",
5503 "function f() {}; f(); export { f };",
5504 "var a, b, c; export { a, b as baz, c };",
5505 "var d, e; export { d as dreary, e, };",
5506 "export default function f() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005507 "export default function() {}",
5508 "export default function*() {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005509 "export default class C {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005510 "export default class {}"
5511 "export default class extends C {}"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005512 "export default 42",
5513 "var x; export default x = 7",
5514 "export { Q } from 'somemodule.js';",
5515 "export * from 'somemodule.js';",
5516 "var foo; export { foo as for };",
5517 "export { arguments } from 'm.js';",
5518 "export { for } from 'm.js';",
5519 "export { yield } from 'm.js'",
5520 "export { static } from 'm.js'",
5521 "export { let } from 'm.js'",
5522 "var a; export { a as b, a as c };",
Ben Murdochc5610432016-08-08 18:44:38 +01005523 "var a; export { a as await };",
5524 "var a; export { a as enum };",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005525
5526 "import 'somemodule.js';",
5527 "import { } from 'm.js';",
5528 "import { a } from 'm.js';",
5529 "import { a, b as d, c, } from 'm.js';",
5530 "import * as thing from 'm.js';",
5531 "import thing from 'm.js';",
5532 "import thing, * as rest from 'm.js';",
5533 "import thing, { a, b, c } from 'm.js';",
5534 "import { arguments as a } from 'm.js';",
5535 "import { for as f } from 'm.js';",
5536 "import { yield as y } from 'm.js';",
5537 "import { static as s } from 'm.js';",
5538 "import { let as l } from 'm.js';",
5539 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005540 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005541
5542 i::Isolate* isolate = CcTest::i_isolate();
5543 i::Factory* factory = isolate->factory();
5544
5545 v8::HandleScope handles(CcTest::isolate());
5546 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5547 v8::Context::Scope context_scope(context);
5548
5549 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5550 128 * 1024);
5551
5552 for (unsigned i = 0; i < arraysize(kSources); ++i) {
5553 i::Handle<i::String> source =
5554 factory->NewStringFromAsciiChecked(kSources[i]);
5555
5556 // Show that parsing as a module works
5557 {
5558 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005559 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005560 i::ParseInfo info(&zone, script);
5561 i::Parser parser(&info);
5562 info.set_module();
5563 if (!parser.Parse(&info)) {
5564 i::Handle<i::JSObject> exception_handle(
5565 i::JSObject::cast(isolate->pending_exception()));
Ben Murdochda12d292016-06-02 14:46:10 +01005566 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
5567 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
5568 .ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005569
5570 v8::base::OS::Print(
5571 "Parser failed on:\n"
5572 "\t%s\n"
5573 "with error:\n"
5574 "\t%s\n"
5575 "However, we expected no error.",
5576 source->ToCString().get(), message_string->ToCString().get());
5577 CHECK(false);
5578 }
5579 }
5580
5581 // And that parsing a script does not.
5582 {
5583 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005584 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005585 i::ParseInfo info(&zone, script);
5586 i::Parser parser(&info);
5587 info.set_global();
5588 CHECK(!parser.Parse(&info));
5589 }
5590 }
5591}
5592
5593
5594TEST(ImportExportParsingErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005595 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005596 const char* kErrorSources[] = {
5597 "export {",
5598 "var a; export { a",
5599 "var a; export { a,",
5600 "var a; export { a, ;",
5601 "var a; export { a as };",
5602 "var a, b; export { a as , b};",
5603 "export }",
5604 "var foo, bar; export { foo bar };",
5605 "export { foo };",
5606 "export { , };",
5607 "export default;",
5608 "export default var x = 7;",
5609 "export default let x = 7;",
5610 "export default const x = 7;",
5611 "export *;",
5612 "export * from;",
5613 "export { Q } from;",
5614 "export default from 'module.js';",
5615 "export { for }",
5616 "export { for as foo }",
5617 "export { arguments }",
5618 "export { arguments as foo }",
5619 "var a; export { a, a };",
5620 "var a, b; export { a as b, b };",
5621 "var a, b; export { a as c, b as c };",
5622 "export default function f(){}; export default class C {};",
5623 "export default function f(){}; var a; export { a as default };",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005624 "export function() {}",
5625 "export function*() {}",
5626 "export class {}",
5627 "export class extends C {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005628
5629 "import from;",
5630 "import from 'm.js';",
5631 "import { };",
5632 "import {;",
5633 "import };",
5634 "import { , };",
5635 "import { , } from 'm.js';",
5636 "import { a } from;",
5637 "import { a } 'm.js';",
5638 "import , from 'm.js';",
5639 "import a , from 'm.js';",
5640 "import a { b, c } from 'm.js';",
5641 "import arguments from 'm.js';",
5642 "import eval from 'm.js';",
5643 "import { arguments } from 'm.js';",
5644 "import { eval } from 'm.js';",
5645 "import { a as arguments } from 'm.js';",
5646 "import { for } from 'm.js';",
5647 "import { y as yield } from 'm.js'",
5648 "import { s as static } from 'm.js'",
5649 "import { l as let } from 'm.js'",
Ben Murdochc5610432016-08-08 18:44:38 +01005650 "import { a as await } from 'm.js';",
5651 "import { a as enum } from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005652 "import { x }, def from 'm.js';",
5653 "import def, def2 from 'm.js';",
5654 "import * as x, def from 'm.js';",
5655 "import * as x, * as y from 'm.js';",
5656 "import {x}, {y} from 'm.js';",
5657 "import * as x, {y} from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005658 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005659 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005660
5661 i::Isolate* isolate = CcTest::i_isolate();
5662 i::Factory* factory = isolate->factory();
5663
5664 v8::HandleScope handles(CcTest::isolate());
5665 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5666 v8::Context::Scope context_scope(context);
5667
5668 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5669 128 * 1024);
5670
5671 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5672 i::Handle<i::String> source =
5673 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5674
5675 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005676 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005677 i::ParseInfo info(&zone, script);
5678 i::Parser parser(&info);
5679 info.set_module();
5680 CHECK(!parser.Parse(&info));
5681 }
5682}
5683
Ben Murdochc5610432016-08-08 18:44:38 +01005684TEST(ModuleTopLevelFunctionDecl) {
5685 // clang-format off
5686 const char* kErrorSources[] = {
5687 "function f() {} function f() {}",
5688 "var f; function f() {}",
5689 "function f() {} var f;",
5690 "function* f() {} function* f() {}",
5691 "var f; function* f() {}",
5692 "function* f() {} var f;",
5693 "function f() {} function* f() {}",
5694 "function* f() {} function f() {}",
5695 };
5696 // clang-format on
5697
5698 i::Isolate* isolate = CcTest::i_isolate();
5699 i::Factory* factory = isolate->factory();
5700
5701 v8::HandleScope handles(CcTest::isolate());
5702 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5703 v8::Context::Scope context_scope(context);
5704
5705 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5706 128 * 1024);
5707
5708 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5709 i::Handle<i::String> source =
5710 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5711
5712 i::Handle<i::Script> script = factory->NewScript(source);
5713 i::Zone zone(CcTest::i_isolate()->allocator());
5714 i::ParseInfo info(&zone, script);
5715 i::Parser parser(&info);
5716 info.set_module();
5717 CHECK(!parser.Parse(&info));
5718 }
5719}
5720
5721TEST(ModuleAwaitReserved) {
5722 // clang-format off
5723 const char* kErrorSources[] = {
5724 "await;",
5725 "await: ;",
5726 "var await;",
5727 "var [await] = [];",
5728 "var { await } = {};",
5729 "var { x: await } = {};",
5730 "{ var await; }",
5731 "let await;",
5732 "let [await] = [];",
5733 "let { await } = {};",
5734 "let { x: await } = {};",
5735 "{ let await; }",
5736 "const await = null;",
5737 "const [await] = [];",
5738 "const { await } = {};",
5739 "const { x: await } = {};",
5740 "{ const await = null; }",
5741 "function await() {}",
5742 "function f(await) {}",
5743 "function* await() {}",
5744 "function* g(await) {}",
5745 "(function await() {});",
5746 "(function (await) {});",
5747 "(function* await() {});",
5748 "(function* (await) {});",
5749 "(await) => {};",
5750 "await => {};",
5751 "class await {}",
5752 "class C { constructor(await) {} }",
5753 "class C { m(await) {} }",
5754 "class C { static m(await) {} }",
5755 "class C { *m(await) {} }",
5756 "class C { static *m(await) {} }",
5757 "(class await {})",
5758 "(class { constructor(await) {} });",
5759 "(class { m(await) {} });",
5760 "(class { static m(await) {} });",
5761 "(class { *m(await) {} });",
5762 "(class { static *m(await) {} });",
5763 "({ m(await) {} });",
5764 "({ *m(await) {} });",
5765 "({ set p(await) {} });",
5766 "try {} catch (await) {}",
5767 "try {} catch (await) {} finally {}",
5768 NULL
5769 };
5770 // clang-format on
5771 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5772
5773 RunModuleParserSyncTest(context_data, kErrorSources, kError);
5774}
5775
5776TEST(ModuleAwaitReservedPreParse) {
5777 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5778 const char* error_data[] = {"function f() { var await = 0; }", NULL};
5779
5780 RunModuleParserSyncTest(context_data, error_data, kError);
5781}
5782
5783TEST(ModuleAwaitPermitted) {
5784 // clang-format off
5785 const char* kValidSources[] = {
5786 "({}).await;",
5787 "({ await: null });",
5788 "({ await() {} });",
5789 "({ get await() {} });",
5790 "({ set await(x) {} });",
5791 "(class { await() {} });",
5792 "(class { static await() {} });",
5793 "(class { *await() {} });",
5794 "(class { static *await() {} });",
5795 NULL
5796 };
5797 // clang-format on
5798 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5799
5800 RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
5801}
5802
5803TEST(EnumReserved) {
5804 // clang-format off
5805 const char* kErrorSources[] = {
5806 "enum;",
5807 "enum: ;",
5808 "var enum;",
5809 "var [enum] = [];",
5810 "var { enum } = {};",
5811 "var { x: enum } = {};",
5812 "{ var enum; }",
5813 "let enum;",
5814 "let [enum] = [];",
5815 "let { enum } = {};",
5816 "let { x: enum } = {};",
5817 "{ let enum; }",
5818 "const enum = null;",
5819 "const [enum] = [];",
5820 "const { enum } = {};",
5821 "const { x: enum } = {};",
5822 "{ const enum = null; }",
5823 "function enum() {}",
5824 "function f(enum) {}",
5825 "function* enum() {}",
5826 "function* g(enum) {}",
5827 "(function enum() {});",
5828 "(function (enum) {});",
5829 "(function* enum() {});",
5830 "(function* (enum) {});",
5831 "(enum) => {};",
5832 "enum => {};",
5833 "class enum {}",
5834 "class C { constructor(enum) {} }",
5835 "class C { m(enum) {} }",
5836 "class C { static m(enum) {} }",
5837 "class C { *m(enum) {} }",
5838 "class C { static *m(enum) {} }",
5839 "(class enum {})",
5840 "(class { constructor(enum) {} });",
5841 "(class { m(enum) {} });",
5842 "(class { static m(enum) {} });",
5843 "(class { *m(enum) {} });",
5844 "(class { static *m(enum) {} });",
5845 "({ m(enum) {} });",
5846 "({ *m(enum) {} });",
5847 "({ set p(enum) {} });",
5848 "try {} catch (enum) {}",
5849 "try {} catch (enum) {} finally {}",
5850 NULL
5851 };
5852 // clang-format on
5853 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5854
5855 RunModuleParserSyncTest(context_data, kErrorSources, kError);
5856}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005857
5858TEST(ModuleParsingInternals) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005859 i::Isolate* isolate = CcTest::i_isolate();
5860 i::Factory* factory = isolate->factory();
5861 v8::HandleScope handles(CcTest::isolate());
5862 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5863 v8::Context::Scope context_scope(context);
5864 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5865 128 * 1024);
5866
5867 static const char kSource[] =
5868 "let x = 5;"
5869 "export { x as y };"
5870 "import { q as z } from 'm.js';"
5871 "import n from 'n.js';"
5872 "export { a as b } from 'm.js';"
5873 "export * from 'p.js';"
5874 "import 'q.js'";
5875 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
5876 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005877 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005878 i::ParseInfo info(&zone, script);
5879 i::Parser parser(&info);
5880 info.set_module();
5881 CHECK(parser.Parse(&info));
5882 CHECK(i::Compiler::Analyze(&info));
5883 i::FunctionLiteral* func = info.literal();
5884 i::Scope* module_scope = func->scope();
5885 i::Scope* outer_scope = module_scope->outer_scope();
5886 CHECK(outer_scope->is_script_scope());
5887 CHECK_NULL(outer_scope->outer_scope());
5888 CHECK(module_scope->is_module_scope());
5889 i::ModuleDescriptor* descriptor = module_scope->module();
5890 CHECK_NOT_NULL(descriptor);
5891 CHECK_EQ(1, descriptor->Length());
5892 const i::AstRawString* export_name =
5893 info.ast_value_factory()->GetOneByteString("y");
5894 const i::AstRawString* local_name =
5895 descriptor->LookupLocalExport(export_name, &zone);
5896 CHECK_NOT_NULL(local_name);
5897 CHECK(local_name->IsOneByteEqualTo("x"));
5898 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
5899 CHECK_EQ(3, declarations->length());
5900 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
5901 i::ImportDeclaration* import_decl =
5902 declarations->at(1)->AsImportDeclaration();
5903 CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
5904 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
5905 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
5906 import_decl = declarations->at(2)->AsImportDeclaration();
5907 CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
5908 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
5909 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
5910 // TODO(adamk): Add test for indirect exports once they're fully implemented.
5911 // TODO(adamk): Add test for star exports once they're fully implemented.
5912 const i::ZoneList<const i::AstRawString*>& requested_modules =
5913 descriptor->requested_modules();
5914 CHECK_EQ(4, requested_modules.length());
5915 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
5916 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
5917 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
5918 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
5919}
5920
5921
5922TEST(DuplicateProtoError) {
5923 const char* context_data[][2] = {
5924 {"({", "});"},
5925 {"'use strict'; ({", "});"},
5926 {NULL, NULL}
5927 };
5928 const char* error_data[] = {
5929 "__proto__: {}, __proto__: {}",
5930 "__proto__: {}, \"__proto__\": {}",
5931 "__proto__: {}, \"__\x70roto__\": {}",
5932 "__proto__: {}, a: 1, __proto__: {}",
5933 NULL
5934 };
5935
5936 RunParserSyncTest(context_data, error_data, kError);
5937}
5938
5939
5940TEST(DuplicateProtoNoError) {
5941 const char* context_data[][2] = {
5942 {"({", "});"},
5943 {"'use strict'; ({", "});"},
5944 {NULL, NULL}
5945 };
5946 const char* error_data[] = {
5947 "__proto__: {}, ['__proto__']: {}",
5948 "__proto__: {}, __proto__() {}",
5949 "__proto__: {}, get __proto__() {}",
5950 "__proto__: {}, set __proto__(v) {}",
5951 "__proto__: {}, __proto__",
5952 NULL
5953 };
5954
5955 RunParserSyncTest(context_data, error_data, kSuccess);
5956}
5957
5958
5959TEST(DeclarationsError) {
5960 const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5961 {"'use strict'; if (false) {} else", ""},
5962 {"'use strict'; while (false)", ""},
5963 {"'use strict'; for (;;)", ""},
5964 {"'use strict'; for (x in y)", ""},
5965 {"'use strict'; do ", " while (false)"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005966 {NULL, NULL}};
5967
5968 const char* statement_data[] = {
5969 "let x = 1;",
5970 "const x = 1;",
5971 "class C {}",
5972 NULL};
5973
Ben Murdochda12d292016-06-02 14:46:10 +01005974 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005975}
5976
5977
5978void TestLanguageMode(const char* source,
5979 i::LanguageMode expected_language_mode) {
5980 i::Isolate* isolate = CcTest::i_isolate();
5981 i::Factory* factory = isolate->factory();
5982 v8::HandleScope handles(CcTest::isolate());
5983 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5984 v8::Context::Scope context_scope(context);
5985 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5986 128 * 1024);
5987
5988 i::Handle<i::Script> script =
5989 factory->NewScript(factory->NewStringFromAsciiChecked(source));
Ben Murdochda12d292016-06-02 14:46:10 +01005990 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005991 i::ParseInfo info(&zone, script);
5992 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005993 info.set_global();
5994 parser.Parse(&info);
5995 CHECK(info.literal() != NULL);
5996 CHECK_EQ(expected_language_mode, info.literal()->language_mode());
5997}
5998
5999
6000TEST(LanguageModeDirectives) {
6001 TestLanguageMode("\"use nothing\"", i::SLOPPY);
6002 TestLanguageMode("\"use strict\"", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006003
6004 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006005
6006 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006007}
6008
6009
6010TEST(PropertyNameEvalArguments) {
6011 const char* context_data[][2] = {{"'use strict';", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006012 {NULL, NULL}};
6013
6014 const char* statement_data[] = {
6015 "({eval: 1})",
6016 "({arguments: 1})",
6017 "({eval() {}})",
6018 "({arguments() {}})",
6019 "({*eval() {}})",
6020 "({*arguments() {}})",
6021 "({get eval() {}})",
6022 "({get arguments() {}})",
6023 "({set eval(_) {}})",
6024 "({set arguments(_) {}})",
6025
6026 "class C {eval() {}}",
6027 "class C {arguments() {}}",
6028 "class C {*eval() {}}",
6029 "class C {*arguments() {}}",
6030 "class C {get eval() {}}",
6031 "class C {get arguments() {}}",
6032 "class C {set eval(_) {}}",
6033 "class C {set arguments(_) {}}",
6034
6035 "class C {static eval() {}}",
6036 "class C {static arguments() {}}",
6037 "class C {static *eval() {}}",
6038 "class C {static *arguments() {}}",
6039 "class C {static get eval() {}}",
6040 "class C {static get arguments() {}}",
6041 "class C {static set eval(_) {}}",
6042 "class C {static set arguments(_) {}}",
6043
6044 NULL};
6045
Ben Murdochda12d292016-06-02 14:46:10 +01006046 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006047}
6048
6049
6050TEST(FunctionLiteralDuplicateParameters) {
6051 const char* strict_context_data[][2] =
6052 {{"'use strict';(function(", "){})();"},
6053 {"(function(", ") { 'use strict'; })();"},
6054 {"'use strict'; function fn(", ") {}; fn();"},
6055 {"function fn(", ") { 'use strict'; }; fn();"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006056 {NULL, NULL}};
6057
6058 const char* sloppy_context_data[][2] =
6059 {{"(function(", "){})();"},
6060 {"(function(", ") {})();"},
6061 {"function fn(", ") {}; fn();"},
6062 {"function fn(", ") {}; fn();"},
6063 {NULL, NULL}};
6064
6065 const char* data[] = {
6066 "a, a",
6067 "a, a, a",
6068 "b, a, a",
6069 "a, b, c, c",
6070 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
6071 NULL};
6072
Ben Murdochda12d292016-06-02 14:46:10 +01006073 RunParserSyncTest(strict_context_data, data, kError);
6074 RunParserSyncTest(sloppy_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006075}
6076
6077
6078TEST(ArrowFunctionASIErrors) {
6079 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
6080 {NULL, NULL}};
6081
6082 const char* data[] = {
6083 "(a\n=> a)(1)",
6084 "(a/*\n*/=> a)(1)",
6085 "((a)\n=> a)(1)",
6086 "((a)/*\n*/=> a)(1)",
6087 "((a, b)\n=> a + b)(1, 2)",
6088 "((a, b)/*\n*/=> a + b)(1, 2)",
6089 NULL};
6090 RunParserSyncTest(context_data, data, kError);
6091}
6092
6093
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006094TEST(DestructuringPositiveTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006095 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6096 {"var ", " = {};"},
6097 {"'use strict'; const ", " = {};"},
6098 {"function f(", ") {}"},
6099 {"function f(argument1, ", ") {}"},
6100 {"var f = (", ") => {};"},
6101 {"var f = (argument1,", ") => {};"},
6102 {"try {} catch(", ") {}"},
6103 {NULL, NULL}};
6104
6105 // clang-format off
6106 const char* data[] = {
6107 "a",
6108 "{ x : y }",
6109 "{ x : y = 1 }",
6110 "{ get, set }",
6111 "{ get = 1, set = 2 }",
6112 "[a]",
6113 "[a = 1]",
6114 "[a,b,c]",
6115 "[a, b = 42, c]",
6116 "{ x : x, y : y }",
6117 "{ x : x = 1, y : y }",
6118 "{ x : x, y : y = 42 }",
6119 "[]",
6120 "{}",
6121 "[{x:x, y:y}, [a,b,c]]",
6122 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
6123 "{x}",
6124 "{x, y}",
6125 "{x = 42, y = 15}",
6126 "[a,,b]",
6127 "{42 : x}",
6128 "{42 : x = 42}",
6129 "{42e-2 : x}",
6130 "{42e-2 : x = 42}",
6131 "{x : y, x : z}",
6132 "{'hi' : x}",
6133 "{'hi' : x = 42}",
6134 "{var: x}",
6135 "{var: x = 42}",
6136 "{[x] : z}",
6137 "{[1+1] : z}",
6138 "{[foo()] : z}",
6139 "{}",
6140 "[...rest]",
6141 "[a,b,...rest]",
6142 "[a,,...rest]",
6143 NULL};
6144 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006145 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006146}
6147
6148
6149TEST(DestructuringNegativeTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006150 { // All modes.
6151 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6152 {"var ", " = {};"},
6153 {"'use strict'; const ", " = {};"},
6154 {"function f(", ") {}"},
6155 {"function f(argument1, ", ") {}"},
6156 {"var f = (", ") => {};"},
6157 {"var f = ", " => {};"},
6158 {"var f = (argument1,", ") => {};"},
6159 {"try {} catch(", ") {}"},
6160 {NULL, NULL}};
6161
6162 // clang-format off
6163 const char* data[] = {
6164 "a++",
6165 "++a",
6166 "delete a",
6167 "void a",
6168 "typeof a",
6169 "--a",
6170 "+a",
6171 "-a",
6172 "~a",
6173 "!a",
6174 "{ x : y++ }",
6175 "[a++]",
6176 "(x => y)",
6177 "a[i]", "a()",
6178 "a.b",
6179 "new a",
6180 "a + a",
6181 "a - a",
6182 "a * a",
6183 "a / a",
6184 "a == a",
6185 "a != a",
6186 "a > a",
6187 "a < a",
6188 "a <<< a",
6189 "a >>> a",
6190 "function a() {}",
6191 "a`bcd`",
6192 "this",
6193 "null",
6194 "true",
6195 "false",
6196 "1",
6197 "'abc'",
6198 "/abc/",
6199 "`abc`",
6200 "class {}",
6201 "{+2 : x}",
6202 "{-2 : x}",
6203 "var",
6204 "[var]",
6205 "{x : {y : var}}",
6206 "{x : x = a+}",
6207 "{x : x = (a+)}",
6208 "{x : x += a}",
6209 "{m() {} = 0}",
6210 "{[1+1]}",
6211 "[...rest, x]",
6212 "[a,b,...rest, x]",
6213 "[a,,...rest, x]",
6214 "[...rest,]",
6215 "[a,b,...rest,]",
6216 "[a,,...rest,]",
6217 "[...rest,...rest1]",
6218 "[a,b,...rest,...rest1]",
6219 "[a,,..rest,...rest1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006220 "[x, y, ...z = 1]",
6221 "[...z = 1]",
6222 "[x, y, ...[z] = [1]]",
6223 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006224 "{ x : 3 }",
6225 "{ x : 'foo' }",
6226 "{ x : /foo/ }",
6227 "{ x : `foo` }",
6228 "{ get a() {} }",
6229 "{ set a() {} }",
6230 "{ method() {} }",
6231 "{ *method() {} }",
6232 NULL};
6233 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006234 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006235 }
6236
6237 { // All modes.
6238 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6239 {"var ", " = {};"},
6240 {"'use strict'; const ", " = {};"},
6241 {"function f(", ") {}"},
6242 {"function f(argument1, ", ") {}"},
6243 {"var f = (", ") => {};"},
6244 {"var f = (argument1,", ") => {};"},
6245 {NULL, NULL}};
6246
6247 // clang-format off
6248 const char* data[] = {
6249 "x => x",
6250 "() => x",
6251 NULL};
6252 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006253 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006254 }
6255
6256 { // Strict mode.
6257 const char* context_data[][2] = {
6258 {"'use strict'; let ", " = {};"},
6259 {"'use strict'; const ", " = {};"},
6260 {"'use strict'; function f(", ") {}"},
6261 {"'use strict'; function f(argument1, ", ") {}"},
6262 {NULL, NULL}};
6263
6264 // clang-format off
6265 const char* data[] = {
6266 "[eval]",
6267 "{ a : arguments }",
6268 "[public]",
6269 "{ x : private }",
6270 NULL};
6271 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006272 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006273 }
6274
6275 { // 'yield' in generators.
6276 const char* context_data[][2] = {
6277 {"function*() { var ", " = {};"},
6278 {"function*() { 'use strict'; let ", " = {};"},
6279 {"function*() { 'use strict'; const ", " = {};"},
6280 {NULL, NULL}};
6281
6282 // clang-format off
6283 const char* data[] = {
6284 "yield",
6285 "[yield]",
6286 "{ x : yield }",
6287 NULL};
6288 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006289 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006290 }
6291
6292 { // Declaration-specific errors
6293 const char* context_data[][2] = {{"'use strict'; var ", ""},
6294 {"'use strict'; let ", ""},
6295 {"'use strict'; const ", ""},
6296 {"'use strict'; for (var ", ";;) {}"},
6297 {"'use strict'; for (let ", ";;) {}"},
6298 {"'use strict'; for (const ", ";;) {}"},
6299 {"var ", ""},
6300 {"let ", ""},
6301 {"const ", ""},
6302 {"for (var ", ";;) {}"},
6303 {"for (let ", ";;) {}"},
6304 {"for (const ", ";;) {}"},
6305 {NULL, NULL}};
6306
6307 // clang-format off
6308 const char* data[] = {
6309 "{ a }",
6310 "[ a ]",
6311 NULL};
6312 // clang-format on
Ben Murdochc5610432016-08-08 18:44:38 +01006313 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006314 }
6315}
6316
6317
6318TEST(DestructuringAssignmentPositiveTests) {
6319 const char* context_data[][2] = {
6320 {"'use strict'; let x, y, z; (", " = {});"},
6321 {"var x, y, z; (", " = {});"},
6322 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6323 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6324 {"var x, y, z; for (x in ", " = {});"},
6325 {"var x, y, z; for (x of ", " = {});"},
6326 {"var x, y, z; for (", " in {});"},
6327 {"var x, y, z; for (", " of {});"},
6328 {"'use strict'; var x, y, z; for (", " in {});"},
6329 {"'use strict'; var x, y, z; for (", " of {});"},
6330 {NULL, NULL}};
6331
6332 const char* mixed_assignments_context_data[][2] = {
6333 {"'use strict'; let x, y, z; (", " = z = {});"},
6334 {"var x, y, z; (", " = z = {});"},
6335 {"'use strict'; let x, y, z; (x = ", " = z = {});"},
6336 {"var x, y, z; (x = ", " = z = {});"},
6337 {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
6338 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
6339 {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
6340 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
6341 {"var x, y, z; for (x in ", " = z = {});"},
6342 {"var x, y, z; for (x in x = ", " = z = {});"},
6343 {"var x, y, z; for (x of ", " = z = {});"},
6344 {"var x, y, z; for (x of x = ", " = z = {});"},
6345 {NULL, NULL}};
6346
6347 // clang-format off
6348 const char* data[] = {
6349 "x",
6350
6351 "{ x : y }",
6352 "{ x : foo().y }",
6353 "{ x : foo()[y] }",
6354 "{ x : y.z }",
6355 "{ x : y[z] }",
6356 "{ x : { y } }",
6357 "{ x : { foo: y } }",
6358 "{ x : { foo: foo().y } }",
6359 "{ x : { foo: foo()[y] } }",
6360 "{ x : { foo: y.z } }",
6361 "{ x : { foo: y[z] } }",
6362 "{ x : [ y ] }",
6363 "{ x : [ foo().y ] }",
6364 "{ x : [ foo()[y] ] }",
6365 "{ x : [ y.z ] }",
6366 "{ x : [ y[z] ] }",
6367
6368 "{ x : y = 10 }",
6369 "{ x : foo().y = 10 }",
6370 "{ x : foo()[y] = 10 }",
6371 "{ x : y.z = 10 }",
6372 "{ x : y[z] = 10 }",
6373 "{ x : { y = 10 } = {} }",
6374 "{ x : { foo: y = 10 } = {} }",
6375 "{ x : { foo: foo().y = 10 } = {} }",
6376 "{ x : { foo: foo()[y] = 10 } = {} }",
6377 "{ x : { foo: y.z = 10 } = {} }",
6378 "{ x : { foo: y[z] = 10 } = {} }",
6379 "{ x : [ y = 10 ] = {} }",
6380 "{ x : [ foo().y = 10 ] = {} }",
6381 "{ x : [ foo()[y] = 10 ] = {} }",
6382 "{ x : [ y.z = 10 ] = {} }",
6383 "{ x : [ y[z] = 10 ] = {} }",
6384
6385 "[ x ]",
6386 "[ foo().x ]",
6387 "[ foo()[x] ]",
6388 "[ x.y ]",
6389 "[ x[y] ]",
6390 "[ { x } ]",
6391 "[ { x : y } ]",
6392 "[ { x : foo().y } ]",
6393 "[ { x : foo()[y] } ]",
6394 "[ { x : x.y } ]",
6395 "[ { x : x[y] } ]",
6396 "[ [ x ] ]",
6397 "[ [ foo().x ] ]",
6398 "[ [ foo()[x] ] ]",
6399 "[ [ x.y ] ]",
6400 "[ [ x[y] ] ]",
6401
6402 "[ x = 10 ]",
6403 "[ foo().x = 10 ]",
6404 "[ foo()[x] = 10 ]",
6405 "[ x.y = 10 ]",
6406 "[ x[y] = 10 ]",
6407 "[ { x = 10 } = {} ]",
6408 "[ { x : y = 10 } = {} ]",
6409 "[ { x : foo().y = 10 } = {} ]",
6410 "[ { x : foo()[y] = 10 } = {} ]",
6411 "[ { x : x.y = 10 } = {} ]",
6412 "[ { x : x[y] = 10 } = {} ]",
6413 "[ [ x = 10 ] = {} ]",
6414 "[ [ foo().x = 10 ] = {} ]",
6415 "[ [ foo()[x] = 10 ] = {} ]",
6416 "[ [ x.y = 10 ] = {} ]",
6417 "[ [ x[y] = 10 ] = {} ]",
6418 "{ x : y = 1 }",
6419 "{ x }",
6420 "{ x, y, z }",
6421 "{ x = 1, y: z, z: y }",
6422 "{x = 42, y = 15}",
6423 "[x]",
6424 "[x = 1]",
6425 "[x,y,z]",
6426 "[x, y = 42, z]",
6427 "{ x : x, y : y }",
6428 "{ x : x = 1, y : y }",
6429 "{ x : x, y : y = 42 }",
6430 "[]",
6431 "{}",
6432 "[{x:x, y:y}, [,x,z,]]",
6433 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
6434 "[x,,y]",
6435 "[(x),,(y)]",
6436 "[(x)]",
6437 "{42 : x}",
6438 "{42 : x = 42}",
6439 "{42e-2 : x}",
6440 "{42e-2 : x = 42}",
6441 "{'hi' : x}",
6442 "{'hi' : x = 42}",
6443 "{var: x}",
6444 "{var: x = 42}",
6445 "{var: (x) = 42}",
6446 "{[x] : z}",
6447 "{[1+1] : z}",
6448 "{[1+1] : (z)}",
6449 "{[foo()] : z}",
6450 "{[foo()] : (z)}",
6451 "{[foo()] : foo().bar}",
6452 "{[foo()] : foo()['bar']}",
6453 "{[foo()] : this.bar}",
6454 "{[foo()] : this['bar']}",
6455 "{[foo()] : 'foo'.bar}",
6456 "{[foo()] : 'foo'['bar']}",
6457 "[...x]",
6458 "[x,y,...z]",
6459 "[x,,...z]",
6460 "{ x: y }",
6461 "[x, y]",
6462 "[((x, y) => z).x]",
6463 "{x: ((y, z) => z).x}",
6464 "[((x, y) => z)['x']]",
6465 "{x: ((y, z) => z)['x']}",
6466
6467 "{x: { y = 10 } }",
6468 "[(({ x } = { x: 1 }) => x).a]",
6469
6470 // v8:4662
6471 "{ x: (y) }",
6472 "{ x: (y) = [] }",
6473 "{ x: (foo.bar) }",
6474 "{ x: (foo['bar']) }",
6475 "[ ...(a) ]",
6476 "[ ...(foo['bar']) ]",
6477 "[ ...(foo.bar) ]",
6478 "[ (y) ]",
6479 "[ (foo.bar) ]",
6480 "[ (foo['bar']) ]",
6481
6482 NULL};
6483 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006484 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006485
Ben Murdochda12d292016-06-02 14:46:10 +01006486 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006487
6488 const char* empty_context_data[][2] = {
6489 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6490
6491 // CoverInitializedName ambiguity handling in various contexts
6492 const char* ambiguity_data[] = {
6493 "var foo = { x = 10 } = {};",
6494 "var foo = { q } = { x = 10 } = {};",
6495 "var foo; foo = { x = 10 } = {};",
6496 "var foo; foo = { q } = { x = 10 } = {};",
6497 "var x; ({ x = 10 } = {});",
6498 "var q, x; ({ q } = { x = 10 } = {});",
6499 "var x; [{ x = 10 } = {}]",
6500 "var x; (true ? { x = true } = {} : { x = false } = {})",
6501 "var q, x; (q, { x = 10 } = {});",
6502 "var { x = 10 } = { x = 20 } = {};",
6503 "var { x = 10 } = (o = { x = 20 } = {});",
6504 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
6505 NULL,
6506 };
Ben Murdochda12d292016-06-02 14:46:10 +01006507 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006508}
6509
6510
6511TEST(DestructuringAssignmentNegativeTests) {
6512 const char* context_data[][2] = {
6513 {"'use strict'; let x, y, z; (", " = {});"},
6514 {"var x, y, z; (", " = {});"},
6515 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6516 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6517 {"var x, y, z; for (x in ", " = {});"},
6518 {"var x, y, z; for (x of ", " = {});"},
6519 {NULL, NULL}};
6520
6521 // clang-format off
6522 const char* data[] = {
6523 "{ x : ++y }",
6524 "{ x : y * 2 }",
6525 "{ ...x }",
6526 "{ get x() {} }",
6527 "{ set x() {} }",
6528 "{ x: y() }",
6529 "{ this }",
6530 "{ x: this }",
6531 "{ x: this = 1 }",
6532 "{ super }",
6533 "{ x: super }",
6534 "{ x: super = 1 }",
6535 "{ new.target }",
6536 "{ x: new.target }",
6537 "{ x: new.target = 1 }",
6538 "[x--]",
6539 "[--x = 1]",
6540 "[x()]",
6541 "[this]",
6542 "[this = 1]",
6543 "[new.target]",
6544 "[new.target = 1]",
6545 "[super]",
6546 "[super = 1]",
6547 "[function f() {}]",
6548 "[50]",
6549 "[(50)]",
6550 "[(function() {})]",
6551 "[(foo())]",
6552 "{ x: 50 }",
6553 "{ x: (50) }",
6554 "['str']",
6555 "{ x: 'str' }",
6556 "{ x: ('str') }",
6557 "{ x: (foo()) }",
6558 "{ x: (function() {}) }",
6559 "{ x: y } = 'str'",
6560 "[x, y] = 'str'",
6561 "[(x,y) => z]",
6562 "{x: (y) => z}",
6563 "[x, ...y, z]",
6564 "[...x,]",
6565 "[x, y, ...z = 1]",
6566 "[...z = 1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006567 "[x, y, ...[z] = [1]]",
6568 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006569
6570 // v8:4657
6571 "({ x: x4, x: (x+=1e4) })",
6572 "(({ x: x4, x: (x+=1e4) }))",
6573 "({ x: x4, x: (x+=1e4) } = {})",
6574 "(({ x: x4, x: (x+=1e4) } = {}))",
6575 "(({ x: x4, x: (x+=1e4) }) = {})",
6576 "({ x: y } = {})",
6577 "(({ x: y } = {}))",
6578 "(({ x: y }) = {})",
6579 "([a])",
6580 "(([a]))",
6581 "([a] = [])",
6582 "(([a] = []))",
6583 "(([a]) = [])",
6584
6585 // v8:4662
6586 "{ x: ([y]) }",
6587 "{ x: ([y] = []) }",
6588 "{ x: ({y}) }",
6589 "{ x: ({y} = {}) }",
6590 "{ x: (++y) }",
6591 "[ (...[a]) ]",
6592 "[ ...([a]) ]",
6593 "[ ...([a] = [])",
6594 "[ ...[ ( [ a ] ) ] ]",
6595 "[ ([a]) ]",
6596 "[ (...[a]) ]",
6597 "[ ([a] = []) ]",
6598 "[ (++y) ]",
6599 "[ ...(++y) ]",
6600
6601 "[ x += x ]",
6602 "{ foo: x += x }",
6603
6604 NULL};
6605 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006606 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006607
6608 const char* empty_context_data[][2] = {
6609 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6610
6611 // CoverInitializedName ambiguity handling in various contexts
6612 const char* ambiguity_data[] = {
6613 "var foo = { x = 10 };",
6614 "var foo = { q } = { x = 10 };",
6615 "var foo; foo = { x = 10 };",
6616 "var foo; foo = { q } = { x = 10 };",
6617 "var x; ({ x = 10 });",
6618 "var q, x; ({ q } = { x = 10 });",
6619 "var x; [{ x = 10 }]",
6620 "var x; (true ? { x = true } : { x = false })",
6621 "var q, x; (q, { x = 10 });",
6622 "var { x = 10 } = { x = 20 };",
6623 "var { x = 10 } = (o = { x = 20 });",
6624 "var x; (({ x = 10 } = { x = 20 }) => x)({})",
6625
6626 // Not ambiguous, but uses same context data
6627 "switch([window %= []] = []) { default: }",
6628
6629 NULL,
6630 };
Ben Murdochda12d292016-06-02 14:46:10 +01006631 RunParserSyncTest(empty_context_data, ambiguity_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006632
6633 // Strict mode errors
6634 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
6635 {"'use strict'; for (", " of {}) {}"},
6636 {"'use strict'; for (", " in {}) {}"},
6637 {NULL, NULL}};
6638 const char* strict_data[] = {"{ eval }",
6639 "{ arguments }",
6640 "{ foo: eval }",
6641 "{ foo: arguments }",
6642 "{ eval = 0 }",
6643 "{ arguments = 0 }",
6644 "{ foo: eval = 0 }",
6645 "{ foo: arguments = 0 }",
6646 "[ eval ]",
6647 "[ arguments ]",
6648 "[ eval = 0 ]",
6649 "[ arguments = 0 ]",
6650
6651 // v8:4662
6652 "{ x: (eval) }",
6653 "{ x: (arguments) }",
6654 "{ x: (eval = 0) }",
6655 "{ x: (arguments = 0) }",
6656 "{ x: (eval) = 0 }",
6657 "{ x: (arguments) = 0 }",
6658 "[ (eval) ]",
6659 "[ (arguments) ]",
6660 "[ (eval = 0) ]",
6661 "[ (arguments = 0) ]",
6662 "[ (eval) = 0 ]",
6663 "[ (arguments) = 0 ]",
6664 "[ ...(eval) ]",
6665 "[ ...(arguments) ]",
6666 "[ ...(eval = 0) ]",
6667 "[ ...(arguments = 0) ]",
6668 "[ ...(eval) = 0 ]",
6669 "[ ...(arguments) = 0 ]",
6670
6671 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01006672 RunParserSyncTest(strict_context_data, strict_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006673}
6674
6675
6676TEST(DestructuringDisallowPatternsInForVarIn) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006677 const char* context_data[][2] = {
6678 {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
6679 // clang-format off
6680 const char* error_data[] = {
6681 "for (let x = {} in null);",
6682 "for (let x = {} of null);",
6683 NULL};
6684 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006685 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006686
6687 // clang-format off
6688 const char* success_data[] = {
6689 "for (var x = {} in null);",
6690 NULL};
6691 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006692 RunParserSyncTest(context_data, success_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006693}
6694
6695
6696TEST(DestructuringDuplicateParams) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006697 const char* context_data[][2] = {{"'use strict';", ""},
6698 {"function outer() { 'use strict';", "}"},
6699 {nullptr, nullptr}};
6700
6701
6702 // clang-format off
6703 const char* error_data[] = {
6704 "function f(x,x){}",
6705 "function f(x, {x : x}){}",
6706 "function f(x, {x}){}",
6707 "function f({x,x}) {}",
6708 "function f([x,x]) {}",
6709 "function f(x, [y,{z:x}]) {}",
6710 "function f([x,{y:x}]) {}",
6711 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6712 "function f(x, x, {a}) {}",
6713 nullptr};
6714 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006715 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006716}
6717
6718
6719TEST(DestructuringDuplicateParamsSloppy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006720 const char* context_data[][2] = {
6721 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
6722
6723
6724 // clang-format off
6725 const char* error_data[] = {
6726 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6727 "function f(x, {x : x}){}",
6728 "function f(x, {x}){}",
6729 "function f({x,x}) {}",
6730 "function f(x, x, {a}) {}",
6731 nullptr};
6732 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006733 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006734}
6735
6736
6737TEST(DestructuringDisallowPatternsInSingleParamArrows) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006738 const char* context_data[][2] = {{"'use strict';", ""},
6739 {"function outer() { 'use strict';", "}"},
6740 {"", ""},
6741 {"function outer() { ", "}"},
6742 {nullptr, nullptr}};
6743
6744 // clang-format off
6745 const char* error_data[] = {
6746 "var f = {x} => {};",
6747 "var f = {x,y} => {};",
6748 nullptr};
6749 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006750 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006751}
6752
6753
6754TEST(DefaultParametersYieldInInitializers) {
6755 // clang-format off
6756 const char* sloppy_function_context_data[][2] = {
6757 {"(function f(", ") { });"},
6758 {NULL, NULL}
6759 };
6760
6761 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006762 {"'use strict'; (function f(", ") { });"},
6763 {NULL, NULL}
6764 };
6765
6766 const char* sloppy_arrow_context_data[][2] = {
6767 {"((", ")=>{});"},
6768 {NULL, NULL}
6769 };
6770
6771 const char* strict_arrow_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006772 {"'use strict'; ((", ")=>{});"},
6773 {NULL, NULL}
6774 };
6775
6776 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006777 {"'use strict'; (function *g(", ") { });"},
6778 {"(function *g(", ") { });"},
Ben Murdochda12d292016-06-02 14:46:10 +01006779 // Arrow function within generator has the same rules.
6780 {"'use strict'; (function *g() { (", ") => {} });"},
6781 {"(function *g() { (", ") => {} });"},
Ben Murdochc5610432016-08-08 18:44:38 +01006782 // And similarly for arrow functions in the parameter list.
6783 {"'use strict'; (function *g(z = (", ") => {}) { });"},
6784 {"(function *g(z = (", ") => {}) { });"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006785 {NULL, NULL}
6786 };
6787
6788 const char* parameter_data[] = {
6789 "x=yield",
6790 "x, y=yield",
6791 "{x=yield}",
6792 "[x=yield]",
6793
6794 "x=(yield)",
6795 "x, y=(yield)",
6796 "{x=(yield)}",
6797 "[x=(yield)]",
6798
6799 "x=f(yield)",
6800 "x, y=f(yield)",
6801 "{x=f(yield)}",
6802 "[x=f(yield)]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006804 "{x}=yield",
6805 "[x]=yield",
6806
6807 "{x}=(yield)",
6808 "[x]=(yield)",
6809
6810 "{x}=f(yield)",
6811 "[x]=f(yield)",
6812 NULL
6813 };
6814
Ben Murdochda12d292016-06-02 14:46:10 +01006815 // Because classes are always in strict mode, these are always errors.
6816 const char* always_error_param_data[] = {
6817 "x = class extends (yield) { }",
6818 "x = class extends f(yield) { }",
6819 "x = class extends (null, yield) { }",
6820 "x = class extends (a ? null : yield) { }",
6821 "[x] = [class extends (a ? null : yield) { }]",
6822 "[x = class extends (a ? null : yield) { }]",
6823 "[x = class extends (a ? null : yield) { }] = [null]",
6824 "x = class { [yield]() { } }",
6825 "x = class { static [yield]() { } }",
6826 "x = class { [(yield, 1)]() { } }",
6827 "x = class { [y = (yield, 1)]() { } }",
6828 NULL
6829 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006830 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006831
Ben Murdochda12d292016-06-02 14:46:10 +01006832 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
6833 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006834
Ben Murdochda12d292016-06-02 14:46:10 +01006835 RunParserSyncTest(strict_function_context_data, parameter_data, kError);
6836 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006837
Ben Murdochda12d292016-06-02 14:46:10 +01006838 RunParserSyncTest(generator_context_data, parameter_data, kError);
6839 RunParserSyncTest(generator_context_data, always_error_param_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006840}
6841
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006842TEST(SpreadArray) {
6843 const char* context_data[][2] = {
6844 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6845
6846 // clang-format off
6847 const char* data[] = {
6848 "[...a]",
6849 "[a, ...b]",
6850 "[...a,]",
6851 "[...a, ,]",
6852 "[, ...a]",
6853 "[...a, ...b]",
6854 "[...a, , ...b]",
6855 "[...[...a]]",
6856 "[, ...a]",
6857 "[, , ...a]",
6858 NULL};
6859 // clang-format on
6860 RunParserSyncTest(context_data, data, kSuccess);
6861}
6862
6863
6864TEST(SpreadArrayError) {
6865 const char* context_data[][2] = {
6866 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6867
6868 // clang-format off
6869 const char* data[] = {
6870 "[...]",
6871 "[a, ...]",
6872 "[..., ]",
6873 "[..., ...]",
6874 "[ (...a)]",
6875 NULL};
6876 // clang-format on
6877 RunParserSyncTest(context_data, data, kError);
6878}
6879
6880
6881TEST(NewTarget) {
6882 // clang-format off
6883 const char* good_context_data[][2] = {
6884 {"function f() {", "}"},
6885 {"'use strict'; function f() {", "}"},
6886 {"var f = function() {", "}"},
6887 {"'use strict'; var f = function() {", "}"},
6888 {"({m: function() {", "}})"},
6889 {"'use strict'; ({m: function() {", "}})"},
6890 {"({m() {", "}})"},
6891 {"'use strict'; ({m() {", "}})"},
6892 {"({get x() {", "}})"},
6893 {"'use strict'; ({get x() {", "}})"},
6894 {"({set x(_) {", "}})"},
6895 {"'use strict'; ({set x(_) {", "}})"},
6896 {"class C {m() {", "}}"},
6897 {"class C {get x() {", "}}"},
6898 {"class C {set x(_) {", "}}"},
6899 {NULL}
6900 };
6901
6902 const char* bad_context_data[][2] = {
6903 {"", ""},
6904 {"'use strict';", ""},
6905 {NULL}
6906 };
6907
6908 const char* data[] = {
6909 "new.target",
6910 "{ new.target }",
6911 "() => { new.target }",
6912 "() => new.target",
6913 "if (1) { new.target }",
6914 "if (1) {} else { new.target }",
6915 "while (0) { new.target }",
6916 "do { new.target } while (0)",
6917 NULL
6918 };
6919
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006920 // clang-format on
6921
Ben Murdochc5610432016-08-08 18:44:38 +01006922 RunParserSyncTest(good_context_data, data, kSuccess);
6923 RunParserSyncTest(bad_context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006924}
6925
6926
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006927TEST(ConstSloppy) {
6928 // clang-format off
6929 const char* context_data[][2] = {
6930 {"", ""},
6931 {"{", "}"},
6932 {NULL, NULL}
6933 };
6934
6935 const char* data[] = {
6936 "const x = 1",
6937 "for (const x = 1; x < 1; x++) {}",
6938 "for (const x in {}) {}",
6939 "for (const x of []) {}",
6940 NULL
6941 };
6942 // clang-format on
Ben Murdochc5610432016-08-08 18:44:38 +01006943 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006944}
6945
6946
6947TEST(LetSloppy) {
6948 // clang-format off
6949 const char* context_data[][2] = {
6950 {"", ""},
6951 {"'use strict';", ""},
6952 {"{", "}"},
6953 {NULL, NULL}
6954 };
6955
6956 const char* data[] = {
6957 "let x",
6958 "let x = 1",
6959 "for (let x = 1; x < 1; x++) {}",
6960 "for (let x in {}) {}",
6961 "for (let x of []) {}",
6962 NULL
6963 };
6964 // clang-format on
6965
Ben Murdochc5610432016-08-08 18:44:38 +01006966 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006967}
6968
6969
6970TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
6971 // TC39 deemed "use strict" directives to be an error when occurring in the
6972 // body of a function with non-simple parameter list, on 29/7/2015.
6973 // https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006974 const char* context_data[][2] = {
6975 {"function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006976 {"function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006977 {"class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006978 {"var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006979 {"var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006980 {"var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006981 {"var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006982 {"var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006983
6984 {"'use strict'; function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006985 {"'use strict'; function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006986 {"'use strict'; class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006987 {"'use strict'; var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006988 {"'use strict'; var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006989 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006990 {"'use strict'; var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006991 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006992
6993 {NULL, NULL}};
6994
6995 const char* data[] = {
6996 // TODO(@caitp): support formal parameter initializers
6997 "{}",
6998 "[]",
6999 "[{}]",
7000 "{a}",
7001 "a, {b}",
7002 "a, b, {c, d, e}",
7003 "initializer = true",
7004 "a, b, c = 1",
7005 "...args",
7006 "a, b, ...rest",
7007 "[a, b, ...rest]",
7008 "{ bindingPattern = {} }",
7009 "{ initializedBindingPattern } = { initializedBindingPattern: true }",
7010 NULL};
7011
Ben Murdochc5610432016-08-08 18:44:38 +01007012 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007013}
7014
7015
7016TEST(LetSloppyOnly) {
7017 // clang-format off
7018 const char* context_data[][2] = {
7019 {"", ""},
7020 {"{", "}"},
7021 {"(function() {", "})()"},
7022 {NULL, NULL}
7023 };
7024
7025 const char* data[] = {
7026 "let",
7027 "let = 1",
7028 "for (let = 1; let < 1; let++) {}",
7029 "for (let in {}) {}",
7030 "for (var let = 1; let < 1; let++) {}",
7031 "for (var let in {}) {}",
7032 "for (var [let] = 1; let < 1; let++) {}",
7033 "for (var [let] in {}) {}",
7034 "var let",
7035 "var [let] = []",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007036 NULL
7037 };
7038 // clang-format on
7039
Ben Murdochc5610432016-08-08 18:44:38 +01007040 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007041
7042 // Some things should be rejected even in sloppy mode
7043 // This addresses BUG(v8:4403).
7044
7045 // clang-format off
7046 const char* fail_data[] = {
7047 "let let = 1",
7048 "for (let let = 1; let < 1; let++) {}",
7049 "for (let let in {}) {}",
7050 "for (let let of []) {}",
7051 "const let = 1",
7052 "for (const let = 1; let < 1; let++) {}",
7053 "for (const let in {}) {}",
7054 "for (const let of []) {}",
7055 "let [let] = 1",
7056 "for (let [let] = 1; let < 1; let++) {}",
7057 "for (let [let] in {}) {}",
7058 "for (let [let] of []) {}",
7059 "const [let] = 1",
7060 "for (const [let] = 1; let < 1; let++) {}",
7061 "for (const [let] in {}) {}",
7062 "for (const [let] of []) {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007063
7064 // Sprinkle in the escaped version too.
7065 "let l\\u0065t = 1",
7066 "const l\\u0065t = 1",
7067 "let [l\\u0065t] = 1",
7068 "const [l\\u0065t] = 1",
7069 "for (let l\\u0065t in {}) {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007070 NULL
7071 };
7072 // clang-format on
7073
Ben Murdochc5610432016-08-08 18:44:38 +01007074 RunParserSyncTest(context_data, fail_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007075}
7076
7077
7078TEST(EscapedKeywords) {
7079 // clang-format off
7080 const char* sloppy_context_data[][2] = {
7081 {"", ""},
7082 {NULL, NULL}
7083 };
7084
7085 const char* strict_context_data[][2] = {
7086 {"'use strict';", ""},
7087 {NULL, NULL}
7088 };
7089
7090 const char* fail_data[] = {
7091 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
7092 "cl\\u0061ss Foo {}",
7093 "var x = cl\\u0061ss {}",
7094 "\\u0063onst foo = 1;",
7095 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
7096 "d\\u0065bugger;",
7097 "d\\u0065lete this.a;",
7098 "\\u0063o { } while(0)",
7099 "if (d\\u006f { true }) {}",
7100 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
7101 "e\\u0078port var foo;",
7102 "try { } catch (e) {} f\\u0069nally { }",
7103 "f\\u006fr (var i = 0; i < 10; ++i);",
7104 "f\\u0075nction fn() {}",
7105 "var f = f\\u0075nction() {}",
7106 "\\u0069f (true) { }",
7107 "\\u0069mport blah from './foo.js';",
7108 "n\\u0065w function f() {}",
7109 "(function() { r\\u0065turn; })()",
7110 "class C extends function() {} { constructor() { sup\\u0065r() } }",
7111 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
7112 "sw\\u0069tch (this.a) {}",
7113 "var x = th\\u0069s;",
7114 "th\\u0069s.a = 1;",
7115 "thr\\u006fw 'boo';",
7116 "t\\u0072y { true } catch (e) {}",
7117 "var x = typ\\u0065of 'blah'",
7118 "v\\u0061r a = true",
7119 "var v\\u0061r = true",
7120 "(function() { return v\\u006fid 0; })()",
7121 "wh\\u0069le (true) { }",
7122 "w\\u0069th (this.scope) { }",
7123 "(function*() { y\\u0069eld 1; })()",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007124 "(function*() { var y\\u0069eld = 1; })()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007125
7126 "var \\u0065num = 1;",
7127 "var { \\u0065num } = {}",
7128 "(\\u0065num = 1);",
7129
7130 // Null / Boolean literals
7131 "(x === n\\u0075ll);",
7132 "var x = n\\u0075ll;",
7133 "var n\\u0075ll = 1;",
7134 "var { n\\u0075ll } = { 1 };",
7135 "n\\u0075ll = 1;",
7136 "(x === tr\\u0075e);",
7137 "var x = tr\\u0075e;",
7138 "var tr\\u0075e = 1;",
7139 "var { tr\\u0075e } = {};",
7140 "tr\\u0075e = 1;",
7141 "(x === f\\u0061lse);",
7142 "var x = f\\u0061lse;",
7143 "var f\\u0061lse = 1;",
7144 "var { f\\u0061lse } = {};",
7145 "f\\u0061lse = 1;",
7146
7147 // TODO(caitp): consistent error messages for labeled statements and
7148 // expressions
7149 "switch (this.a) { c\\u0061se 6: break; }",
7150 "try { } c\\u0061tch (e) {}",
7151 "switch (this.a) { d\\u0065fault: break; }",
7152 "class C \\u0065xtends function B() {} {}",
7153 "for (var a i\\u006e this) {}",
7154 "if ('foo' \\u0069n this) {}",
7155 "if (this \\u0069nstanceof Array) {}",
7156 "(n\\u0065w function f() {})",
7157 "(typ\\u0065of 123)",
7158 "(v\\u006fid 0)",
7159 "do { ; } wh\\u0069le (true) { }",
7160 "(function*() { return (n++, y\\u0069eld 1); })()",
7161 "class C { st\\u0061tic bar() {} }",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007162 "class C { st\\u0061tic *bar() {} }",
7163 "class C { st\\u0061tic get bar() {} }",
7164 "class C { st\\u0061tic set bar() {} }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007165
Ben Murdoch097c5b22016-05-18 11:27:45 +01007166 // TODO(adamk): These should not be errors in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007167 "(y\\u0069eld);",
7168 "var y\\u0069eld = 1;",
7169 "var { y\\u0069eld } = {};",
7170 NULL
7171 };
7172 // clang-format on
7173
Ben Murdochc5610432016-08-08 18:44:38 +01007174 RunParserSyncTest(sloppy_context_data, fail_data, kError);
7175 RunParserSyncTest(strict_context_data, fail_data, kError);
7176 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007177
7178 // clang-format off
7179 const char* let_data[] = {
7180 "var l\\u0065t = 1;",
7181 "l\\u0065t = 1;",
7182 "(l\\u0065t === 1);",
7183 NULL
7184 };
7185 // clang-format on
7186
Ben Murdochc5610432016-08-08 18:44:38 +01007187 RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
7188 RunParserSyncTest(strict_context_data, let_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007189
7190 // Non-errors in sloppy mode
7191 const char* valid_data[] = {"(\\u0069mplements = 1);",
7192 "var impl\\u0065ments = 1;",
7193 "var { impl\\u0065ments } = {};",
7194 "(\\u0069nterface = 1);",
7195 "var int\\u0065rface = 1;",
7196 "var { int\\u0065rface } = {};",
7197 "(p\\u0061ckage = 1);",
7198 "var packa\\u0067e = 1;",
7199 "var { packa\\u0067e } = {};",
7200 "(p\\u0072ivate = 1);",
7201 "var p\\u0072ivate;",
7202 "var { p\\u0072ivate } = {};",
7203 "(prot\\u0065cted);",
7204 "var prot\\u0065cted = 1;",
7205 "var { prot\\u0065cted } = {};",
7206 "(publ\\u0069c);",
7207 "var publ\\u0069c = 1;",
7208 "var { publ\\u0069c } = {};",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007209 "(st\\u0061tic);",
7210 "var st\\u0061tic = 1;",
7211 "var { st\\u0061tic } = {};",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007212 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01007213 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
7214 RunParserSyncTest(strict_context_data, valid_data, kError);
7215 RunModuleParserSyncTest(strict_context_data, valid_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007216}
7217
7218
7219TEST(MiscSyntaxErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007220 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007221 const char* context_data[][2] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007222 { "'use strict'", "" },
7223 { "", "" },
7224 { NULL, NULL }
7225 };
7226 const char* error_data[] = {
7227 "for (();;) {}",
7228
7229 // crbug.com/582626
7230 "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
7231 NULL
7232 };
7233 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007234
Ben Murdochc5610432016-08-08 18:44:38 +01007235 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007236}
Ben Murdoch097c5b22016-05-18 11:27:45 +01007237
Ben Murdochda12d292016-06-02 14:46:10 +01007238
7239TEST(EscapeSequenceErrors) {
7240 // clang-format off
7241 const char* context_data[][2] = {
7242 { "'", "'" },
7243 { "\"", "\"" },
7244 { "`", "`" },
7245 { "`${'", "'}`" },
7246 { "`${\"", "\"}`" },
7247 { "`${`", "`}`" },
7248 { "f(tag`", "`);" },
7249 { NULL, NULL }
7250 };
7251 const char* error_data[] = {
7252 "\\uABCG",
7253 "\\u{ZZ}",
7254 "\\u{FFZ}",
7255 "\\u{FFFFFFFFFF }",
7256 "\\u{110000}",
7257 "\\u{110000",
7258 "\\u{FFFD }",
7259 "\\xZF",
7260 NULL
7261 };
7262 // clang-format on
7263
Ben Murdochc5610432016-08-08 18:44:38 +01007264 RunParserSyncTest(context_data, error_data, kError);
Ben Murdochda12d292016-06-02 14:46:10 +01007265}
7266
7267
Ben Murdoch097c5b22016-05-18 11:27:45 +01007268TEST(FunctionSentErrors) {
7269 // clang-format off
7270 const char* context_data[][2] = {
7271 { "'use strict'", "" },
7272 { "", "" },
7273 { NULL, NULL }
7274 };
7275 const char* error_data[] = {
7276 "var x = function.sent",
7277 "function* g() { yield function.s\\u0065nt; }",
7278 NULL
7279 };
7280 // clang-format on
7281
7282 static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
7283 RunParserSyncTest(context_data, error_data, kError, always_flags,
7284 arraysize(always_flags));
7285}
7286
7287TEST(NewTargetErrors) {
7288 // clang-format off
7289 const char* context_data[][2] = {
7290 { "'use strict'", "" },
7291 { "", "" },
7292 { NULL, NULL }
7293 };
7294 const char* error_data[] = {
7295 "var x = new.target",
7296 "function f() { return new.t\\u0061rget; }",
7297 NULL
7298 };
7299 // clang-format on
7300 RunParserSyncTest(context_data, error_data, kError);
7301}
Ben Murdochda12d292016-06-02 14:46:10 +01007302
7303TEST(FunctionDeclarationError) {
7304 // clang-format off
7305 const char* strict_context[][2] = {
7306 { "'use strict';", "" },
7307 { "'use strict'; { ", "}" },
7308 {"(function() { 'use strict';", "})()"},
7309 {"(function() { 'use strict'; {", "} })()"},
7310 { NULL, NULL }
7311 };
7312 const char* sloppy_context[][2] = {
7313 { "", "" },
7314 { "{", "}" },
7315 {"(function() {", "})()"},
7316 {"(function() { {", "} })()"},
7317 { NULL, NULL }
7318 };
7319 // Invalid in all contexts
7320 const char* error_data[] = {
7321 "try function foo() {} catch (e) {}",
7322 NULL
7323 };
7324 // Valid in sloppy mode only, and only when the
7325 // --harmony-restrictive-declarations flag is off
7326 const char* unrestricted_data[] = {
7327 "do function foo() {} while (0);",
7328 "for (;false;) function foo() {}",
7329 "for (var i = 0; i < 1; i++) function f() { };",
7330 "for (var x in {a: 1}) function f() { };",
7331 "for (var x in {}) function f() { };",
7332 "for (var x in {}) function foo() {}",
7333 "for (x in {a: 1}) function f() { };",
7334 "for (x in {}) function f() { };",
7335 "var x; for (x in {}) function foo() {}",
7336 "with ({}) function f() { };",
7337 "do label: function foo() {} while (0);",
7338 "for (;false;) label: function foo() {}",
7339 "for (var i = 0; i < 1; i++) label: function f() { };",
7340 "for (var x in {a: 1}) label: function f() { };",
7341 "for (var x in {}) label: function f() { };",
7342 "for (var x in {}) label: function foo() {}",
7343 "for (x in {a: 1}) label: function f() { };",
7344 "for (x in {}) label: function f() { };",
7345 "var x; for (x in {}) label: function foo() {}",
7346 "with ({}) label: function f() { };",
7347 "if (true) label: function f() {}",
7348 "if (true) {} else label: function f() {}",
Ben Murdochc5610432016-08-08 18:44:38 +01007349 "if (true) function* f() { }",
7350 "label: function* f() { }",
7351 // TODO(littledan, v8:4806): Ban duplicate generator declarations in
7352 // a block, maybe by tracking whether a Variable is a generator declaration
7353 // "{ function* f() {} function* f() {} }",
7354 // "{ function f() {} function* f() {} }",
7355 // "{ function* f() {} function f() {} }",
Ben Murdochda12d292016-06-02 14:46:10 +01007356 NULL
7357 };
7358 // Valid only in sloppy mode, with or without
7359 // --harmony-restrictive-declarations
7360 const char* sloppy_data[] = {
7361 "if (true) function foo() {}",
7362 "if (false) {} else function f() { };",
7363 "label: function f() { }",
7364 "label: if (true) function f() { }",
7365 "label: if (true) {} else function f() { }",
7366 NULL
7367 };
7368 // clang-format on
7369
7370 static const ParserFlag restrictive_flags[] = {
7371 kAllowHarmonyRestrictiveDeclarations};
7372
7373 // Nothing parses in strict mode without a SyntaxError
7374 RunParserSyncTest(strict_context, error_data, kError);
7375 RunParserSyncTest(strict_context, error_data, kError, NULL, 0,
7376 restrictive_flags, arraysize(restrictive_flags));
7377 RunParserSyncTest(strict_context, unrestricted_data, kError);
7378 RunParserSyncTest(strict_context, unrestricted_data, kError, NULL, 0,
7379 restrictive_flags, arraysize(restrictive_flags));
7380 RunParserSyncTest(strict_context, sloppy_data, kError);
7381 RunParserSyncTest(strict_context, sloppy_data, kError, NULL, 0,
7382 restrictive_flags, arraysize(restrictive_flags));
7383
7384 // In sloppy mode, some things are successful, depending on the flag
7385 RunParserSyncTest(sloppy_context, error_data, kError);
7386 RunParserSyncTest(sloppy_context, error_data, kError, NULL, 0,
7387 restrictive_flags, arraysize(restrictive_flags));
7388 RunParserSyncTest(sloppy_context, unrestricted_data, kSuccess);
7389 RunParserSyncTest(sloppy_context, unrestricted_data, kError, NULL, 0,
7390 restrictive_flags, arraysize(restrictive_flags));
7391 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
7392 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess, restrictive_flags,
7393 arraysize(restrictive_flags));
7394}
7395
7396TEST(ExponentiationOperator) {
7397 // clang-format off
7398 const char* context_data[][2] = {
7399 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7400 { "var O = { p: 1 }, x = 10; ; (", ")" },
7401 { "var O = { p: 1 }, x = 10; foo(", ")" },
7402 { NULL, NULL }
7403 };
7404 const char* data[] = {
7405 "(delete O.p) ** 10",
7406 "(delete x) ** 10",
7407 "(~O.p) ** 10",
7408 "(~x) ** 10",
7409 "(!O.p) ** 10",
7410 "(!x) ** 10",
7411 "(+O.p) ** 10",
7412 "(+x) ** 10",
7413 "(-O.p) ** 10",
7414 "(-x) ** 10",
7415 "(typeof O.p) ** 10",
7416 "(typeof x) ** 10",
7417 "(void 0) ** 10",
7418 "(void O.p) ** 10",
7419 "(void x) ** 10",
7420 "++O.p ** 10",
7421 "++x ** 10",
7422 "--O.p ** 10",
7423 "--x ** 10",
7424 "O.p++ ** 10",
7425 "x++ ** 10",
7426 "O.p-- ** 10",
7427 "x-- ** 10",
7428 NULL
7429 };
7430 // clang-format on
7431
7432 static const ParserFlag always_flags[] = {
7433 kAllowHarmonyExponentiationOperator};
7434 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7435 arraysize(always_flags));
7436}
7437
7438TEST(ExponentiationOperatorErrors) {
7439 // clang-format off
7440 const char* context_data[][2] = {
7441 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7442 { "var O = { p: 1 }, x = 10; ; (", ")" },
7443 { "var O = { p: 1 }, x = 10; foo(", ")" },
7444 { NULL, NULL }
7445 };
7446 const char* error_data[] = {
7447 "delete O.p ** 10",
7448 "delete x ** 10",
7449 "~O.p ** 10",
7450 "~x ** 10",
7451 "!O.p ** 10",
7452 "!x ** 10",
7453 "+O.p ** 10",
7454 "+x ** 10",
7455 "-O.p ** 10",
7456 "-x ** 10",
7457 "typeof O.p ** 10",
7458 "typeof x ** 10",
7459 "void ** 10",
7460 "void O.p ** 10",
7461 "void x ** 10",
7462 "++delete O.p ** 10",
7463 "--delete O.p ** 10",
7464 "++~O.p ** 10",
7465 "++~x ** 10",
7466 "--!O.p ** 10",
7467 "--!x ** 10",
7468 "++-O.p ** 10",
7469 "++-x ** 10",
7470 "--+O.p ** 10",
7471 "--+x ** 10",
7472 "[ x ] **= [ 2 ]",
7473 "[ x **= 2 ] = [ 2 ]",
7474 "{ x } **= { x: 2 }",
7475 "{ x: x **= 2 ] = { x: 2 }",
7476 // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
7477 // "Array() **= 10",
7478 NULL
7479 };
7480 // clang-format on
7481
7482 static const ParserFlag always_flags[] = {
7483 kAllowHarmonyExponentiationOperator};
7484 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7485 arraysize(always_flags));
7486}
Ben Murdochc5610432016-08-08 18:44:38 +01007487
7488TEST(AsyncAwait) {
7489 // clang-format off
7490 const char* context_data[][2] = {
7491 { "'use strict';", "" },
7492 { "", "" },
7493 { NULL, NULL }
7494 };
7495
7496 const char* data[] = {
7497 "var asyncFn = async function() { await 1; };",
7498 "var asyncFn = async function withName() { await 1; };",
7499 "var asyncFn = async () => await 'test';",
7500 "var asyncFn = async x => await x + 'test';",
7501 "async function asyncFn() { await 1; }",
7502 "var O = { async method() { await 1; } }",
7503 "var O = { async ['meth' + 'od']() { await 1; } }",
7504 "var O = { async 'method'() { await 1; } }",
7505 "var O = { async 0() { await 1; } }",
7506 "async function await() {}",
Ben Murdoch61f157c2016-09-16 13:49:30 +01007507
7508 "var asyncFn = async({ foo = 1 }) => foo;",
7509 "var asyncFn = async({ foo = 1 } = {}) => foo;",
Ben Murdochc5610432016-08-08 18:44:38 +01007510 NULL
7511 };
7512 // clang-format on
7513
7514 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7515 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7516 arraysize(always_flags));
7517
7518 // clang-format off
7519 const char* async_body_context_data[][2] = {
7520 { "async function f() {", "}" },
7521 { "var f = async function() {", "}" },
7522 { "var f = async() => {", "}" },
7523 { "var O = { async method() {", "} }" },
7524 { "'use strict'; async function f() {", "}" },
7525 { "'use strict'; var f = async function() {", "}" },
7526 { "'use strict'; var f = async() => {", "}" },
7527 { "'use strict'; var O = { async method() {", "} }" },
7528 { NULL, NULL }
7529 };
7530
7531 const char* body_context_data[][2] = {
7532 { "function f() {", "}" },
7533 { "function* g() {", "}" },
7534 { "var f = function() {", "}" },
7535 { "var g = function*() {", "}" },
7536 { "var O = { method() {", "} }" },
7537 { "var O = { *method() {", "} }" },
7538 { "var f = () => {", "}" },
7539 { "'use strict'; function f() {", "}" },
7540 { "'use strict'; function* g() {", "}" },
7541 { "'use strict'; var f = function() {", "}" },
7542 { "'use strict'; var g = function*() {", "}" },
7543 { "'use strict'; var O = { method() {", "} }" },
7544 { "'use strict'; var O = { *method() {", "} }" },
7545 { "'use strict'; var f = () => {", "}" },
7546 { NULL, NULL }
7547 };
7548
7549 const char* body_data[] = {
7550 "var async = 1; return async;",
7551 "let async = 1; return async;",
7552 "const async = 1; return async;",
7553 "function async() {} return async();",
7554 "var async = async => async; return async();",
7555 "function foo() { var await = 1; return await; }",
7556 "function foo(await) { return await; }",
7557 "function* foo() { var await = 1; return await; }",
7558 "function* foo(await) { return await; }",
7559 "var f = (await) => await;",
7560 "var f = () => { var await = 1; return await; }",
7561 "var O = { method() { var await = 1; return await; } };",
7562 "var O = { method(await) { return await; } };",
7563 "var O = { *method() { var await = 1; return await; } };",
7564 "var O = { *method(await) { return await; } };",
7565
7566 "(function await() {})",
7567 NULL
7568 };
7569 // clang-format on
7570
7571 RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0,
7572 always_flags, arraysize(always_flags));
7573 RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0,
7574 always_flags, arraysize(always_flags));
7575}
7576
7577TEST(AsyncAwaitErrors) {
7578 // clang-format off
7579 const char* context_data[][2] = {
7580 { "'use strict';", "" },
7581 { "", "" },
7582 { NULL, NULL }
7583 };
7584
7585 const char* strict_context_data[][2] = {
7586 { "'use strict';", "" },
7587 { NULL, NULL }
7588 };
7589
7590 const char* error_data[] = {
7591 "var asyncFn = async function() { var await = 1; };",
7592 "var asyncFn = async function() { var { await } = 1; };",
7593 "var asyncFn = async function() { var [ await ] = 1; };",
7594 "var asyncFn = async function await() {};",
7595 "var asyncFn = async () => var await = 'test';",
7596 "var asyncFn = async await => await + 'test';",
7597 "var asyncFn = async function(await) {};",
7598 "var asyncFn = async function() { return async (await) => {}; }",
7599 "var asyncFn = async (await) => 'test';",
7600 "var asyncFn = async x => { var await = 1; }",
7601 "var asyncFn = async x => { var { await } = 1; }",
7602 "var asyncFn = async x => { var [ await ] = 1; }",
7603 "async function f(await) {}",
7604 "async function f() { var await = 1; }",
7605 "async function f() { var { await } = 1; }",
7606 "async function f() { var [ await ] = 1; }",
7607
7608 "var O = { async method(a, a) {} }",
7609 "var O = { async ['meth' + 'od'](a, a) {} }",
7610 "var O = { async 'method'(a, a) {} }",
7611 "var O = { async 0(a, a) {} }",
7612
7613 "async function f() { var O = { async [await](a, a) {} } }",
7614
7615 "var asyncFn = async function() { await; }",
7616 "async function f() { await; }",
7617 "var O = { async method() { await; } };",
7618 "var f = async() => await;",
7619 "var f = async() => { await; };",
7620
7621 "var asyncFn = async function*() {}",
7622 "async function* f() {}",
7623 "var O = { *async method() {} };",
7624 "var O = { async *method() {} };",
7625 "var O = { async method*() {} };",
7626
7627 "var asyncFn = async function(x = await 1) { return x; }",
7628 "async function f(x = await 1) { return x; }",
7629 "var f = async(x = await 1) => x;",
7630 "var O = { async method(x = await 1) { return x; } };",
7631
7632 "var f = async(x = await) => 1;",
7633
7634 "class C { async constructor() {} }",
7635 "class C {}; class C2 extends C { async constructor() {} }",
7636 "class C { static async prototype() {} }",
7637 "class C {}; class C2 extends C { static async prototype() {} }",
7638
7639 "var f = async() => ((async(x = await 1) => x)();",
7640
7641 "var asyncFn = async function() { function await() {} }",
7642 "var asyncFn = async() => { function await() {} }",
7643 "var O = { async method() { function await() {} } }",
7644 "async function foo() { function await() {} }",
7645
Ben Murdoch61f157c2016-09-16 13:49:30 +01007646 // Henrique Ferreiro's bug (tm)
7647 "(async function foo() { } foo => 1)",
7648 "(async function foo() { } () => 1)",
7649 "(async function foo() { } => 1)",
7650 "(async function() { } foo => 1)",
7651 "(async function() { } () => 1)",
7652 "(async function() { } => 1)",
7653 "(async.foo => 1)",
7654 "(async.foo foo => 1)",
7655 "(async.foo () => 1)",
7656 "(async().foo => 1)",
7657 "(async().foo foo => 1)",
7658 "(async().foo () => 1)",
7659 "(async['foo'] => 1)",
7660 "(async['foo'] foo => 1)",
7661 "(async['foo'] () => 1)",
7662 "(async()['foo'] => 1)",
7663 "(async()['foo'] foo => 1)",
7664 "(async()['foo'] () => 1)",
7665 "(async`foo` => 1)",
7666 "(async`foo` foo => 1)",
7667 "(async`foo` () => 1)",
7668 "(async`foo`.bar => 1)",
7669 "(async`foo`.bar foo => 1)",
7670 "(async`foo`.bar () => 1)",
7671
7672 // v8:5148 assert that errors are still thrown for calls that may have been
7673 // async functions
7674 "async({ foo = 1 })",
Ben Murdochc5610432016-08-08 18:44:38 +01007675 NULL
7676 };
7677
7678 const char* strict_error_data[] = {
7679 "var O = { async method(eval) {} }",
7680 "var O = { async ['meth' + 'od'](eval) {} }",
7681 "var O = { async 'method'(eval) {} }",
7682 "var O = { async 0(eval) {} }",
7683
7684 "var O = { async method(arguments) {} }",
7685 "var O = { async ['meth' + 'od'](arguments) {} }",
7686 "var O = { async 'method'(arguments) {} }",
7687 "var O = { async 0(arguments) {} }",
7688
7689 "var O = { async method(dupe, dupe) {} }",
7690
7691 // TODO(caitp): preparser needs to report duplicate parameter errors, too.
7692 // "var f = async(dupe, dupe) => {}",
7693
7694 NULL
7695 };
Ben Murdoch61f157c2016-09-16 13:49:30 +01007696
7697 const char* formal_parameters_data[] = {
7698 "var f = async({ await }) => 1;",
7699 "var f = async({ await = 1 }) => 1;",
7700 "var f = async({ await } = {}) => 1;",
7701 "var f = async({ await = 1 } = {}) => 1;",
7702 "var f = async([await]) => 1;",
7703 "var f = async([await] = []) => 1;",
7704 "var f = async([await = 1]) => 1;",
7705 "var f = async([await = 1] = []) => 1;",
7706 "var f = async(...await) => 1;",
7707 "var f = async(await) => 1;",
7708 "var f = async(await = 1) => 1;",
7709 "var f = async(...[await]) => 1;",
7710 NULL
7711 };
Ben Murdochc5610432016-08-08 18:44:38 +01007712 // clang-format on
7713
7714 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7715 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7716 arraysize(always_flags));
7717 RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0,
7718 always_flags, arraysize(always_flags));
Ben Murdoch61f157c2016-09-16 13:49:30 +01007719
7720 RunParserSyncTest(context_data, formal_parameters_data, kError, NULL, 0,
7721 always_flags, arraysize(always_flags));
Ben Murdochc5610432016-08-08 18:44:38 +01007722}
7723
7724TEST(AsyncAwaitModule) {
7725 // clang-format off
7726 const char* context_data[][2] = {
7727 { "", "" },
7728 { NULL, NULL }
7729 };
7730
7731 const char* data[] = {
7732 "export default async function() { await 1; }",
7733 "export default async function async() { await 1; }",
7734 "export async function async() { await 1; }",
7735 NULL
7736 };
7737 // clang-format on
7738
7739 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7740 RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7741 arraysize(always_flags), NULL, 0, false);
7742}
7743
7744TEST(AsyncAwaitModuleErrors) {
7745 // clang-format off
7746 const char* context_data[][2] = {
7747 { "", "" },
7748 { NULL, NULL }
7749 };
7750
7751 const char* error_data[] = {
7752 "export default (async function await() {})",
7753 "export default async function await() {}",
7754 "export async function await() {}",
7755 "export async function() {}",
7756 "export async",
7757 NULL
7758 };
7759 // clang-format on
7760
7761 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7762 RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0,
7763 always_flags, arraysize(always_flags), NULL, 0,
7764 false);
7765}
7766
7767TEST(RestrictiveForInErrors) {
7768 // clang-format off
7769 const char* context_data[][2] = {
7770 { "'use strict'", "" },
7771 { "", "" },
7772 { NULL, NULL }
7773 };
7774 const char* error_data[] = {
7775 "for (var x = 0 in {});",
7776 "for (const x = 0 in {});",
7777 "for (let x = 0 in {});",
7778 NULL
7779 };
7780 // clang-format on
7781
7782 static const ParserFlag always_flags[] = {kAllowHarmonyForIn};
7783 RunParserSyncTest(context_data, error_data, kError, nullptr, 0, always_flags,
7784 arraysize(always_flags));
7785}
Ben Murdoch61f157c2016-09-16 13:49:30 +01007786
7787TEST(NoDuplicateGeneratorsInBlock) {
7788 const char* block_context_data[][2] = {
7789 {"'use strict'; {", "}"},
7790 {"{", "}"},
7791 {"(function() { {", "} })()"},
7792 {"(function() {'use strict'; {", "} })()"},
7793 {NULL, NULL}};
7794 const char* top_level_context_data[][2] = {
7795 {"'use strict';", ""},
7796 {"", ""},
7797 {"(function() {", "})()"},
7798 {"(function() {'use strict';", "})()"},
7799 {NULL, NULL}};
7800 const char* error_data[] = {"function* x() {} function* x() {}",
7801 "function x() {} function* x() {}",
7802 "function* x() {} function x() {}", NULL};
7803 static const ParserFlag always_flags[] = {kAllowHarmonyRestrictiveGenerators};
7804 // The preparser doesn't enforce the restriction, so turn it off.
7805 bool test_preparser = false;
7806 RunParserSyncTest(block_context_data, error_data, kError, NULL, 0,
7807 always_flags, arraysize(always_flags), NULL, 0, false,
7808 test_preparser);
7809 RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0,
7810 always_flags, arraysize(always_flags));
7811}
7812
7813TEST(NoDuplicateAsyncFunctionInBlock) {
7814 const char* block_context_data[][2] = {
7815 {"'use strict'; {", "}"},
7816 {"{", "}"},
7817 {"(function() { {", "} })()"},
7818 {"(function() {'use strict'; {", "} })()"},
7819 {NULL, NULL}};
7820 const char* top_level_context_data[][2] = {
7821 {"'use strict';", ""},
7822 {"", ""},
7823 {"(function() {", "})()"},
7824 {"(function() {'use strict';", "})()"},
7825 {NULL, NULL}};
7826 const char* error_data[] = {"async function x() {} async function x() {}",
7827 "function x() {} async function x() {}",
7828 "async function x() {} function x() {}",
7829 "function* x() {} async function x() {}",
7830 "function* x() {} async function x() {}",
7831 "async function x() {} function* x() {}",
7832 "function* x() {} async function x() {}",
7833 NULL};
7834 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7835 // The preparser doesn't enforce the restriction, so turn it off.
7836 bool test_preparser = false;
7837 RunParserSyncTest(block_context_data, error_data, kError, NULL, 0,
7838 always_flags, arraysize(always_flags), NULL, 0, false,
7839 test_preparser);
7840 RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0,
7841 always_flags, arraysize(always_flags));
7842}