blob: 36f729344f94e2fc931bfe43fa42f2d46cfcbb12 [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,
1512 kAllowHarmonyAsyncAwait
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513};
1514
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515enum ParserSyncTestResult {
1516 kSuccessOrError,
1517 kSuccess,
1518 kError
1519};
1520
1521template <typename Traits>
1522void SetParserFlags(i::ParserBase<Traits>* parser,
1523 i::EnumSet<ParserFlag> flags) {
1524 parser->set_allow_lazy(flags.Contains(kAllowLazy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001525 parser->set_allow_natives(flags.Contains(kAllowNatives));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001526 parser->set_allow_harmony_function_sent(
1527 flags.Contains(kAllowHarmonyFunctionSent));
Ben Murdochda12d292016-06-02 14:46:10 +01001528 parser->set_allow_harmony_restrictive_declarations(
1529 flags.Contains(kAllowHarmonyRestrictiveDeclarations));
1530 parser->set_allow_harmony_exponentiation_operator(
1531 flags.Contains(kAllowHarmonyExponentiationOperator));
Ben Murdochc5610432016-08-08 18:44:38 +01001532 parser->set_allow_harmony_for_in(flags.Contains(kAllowHarmonyForIn));
1533 parser->set_allow_harmony_async_await(
1534 flags.Contains(kAllowHarmonyAsyncAwait));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535}
1536
1537
1538void TestParserSyncWithFlags(i::Handle<i::String> source,
1539 i::EnumSet<ParserFlag> flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001540 ParserSyncTestResult result,
Ben Murdochc5610432016-08-08 18:44:38 +01001541 bool is_module = false,
1542 bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001543 i::Isolate* isolate = CcTest::i_isolate();
1544 i::Factory* factory = isolate->factory();
1545
1546 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001547 int preparser_materialized_literals = -1;
1548 int parser_materialized_literals = -2;
Ben Murdoch692be652012-01-10 18:47:50 +00001549
1550 // Preparse the data.
1551 i::CompleteParserRecorder log;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 if (test_preparser) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001553 i::Scanner scanner(isolate->unicode_cache());
1554 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
Ben Murdochda12d292016-06-02 14:46:10 +01001555 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556 i::AstValueFactory ast_value_factory(
1557 &zone, CcTest::i_isolate()->heap()->HashSeed());
1558 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
1559 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560 SetParserFlags(&preparser, flags);
1561 scanner.Initialize(&stream);
Ben Murdochc5610432016-08-08 18:44:38 +01001562 i::PreParser::PreParseResult result =
1563 preparser.PreParseProgram(&preparser_materialized_literals, is_module);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001564 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1565 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001566 bool preparse_error = log.HasError();
Ben Murdoch692be652012-01-10 18:47:50 +00001567
1568 // Parse the data
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 i::FunctionLiteral* function;
1570 {
1571 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001572 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 i::ParseInfo info(&zone, script);
1574 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001575 SetParserFlags(&parser, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 if (is_module) {
1577 info.set_module();
1578 } else {
1579 info.set_global();
1580 }
1581 parser.Parse(&info);
1582 function = info.literal();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001583 if (function) {
1584 parser_materialized_literals = function->materialized_literal_count();
1585 }
Ben Murdoch692be652012-01-10 18:47:50 +00001586 }
1587
1588 // Check that preparsing fails iff parsing fails.
Ben Murdoch692be652012-01-10 18:47:50 +00001589 if (function == NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590 // Extract exception from the parser.
1591 CHECK(isolate->has_pending_exception());
1592 i::Handle<i::JSObject> exception_handle(
1593 i::JSObject::cast(isolate->pending_exception()));
Ben Murdochda12d292016-06-02 14:46:10 +01001594 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
1595 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1596 .ToHandleChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001597
1598 if (result == kSuccess) {
1599 v8::base::OS::Print(
1600 "Parser failed on:\n"
1601 "\t%s\n"
1602 "with error:\n"
1603 "\t%s\n"
1604 "However, we expected no error.",
1605 source->ToCString().get(), message_string->ToCString().get());
1606 CHECK(false);
1607 }
1608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609 if (test_preparser && !preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 v8::base::OS::Print(
1611 "Parser failed on:\n"
1612 "\t%s\n"
1613 "with error:\n"
1614 "\t%s\n"
1615 "However, the preparser succeeded",
1616 source->ToCString().get(), message_string->ToCString().get());
1617 CHECK(false);
1618 }
1619 // Check that preparser and parser produce the same error.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620 if (test_preparser) {
1621 i::Handle<i::String> preparser_message =
1622 FormatMessage(log.ErrorMessageData());
1623 if (!i::String::Equals(message_string, preparser_message)) {
1624 v8::base::OS::Print(
1625 "Expected parser and preparser to produce the same error on:\n"
1626 "\t%s\n"
1627 "However, found the following error messages\n"
1628 "\tparser: %s\n"
1629 "\tpreparser: %s\n",
1630 source->ToCString().get(), message_string->ToCString().get(),
1631 preparser_message->ToCString().get());
1632 CHECK(false);
1633 }
Ben Murdoch692be652012-01-10 18:47:50 +00001634 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 } else if (test_preparser && preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001636 v8::base::OS::Print(
1637 "Preparser failed on:\n"
1638 "\t%s\n"
1639 "with error:\n"
1640 "\t%s\n"
1641 "However, the parser succeeded",
1642 source->ToCString().get(),
1643 FormatMessage(log.ErrorMessageData())->ToCString().get());
1644 CHECK(false);
1645 } else if (result == kError) {
1646 v8::base::OS::Print(
1647 "Expected error on:\n"
1648 "\t%s\n"
1649 "However, parser and preparser succeeded",
1650 source->ToCString().get());
1651 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001652 } else if (test_preparser &&
1653 preparser_materialized_literals != parser_materialized_literals) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001654 v8::base::OS::Print(
1655 "Preparser materialized literals (%d) differ from Parser materialized "
1656 "literals (%d) on:\n"
1657 "\t%s\n"
1658 "However, parser and preparser succeeded",
1659 preparser_materialized_literals, parser_materialized_literals,
1660 source->ToCString().get());
1661 CHECK(false);
Ben Murdoch692be652012-01-10 18:47:50 +00001662 }
1663}
1664
1665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666void TestParserSync(const char* source, const ParserFlag* varying_flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001667 size_t varying_flags_length,
1668 ParserSyncTestResult result = kSuccessOrError,
1669 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001670 size_t always_true_flags_length = 0,
1671 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 size_t always_false_flags_length = 0,
Ben Murdochc5610432016-08-08 18:44:38 +01001673 bool is_module = false, bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 i::Handle<i::String> str =
1675 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1676 for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1677 i::EnumSet<ParserFlag> flags;
1678 for (size_t flag_index = 0; flag_index < varying_flags_length;
1679 ++flag_index) {
1680 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1681 }
1682 for (size_t flag_index = 0; flag_index < always_true_flags_length;
1683 ++flag_index) {
1684 flags.Add(always_true_flags[flag_index]);
1685 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001686 for (size_t flag_index = 0; flag_index < always_false_flags_length;
1687 ++flag_index) {
1688 flags.Remove(always_false_flags[flag_index]);
1689 }
Ben Murdochc5610432016-08-08 18:44:38 +01001690 TestParserSyncWithFlags(str, flags, result, is_module, test_preparser);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001691 }
1692}
1693
1694
Ben Murdoch692be652012-01-10 18:47:50 +00001695TEST(ParserSync) {
1696 const char* context_data[][2] = {
1697 { "", "" },
1698 { "{", "}" },
1699 { "if (true) ", " else {}" },
1700 { "if (true) {} else ", "" },
1701 { "if (true) ", "" },
1702 { "do ", " while (false)" },
1703 { "while (false) ", "" },
1704 { "for (;;) ", "" },
1705 { "with ({})", "" },
1706 { "switch (12) { case 12: ", "}" },
1707 { "switch (12) { default: ", "}" },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708 { "switch (12) { ", "case 12: }" },
Ben Murdoch692be652012-01-10 18:47:50 +00001709 { "label2: ", "" },
1710 { NULL, NULL }
1711 };
1712
1713 const char* statement_data[] = {
1714 "{}",
1715 "var x",
1716 "var x = 1",
1717 "const x",
1718 "const x = 1",
1719 ";",
1720 "12",
1721 "if (false) {} else ;",
1722 "if (false) {} else {}",
1723 "if (false) {} else 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001724 "if (false) ;",
Ben Murdoch692be652012-01-10 18:47:50 +00001725 "if (false) {}",
1726 "if (false) 12",
1727 "do {} while (false)",
1728 "for (;;) ;",
1729 "for (;;) {}",
1730 "for (;;) 12",
1731 "continue",
1732 "continue label",
1733 "continue\nlabel",
1734 "break",
1735 "break label",
1736 "break\nlabel",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737 // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1738 // "return",
1739 // "return 12",
1740 // "return\n12",
Ben Murdoch692be652012-01-10 18:47:50 +00001741 "with ({}) ;",
1742 "with ({}) {}",
1743 "with ({}) 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001744 "switch ({}) { default: }",
1745 "label3: ",
Ben Murdoch692be652012-01-10 18:47:50 +00001746 "throw",
1747 "throw 12",
1748 "throw\n12",
1749 "try {} catch(e) {}",
1750 "try {} finally {}",
1751 "try {} catch(e) {} finally {}",
1752 "debugger",
1753 NULL
1754 };
1755
1756 const char* termination_data[] = {
1757 "",
1758 ";",
1759 "\n",
1760 ";\n",
1761 "\n;",
1762 NULL
1763 };
1764
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001765 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001766 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch692be652012-01-10 18:47:50 +00001767 v8::Context::Scope context_scope(context);
1768
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1770 i::GetCurrentStackPosition() - 128 * 1024);
1771
Ben Murdoch692be652012-01-10 18:47:50 +00001772 for (int i = 0; context_data[i][0] != NULL; ++i) {
1773 for (int j = 0; statement_data[j] != NULL; ++j) {
1774 for (int k = 0; termination_data[k] != NULL; ++k) {
1775 int kPrefixLen = i::StrLength(context_data[i][0]);
1776 int kStatementLen = i::StrLength(statement_data[j]);
1777 int kTerminationLen = i::StrLength(termination_data[k]);
1778 int kSuffixLen = i::StrLength(context_data[i][1]);
1779 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1780 + kSuffixLen + i::StrLength("label: for (;;) { }");
1781
1782 // Plug the source code pieces together.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001783 i::ScopedVector<char> program(kProgramSize + 1);
1784 int length = i::SNPrintF(program,
Ben Murdoch692be652012-01-10 18:47:50 +00001785 "label: for (;;) { %s%s%s%s }",
1786 context_data[i][0],
1787 statement_data[j],
1788 termination_data[k],
1789 context_data[i][1]);
1790 CHECK(length == kProgramSize);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001791 TestParserSync(program.start(), NULL, 0);
Ben Murdoch692be652012-01-10 18:47:50 +00001792 }
1793 }
1794 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795
1796 // Neither Harmony numeric literals nor our natives syntax have any
1797 // interaction with the flags above, so test these separately to reduce
1798 // the combinatorial explosion.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 TestParserSync("0o1234", NULL, 0);
1800 TestParserSync("0b1011", NULL, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001801
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001802 static const ParserFlag flags3[] = { kAllowNatives };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001803 TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1804}
1805
1806
1807TEST(StrictOctal) {
1808 // Test that syntax error caused by octal literal is reported correctly as
1809 // such (issue 2220).
1810 v8::V8::Initialize();
1811 v8::HandleScope scope(CcTest::isolate());
1812 v8::Context::Scope context_scope(
1813 v8::Context::New(CcTest::isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001814 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001815 const char* script =
1816 "\"use strict\"; \n"
1817 "a = function() { \n"
1818 " b = function() { \n"
1819 " 01; \n"
1820 " }; \n"
1821 "}; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 v8_compile(v8_str(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001823 CHECK(try_catch.HasCaught());
1824 v8::String::Utf8Value exception(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825 CHECK_EQ(0,
1826 strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1827 *exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828}
1829
1830
1831void RunParserSyncTest(const char* context_data[][2],
1832 const char* statement_data[],
1833 ParserSyncTestResult result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001834 const ParserFlag* flags = NULL, int flags_len = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001835 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001836 int always_true_len = 0,
1837 const ParserFlag* always_false_flags = NULL,
Ben Murdochc5610432016-08-08 18:44:38 +01001838 int always_false_len = 0, bool is_module = false,
1839 bool test_preparser = true) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001841 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001842 v8::Context::Scope context_scope(context);
1843
1844 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1845 i::GetCurrentStackPosition() - 128 * 1024);
1846
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001847 // Experimental feature flags should not go here; pass the flags as
1848 // always_true_flags if the test needs them.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001849 static const ParserFlag default_flags[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001850 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001851 kAllowNatives,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001852 };
1853 ParserFlag* generated_flags = NULL;
1854 if (flags == NULL) {
1855 flags = default_flags;
1856 flags_len = arraysize(default_flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001857 if (always_true_flags != NULL || always_false_flags != NULL) {
1858 // Remove always_true/false_flags from default_flags (if present).
1859 CHECK((always_true_flags != NULL) == (always_true_len > 0));
1860 CHECK((always_false_flags != NULL) == (always_false_len > 0));
1861 generated_flags = new ParserFlag[flags_len + always_true_len];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001862 int flag_index = 0;
1863 for (int i = 0; i < flags_len; ++i) {
1864 bool use_flag = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001865 for (int j = 0; use_flag && j < always_true_len; ++j) {
1866 if (flags[i] == always_true_flags[j]) use_flag = false;
1867 }
1868 for (int j = 0; use_flag && j < always_false_len; ++j) {
1869 if (flags[i] == always_false_flags[j]) use_flag = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001870 }
1871 if (use_flag) generated_flags[flag_index++] = flags[i];
1872 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 flags_len = flag_index;
1874 flags = generated_flags;
1875 }
1876 }
1877 for (int i = 0; context_data[i][0] != NULL; ++i) {
1878 for (int j = 0; statement_data[j] != NULL; ++j) {
1879 int kPrefixLen = i::StrLength(context_data[i][0]);
1880 int kStatementLen = i::StrLength(statement_data[j]);
1881 int kSuffixLen = i::StrLength(context_data[i][1]);
1882 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1883
1884 // Plug the source code pieces together.
1885 i::ScopedVector<char> program(kProgramSize + 1);
1886 int length = i::SNPrintF(program,
1887 "%s%s%s",
1888 context_data[i][0],
1889 statement_data[j],
1890 context_data[i][1]);
1891 CHECK(length == kProgramSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001892 TestParserSync(program.start(), flags, flags_len, result,
1893 always_true_flags, always_true_len, always_false_flags,
Ben Murdochc5610432016-08-08 18:44:38 +01001894 always_false_len, is_module, test_preparser);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001895 }
1896 }
1897 delete[] generated_flags;
1898}
1899
1900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901void RunModuleParserSyncTest(const char* context_data[][2],
1902 const char* statement_data[],
1903 ParserSyncTestResult result,
1904 const ParserFlag* flags = NULL, int flags_len = 0,
1905 const ParserFlag* always_true_flags = NULL,
1906 int always_true_len = 0,
1907 const ParserFlag* always_false_flags = NULL,
Ben Murdochc5610432016-08-08 18:44:38 +01001908 int always_false_len = 0,
1909 bool test_preparser = true) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001910 RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1911 always_true_flags, always_true_len, always_false_flags,
Ben Murdochc5610432016-08-08 18:44:38 +01001912 always_false_len, true, test_preparser);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001913}
1914
1915
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001916TEST(ErrorsEvalAndArguments) {
1917 // Tests that both preparsing and parsing produce the right kind of errors for
1918 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1919 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1920 // isn't.
1921 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001922 {"\"use strict\";", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001923 {"var eval; function test_func() {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001925
1926 const char* statement_data[] = {
1927 "var eval;",
1928 "var arguments",
1929 "var foo, eval;",
1930 "var foo, arguments;",
1931 "try { } catch (eval) { }",
1932 "try { } catch (arguments) { }",
1933 "function eval() { }",
1934 "function arguments() { }",
1935 "function foo(eval) { }",
1936 "function foo(arguments) { }",
1937 "function foo(bar, eval) { }",
1938 "function foo(bar, arguments) { }",
1939 "(eval) => { }",
1940 "(arguments) => { }",
1941 "(foo, eval) => { }",
1942 "(foo, arguments) => { }",
1943 "eval = 1;",
1944 "arguments = 1;",
1945 "var foo = eval = 1;",
1946 "var foo = arguments = 1;",
1947 "++eval;",
1948 "++arguments;",
1949 "eval++;",
1950 "arguments++;",
1951 NULL
1952 };
1953
Ben Murdochda12d292016-06-02 14:46:10 +01001954 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001955}
1956
1957
1958TEST(NoErrorsEvalAndArgumentsSloppy) {
1959 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1960 // identifiers when needed.
1961 const char* context_data[][2] = {
1962 { "", "" },
1963 { "function test_func() {", "}"},
1964 { NULL, NULL }
1965 };
1966
1967 const char* statement_data[] = {
1968 "var eval;",
1969 "var arguments",
1970 "var foo, eval;",
1971 "var foo, arguments;",
1972 "try { } catch (eval) { }",
1973 "try { } catch (arguments) { }",
1974 "function eval() { }",
1975 "function arguments() { }",
1976 "function foo(eval) { }",
1977 "function foo(arguments) { }",
1978 "function foo(bar, eval) { }",
1979 "function foo(bar, arguments) { }",
1980 "eval = 1;",
1981 "arguments = 1;",
1982 "var foo = eval = 1;",
1983 "var foo = arguments = 1;",
1984 "++eval;",
1985 "++arguments;",
1986 "eval++;",
1987 "arguments++;",
1988 NULL
1989 };
1990
1991 RunParserSyncTest(context_data, statement_data, kSuccess);
1992}
1993
1994
1995TEST(NoErrorsEvalAndArgumentsStrict) {
1996 const char* context_data[][2] = {
1997 { "\"use strict\";", "" },
1998 { "function test_func() { \"use strict\";", "}" },
1999 { "() => { \"use strict\"; ", "}" },
2000 { NULL, NULL }
2001 };
2002
2003 const char* statement_data[] = {
2004 "eval;",
2005 "arguments;",
2006 "var foo = eval;",
2007 "var foo = arguments;",
2008 "var foo = { eval: 1 };",
2009 "var foo = { arguments: 1 };",
2010 "var foo = { }; foo.eval = {};",
2011 "var foo = { }; foo.arguments = {};",
2012 NULL
2013 };
2014
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002015 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002016}
2017
Ben Murdochc5610432016-08-08 18:44:38 +01002018#define FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2019 V(implements) \
2020 V(interface) \
2021 V(package) \
2022 V(private) \
2023 V(protected) \
2024 V(public) \
2025 V(static) \
2026 V(yield)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002027
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002028#define FUTURE_STRICT_RESERVED_WORDS(V) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002029 V(let) \
Ben Murdochc5610432016-08-08 18:44:38 +01002030 FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002031
Ben Murdochc5610432016-08-08 18:44:38 +01002032#define LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V) \
2033 V(implements) \
2034 V(static) \
2035 V(yield)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002036
2037#define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002038 V(let) \
Ben Murdochc5610432016-08-08 18:44:38 +01002039 LIMITED_FUTURE_STRICT_RESERVED_WORDS_NO_LET(V)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002040
2041#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2042 "var " #NAME ";", \
2043 "var foo, " #NAME ";", \
2044 "try { } catch (" #NAME ") { }", \
2045 "function " #NAME "() { }", \
2046 "(function " #NAME "() { })", \
2047 "function foo(" #NAME ") { }", \
2048 "function foo(bar, " #NAME ") { }", \
2049 #NAME " = 1;", \
2050 #NAME " += 1;", \
2051 "var foo = " #NAME " = 1;", \
2052 "++" #NAME ";", \
2053 #NAME " ++;",
2054
Ben Murdochc5610432016-08-08 18:44:38 +01002055// clang-format off
2056#define FUTURE_STRICT_RESERVED_LEX_BINDINGS(NAME) \
2057 "let " #NAME ";", \
2058 "for (let " #NAME "; false; ) {}", \
2059 "for (let " #NAME " in {}) {}", \
2060 "for (let " #NAME " of []) {}", \
2061 "const " #NAME " = null;", \
2062 "for (const " #NAME " = null; false; ) {}", \
2063 "for (const " #NAME " in {}) {}", \
2064 "for (const " #NAME " of []) {}",
2065// clang-format on
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002066
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002067TEST(ErrorsFutureStrictReservedWords) {
2068 // Tests that both preparsing and parsing produce the right kind of errors for
2069 // using future strict reserved words as identifiers. Without the strict mode,
2070 // it's ok to use future strict reserved words as identifiers. With the strict
2071 // mode, it isn't.
Ben Murdochc5610432016-08-08 18:44:38 +01002072 const char* strict_contexts[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002073 {"function test_func() {\"use strict\"; ", "}"},
2074 {"() => { \"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002075 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076
Ben Murdochc5610432016-08-08 18:44:38 +01002077 // clang-format off
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002078 const char* statement_data[] {
2079 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochc5610432016-08-08 18:44:38 +01002080 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002081 NULL
2082 };
Ben Murdochc5610432016-08-08 18:44:38 +01002083 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002084
Ben Murdochc5610432016-08-08 18:44:38 +01002085 RunParserSyncTest(strict_contexts, statement_data, kError);
2086
2087 // From ES2015, 13.3.1.1 Static Semantics: Early Errors:
2088 //
2089 // > LexicalDeclaration : LetOrConst BindingList ;
2090 // >
2091 // > - It is a Syntax Error if the BoundNames of BindingList contains "let".
2092 const char* non_strict_contexts[][2] = {{"", ""},
2093 {"function test_func() {", "}"},
2094 {"() => {", "}"},
2095 {NULL, NULL}};
2096 const char* invalid_statements[] = {FUTURE_STRICT_RESERVED_LEX_BINDINGS("let")
2097 NULL};
2098
2099 RunParserSyncTest(non_strict_contexts, invalid_statements, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002100}
2101
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002102#undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2103
2104
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002105TEST(NoErrorsFutureStrictReservedWords) {
2106 const char* context_data[][2] = {
2107 { "", "" },
2108 { "function test_func() {", "}"},
2109 { "() => {", "}" },
2110 { NULL, NULL }
2111 };
2112
Ben Murdochc5610432016-08-08 18:44:38 +01002113 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002114 const char* statement_data[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002115 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochc5610432016-08-08 18:44:38 +01002116 FUTURE_STRICT_RESERVED_WORDS_NO_LET(FUTURE_STRICT_RESERVED_LEX_BINDINGS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002117 NULL
2118 };
Ben Murdochc5610432016-08-08 18:44:38 +01002119 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002121 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002122}
2123
2124
2125TEST(ErrorsReservedWords) {
2126 // Tests that both preparsing and parsing produce the right kind of errors for
2127 // using future reserved words as identifiers. These tests don't depend on the
2128 // strict mode.
2129 const char* context_data[][2] = {
2130 { "", "" },
2131 { "\"use strict\";", "" },
2132 { "var eval; function test_func() {", "}"},
2133 { "var eval; function test_func() {\"use strict\"; ", "}"},
2134 { "var eval; () => {", "}"},
2135 { "var eval; () => {\"use strict\"; ", "}"},
2136 { NULL, NULL }
2137 };
2138
2139 const char* statement_data[] = {
2140 "var super;",
2141 "var foo, super;",
2142 "try { } catch (super) { }",
2143 "function super() { }",
2144 "function foo(super) { }",
2145 "function foo(bar, super) { }",
2146 "(super) => { }",
2147 "(bar, super) => { }",
2148 "super = 1;",
2149 "var foo = super = 1;",
2150 "++super;",
2151 "super++;",
2152 "function foo super",
2153 NULL
2154 };
2155
2156 RunParserSyncTest(context_data, statement_data, kError);
2157}
2158
2159
2160TEST(NoErrorsLetSloppyAllModes) {
2161 // In sloppy mode, it's okay to use "let" as identifier.
2162 const char* context_data[][2] = {
2163 { "", "" },
2164 { "function f() {", "}" },
2165 { "(function f() {", "})" },
2166 { NULL, NULL }
2167 };
2168
2169 const char* statement_data[] = {
2170 "var let;",
2171 "var foo, let;",
2172 "try { } catch (let) { }",
2173 "function let() { }",
2174 "(function let() { })",
2175 "function foo(let) { }",
2176 "function foo(bar, let) { }",
2177 "let = 1;",
2178 "var foo = let = 1;",
2179 "let * 2;",
2180 "++let;",
2181 "let++;",
2182 "let: 34",
2183 "function let(let) { let: let(let + let(0)); }",
2184 "({ let: 1 })",
2185 "({ get let() { 1 } })",
2186 "let(100)",
2187 NULL
2188 };
2189
2190 RunParserSyncTest(context_data, statement_data, kSuccess);
2191}
2192
2193
2194TEST(NoErrorsYieldSloppyAllModes) {
2195 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2196 // generator (see other test).
2197 const char* context_data[][2] = {
2198 { "", "" },
2199 { "function not_gen() {", "}" },
2200 { "(function not_gen() {", "})" },
2201 { NULL, NULL }
2202 };
2203
2204 const char* statement_data[] = {
2205 "var yield;",
2206 "var foo, yield;",
2207 "try { } catch (yield) { }",
2208 "function yield() { }",
2209 "(function yield() { })",
2210 "function foo(yield) { }",
2211 "function foo(bar, yield) { }",
2212 "yield = 1;",
2213 "var foo = yield = 1;",
2214 "yield * 2;",
2215 "++yield;",
2216 "yield++;",
2217 "yield: 34",
2218 "function yield(yield) { yield: yield (yield + yield(0)); }",
2219 "({ yield: 1 })",
2220 "({ get yield() { 1 } })",
2221 "yield(100)",
2222 "yield[100]",
2223 NULL
2224 };
2225
2226 RunParserSyncTest(context_data, statement_data, kSuccess);
2227}
2228
2229
2230TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2231 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2232 // generator (see next test).
2233 const char* context_data[][2] = {
2234 { "", "" },
2235 { "function not_gen() {", "}" },
2236 { "function * gen() { function not_gen() {", "} }" },
2237 { "(function not_gen() {", "})" },
2238 { "(function * gen() { (function not_gen() {", "}) })" },
2239 { NULL, NULL }
2240 };
2241
2242 const char* statement_data[] = {
2243 "var yield;",
2244 "var foo, yield;",
2245 "try { } catch (yield) { }",
2246 "function yield() { }",
2247 "(function yield() { })",
2248 "function foo(yield) { }",
2249 "function foo(bar, yield) { }",
2250 "function * yield() { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002251 "yield = 1;",
2252 "var foo = yield = 1;",
2253 "yield * 2;",
2254 "++yield;",
2255 "yield++;",
2256 "yield: 34",
2257 "function yield(yield) { yield: yield (yield + yield(0)); }",
2258 "({ yield: 1 })",
2259 "({ get yield() { 1 } })",
2260 "yield(100)",
2261 "yield[100]",
2262 NULL
2263 };
2264
2265 RunParserSyncTest(context_data, statement_data, kSuccess);
2266}
2267
2268
2269TEST(ErrorsYieldStrict) {
2270 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002271 {"\"use strict\";", ""},
2272 {"\"use strict\"; function not_gen() {", "}"},
2273 {"function test_func() {\"use strict\"; ", "}"},
2274 {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2275 {"\"use strict\"; (function not_gen() {", "})"},
2276 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2277 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002278 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002279
2280 const char* statement_data[] = {
2281 "var yield;",
2282 "var foo, yield;",
2283 "try { } catch (yield) { }",
2284 "function yield() { }",
2285 "(function yield() { })",
2286 "function foo(yield) { }",
2287 "function foo(bar, yield) { }",
2288 "function * yield() { }",
2289 "(function * yield() { })",
2290 "yield = 1;",
2291 "var foo = yield = 1;",
2292 "++yield;",
2293 "yield++;",
2294 "yield: 34;",
2295 NULL
2296 };
2297
Ben Murdochda12d292016-06-02 14:46:10 +01002298 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002299}
2300
2301
2302TEST(ErrorsYieldSloppy) {
2303 const char* context_data[][2] = {
2304 { "", "" },
2305 { "function not_gen() {", "}" },
2306 { "(function not_gen() {", "})" },
2307 { NULL, NULL }
2308 };
2309
2310 const char* statement_data[] = {
2311 "(function * yield() { })",
2312 NULL
2313 };
2314
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002315 RunParserSyncTest(context_data, statement_data, kError);
2316}
2317
2318
2319TEST(NoErrorsGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002320 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002321 const char* context_data[][2] = {
2322 { "function * gen() {", "}" },
2323 { "(function * gen() {", "})" },
2324 { "(function * () {", "})" },
2325 { NULL, NULL }
2326 };
2327
2328 const char* statement_data[] = {
2329 // A generator without a body is valid.
2330 ""
2331 // Valid yield expressions inside generators.
2332 "yield 2;",
2333 "yield * 2;",
2334 "yield * \n 2;",
2335 "yield yield 1;",
2336 "yield * yield * 1;",
2337 "yield 3 + (yield 4);",
2338 "yield * 3 + (yield * 4);",
2339 "(yield * 3) + (yield * 4);",
2340 "yield 3; yield 4;",
2341 "yield * 3; yield * 4;",
2342 "(function (yield) { })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002343 "(function yield() { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002344 "yield { yield: 12 }",
2345 "yield /* comment */ { yield: 12 }",
2346 "yield * \n { yield: 12 }",
2347 "yield /* comment */ * \n { yield: 12 }",
2348 // You can return in a generator.
2349 "yield 1; return",
2350 "yield * 1; return",
2351 "yield 1; return 37",
2352 "yield * 1; return 37",
2353 "yield 1; return 37; yield 'dead';",
2354 "yield * 1; return 37; yield * 'dead';",
2355 // Yield is still a valid key in object literals.
2356 "({ yield: 1 })",
2357 "({ get yield() { } })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002358 // And in assignment pattern computed properties
2359 "({ [yield]: x } = { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002360 // Yield without RHS.
2361 "yield;",
2362 "yield",
2363 "yield\n",
2364 "yield /* comment */"
2365 "yield // comment\n"
2366 "(yield)",
2367 "[yield]",
2368 "{yield}",
2369 "yield, yield",
2370 "yield; yield",
2371 "(yield) ? yield : yield",
2372 "(yield) \n ? yield : yield",
2373 // If there is a newline before the next token, we don't look for RHS.
2374 "yield\nfor (;;) {}",
Ben Murdochda12d292016-06-02 14:46:10 +01002375 "x = class extends (yield) {}",
2376 "x = class extends f(yield) {}",
2377 "x = class extends (null, yield) { }",
2378 "x = class extends (a ? null : yield) { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002379 NULL
2380 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002381 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002382
Ben Murdochc5610432016-08-08 18:44:38 +01002383 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002384}
2385
2386
2387TEST(ErrorsYieldGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002388 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002389 const char* context_data[][2] = {
2390 { "function * gen() {", "}" },
2391 { "\"use strict\"; function * gen() {", "}" },
2392 { NULL, NULL }
2393 };
2394
2395 const char* statement_data[] = {
2396 // Invalid yield expressions inside generators.
2397 "var yield;",
2398 "var foo, yield;",
2399 "try { } catch (yield) { }",
2400 "function yield() { }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002401 // The name of the NFE is bound in the generator, which does not permit
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002402 // yield to be an identifier.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002403 "(function * yield() { })",
2404 // Yield isn't valid as a formal parameter for generators.
2405 "function * foo(yield) { }",
2406 "(function * foo(yield) { })",
2407 "yield = 1;",
2408 "var foo = yield = 1;",
2409 "++yield;",
2410 "yield++;",
2411 "yield *",
2412 "(yield *)",
2413 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2414 // is invalid.
2415 "yield 3 + yield 4;",
2416 "yield: 34",
2417 "yield ? 1 : 2",
2418 // Parses as yield (/ yield): invalid.
2419 "yield / yield",
2420 "+ yield",
2421 "+ yield 3",
2422 // Invalid (no newline allowed between yield and *).
2423 "yield\n*3",
2424 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2425 // object literal, and yield is not a valid label).
2426 "yield\n{yield: 42}",
2427 "yield /* comment */\n {yield: 42}",
2428 "yield //comment\n {yield: 42}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002429 // Destructuring binding and assignment are both disallowed
2430 "var [yield] = [42];",
2431 "var {foo: yield} = {a: 42};",
2432 "[yield] = [42];",
2433 "({a: yield} = {a: 42});",
2434 // Also disallow full yield expressions on LHS
2435 "var [yield 24] = [42];",
2436 "var {foo: yield 24} = {a: 42};",
2437 "[yield 24] = [42];",
2438 "({a: yield 24} = {a: 42});",
Ben Murdochc5610432016-08-08 18:44:38 +01002439 "for (yield 'x' in {});",
2440 "for (yield 'x' of {});",
2441 "for (yield 'x' in {} in {});",
2442 "for (yield 'x' in {} of {});",
Ben Murdochda12d292016-06-02 14:46:10 +01002443 "class C extends yield { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444 NULL
2445 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002446 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002447
2448 RunParserSyncTest(context_data, statement_data, kError);
2449}
2450
2451
2452TEST(ErrorsNameOfStrictFunction) {
2453 // Tests that illegal tokens as names of a strict function produce the correct
2454 // errors.
2455 const char* context_data[][2] = {
2456 { "function ", ""},
2457 { "\"use strict\"; function", ""},
2458 { "function * ", ""},
2459 { "\"use strict\"; function * ", ""},
2460 { NULL, NULL }
2461 };
2462
2463 const char* statement_data[] = {
2464 "eval() {\"use strict\";}",
2465 "arguments() {\"use strict\";}",
2466 "interface() {\"use strict\";}",
2467 "yield() {\"use strict\";}",
2468 // Future reserved words are always illegal
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002469 "super() { }",
2470 "super() {\"use strict\";}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002471 NULL
2472 };
2473
Ben Murdochda12d292016-06-02 14:46:10 +01002474 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002475}
2476
2477
2478TEST(NoErrorsNameOfStrictFunction) {
2479 const char* context_data[][2] = {
2480 { "function ", ""},
2481 { NULL, NULL }
2482 };
2483
2484 const char* statement_data[] = {
2485 "eval() { }",
2486 "arguments() { }",
2487 "interface() { }",
2488 "yield() { }",
2489 NULL
2490 };
2491
2492 RunParserSyncTest(context_data, statement_data, kSuccess);
2493}
2494
2495
2496TEST(NoErrorsNameOfStrictGenerator) {
2497 const char* context_data[][2] = {
2498 { "function * ", ""},
2499 { NULL, NULL }
2500 };
2501
2502 const char* statement_data[] = {
2503 "eval() { }",
2504 "arguments() { }",
2505 "interface() { }",
2506 "yield() { }",
2507 NULL
2508 };
2509
2510 RunParserSyncTest(context_data, statement_data, kSuccess);
2511}
2512
2513
2514TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2515 // Using future reserved words as labels is always an error.
2516 const char* context_data[][2] = {
2517 { "", ""},
2518 { "function test_func() {", "}" },
2519 { "() => {", "}" },
2520 { NULL, NULL }
2521 };
2522
2523 const char* statement_data[] = {
2524 "super: while(true) { break super; }",
2525 NULL
2526 };
2527
2528 RunParserSyncTest(context_data, statement_data, kError);
2529}
2530
2531
2532TEST(ErrorsIllegalWordsAsLabelsStrict) {
2533 // Tests that illegal tokens as labels produce the correct errors.
2534 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002535 {"\"use strict\";", ""},
2536 {"function test_func() {\"use strict\"; ", "}"},
2537 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002538 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002539
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002540#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002541 const char* statement_data[] = {
2542 "super: while(true) { break super; }",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002543 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544 NULL
2545 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002546#undef LABELLED_WHILE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002547
Ben Murdochda12d292016-06-02 14:46:10 +01002548 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002549}
2550
2551
2552TEST(NoErrorsIllegalWordsAsLabels) {
2553 // Using eval and arguments as labels is legal even in strict mode.
2554 const char* context_data[][2] = {
2555 { "", ""},
2556 { "function test_func() {", "}" },
2557 { "() => {", "}" },
2558 { "\"use strict\";", "" },
2559 { "\"use strict\"; function test_func() {", "}" },
2560 { "\"use strict\"; () => {", "}" },
2561 { NULL, NULL }
2562 };
2563
2564 const char* statement_data[] = {
2565 "mylabel: while(true) { break mylabel; }",
2566 "eval: while(true) { break eval; }",
2567 "arguments: while(true) { break arguments; }",
2568 NULL
2569 };
2570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002571 RunParserSyncTest(context_data, statement_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002572}
2573
2574
2575TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2576 const char* context_data[][2] = {
2577 { "", ""},
2578 { "function test_func() {", "}" },
2579 { "() => {", "}" },
2580 { NULL, NULL }
2581 };
2582
2583#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2584 const char* statement_data[] {
2585 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2586 NULL
2587 };
2588#undef LABELLED_WHILE
2589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002590 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002591}
2592
2593
2594TEST(ErrorsParenthesizedLabels) {
2595 // Parenthesized identifiers shouldn't be recognized as labels.
2596 const char* context_data[][2] = {
2597 { "", ""},
2598 { "function test_func() {", "}" },
2599 { "() => {", "}" },
2600 { NULL, NULL }
2601 };
2602
2603 const char* statement_data[] = {
2604 "(mylabel): while(true) { break mylabel; }",
2605 NULL
2606 };
2607
2608 RunParserSyncTest(context_data, statement_data, kError);
2609}
2610
2611
2612TEST(NoErrorsParenthesizedDirectivePrologue) {
2613 // Parenthesized directive prologue shouldn't be recognized.
2614 const char* context_data[][2] = {
2615 { "", ""},
2616 { NULL, NULL }
2617 };
2618
2619 const char* statement_data[] = {
2620 "(\"use strict\"); var eval;",
2621 NULL
2622 };
2623
Ben Murdochda12d292016-06-02 14:46:10 +01002624 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002625}
2626
2627
2628TEST(ErrorsNotAnIdentifierName) {
2629 const char* context_data[][2] = {
2630 { "", ""},
2631 { "\"use strict\";", ""},
2632 { NULL, NULL }
2633 };
2634
2635 const char* statement_data[] = {
2636 "var foo = {}; foo.{;",
2637 "var foo = {}; foo.};",
2638 "var foo = {}; foo.=;",
2639 "var foo = {}; foo.888;",
2640 "var foo = {}; foo.-;",
2641 "var foo = {}; foo.--;",
2642 NULL
2643 };
2644
2645 RunParserSyncTest(context_data, statement_data, kError);
2646}
2647
2648
2649TEST(NoErrorsIdentifierNames) {
2650 // Keywords etc. are valid as property names.
2651 const char* context_data[][2] = {
2652 { "", ""},
2653 { "\"use strict\";", ""},
2654 { NULL, NULL }
2655 };
2656
2657 const char* statement_data[] = {
2658 "var foo = {}; foo.if;",
2659 "var foo = {}; foo.yield;",
2660 "var foo = {}; foo.super;",
2661 "var foo = {}; foo.interface;",
2662 "var foo = {}; foo.eval;",
2663 "var foo = {}; foo.arguments;",
2664 NULL
2665 };
2666
2667 RunParserSyncTest(context_data, statement_data, kSuccess);
2668}
2669
2670
2671TEST(DontRegressPreParserDataSizes) {
2672 // These tests make sure that Parser doesn't start producing less "preparse
2673 // data" (data which the embedder can cache).
2674 v8::V8::Initialize();
2675 v8::Isolate* isolate = CcTest::isolate();
2676 v8::HandleScope handles(isolate);
2677
2678 CcTest::i_isolate()->stack_guard()->SetStackLimit(
2679 i::GetCurrentStackPosition() - 128 * 1024);
2680
2681 struct TestCase {
2682 const char* program;
2683 int functions;
2684 } test_cases[] = {
2685 // No functions.
2686 {"var x = 42;", 0},
2687 // Functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002688 {"function foo() {}", 1},
2689 {"function foo() {} function bar() {}", 2},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002690 // Getter / setter functions are recorded as functions if they're on the top
2691 // level.
2692 {"var x = {get foo(){} };", 1},
2693 // Functions insize lazy functions are not recorded.
2694 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2695 {"function lazy() { var x = {get foo(){} } }", 1},
2696 {NULL, 0}
2697 };
2698
2699 for (int i = 0; test_cases[i].program; i++) {
2700 const char* program = test_cases[i].program;
2701 i::Factory* factory = CcTest::i_isolate()->factory();
2702 i::Handle<i::String> source =
2703 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2704 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01002705 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002706 i::ParseInfo info(&zone, script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002707 i::ScriptData* sd = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002708 info.set_cached_data(&sd);
2709 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
2710 info.set_allow_lazy_parsing();
2711 i::Parser::ParseStatic(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002712 i::ParseData* pd = i::ParseData::FromCachedData(sd);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002713
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002714 if (pd->FunctionCount() != test_cases[i].functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002715 v8::base::OS::Print(
2716 "Expected preparse data for program:\n"
2717 "\t%s\n"
2718 "to contain %d functions, however, received %d functions.\n",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002719 program, test_cases[i].functions, pd->FunctionCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002720 CHECK(false);
2721 }
2722 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002723 delete pd;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002724 }
2725}
2726
2727
2728TEST(FunctionDeclaresItselfStrict) {
2729 // Tests that we produce the right kinds of errors when a function declares
2730 // itself strict (we cannot produce there errors as soon as we see the
2731 // offending identifiers, because we don't know at that point whether the
2732 // function is strict or not).
2733 const char* context_data[][2] = {
2734 {"function eval() {", "}"},
2735 {"function arguments() {", "}"},
2736 {"function yield() {", "}"},
2737 {"function interface() {", "}"},
2738 {"function foo(eval) {", "}"},
2739 {"function foo(arguments) {", "}"},
2740 {"function foo(yield) {", "}"},
2741 {"function foo(interface) {", "}"},
2742 {"function foo(bar, eval) {", "}"},
2743 {"function foo(bar, arguments) {", "}"},
2744 {"function foo(bar, yield) {", "}"},
2745 {"function foo(bar, interface) {", "}"},
2746 {"function foo(bar, bar) {", "}"},
2747 { NULL, NULL }
2748 };
2749
2750 const char* strict_statement_data[] = {
2751 "\"use strict\";",
2752 NULL
2753 };
2754
2755 const char* non_strict_statement_data[] = {
2756 ";",
2757 NULL
2758 };
2759
Ben Murdochda12d292016-06-02 14:46:10 +01002760 RunParserSyncTest(context_data, strict_statement_data, kError);
2761 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002762}
2763
2764
2765TEST(ErrorsTryWithoutCatchOrFinally) {
2766 const char* context_data[][2] = {
2767 {"", ""},
2768 { NULL, NULL }
2769 };
2770
2771 const char* statement_data[] = {
2772 "try { }",
2773 "try { } foo();",
2774 "try { } catch (e) foo();",
2775 "try { } catch { }",
2776 "try { } finally foo();",
2777 NULL
2778 };
2779
2780 RunParserSyncTest(context_data, statement_data, kError);
2781}
2782
2783
2784TEST(NoErrorsTryCatchFinally) {
2785 const char* context_data[][2] = {
2786 {"", ""},
2787 { NULL, NULL }
2788 };
2789
2790 const char* statement_data[] = {
2791 "try { } catch (e) { }",
2792 "try { } catch (e) { } finally { }",
2793 "try { } finally { }",
2794 NULL
2795 };
2796
2797 RunParserSyncTest(context_data, statement_data, kSuccess);
2798}
2799
2800
2801TEST(ErrorsRegexpLiteral) {
2802 const char* context_data[][2] = {
2803 {"var r = ", ""},
2804 { NULL, NULL }
2805 };
2806
2807 const char* statement_data[] = {
2808 "/unterminated",
2809 NULL
2810 };
2811
2812 RunParserSyncTest(context_data, statement_data, kError);
2813}
2814
2815
2816TEST(NoErrorsRegexpLiteral) {
2817 const char* context_data[][2] = {
2818 {"var r = ", ""},
2819 { NULL, NULL }
2820 };
2821
2822 const char* statement_data[] = {
2823 "/foo/",
2824 "/foo/g",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002825 NULL
2826 };
2827
2828 RunParserSyncTest(context_data, statement_data, kSuccess);
2829}
2830
2831
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002832TEST(NoErrorsNewExpression) {
2833 const char* context_data[][2] = {
2834 {"", ""},
2835 {"var f =", ""},
2836 { NULL, NULL }
2837 };
2838
2839 const char* statement_data[] = {
2840 "new foo",
2841 "new foo();",
2842 "new foo(1);",
2843 "new foo(1, 2);",
2844 // The first () will be processed as a part of the NewExpression and the
2845 // second () will be processed as part of LeftHandSideExpression.
2846 "new foo()();",
2847 // The first () will be processed as a part of the inner NewExpression and
2848 // the second () will be processed as a part of the outer NewExpression.
2849 "new new foo()();",
2850 "new foo.bar;",
2851 "new foo.bar();",
2852 "new foo.bar.baz;",
2853 "new foo.bar().baz;",
2854 "new foo[bar];",
2855 "new foo[bar]();",
2856 "new foo[bar][baz];",
2857 "new foo[bar]()[baz];",
2858 "new foo[bar].baz(baz)()[bar].baz;",
2859 "new \"foo\"", // Runtime error
2860 "new 1", // Runtime error
2861 // This even runs:
2862 "(new new Function(\"this.x = 1\")).x;",
2863 "new new Test_Two(String, 2).v(0123).length;",
2864 NULL
2865 };
2866
2867 RunParserSyncTest(context_data, statement_data, kSuccess);
2868}
2869
2870
2871TEST(ErrorsNewExpression) {
2872 const char* context_data[][2] = {
2873 {"", ""},
2874 {"var f =", ""},
2875 { NULL, NULL }
2876 };
2877
2878 const char* statement_data[] = {
2879 "new foo bar",
2880 "new ) foo",
2881 "new ++foo",
2882 "new foo ++",
2883 NULL
2884 };
2885
2886 RunParserSyncTest(context_data, statement_data, kError);
2887}
2888
2889
2890TEST(StrictObjectLiteralChecking) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002891 const char* context_data[][2] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002892 {"\"use strict\"; var myobject = {", "};"},
2893 {"\"use strict\"; var myobject = {", ",};"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002894 {"var myobject = {", "};"},
2895 {"var myobject = {", ",};"},
2896 { NULL, NULL }
2897 };
2898
2899 // These are only errors in strict mode.
2900 const char* statement_data[] = {
2901 "foo: 1, foo: 2",
2902 "\"foo\": 1, \"foo\": 2",
2903 "foo: 1, \"foo\": 2",
2904 "1: 1, 1: 2",
2905 "1: 1, \"1\": 2",
2906 "get: 1, get: 2", // Not a getter for real, just a property called get.
2907 "set: 1, set: 2", // Not a setter for real, just a property called set.
2908 NULL
2909 };
2910
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002911 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002912}
2913
2914
2915TEST(ErrorsObjectLiteralChecking) {
2916 const char* context_data[][2] = {
2917 {"\"use strict\"; var myobject = {", "};"},
2918 {"var myobject = {", "};"},
2919 { NULL, NULL }
2920 };
2921
2922 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002923 ",",
2924 // Wrong number of parameters
2925 "get bar(x) {}",
2926 "get bar(x, y) {}",
2927 "set bar() {}",
2928 "set bar(x, y) {}",
2929 // Parsing FunctionLiteral for getter or setter fails
2930 "get foo( +",
2931 "get foo() \"error\"",
2932 NULL
2933 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002934
2935 RunParserSyncTest(context_data, statement_data, kError);
2936}
2937
2938
2939TEST(NoErrorsObjectLiteralChecking) {
2940 const char* context_data[][2] = {
2941 {"var myobject = {", "};"},
2942 {"var myobject = {", ",};"},
2943 {"\"use strict\"; var myobject = {", "};"},
2944 {"\"use strict\"; var myobject = {", ",};"},
2945 { NULL, NULL }
2946 };
2947
2948 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002949 "foo: 1, get foo() {}",
2950 "foo: 1, set foo(v) {}",
2951 "\"foo\": 1, get \"foo\"() {}",
2952 "\"foo\": 1, set \"foo\"(v) {}",
2953 "1: 1, get 1() {}",
2954 "1: 1, set 1(v) {}",
2955 "get foo() {}, get foo() {}",
2956 "set foo(_) {}, set foo(v) {}",
2957 "foo: 1, get \"foo\"() {}",
2958 "foo: 1, set \"foo\"(v) {}",
2959 "\"foo\": 1, get foo() {}",
2960 "\"foo\": 1, set foo(v) {}",
2961 "1: 1, get \"1\"() {}",
2962 "1: 1, set \"1\"(v) {}",
2963 "\"1\": 1, get 1() {}",
2964 "\"1\": 1, set 1(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002965 "foo: 1, bar: 2",
2966 "\"foo\": 1, \"bar\": 2",
2967 "1: 1, 2: 2",
2968 // Syntax: IdentifierName ':' AssignmentExpression
2969 "foo: bar = 5 + baz",
2970 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2971 "get foo() {}",
2972 "get \"foo\"() {}",
2973 "get 1() {}",
2974 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2975 // '{' FunctionBody '}'
2976 "set foo(v) {}",
2977 "set \"foo\"(v) {}",
2978 "set 1(v) {}",
2979 // Non-colliding getters and setters -> no errors
2980 "foo: 1, get bar() {}",
2981 "foo: 1, set bar(v) {}",
2982 "\"foo\": 1, get \"bar\"() {}",
2983 "\"foo\": 1, set \"bar\"(v) {}",
2984 "1: 1, get 2() {}",
2985 "1: 1, set 2(v) {}",
2986 "get: 1, get foo() {}",
2987 "set: 1, set foo(_) {}",
2988 // Keywords, future reserved and strict future reserved are also allowed as
2989 // property names.
2990 "if: 4",
2991 "interface: 5",
2992 "super: 6",
2993 "eval: 7",
2994 "arguments: 8",
2995 NULL
2996 };
2997
2998 RunParserSyncTest(context_data, statement_data, kSuccess);
2999}
3000
3001
3002TEST(TooManyArguments) {
3003 const char* context_data[][2] = {
3004 {"foo(", "0)"},
3005 { NULL, NULL }
3006 };
3007
3008 using v8::internal::Code;
3009 char statement[Code::kMaxArguments * 2 + 1];
3010 for (int i = 0; i < Code::kMaxArguments; ++i) {
3011 statement[2 * i] = '0';
3012 statement[2 * i + 1] = ',';
3013 }
3014 statement[Code::kMaxArguments * 2] = 0;
3015
3016 const char* statement_data[] = {
3017 statement,
3018 NULL
3019 };
3020
3021 // The test is quite slow, so run it with a reduced set of flags.
3022 static const ParserFlag empty_flags[] = {kAllowLazy};
3023 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
3024}
3025
3026
3027TEST(StrictDelete) {
3028 // "delete <Identifier>" is not allowed in strict mode.
3029 const char* strict_context_data[][2] = {
3030 {"\"use strict\"; ", ""},
3031 { NULL, NULL }
3032 };
3033
3034 const char* sloppy_context_data[][2] = {
3035 {"", ""},
3036 { NULL, NULL }
3037 };
3038
3039 // These are errors in the strict mode.
3040 const char* sloppy_statement_data[] = {
3041 "delete foo;",
3042 "delete foo + 1;",
3043 "delete (foo);",
3044 "delete eval;",
3045 "delete interface;",
3046 NULL
3047 };
3048
3049 // These are always OK
3050 const char* good_statement_data[] = {
3051 "delete this;",
3052 "delete 1;",
3053 "delete 1 + 2;",
3054 "delete foo();",
3055 "delete foo.bar;",
3056 "delete foo[bar];",
3057 "delete foo--;",
3058 "delete --foo;",
3059 "delete new foo();",
3060 "delete new foo(bar);",
3061 NULL
3062 };
3063
3064 // These are always errors
3065 const char* bad_statement_data[] = {
3066 "delete if;",
3067 NULL
3068 };
3069
Ben Murdochda12d292016-06-02 14:46:10 +01003070 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
3071 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003072
Ben Murdochda12d292016-06-02 14:46:10 +01003073 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
3074 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003075
Ben Murdochda12d292016-06-02 14:46:10 +01003076 RunParserSyncTest(strict_context_data, bad_statement_data, kError);
3077 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003078}
3079
3080
3081TEST(NoErrorsDeclsInCase) {
3082 const char* context_data[][2] = {
3083 {"'use strict'; switch(x) { case 1:", "}"},
3084 {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3085 {"'use strict'; switch(x) { case 1: case 2:", "}"},
3086 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3087 {"'use strict'; switch(x) { default:", "}"},
3088 {"function foo() {'use strict'; switch(x) { default:", "}}"},
3089 {"'use strict'; switch(x) { case 1: default:", "}"},
3090 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3091 { nullptr, nullptr }
3092 };
3093
3094 const char* statement_data[] = {
3095 "function f() { }",
3096 "class C { }",
3097 "class C extends Q {}",
3098 "function f() { } class C {}",
3099 "function f() { }; class C {}",
3100 "class C {}; function f() {}",
3101 nullptr
3102 };
3103
3104 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003105}
3106
3107
3108TEST(InvalidLeftHandSide) {
3109 const char* assignment_context_data[][2] = {
3110 {"", " = 1;"},
3111 {"\"use strict\"; ", " = 1;"},
3112 { NULL, NULL }
3113 };
3114
3115 const char* prefix_context_data[][2] = {
3116 {"++", ";"},
3117 {"\"use strict\"; ++", ";"},
3118 {NULL, NULL},
3119 };
3120
3121 const char* postfix_context_data[][2] = {
3122 {"", "++;"},
3123 {"\"use strict\"; ", "++;"},
3124 { NULL, NULL }
3125 };
3126
3127 // Good left hand sides for assigment or prefix / postfix operations.
3128 const char* good_statement_data[] = {
3129 "foo",
3130 "foo.bar",
3131 "foo[bar]",
3132 "foo()[bar]",
3133 "foo().bar",
3134 "this.foo",
3135 "this[foo]",
3136 "new foo()[bar]",
3137 "new foo().bar",
3138 "foo()",
3139 "foo(bar)",
3140 "foo[bar]()",
3141 "foo.bar()",
3142 "this()",
3143 "this.foo()",
3144 "this[foo].bar()",
3145 "this.foo[foo].bar(this)(bar)[foo]()",
3146 NULL
3147 };
3148
3149 // Bad left hand sides for assigment or prefix / postfix operations.
3150 const char* bad_statement_data_common[] = {
3151 "2",
3152 "new foo",
3153 "new foo()",
3154 "null",
3155 "if", // Unexpected token
3156 "{x: 1}", // Unexpected token
3157 "this",
3158 "\"bar\"",
3159 "(foo + bar)",
3160 "new new foo()[bar]", // means: new (new foo()[bar])
3161 "new new foo().bar", // means: new (new foo()[bar])
3162 NULL
3163 };
3164
3165 // These are not okay for assignment, but okay for prefix / postix.
3166 const char* bad_statement_data_for_assignment[] = {
3167 "++foo",
3168 "foo++",
3169 "foo + bar",
3170 NULL
3171 };
3172
3173 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3174 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3175 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3176 kError);
3177
3178 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3179 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3180
3181 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3182 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3183}
3184
3185
3186TEST(FuncNameInferrerBasic) {
3187 // Tests that function names are inferred properly.
3188 i::FLAG_allow_natives_syntax = true;
3189 v8::Isolate* isolate = CcTest::isolate();
3190 v8::HandleScope scope(isolate);
3191 LocalContext env;
3192 CompileRun("var foo1 = function() {}; "
3193 "var foo2 = function foo3() {}; "
3194 "function not_ctor() { "
3195 " var foo4 = function() {}; "
3196 " return %FunctionGetInferredName(foo4); "
3197 "} "
3198 "function Ctor() { "
3199 " var foo5 = function() {}; "
3200 " return %FunctionGetInferredName(foo5); "
3201 "} "
3202 "var obj1 = { foo6: function() {} }; "
3203 "var obj2 = { 'foo7': function() {} }; "
3204 "var obj3 = {}; "
3205 "obj3[1] = function() {}; "
3206 "var obj4 = {}; "
3207 "obj4[1] = function foo8() {}; "
3208 "var obj5 = {}; "
3209 "obj5['foo9'] = function() {}; "
3210 "var obj6 = { obj7 : { foo10: function() {} } };");
3211 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3212 // foo2 is not unnamed -> its name is not inferred.
3213 ExpectString("%FunctionGetInferredName(foo2)", "");
3214 ExpectString("not_ctor()", "foo4");
3215 ExpectString("Ctor()", "Ctor.foo5");
3216 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3217 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3218 ExpectString("%FunctionGetInferredName(obj3[1])",
3219 "obj3.(anonymous function)");
3220 ExpectString("%FunctionGetInferredName(obj4[1])", "");
3221 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3222 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3223}
3224
3225
3226TEST(FuncNameInferrerTwoByte) {
3227 // Tests function name inferring in cases where some parts of the inferred
3228 // function name are two-byte strings.
3229 i::FLAG_allow_natives_syntax = true;
3230 v8::Isolate* isolate = CcTest::isolate();
3231 v8::HandleScope scope(isolate);
3232 LocalContext env;
3233 uint16_t* two_byte_source = AsciiToTwoByteString(
3234 "var obj1 = { oXj2 : { foo1: function() {} } }; "
3235 "%FunctionGetInferredName(obj1.oXj2.foo1)");
3236 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3237 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3238 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3239 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003240 v8::String::NewFromTwoByte(isolate, two_byte_source,
3241 v8::NewStringType::kNormal)
3242 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003243 v8::Local<v8::Value> result = CompileRun(source);
3244 CHECK(result->IsString());
3245 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003246 v8::String::NewFromTwoByte(isolate, two_byte_name,
3247 v8::NewStringType::kNormal)
3248 .ToLocalChecked();
3249 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003250 i::DeleteArray(two_byte_source);
3251 i::DeleteArray(two_byte_name);
3252}
3253
3254
3255TEST(FuncNameInferrerEscaped) {
3256 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3257 // character as a unicode escape.
3258 i::FLAG_allow_natives_syntax = true;
3259 v8::Isolate* isolate = CcTest::isolate();
3260 v8::HandleScope scope(isolate);
3261 LocalContext env;
3262 uint16_t* two_byte_source = AsciiToTwoByteString(
3263 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3264 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3265 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3266 // Fix to correspond to the non-ASCII name in two_byte_source.
3267 two_byte_name[6] = 0x010d;
3268 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003269 v8::String::NewFromTwoByte(isolate, two_byte_source,
3270 v8::NewStringType::kNormal)
3271 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003272 v8::Local<v8::Value> result = CompileRun(source);
3273 CHECK(result->IsString());
3274 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003275 v8::String::NewFromTwoByte(isolate, two_byte_name,
3276 v8::NewStringType::kNormal)
3277 .ToLocalChecked();
3278 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003279 i::DeleteArray(two_byte_source);
3280 i::DeleteArray(two_byte_name);
3281}
3282
3283
3284TEST(RegressionLazyFunctionWithErrorWithArg) {
Ben Murdochda12d292016-06-02 14:46:10 +01003285 // Test only applies when lazy parsing.
3286 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
3287
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003288 // The bug occurred when a lazy function had an error which requires a
3289 // parameter (such as "unknown label" here). The error message was processed
3290 // before the AstValueFactory containing the error message string was
3291 // internalized.
3292 v8::Isolate* isolate = CcTest::isolate();
3293 v8::HandleScope scope(isolate);
3294 LocalContext env;
3295 i::FLAG_lazy = true;
3296 i::FLAG_min_preparse_length = 0;
3297 CompileRun("function this_is_lazy() {\n"
3298 " break p;\n"
3299 "}\n"
3300 "this_is_lazy();\n");
3301}
3302
3303
3304TEST(SerializationOfMaybeAssignmentFlag) {
3305 i::Isolate* isolate = CcTest::i_isolate();
3306 i::Factory* factory = isolate->factory();
3307 i::HandleScope scope(isolate);
3308 LocalContext env;
3309
3310 const char* src =
3311 "function h() {"
3312 " var result = [];"
3313 " function f() {"
3314 " result.push(2);"
3315 " }"
3316 " function assertResult(r) {"
3317 " f();"
3318 " result = [];"
3319 " }"
3320 " assertResult([2]);"
3321 " assertResult([2]);"
3322 " return f;"
3323 "};"
3324 "h();";
3325
3326 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3327 i::SNPrintF(program, "%s", src);
3328 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3329 source->PrintOn(stdout);
3330 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003331 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003332 v8::Local<v8::Value> v = CompileRun(src);
3333 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3334 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3335 i::Context* context = f->context();
3336 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3337 avf.Internalize(isolate);
3338 const i::AstRawString* name = avf.GetOneByteString("result");
3339 i::Handle<i::String> str = name->string();
3340 CHECK(str->IsInternalizedString());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003341 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003342 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003343 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003344 i::Scope* s =
3345 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3346 CHECK(s != script_scope);
3347 CHECK(name != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003348
3349 // Get result from h's function context (that is f's context)
3350 i::Variable* var = s->Lookup(name);
3351
3352 CHECK(var != NULL);
3353 // Maybe assigned should survive deserialization
3354 CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3355 // TODO(sigurds) Figure out if is_used should survive context serialization.
3356}
3357
3358
3359TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3360 i::Isolate* isolate = CcTest::i_isolate();
3361 i::Factory* factory = isolate->factory();
3362 i::HandleScope scope(isolate);
3363 LocalContext env;
3364
3365
3366 const char* src =
3367 "function f(x) {"
3368 " var a = arguments;"
3369 " function g(i) {"
3370 " ++a[0];"
3371 " };"
3372 " return g;"
3373 " }"
3374 "f(0);";
3375
3376 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3377 i::SNPrintF(program, "%s", src);
3378 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3379 source->PrintOn(stdout);
3380 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003381 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003382 v8::Local<v8::Value> v = CompileRun(src);
3383 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3384 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3385 i::Context* context = f->context();
3386 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3387 avf.Internalize(isolate);
3388
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003389 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003390 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003391 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003392 i::Scope* s =
3393 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3394 CHECK(s != script_scope);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003395 const i::AstRawString* name_x = avf.GetOneByteString("x");
3396
3397 // Get result from f's function context (that is g's outer context)
3398 i::Variable* var_x = s->Lookup(name_x);
3399 CHECK(var_x != NULL);
3400 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3401}
3402
3403
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003404TEST(InnerAssignment) {
3405 i::Isolate* isolate = CcTest::i_isolate();
3406 i::Factory* factory = isolate->factory();
3407 i::HandleScope scope(isolate);
3408 LocalContext env;
3409
3410 const char* prefix = "function f() {";
3411 const char* midfix = " function g() {";
3412 const char* suffix = "}}";
3413 struct { const char* source; bool assigned; bool strict; } outers[] = {
3414 // Actual assignments.
3415 { "var x; var x = 5;", true, false },
3416 { "var x; { var x = 5; }", true, false },
3417 { "'use strict'; let x; x = 6;", true, true },
3418 { "var x = 5; function x() {}", true, false },
3419 // Actual non-assignments.
3420 { "var x;", false, false },
3421 { "var x = 5;", false, false },
3422 { "'use strict'; let x;", false, true },
3423 { "'use strict'; let x = 6;", false, true },
3424 { "'use strict'; var x = 0; { let x = 6; }", false, true },
3425 { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3426 { "'use strict'; let x = 0; { let x = 6; }", false, true },
3427 { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3428 { "var x; try {} catch (x) { x = 5; }", false, false },
3429 { "function x() {}", false, false },
3430 // Eval approximation.
3431 { "var x; eval('');", true, false },
3432 { "eval(''); var x;", true, false },
3433 { "'use strict'; let x; eval('');", true, true },
3434 { "'use strict'; eval(''); let x;", true, true },
3435 // Non-assignments not recognized, because the analysis is approximative.
3436 { "var x; var x;", true, false },
3437 { "var x = 5; var x;", true, false },
3438 { "var x; { var x; }", true, false },
3439 { "var x; function x() {}", true, false },
3440 { "function x() {}; var x;", true, false },
3441 { "var x; try {} catch (x) { var x = 5; }", true, false },
3442 };
3443 struct { const char* source; bool assigned; bool with; } inners[] = {
3444 // Actual assignments.
3445 { "x = 1;", true, false },
3446 { "x++;", true, false },
3447 { "++x;", true, false },
3448 { "x--;", true, false },
3449 { "--x;", true, false },
3450 { "{ x = 1; }", true, false },
3451 { "'use strict'; { let x; }; x = 0;", true, false },
3452 { "'use strict'; { const x = 1; }; x = 0;", true, false },
3453 { "'use strict'; { function x() {} }; x = 0;", true, false },
3454 { "with ({}) { x = 1; }", true, true },
3455 { "eval('');", true, false },
3456 { "'use strict'; { let y; eval('') }", true, false },
3457 { "function h() { x = 0; }", true, false },
3458 { "(function() { x = 0; })", true, false },
3459 { "(function() { x = 0; })", true, false },
3460 { "with ({}) (function() { x = 0; })", true, true },
3461 // Actual non-assignments.
3462 { "", false, false },
3463 { "x;", false, false },
3464 { "var x;", false, false },
3465 { "var x = 8;", false, false },
3466 { "var x; x = 8;", false, false },
3467 { "'use strict'; let x;", false, false },
3468 { "'use strict'; let x = 8;", false, false },
3469 { "'use strict'; let x; x = 8;", false, false },
3470 { "'use strict'; const x = 8;", false, false },
3471 { "function x() {}", false, false },
3472 { "function x() { x = 0; }", false, false },
3473 { "function h(x) { x = 0; }", false, false },
3474 { "'use strict'; { let x; x = 0; }", false, false },
3475 { "{ var x; }; x = 0;", false, false },
3476 { "with ({}) {}", false, true },
3477 { "var x; { with ({}) { x = 1; } }", false, true },
3478 { "try {} catch(x) { x = 0; }", false, false },
3479 { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3480 // Eval approximation.
3481 { "eval('');", true, false },
3482 { "function h() { eval(''); }", true, false },
3483 { "(function() { eval(''); })", true, false },
3484 // Shadowing not recognized because of eval approximation.
3485 { "var x; eval('');", true, false },
3486 { "'use strict'; let x; eval('');", true, false },
3487 { "try {} catch(x) { eval(''); }", true, false },
3488 { "function x() { eval(''); }", true, false },
3489 { "(function(x) { eval(''); })", true, false },
3490 };
3491
3492 // Used to trigger lazy compilation of function
3493 int comment_len = 2048;
3494 i::ScopedVector<char> comment(comment_len + 1);
3495 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3496 int prefix_len = Utf8LengthHelper(prefix);
3497 int midfix_len = Utf8LengthHelper(midfix);
3498 int suffix_len = Utf8LengthHelper(suffix);
3499 for (unsigned i = 0; i < arraysize(outers); ++i) {
3500 const char* outer = outers[i].source;
3501 int outer_len = Utf8LengthHelper(outer);
3502 for (unsigned j = 0; j < arraysize(inners); ++j) {
3503 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3504 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3505 if (outers[i].strict && inners[j].with) continue;
3506 const char* inner = inners[j].source;
3507 int inner_len = Utf8LengthHelper(inner);
3508
3509 int outer_comment_len = outer_lazy ? comment_len : 0;
3510 int inner_comment_len = inner_lazy ? comment_len : 0;
3511 const char* outer_comment = outer_lazy ? comment.start() : "";
3512 const char* inner_comment = inner_lazy ? comment.start() : "";
3513 int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3514 inner_comment_len + inner_len + suffix_len;
3515 i::ScopedVector<char> program(len + 1);
3516
3517 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3518 midfix, inner_comment, inner, suffix);
3519 i::Handle<i::String> source =
3520 factory->InternalizeUtf8String(program.start());
3521 source->PrintOn(stdout);
3522 printf("\n");
3523
3524 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01003525 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003526 i::ParseInfo info(&zone, script);
3527 i::Parser parser(&info);
3528 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003529 CHECK(i::Compiler::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003530 CHECK(info.literal() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003532 i::Scope* scope = info.literal()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003533 CHECK_EQ(scope->inner_scopes()->length(), 1);
3534 i::Scope* inner_scope = scope->inner_scopes()->at(0);
3535 const i::AstRawString* var_name =
3536 info.ast_value_factory()->GetOneByteString("x");
3537 i::Variable* var = inner_scope->Lookup(var_name);
3538 bool expected = outers[i].assigned || inners[j].assigned;
3539 CHECK(var != NULL);
3540 CHECK(var->is_used() || !expected);
3541 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3542 }
3543 }
3544 }
3545 }
3546}
3547
3548namespace {
3549
3550int* global_use_counts = NULL;
3551
3552void MockUseCounterCallback(v8::Isolate* isolate,
3553 v8::Isolate::UseCounterFeature feature) {
3554 ++global_use_counts[feature];
3555}
3556
3557}
3558
3559
3560TEST(UseAsmUseCount) {
3561 i::Isolate* isolate = CcTest::i_isolate();
3562 i::HandleScope scope(isolate);
3563 LocalContext env;
3564 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3565 global_use_counts = use_counts;
3566 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3567 CompileRun("\"use asm\";\n"
3568 "var foo = 1;\n"
3569 "\"use asm\";\n" // Only the first one counts.
3570 "function bar() { \"use asm\"; var baz = 1; }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003571 // Optimizing will double-count because the source is parsed twice.
3572 CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
3573}
3574
3575
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003576TEST(StrictModeUseCount) {
3577 i::Isolate* isolate = CcTest::i_isolate();
3578 i::HandleScope scope(isolate);
3579 LocalContext env;
3580 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3581 global_use_counts = use_counts;
3582 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3583 CompileRun(
3584 "\"use strict\";\n"
3585 "function bar() { var baz = 1; }"); // strict mode inherits
3586 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3587 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
3588}
3589
3590
3591TEST(SloppyModeUseCount) {
3592 i::Isolate* isolate = CcTest::i_isolate();
3593 i::HandleScope scope(isolate);
3594 LocalContext env;
3595 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3596 global_use_counts = use_counts;
3597 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3598 CompileRun("function bar() { var baz = 1; }");
3599 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3600 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
3601}
3602
3603
3604TEST(BothModesUseCount) {
3605 i::Isolate* isolate = CcTest::i_isolate();
3606 i::HandleScope scope(isolate);
3607 LocalContext env;
3608 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3609 global_use_counts = use_counts;
3610 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3611 CompileRun("function bar() { 'use strict'; var baz = 1; }");
3612 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3613 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3614}
3615
3616
3617TEST(ErrorsArrowFormalParameters) {
3618 const char* context_data[][2] = {
3619 { "()", "=>{}" },
3620 { "()", "=>{};" },
3621 { "var x = ()", "=>{}" },
3622 { "var x = ()", "=>{};" },
3623
3624 { "a", "=>{}" },
3625 { "a", "=>{};" },
3626 { "var x = a", "=>{}" },
3627 { "var x = a", "=>{};" },
3628
3629 { "(a)", "=>{}" },
3630 { "(a)", "=>{};" },
3631 { "var x = (a)", "=>{}" },
3632 { "var x = (a)", "=>{};" },
3633
3634 { "(...a)", "=>{}" },
3635 { "(...a)", "=>{};" },
3636 { "var x = (...a)", "=>{}" },
3637 { "var x = (...a)", "=>{};" },
3638
3639 { "(a,b)", "=>{}" },
3640 { "(a,b)", "=>{};" },
3641 { "var x = (a,b)", "=>{}" },
3642 { "var x = (a,b)", "=>{};" },
3643
3644 { "(a,...b)", "=>{}" },
3645 { "(a,...b)", "=>{};" },
3646 { "var x = (a,...b)", "=>{}" },
3647 { "var x = (a,...b)", "=>{};" },
3648
3649 { nullptr, nullptr }
3650 };
3651 const char* assignment_expression_suffix_data[] = {
3652 "?c:d=>{}",
3653 "=c=>{}",
3654 "()",
3655 "(c)",
3656 "[1]",
3657 "[c]",
3658 ".c",
3659 "-c",
3660 "+c",
3661 "c++",
3662 "`c`",
3663 "`${c}`",
3664 "`template-head${c}`",
3665 "`${c}template-tail`",
3666 "`template-head${c}template-tail`",
3667 "`${c}template-tail`",
3668 nullptr
3669 };
3670
3671 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003672}
3673
3674
3675TEST(ErrorsArrowFunctions) {
3676 // Tests that parser and preparser generate the same kind of errors
3677 // on invalid arrow function syntax.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003678
3679 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003680 const char* context_data[][2] = {
3681 {"", ";"},
3682 {"v = ", ";"},
3683 {"bar ? (", ") : baz;"},
3684 {"bar ? baz : (", ");"},
3685 {"bar[", "];"},
3686 {"bar, ", ";"},
3687 {"", ", bar;"},
3688 {NULL, NULL}
3689 };
3690
3691 const char* statement_data[] = {
3692 "=> 0",
3693 "=>",
3694 "() =>",
3695 "=> {}",
3696 ") => {}",
3697 ", => {}",
3698 "(,) => {}",
3699 "return => {}",
3700 "() => {'value': 42}",
3701
3702 // Check that the early return introduced in ParsePrimaryExpression
3703 // does not accept stray closing parentheses.
3704 ")",
3705 ") => 0",
3706 "foo[()]",
3707 "()",
3708
3709 // Parameter lists with extra parens should be recognized as errors.
3710 "(()) => 0",
3711 "((x)) => 0",
3712 "((x, y)) => 0",
3713 "(x, (y)) => 0",
3714 "((x, y, z)) => 0",
3715 "(x, (y, z)) => 0",
3716 "((x, y), z) => 0",
3717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003718 // Arrow function formal parameters are parsed as StrictFormalParameters,
3719 // which confusingly only implies that there are no duplicates. Words
3720 // reserved in strict mode, and eval or arguments, are indeed valid in
3721 // sloppy mode.
3722 "eval => { 'use strict'; 0 }",
3723 "arguments => { 'use strict'; 0 }",
3724 "yield => { 'use strict'; 0 }",
3725 "interface => { 'use strict'; 0 }",
3726 "(eval) => { 'use strict'; 0 }",
3727 "(arguments) => { 'use strict'; 0 }",
3728 "(yield) => { 'use strict'; 0 }",
3729 "(interface) => { 'use strict'; 0 }",
3730 "(eval, bar) => { 'use strict'; 0 }",
3731 "(bar, eval) => { 'use strict'; 0 }",
3732 "(bar, arguments) => { 'use strict'; 0 }",
3733 "(bar, yield) => { 'use strict'; 0 }",
3734 "(bar, interface) => { 'use strict'; 0 }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003735 // TODO(aperez): Detecting duplicates does not work in PreParser.
3736 // "(bar, bar) => {}",
3737
3738 // The parameter list is parsed as an expression, but only
3739 // a comma-separated list of identifier is valid.
3740 "32 => {}",
3741 "(32) => {}",
3742 "(a, 32) => {}",
3743 "if => {}",
3744 "(if) => {}",
3745 "(a, if) => {}",
3746 "a + b => {}",
3747 "(a + b) => {}",
3748 "(a + b, c) => {}",
3749 "(a, b - c) => {}",
3750 "\"a\" => {}",
3751 "(\"a\") => {}",
3752 "(\"a\", b) => {}",
3753 "(a, \"b\") => {}",
3754 "-a => {}",
3755 "(-a) => {}",
3756 "(-a, b) => {}",
3757 "(a, -b) => {}",
3758 "{} => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003759 "a++ => {}",
3760 "(a++) => {}",
3761 "(a++, b) => {}",
3762 "(a, b++) => {}",
3763 "[] => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003764 "(foo ? bar : baz) => {}",
3765 "(a, foo ? bar : baz) => {}",
3766 "(foo ? bar : baz, a) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003767 "(a.b, c) => {}",
3768 "(c, a.b) => {}",
3769 "(a['b'], c) => {}",
3770 "(c, a['b']) => {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01003771
3772 // crbug.com/582626
3773 "(...rest - a) => b",
3774 "(a, ...b - 10) => b",
3775
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003776 NULL
3777 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01003778 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003779
3780 // The test is quite slow, so run it with a reduced set of flags.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003781 static const ParserFlag flags[] = {kAllowLazy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003782 RunParserSyncTest(context_data, statement_data, kError, flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003783 arraysize(flags));
3784
3785 // In a context where a concise arrow body is parsed with [~In] variant,
3786 // ensure that an error is reported in both full parser and preparser.
3787 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3788 {nullptr, nullptr}};
3789 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
3790 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
3791 arraysize(flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003792}
3793
3794
3795TEST(NoErrorsArrowFunctions) {
3796 // Tests that parser and preparser accept valid arrow functions syntax.
Ben Murdochda12d292016-06-02 14:46:10 +01003797 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003798 const char* context_data[][2] = {
3799 {"", ";"},
3800 {"bar ? (", ") : baz;"},
3801 {"bar ? baz : (", ");"},
3802 {"bar, ", ";"},
3803 {"", ", bar;"},
3804 {NULL, NULL}
3805 };
3806
3807 const char* statement_data[] = {
3808 "() => {}",
3809 "() => { return 42 }",
3810 "x => { return x; }",
3811 "(x) => { return x; }",
3812 "(x, y) => { return x + y; }",
3813 "(x, y, z) => { return x + y + z; }",
3814 "(x, y) => { x.a = y; }",
3815 "() => 42",
3816 "x => x",
3817 "x => x * x",
3818 "(x) => x",
3819 "(x) => x * x",
3820 "(x, y) => x + y",
3821 "(x, y, z) => x, y, z",
3822 "(x, y) => x.a = y",
3823 "() => ({'value': 42})",
3824 "x => y => x + y",
3825 "(x, y) => (u, v) => x*u + y*v",
3826 "(x, y) => z => z * (x + y)",
3827 "x => (y, z) => z * (x + y)",
3828
3829 // Those are comma-separated expressions, with arrow functions as items.
3830 // They stress the code for validating arrow function parameter lists.
3831 "a, b => 0",
3832 "a, b, (c, d) => 0",
3833 "(a, b, (c, d) => 0)",
3834 "(a, b) => 0, (c, d) => 1",
3835 "(a, b => {}, a => a + 1)",
3836 "((a, b) => {}, (a => a + 1))",
3837 "(a, (a, (b, c) => 0))",
3838
3839 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3840 "foo ? bar : baz => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841
3842 // Arrows with non-simple parameters.
Ben Murdochda12d292016-06-02 14:46:10 +01003843 "({}) => {}",
3844 "(a, {}) => {}",
3845 "({}, a) => {}",
3846 "([]) => {}",
3847 "(a, []) => {}",
3848 "([], a) => {}",
3849 "(a = b) => {}",
3850 "(a = b, c) => {}",
3851 "(a, b = c) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003852 "({a}) => {}",
3853 "(x = 9) => {}",
3854 "(x, y = 9) => {}",
3855 "(x = 9, y) => {}",
3856 "(x, y = 9, z) => {}",
3857 "(x, y = 9, z = 8) => {}",
3858 "(...a) => {}",
3859 "(x, ...a) => {}",
3860 "(x = 9, ...a) => {}",
3861 "(x, y = 9, ...a) => {}",
3862 "(x, y = 9, {b}, z = 8, ...a) => {}",
Ben Murdochda12d292016-06-02 14:46:10 +01003863 "({a} = {}) => {}",
3864 "([x] = []) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003865 "({a = 42}) => {}",
3866 "([x = 0]) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003867 NULL
3868 };
Ben Murdochda12d292016-06-02 14:46:10 +01003869 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003870
Ben Murdochda12d292016-06-02 14:46:10 +01003871 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003872
3873 static const ParserFlag flags[] = {kAllowLazy};
3874 // In a context where a concise arrow body is parsed with [~In] variant,
3875 // ensure that nested expressions can still use the 'in' operator,
3876 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3877 {nullptr, nullptr}};
3878 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
3879 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
3880 arraysize(flags));
3881}
3882
3883
3884TEST(ArrowFunctionsSloppyParameterNames) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003885 const char* strict_context_data[][2] = {
3886 {"'use strict'; ", ";"},
3887 {"'use strict'; bar ? (", ") : baz;"},
3888 {"'use strict'; bar ? baz : (", ");"},
3889 {"'use strict'; bar, ", ";"},
3890 {"'use strict'; ", ", bar;"},
3891 {NULL, NULL}
3892 };
3893
3894 const char* sloppy_context_data[][2] = {
3895 {"", ";"},
3896 {"bar ? (", ") : baz;"},
3897 {"bar ? baz : (", ");"},
3898 {"bar, ", ";"},
3899 {"", ", bar;"},
3900 {NULL, NULL}
3901 };
3902
3903 const char* statement_data[] = {
3904 "eval => {}",
3905 "arguments => {}",
3906 "yield => {}",
3907 "interface => {}",
3908 "(eval) => {}",
3909 "(arguments) => {}",
3910 "(yield) => {}",
3911 "(interface) => {}",
3912 "(eval, bar) => {}",
3913 "(bar, eval) => {}",
3914 "(bar, arguments) => {}",
3915 "(bar, yield) => {}",
3916 "(bar, interface) => {}",
3917 "(interface, eval) => {}",
3918 "(interface, arguments) => {}",
3919 "(eval, interface) => {}",
3920 "(arguments, interface) => {}",
3921 NULL
3922 };
3923
Ben Murdochda12d292016-06-02 14:46:10 +01003924 RunParserSyncTest(strict_context_data, statement_data, kError);
3925 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003926}
3927
3928
3929TEST(ArrowFunctionsYieldParameterNameInGenerator) {
3930 const char* sloppy_function_context_data[][2] = {
3931 {"(function f() { (", "); });"},
3932 {NULL, NULL}
3933 };
3934
3935 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003936 {"(function f() {'use strict'; (", "); });"},
3937 {NULL, NULL}
3938 };
3939
3940 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003941 {"(function *g() {'use strict'; (", "); });"},
3942 {"(function *g() { (", "); });"},
3943 {NULL, NULL}
3944 };
3945
3946 const char* arrow_data[] = {
3947 "yield => {}",
3948 "(yield) => {}",
3949 "(a, yield) => {}",
3950 "(yield, a) => {}",
3951 "(yield, ...a) => {}",
3952 "(a, ...yield) => {}",
3953 "({yield}) => {}",
3954 "([yield]) => {}",
3955 NULL
3956 };
3957
Ben Murdochda12d292016-06-02 14:46:10 +01003958 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
3959 RunParserSyncTest(strict_function_context_data, arrow_data, kError);
3960 RunParserSyncTest(generator_context_data, arrow_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003961}
3962
3963
3964TEST(SuperNoErrors) {
3965 // Tests that parser and preparser accept 'super' keyword in right places.
3966 const char* context_data[][2] = {
3967 {"class C { m() { ", "; } }"},
3968 {"class C { m() { k = ", "; } }"},
3969 {"class C { m() { foo(", "); } }"},
3970 {"class C { m() { () => ", "; } }"},
3971 {NULL, NULL}
3972 };
3973
3974 const char* statement_data[] = {
3975 "super.x",
3976 "super[27]",
3977 "new super.x",
3978 "new super.x()",
3979 "new super[27]",
3980 "new super[27]()",
3981 "z.super", // Ok, property lookup.
3982 NULL
3983 };
3984
Ben Murdochc5610432016-08-08 18:44:38 +01003985 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003986}
3987
3988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003989TEST(SuperErrors) {
3990 const char* context_data[][2] = {
3991 {"class C { m() { ", "; } }"},
3992 {"class C { m() { k = ", "; } }"},
3993 {"class C { m() { foo(", "); } }"},
3994 {"class C { m() { () => ", "; } }"},
3995 {NULL, NULL}
3996 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003998 const char* expression_data[] = {
3999 "super",
4000 "super = x",
4001 "y = super",
4002 "f(super)",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004003 "new super",
4004 "new super()",
4005 "new super(12, 45)",
4006 "new new super",
4007 "new new super()",
4008 "new new super()()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004009 NULL
4010 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004011
Ben Murdochc5610432016-08-08 18:44:38 +01004012 RunParserSyncTest(context_data, expression_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004013}
4014
4015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004016TEST(SuperCall) {
4017 const char* context_data[][2] = {{"", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004018 {NULL, NULL}};
4019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004020 const char* success_data[] = {
4021 "class C extends B { constructor() { super(); } }",
4022 "class C extends B { constructor() { () => super(); } }",
4023 NULL
4024 };
4025
Ben Murdochc5610432016-08-08 18:44:38 +01004026 RunParserSyncTest(context_data, success_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004027
4028 const char* error_data[] = {
4029 "class C { constructor() { super(); } }",
4030 "class C { method() { super(); } }",
4031 "class C { method() { () => super(); } }",
4032 "class C { *method() { super(); } }",
4033 "class C { get x() { super(); } }",
4034 "class C { set x(_) { super(); } }",
4035 "({ method() { super(); } })",
4036 "({ *method() { super(); } })",
4037 "({ get x() { super(); } })",
4038 "({ set x(_) { super(); } })",
4039 "({ f: function() { super(); } })",
4040 "(function() { super(); })",
4041 "var f = function() { super(); }",
4042 "({ f: function*() { super(); } })",
4043 "(function*() { super(); })",
4044 "var f = function*() { super(); }",
4045 NULL
4046 };
4047
Ben Murdochc5610432016-08-08 18:44:38 +01004048 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004049}
4050
4051
4052TEST(SuperNewNoErrors) {
4053 const char* context_data[][2] = {
4054 {"class C { constructor() { ", " } }"},
4055 {"class C { *method() { ", " } }"},
4056 {"class C { get x() { ", " } }"},
4057 {"class C { set x(_) { ", " } }"},
4058 {"({ method() { ", " } })"},
4059 {"({ *method() { ", " } })"},
4060 {"({ get x() { ", " } })"},
4061 {"({ set x(_) { ", " } })"},
4062 {NULL, NULL}
4063 };
4064
4065 const char* expression_data[] = {
4066 "new super.x;",
4067 "new super.x();",
4068 "() => new super.x;",
4069 "() => new super.x();",
4070 NULL
4071 };
4072
Ben Murdochc5610432016-08-08 18:44:38 +01004073 RunParserSyncTest(context_data, expression_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004074}
4075
4076
4077TEST(SuperNewErrors) {
4078 const char* context_data[][2] = {
4079 {"class C { method() { ", " } }"},
4080 {"class C { *method() { ", " } }"},
4081 {"class C { get x() { ", " } }"},
4082 {"class C { set x(_) { ", " } }"},
4083 {"({ method() { ", " } })"},
4084 {"({ *method() { ", " } })"},
4085 {"({ get x() { ", " } })"},
4086 {"({ set x(_) { ", " } })"},
4087 {"({ f: function() { ", " } })"},
4088 {"(function() { ", " })"},
4089 {"var f = function() { ", " }"},
4090 {"({ f: function*() { ", " } })"},
4091 {"(function*() { ", " })"},
4092 {"var f = function*() { ", " }"},
4093 {NULL, NULL}
4094 };
4095
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004096 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004097 "new super;",
4098 "new super();",
4099 "() => new super;",
4100 "() => new super();",
4101 NULL
4102 };
4103
Ben Murdochc5610432016-08-08 18:44:38 +01004104 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004105}
4106
4107
4108TEST(SuperErrorsNonMethods) {
4109 // super is only allowed in methods, accessors and constructors.
4110 const char* context_data[][2] = {
4111 {"", ";"},
4112 {"k = ", ";"},
4113 {"foo(", ");"},
4114 {"if (", ") {}"},
4115 {"if (true) {", "}"},
4116 {"if (false) {} else {", "}"},
4117 {"while (true) {", "}"},
4118 {"function f() {", "}"},
4119 {"class C extends (", ") {}"},
4120 {"class C { m() { function f() {", "} } }"},
4121 {"({ m() { function f() {", "} } })"},
4122 {NULL, NULL}
4123 };
4124
4125 const char* statement_data[] = {
4126 "super",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004127 "super = x",
4128 "y = super",
4129 "f(super)",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004130 "super.x",
4131 "super[27]",
4132 "super.x()",
4133 "super[27]()",
4134 "super()",
4135 "new super.x",
4136 "new super.x()",
4137 "new super[27]",
4138 "new super[27]()",
4139 NULL
4140 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004141
Ben Murdochc5610432016-08-08 18:44:38 +01004142 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004143}
4144
4145
4146TEST(NoErrorsMethodDefinition) {
4147 const char* context_data[][2] = {{"({", "});"},
4148 {"'use strict'; ({", "});"},
4149 {"({*", "});"},
4150 {"'use strict'; ({*", "});"},
4151 {NULL, NULL}};
4152
4153 const char* object_literal_body_data[] = {
4154 "m() {}",
4155 "m(x) { return x; }",
4156 "m(x, y) {}, n() {}",
4157 "set(x, y) {}",
4158 "get(x, y) {}",
4159 NULL
4160 };
4161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004162 RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004163}
4164
4165
4166TEST(MethodDefinitionNames) {
4167 const char* context_data[][2] = {{"({", "(x, y) {}});"},
4168 {"'use strict'; ({", "(x, y) {}});"},
4169 {"({*", "(x, y) {}});"},
4170 {"'use strict'; ({*", "(x, y) {}});"},
4171 {NULL, NULL}};
4172
4173 const char* name_data[] = {
4174 "m",
4175 "'m'",
4176 "\"m\"",
4177 "\"m n\"",
4178 "true",
4179 "false",
4180 "null",
4181 "0",
4182 "1.2",
4183 "1e1",
4184 "1E1",
4185 "1e+1",
4186 "1e-1",
4187
4188 // Keywords
4189 "async",
4190 "await",
4191 "break",
4192 "case",
4193 "catch",
4194 "class",
4195 "const",
4196 "continue",
4197 "debugger",
4198 "default",
4199 "delete",
4200 "do",
4201 "else",
4202 "enum",
4203 "export",
4204 "extends",
4205 "finally",
4206 "for",
4207 "function",
4208 "if",
4209 "implements",
4210 "import",
4211 "in",
4212 "instanceof",
4213 "interface",
4214 "let",
4215 "new",
4216 "package",
4217 "private",
4218 "protected",
4219 "public",
4220 "return",
4221 "static",
4222 "super",
4223 "switch",
4224 "this",
4225 "throw",
4226 "try",
4227 "typeof",
4228 "var",
4229 "void",
4230 "while",
4231 "with",
4232 "yield",
4233 NULL
4234 };
4235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004236 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004237}
4238
4239
4240TEST(MethodDefinitionStrictFormalParamereters) {
4241 const char* context_data[][2] = {{"({method(", "){}});"},
4242 {"'use strict'; ({method(", "){}});"},
4243 {"({*method(", "){}});"},
4244 {"'use strict'; ({*method(", "){}});"},
4245 {NULL, NULL}};
4246
4247 const char* params_data[] = {
4248 "x, x",
4249 "x, y, x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004250 "var",
4251 "const",
4252 NULL
4253 };
4254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004255 RunParserSyncTest(context_data, params_data, kError);
4256}
4257
4258
4259TEST(MethodDefinitionEvalArguments) {
4260 const char* strict_context_data[][2] =
4261 {{"'use strict'; ({method(", "){}});"},
4262 {"'use strict'; ({*method(", "){}});"},
4263 {NULL, NULL}};
4264 const char* sloppy_context_data[][2] =
4265 {{"({method(", "){}});"},
4266 {"({*method(", "){}});"},
4267 {NULL, NULL}};
4268
4269 const char* data[] = {
4270 "eval",
4271 "arguments",
4272 NULL};
4273
4274 // Fail in strict mode
4275 RunParserSyncTest(strict_context_data, data, kError);
4276
4277 // OK in sloppy mode
4278 RunParserSyncTest(sloppy_context_data, data, kSuccess);
4279}
4280
4281
4282TEST(MethodDefinitionDuplicateEvalArguments) {
4283 const char* context_data[][2] =
4284 {{"'use strict'; ({method(", "){}});"},
4285 {"'use strict'; ({*method(", "){}});"},
4286 {"({method(", "){}});"},
4287 {"({*method(", "){}});"},
4288 {NULL, NULL}};
4289
4290 const char* data[] = {
4291 "eval, eval",
4292 "eval, a, eval",
4293 "arguments, arguments",
4294 "arguments, a, arguments",
4295 NULL};
4296
4297 // In strict mode, the error is using "eval" or "arguments" as parameter names
4298 // In sloppy mode, the error is that eval / arguments are duplicated
4299 RunParserSyncTest(context_data, data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004300}
4301
4302
4303TEST(MethodDefinitionDuplicateProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004304 const char* context_data[][2] = {{"'use strict'; ({", "});"},
4305 {NULL, NULL}};
4306
4307 const char* params_data[] = {
4308 "x: 1, x() {}",
4309 "x() {}, x: 1",
4310 "x() {}, get x() {}",
4311 "x() {}, set x(_) {}",
4312 "x() {}, x() {}",
4313 "x() {}, y() {}, x() {}",
4314 "x() {}, \"x\"() {}",
4315 "x() {}, 'x'() {}",
4316 "0() {}, '0'() {}",
4317 "1.0() {}, 1: 1",
4318
4319 "x: 1, *x() {}",
4320 "*x() {}, x: 1",
4321 "*x() {}, get x() {}",
4322 "*x() {}, set x(_) {}",
4323 "*x() {}, *x() {}",
4324 "*x() {}, y() {}, *x() {}",
4325 "*x() {}, *\"x\"() {}",
4326 "*x() {}, *'x'() {}",
4327 "*0() {}, *'0'() {}",
4328 "*1.0() {}, 1: 1",
4329
4330 NULL
4331 };
4332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004333 RunParserSyncTest(context_data, params_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004334}
4335
4336
4337TEST(ClassExpressionNoErrors) {
4338 const char* context_data[][2] = {{"(", ");"},
4339 {"var C = ", ";"},
4340 {"bar, ", ";"},
4341 {NULL, NULL}};
4342 const char* class_data[] = {
4343 "class {}",
4344 "class name {}",
4345 "class extends F {}",
4346 "class name extends F {}",
4347 "class extends (F, G) {}",
4348 "class name extends (F, G) {}",
4349 "class extends class {} {}",
4350 "class name extends class {} {}",
4351 "class extends class base {} {}",
4352 "class name extends class base {} {}",
4353 NULL};
4354
Ben Murdochc5610432016-08-08 18:44:38 +01004355 RunParserSyncTest(context_data, class_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004356}
4357
4358
4359TEST(ClassDeclarationNoErrors) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004360 const char* context_data[][2] = {{"'use strict'; ", ""},
4361 {"'use strict'; {", "}"},
4362 {"'use strict'; if (true) {", "}"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004363 {NULL, NULL}};
4364 const char* statement_data[] = {
4365 "class name {}",
4366 "class name extends F {}",
4367 "class name extends (F, G) {}",
4368 "class name extends class {} {}",
4369 "class name extends class base {} {}",
4370 NULL};
4371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004372 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004373}
4374
4375
4376TEST(ClassBodyNoErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004377 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004378 // Tests that parser and preparser accept valid class syntax.
4379 const char* context_data[][2] = {{"(class {", "});"},
4380 {"(class extends Base {", "});"},
4381 {"class C {", "}"},
4382 {"class C extends Base {", "}"},
4383 {NULL, NULL}};
4384 const char* class_body_data[] = {
4385 ";",
4386 ";;",
4387 "m() {}",
4388 "m() {};",
4389 "; m() {}",
4390 "m() {}; n(x) {}",
4391 "get x() {}",
4392 "set x(v) {}",
4393 "get() {}",
4394 "set() {}",
4395 "*g() {}",
4396 "*g() {};",
4397 "; *g() {}",
4398 "*g() {}; *h(x) {}",
4399 "static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004400 "get static() {}",
4401 "set static(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004402 "static m() {}",
4403 "static get x() {}",
4404 "static set x(v) {}",
4405 "static get() {}",
4406 "static set() {}",
4407 "static static() {}",
4408 "static get static() {}",
4409 "static set static(v) {}",
4410 "*static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004411 "static *static() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004412 "*get() {}",
4413 "*set() {}",
4414 "static *g() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004415
4416 // Escaped 'static' should be allowed anywhere
4417 // static-as-PropertyName is.
4418 "st\\u0061tic() {}",
4419 "get st\\u0061tic() {}",
4420 "set st\\u0061tic(v) {}",
4421 "static st\\u0061tic() {}",
4422 "static get st\\u0061tic() {}",
4423 "static set st\\u0061tic(v) {}",
4424 "*st\\u0061tic() {}",
4425 "static *st\\u0061tic() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004426 NULL};
Ben Murdoch097c5b22016-05-18 11:27:45 +01004427 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004428
Ben Murdochc5610432016-08-08 18:44:38 +01004429 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004430}
4431
4432
4433TEST(ClassPropertyNameNoErrors) {
4434 const char* context_data[][2] = {{"(class {", "() {}});"},
4435 {"(class { get ", "() {}});"},
4436 {"(class { set ", "(v) {}});"},
4437 {"(class { static ", "() {}});"},
4438 {"(class { static get ", "() {}});"},
4439 {"(class { static set ", "(v) {}});"},
4440 {"(class { *", "() {}});"},
4441 {"(class { static *", "() {}});"},
4442 {"class C {", "() {}}"},
4443 {"class C { get ", "() {}}"},
4444 {"class C { set ", "(v) {}}"},
4445 {"class C { static ", "() {}}"},
4446 {"class C { static get ", "() {}}"},
4447 {"class C { static set ", "(v) {}}"},
4448 {"class C { *", "() {}}"},
4449 {"class C { static *", "() {}}"},
4450 {NULL, NULL}};
4451 const char* name_data[] = {
4452 "42",
4453 "42.5",
4454 "42e2",
4455 "42e+2",
4456 "42e-2",
4457 "null",
4458 "false",
4459 "true",
4460 "'str'",
4461 "\"str\"",
4462 "static",
4463 "get",
4464 "set",
4465 "var",
4466 "const",
4467 "let",
4468 "this",
4469 "class",
4470 "function",
4471 "yield",
4472 "if",
4473 "else",
4474 "for",
4475 "while",
4476 "do",
4477 "try",
4478 "catch",
4479 "finally",
4480 NULL};
4481
Ben Murdochc5610432016-08-08 18:44:38 +01004482 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004483}
4484
4485
4486TEST(ClassExpressionErrors) {
4487 const char* context_data[][2] = {{"(", ");"},
4488 {"var C = ", ";"},
4489 {"bar, ", ";"},
4490 {NULL, NULL}};
4491 const char* class_data[] = {
4492 "class",
4493 "class name",
4494 "class name extends",
4495 "class extends",
4496 "class {",
4497 "class { m }",
4498 "class { m; n }",
4499 "class { m: 1 }",
4500 "class { m(); n() }",
4501 "class { get m }",
4502 "class { get m() }",
4503 "class { get m() { }",
4504 "class { set m() {} }", // Missing required parameter.
4505 "class { m() {}, n() {} }", // No commas allowed.
4506 NULL};
4507
Ben Murdochc5610432016-08-08 18:44:38 +01004508 RunParserSyncTest(context_data, class_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004509}
4510
4511
4512TEST(ClassDeclarationErrors) {
4513 const char* context_data[][2] = {{"", ""},
4514 {"{", "}"},
4515 {"if (true) {", "}"},
4516 {NULL, NULL}};
4517 const char* class_data[] = {
4518 "class",
4519 "class name",
4520 "class name extends",
4521 "class extends",
4522 "class name {",
4523 "class name { m }",
4524 "class name { m; n }",
4525 "class name { m: 1 }",
4526 "class name { m(); n() }",
4527 "class name { get x }",
4528 "class name { get x() }",
4529 "class name { set x() {) }", // missing required param
4530 "class {}", // Name is required for declaration
4531 "class extends base {}",
4532 "class name { *",
4533 "class name { * }",
4534 "class name { *; }",
4535 "class name { *get x() {} }",
4536 "class name { *set x(_) {} }",
4537 "class name { *static m() {} }",
4538 NULL};
4539
Ben Murdochc5610432016-08-08 18:44:38 +01004540 RunParserSyncTest(context_data, class_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004541}
4542
4543
4544TEST(ClassNameErrors) {
4545 const char* context_data[][2] = {{"class ", "{}"},
4546 {"(class ", "{});"},
4547 {"'use strict'; class ", "{}"},
4548 {"'use strict'; (class ", "{});"},
4549 {NULL, NULL}};
4550 const char* class_name[] = {
4551 "arguments",
4552 "eval",
4553 "implements",
4554 "interface",
4555 "let",
4556 "package",
4557 "private",
4558 "protected",
4559 "public",
4560 "static",
4561 "var",
4562 "yield",
4563 NULL};
4564
Ben Murdochc5610432016-08-08 18:44:38 +01004565 RunParserSyncTest(context_data, class_name, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004566}
4567
4568
4569TEST(ClassGetterParamNameErrors) {
4570 const char* context_data[][2] = {
4571 {"class C { get name(", ") {} }"},
4572 {"(class { get name(", ") {} });"},
4573 {"'use strict'; class C { get name(", ") {} }"},
4574 {"'use strict'; (class { get name(", ") {} })"},
4575 {NULL, NULL}
4576 };
4577
4578 const char* class_name[] = {
4579 "arguments",
4580 "eval",
4581 "implements",
4582 "interface",
4583 "let",
4584 "package",
4585 "private",
4586 "protected",
4587 "public",
4588 "static",
4589 "var",
4590 "yield",
4591 NULL};
4592
Ben Murdochc5610432016-08-08 18:44:38 +01004593 RunParserSyncTest(context_data, class_name, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004594}
4595
4596
4597TEST(ClassStaticPrototypeErrors) {
4598 const char* context_data[][2] = {{"class C {", "}"},
4599 {"(class {", "});"},
4600 {NULL, NULL}};
4601
4602 const char* class_body_data[] = {
4603 "static prototype() {}",
4604 "static get prototype() {}",
4605 "static set prototype(_) {}",
4606 "static *prototype() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004607 "static 'prototype'() {}",
4608 "static *'prototype'() {}",
4609 "static prot\\u006ftype() {}",
4610 "static 'prot\\u006ftype'() {}",
4611 "static get 'prot\\u006ftype'() {}",
4612 "static set 'prot\\u006ftype'(_) {}",
4613 "static *'prot\\u006ftype'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004614 NULL};
4615
Ben Murdochc5610432016-08-08 18:44:38 +01004616 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004617}
4618
4619
4620TEST(ClassSpecialConstructorErrors) {
4621 const char* context_data[][2] = {{"class C {", "}"},
4622 {"(class {", "});"},
4623 {NULL, NULL}};
4624
4625 const char* class_body_data[] = {
4626 "get constructor() {}",
4627 "get constructor(_) {}",
4628 "*constructor() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004629 "get 'constructor'() {}",
4630 "*'constructor'() {}",
4631 "get c\\u006fnstructor() {}",
4632 "*c\\u006fnstructor() {}",
4633 "get 'c\\u006fnstructor'() {}",
4634 "get 'c\\u006fnstructor'(_) {}",
4635 "*'c\\u006fnstructor'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004636 NULL};
4637
Ben Murdochc5610432016-08-08 18:44:38 +01004638 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004639}
4640
4641
4642TEST(ClassConstructorNoErrors) {
4643 const char* context_data[][2] = {{"class C {", "}"},
4644 {"(class {", "});"},
4645 {NULL, NULL}};
4646
4647 const char* class_body_data[] = {
4648 "constructor() {}",
4649 "static constructor() {}",
4650 "static get constructor() {}",
4651 "static set constructor(_) {}",
4652 "static *constructor() {}",
4653 NULL};
4654
Ben Murdochc5610432016-08-08 18:44:38 +01004655 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004656}
4657
4658
4659TEST(ClassMultipleConstructorErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004660 const char* context_data[][2] = {{"class C {", "}"},
4661 {"(class {", "});"},
4662 {NULL, NULL}};
4663
4664 const char* class_body_data[] = {
4665 "constructor() {}; constructor() {}",
4666 NULL};
4667
Ben Murdochc5610432016-08-08 18:44:38 +01004668 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004669}
4670
4671
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004672TEST(ClassMultiplePropertyNamesNoErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004673 const char* context_data[][2] = {{"class C {", "}"},
4674 {"(class {", "});"},
4675 {NULL, NULL}};
4676
4677 const char* class_body_data[] = {
4678 "constructor() {}; static constructor() {}",
4679 "m() {}; static m() {}",
4680 "m() {}; m() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004681 "static m() {}; static m() {}",
4682 "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004683 NULL};
4684
Ben Murdochc5610432016-08-08 18:44:38 +01004685 RunParserSyncTest(context_data, class_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004686}
4687
4688
4689TEST(ClassesAreStrictErrors) {
4690 const char* context_data[][2] = {{"", ""},
4691 {"(", ");"},
4692 {NULL, NULL}};
4693
4694 const char* class_body_data[] = {
4695 "class C { method() { with ({}) {} } }",
4696 "class C extends function() { with ({}) {} } {}",
4697 "class C { *method() { with ({}) {} } }",
4698 NULL};
4699
Ben Murdochc5610432016-08-08 18:44:38 +01004700 RunParserSyncTest(context_data, class_body_data, kError);
Ben Murdoch692be652012-01-10 18:47:50 +00004701}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004702
4703
4704TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4705 const char* context_data[][2] = {{"({", "});"},
4706 {"'use strict'; ({", "});"},
4707 {NULL, NULL}};
4708
4709 const char* name_data[] = {
4710 "break",
4711 "case",
4712 "catch",
4713 "class",
4714 "const",
4715 "continue",
4716 "debugger",
4717 "default",
4718 "delete",
4719 "do",
4720 "else",
4721 "enum",
4722 "export",
4723 "extends",
4724 "false",
4725 "finally",
4726 "for",
4727 "function",
4728 "if",
4729 "import",
4730 "in",
4731 "instanceof",
4732 "new",
4733 "null",
4734 "return",
4735 "super",
4736 "switch",
4737 "this",
4738 "throw",
4739 "true",
4740 "try",
4741 "typeof",
4742 "var",
4743 "void",
4744 "while",
4745 "with",
4746 NULL
4747 };
4748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004749 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004750}
4751
4752
4753TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4754 const char* context_data[][2] = {{"({", "});"},
4755 {NULL, NULL}};
4756
4757 const char* name_data[] = {
4758 "implements",
4759 "interface",
4760 "let",
4761 "package",
4762 "private",
4763 "protected",
4764 "public",
4765 "static",
4766 "yield",
4767 NULL
4768 };
4769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004770 RunParserSyncTest(context_data, name_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004771
4772 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4773 {NULL, NULL}};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004774 RunParserSyncTest(context_strict_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004775}
4776
4777
4778TEST(ObjectLiteralPropertyShorthandError) {
4779 const char* context_data[][2] = {{"({", "});"},
4780 {"'use strict'; ({", "});"},
4781 {NULL, NULL}};
4782
4783 const char* name_data[] = {
4784 "1",
4785 "1.2",
4786 "0",
4787 "0.1",
4788 "1.0",
4789 "1e1",
4790 "0x1",
4791 "\"s\"",
4792 "'s'",
4793 NULL
4794 };
4795
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004796 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004797}
4798
4799
4800TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4801 const char* context_data[][2] = {{"", ""},
4802 {NULL, NULL}};
4803
4804 const char* name_data[] = {
4805 "function* g() { ({yield}); }",
4806 NULL
4807 };
4808
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004809 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004810}
4811
4812
4813TEST(ConstParsingInForIn) {
4814 const char* context_data[][2] = {{"'use strict';", ""},
4815 {"function foo(){ 'use strict';", "}"},
4816 {NULL, NULL}};
4817
4818 const char* data[] = {
4819 "for(const x = 1; ; ) {}",
4820 "for(const x = 1, y = 2;;){}",
4821 "for(const x in [1,2,3]) {}",
4822 "for(const x of [1,2,3]) {}",
4823 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004824 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004825}
4826
4827
Ben Murdoch097c5b22016-05-18 11:27:45 +01004828TEST(StatementParsingInForIn) {
4829 const char* context_data[][2] = {{"", ""},
4830 {"'use strict';", ""},
4831 {"function foo(){ 'use strict';", "}"},
4832 {NULL, NULL}};
4833
4834 const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
4835 "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
4836 NULL};
4837
Ben Murdochc5610432016-08-08 18:44:38 +01004838 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004839}
4840
4841
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004842TEST(ConstParsingInForInError) {
4843 const char* context_data[][2] = {{"'use strict';", ""},
4844 {"function foo(){ 'use strict';", "}"},
4845 {NULL, NULL}};
4846
4847 const char* data[] = {
4848 "for(const x,y = 1; ; ) {}",
4849 "for(const x = 4 in [1,2,3]) {}",
4850 "for(const x = 4, y in [1,2,3]) {}",
4851 "for(const x = 4 of [1,2,3]) {}",
4852 "for(const x = 4, y of [1,2,3]) {}",
4853 "for(const x = 1, y = 2 in []) {}",
4854 "for(const x,y in []) {}",
4855 "for(const x = 1, y = 2 of []) {}",
4856 "for(const x,y of []) {}",
4857 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004858 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
4859}
4860
4861
4862TEST(InitializedDeclarationsInStrictForInError) {
4863 const char* context_data[][2] = {{"'use strict';", ""},
4864 {"function foo(){ 'use strict';", "}"},
4865 {NULL, NULL}};
4866
4867 const char* data[] = {
4868 "for (var i = 1 in {}) {}",
4869 "for (var i = void 0 in [1, 2, 3]) {}",
4870 "for (let i = 1 in {}) {}",
4871 "for (let i = void 0 in [1, 2, 3]) {}",
4872 "for (const i = 1 in {}) {}",
4873 "for (const i = void 0 in [1, 2, 3]) {}",
4874 NULL};
4875 RunParserSyncTest(context_data, data, kError);
4876}
4877
4878
4879TEST(InitializedDeclarationsInStrictForOfError) {
4880 const char* context_data[][2] = {{"'use strict';", ""},
4881 {"function foo(){ 'use strict';", "}"},
4882 {NULL, NULL}};
4883
4884 const char* data[] = {
4885 "for (var i = 1 of {}) {}",
4886 "for (var i = void 0 of [1, 2, 3]) {}",
4887 "for (let i = 1 of {}) {}",
4888 "for (let i = void 0 of [1, 2, 3]) {}",
4889 "for (const i = 1 of {}) {}",
4890 "for (const i = void 0 of [1, 2, 3]) {}",
4891 NULL};
4892 RunParserSyncTest(context_data, data, kError);
4893}
4894
4895
4896TEST(InitializedDeclarationsInSloppyForInError) {
4897 const char* context_data[][2] = {{"", ""},
4898 {"function foo(){", "}"},
4899 {NULL, NULL}};
4900
4901 const char* data[] = {
4902 "for (var i = 1 in {}) {}",
4903 "for (var i = void 0 in [1, 2, 3]) {}",
4904 NULL};
4905 // TODO(caitp): This should be an error in sloppy mode.
4906 RunParserSyncTest(context_data, data, kSuccess);
4907}
4908
4909
4910TEST(InitializedDeclarationsInSloppyForOfError) {
4911 const char* context_data[][2] = {{"", ""},
4912 {"function foo(){", "}"},
4913 {NULL, NULL}};
4914
4915 const char* data[] = {
4916 "for (var i = 1 of {}) {}",
4917 "for (var i = void 0 of [1, 2, 3]) {}",
4918 NULL};
4919 RunParserSyncTest(context_data, data, kError);
4920}
4921
4922
4923TEST(ForInMultipleDeclarationsError) {
4924 const char* context_data[][2] = {{"", ""},
4925 {"function foo(){", "}"},
4926 {"'use strict';", ""},
4927 {"function foo(){ 'use strict';", "}"},
4928 {NULL, NULL}};
4929
4930 const char* data[] = {
4931 "for (var i, j in {}) {}",
4932 "for (var i, j in [1, 2, 3]) {}",
4933 "for (var i, j = 1 in {}) {}",
4934 "for (var i, j = void 0 in [1, 2, 3]) {}",
4935
4936 "for (let i, j in {}) {}",
4937 "for (let i, j in [1, 2, 3]) {}",
4938 "for (let i, j = 1 in {}) {}",
4939 "for (let i, j = void 0 in [1, 2, 3]) {}",
4940
4941 "for (const i, j in {}) {}",
4942 "for (const i, j in [1, 2, 3]) {}",
4943 "for (const i, j = 1 in {}) {}",
4944 "for (const i, j = void 0 in [1, 2, 3]) {}",
4945 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004946 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004947}
4948
4949
4950TEST(ForOfMultipleDeclarationsError) {
4951 const char* context_data[][2] = {{"", ""},
4952 {"function foo(){", "}"},
4953 {"'use strict';", ""},
4954 {"function foo(){ 'use strict';", "}"},
4955 {NULL, NULL}};
4956
4957 const char* data[] = {
4958 "for (var i, j of {}) {}",
4959 "for (var i, j of [1, 2, 3]) {}",
4960 "for (var i, j = 1 of {}) {}",
4961 "for (var i, j = void 0 of [1, 2, 3]) {}",
4962
4963 "for (let i, j of {}) {}",
4964 "for (let i, j of [1, 2, 3]) {}",
4965 "for (let i, j = 1 of {}) {}",
4966 "for (let i, j = void 0 of [1, 2, 3]) {}",
4967
4968 "for (const i, j of {}) {}",
4969 "for (const i, j of [1, 2, 3]) {}",
4970 "for (const i, j = 1 of {}) {}",
4971 "for (const i, j = void 0 of [1, 2, 3]) {}",
4972 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004973 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004974}
4975
4976
4977TEST(ForInNoDeclarationsError) {
4978 const char* context_data[][2] = {{"", ""},
4979 {"function foo(){", "}"},
4980 {"'use strict';", ""},
4981 {"function foo(){ 'use strict';", "}"},
4982 {NULL, NULL}};
4983
4984 const char* data[] = {
4985 "for (var in {}) {}",
4986 "for (const in {}) {}",
4987 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01004988 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004989}
4990
4991
4992TEST(ForOfNoDeclarationsError) {
4993 const char* context_data[][2] = {{"", ""},
4994 {"function foo(){", "}"},
4995 {"'use strict';", ""},
4996 {"function foo(){ 'use strict';", "}"},
4997 {NULL, NULL}};
4998
4999 const char* data[] = {
5000 "for (var of [1, 2, 3]) {}",
5001 "for (const of [1, 2, 3]) {}",
5002 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005003 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005004}
5005
5006
Ben Murdoch097c5b22016-05-18 11:27:45 +01005007TEST(ForOfInOperator) {
5008 const char* context_data[][2] = {{"", ""},
5009 {"'use strict';", ""},
5010 {"function foo(){ 'use strict';", "}"},
5011 {NULL, NULL}};
5012
5013 const char* data[] = {
5014 "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
5015 "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
5016
Ben Murdochc5610432016-08-08 18:44:38 +01005017 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005018}
5019
5020
5021TEST(ForOfYieldIdentifier) {
5022 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5023
5024 const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
5025 "for(let x of yield) {}", "for(const x of yield) {}",
5026 NULL};
5027
Ben Murdochc5610432016-08-08 18:44:38 +01005028 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005029}
5030
5031
5032TEST(ForOfYieldExpression) {
5033 const char* context_data[][2] = {{"", ""},
5034 {"'use strict';", ""},
5035 {"function foo(){ 'use strict';", "}"},
5036 {NULL, NULL}};
5037
5038 const char* data[] = {"function* g() { for(x of yield) {} }",
5039 "function* g() { for(var x of yield) {} }",
5040 "function* g() { for(let x of yield) {} }",
5041 "function* g() { for(const x of yield) {} }", NULL};
5042
Ben Murdochc5610432016-08-08 18:44:38 +01005043 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005044}
5045
5046
5047TEST(ForOfExpressionError) {
5048 const char* context_data[][2] = {{"", ""},
5049 {"'use strict';", ""},
5050 {"function foo(){ 'use strict';", "}"},
5051 {NULL, NULL}};
5052
5053 const char* data[] = {
5054 "for(x of [], []) {}", "for(var x of [], []) {}",
5055 "for(let x of [], []) {}", "for(const x of [], []) {}",
5056
5057 // AssignmentExpression should be validated statically:
5058 "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
5059 "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
5060
Ben Murdochc5610432016-08-08 18:44:38 +01005061 RunParserSyncTest(context_data, data, kError);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005062}
5063
5064
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005065TEST(InvalidUnicodeEscapes) {
5066 const char* context_data[][2] = {{"", ""},
5067 {"'use strict';", ""},
5068 {NULL, NULL}};
5069 const char* data[] = {
5070 "var foob\\u123r = 0;",
5071 "var \\u123roo = 0;",
5072 "\"foob\\u123rr\"",
5073 // No escapes allowed in regexp flags
5074 "/regex/\\u0069g",
5075 "/regex/\\u006g",
5076 // Braces gone wrong
5077 "var foob\\u{c481r = 0;",
5078 "var foob\\uc481}r = 0;",
5079 "var \\u{0052oo = 0;",
5080 "var \\u0052}oo = 0;",
5081 "\"foob\\u{c481r\"",
5082 "var foob\\u{}ar = 0;",
5083 // Too high value for the unicode escape
5084 "\"\\u{110000}\"",
5085 // Not an unicode escape
5086 "var foob\\v1234r = 0;",
5087 "var foob\\U1234r = 0;",
5088 "var foob\\v{1234}r = 0;",
5089 "var foob\\U{1234}r = 0;",
5090 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005091 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005092}
5093
5094
5095TEST(UnicodeEscapes) {
5096 const char* context_data[][2] = {{"", ""},
5097 {"'use strict';", ""},
5098 {NULL, NULL}};
5099 const char* data[] = {
5100 // Identifier starting with escape
5101 "var \\u0052oo = 0;",
5102 "var \\u{0052}oo = 0;",
5103 "var \\u{52}oo = 0;",
5104 "var \\u{00000000052}oo = 0;",
5105 // Identifier with an escape but not starting with an escape
5106 "var foob\\uc481r = 0;",
5107 "var foob\\u{c481}r = 0;",
5108 // String with an escape
5109 "\"foob\\uc481r\"",
5110 "\"foob\\{uc481}r\"",
5111 // This character is a valid unicode character, representable as a surrogate
5112 // pair, not representable as 4 hex digits.
5113 "\"foo\\u{10e6d}\"",
5114 // Max value for the unicode escape
5115 "\"\\u{10ffff}\"",
5116 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005117 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005118}
5119
5120
5121TEST(ScanTemplateLiterals) {
5122 const char* context_data[][2] = {{"'use strict';", ""},
5123 {"function foo(){ 'use strict';"
5124 " var a, b, c; return ", "}"},
5125 {NULL, NULL}};
5126
5127 const char* data[] = {
5128 "``",
5129 "`no-subst-template`",
5130 "`template-head${a}`",
5131 "`${a}`",
5132 "`${a}template-tail`",
5133 "`template-head${a}template-tail`",
5134 "`${a}${b}${c}`",
5135 "`a${a}b${b}c${c}`",
5136 "`${a}a${b}b${c}c`",
5137 "`foo\n\nbar\r\nbaz`",
5138 "`foo\n\n${ bar }\r\nbaz`",
5139 "`foo${a /* comment */}`",
5140 "`foo${a // comment\n}`",
5141 "`foo${a \n}`",
5142 "`foo${a \r\n}`",
5143 "`foo${a \r}`",
5144 "`foo${/* comment */ a}`",
5145 "`foo${// comment\na}`",
5146 "`foo${\n a}`",
5147 "`foo${\r\n a}`",
5148 "`foo${\r a}`",
5149 "`foo${'a' in a}`",
5150 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005151 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005152}
5153
5154
5155TEST(ScanTaggedTemplateLiterals) {
5156 const char* context_data[][2] = {{"'use strict';", ""},
5157 {"function foo(){ 'use strict';"
5158 " function tag() {}"
5159 " var a, b, c; return ", "}"},
5160 {NULL, NULL}};
5161
5162 const char* data[] = {
5163 "tag ``",
5164 "tag `no-subst-template`",
5165 "tag`template-head${a}`",
5166 "tag `${a}`",
5167 "tag `${a}template-tail`",
5168 "tag `template-head${a}template-tail`",
5169 "tag\n`${a}${b}${c}`",
5170 "tag\r\n`a${a}b${b}c${c}`",
5171 "tag `${a}a${b}b${c}c`",
5172 "tag\t`foo\n\nbar\r\nbaz`",
5173 "tag\r`foo\n\n${ bar }\r\nbaz`",
5174 "tag`foo${a /* comment */}`",
5175 "tag`foo${a // comment\n}`",
5176 "tag`foo${a \n}`",
5177 "tag`foo${a \r\n}`",
5178 "tag`foo${a \r}`",
5179 "tag`foo${/* comment */ a}`",
5180 "tag`foo${// comment\na}`",
5181 "tag`foo${\n a}`",
5182 "tag`foo${\r\n a}`",
5183 "tag`foo${\r a}`",
5184 "tag`foo${'a' in a}`",
5185 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005186 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005187}
5188
5189
5190TEST(TemplateMaterializedLiterals) {
5191 const char* context_data[][2] = {
5192 {
5193 "'use strict';\n"
5194 "function tag() {}\n"
5195 "var a, b, c;\n"
5196 "(", ")"
5197 },
5198 {NULL, NULL}
5199 };
5200
5201 const char* data[] = {
5202 "tag``",
5203 "tag`a`",
5204 "tag`a${1}b`",
5205 "tag`a${1}b${2}c`",
5206 "``",
5207 "`a`",
5208 "`a${1}b`",
5209 "`a${1}b${2}c`",
5210 NULL
5211 };
5212
Ben Murdochc5610432016-08-08 18:44:38 +01005213 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005214}
5215
5216
5217TEST(ScanUnterminatedTemplateLiterals) {
5218 const char* context_data[][2] = {{"'use strict';", ""},
5219 {"function foo(){ 'use strict';"
5220 " var a, b, c; return ", "}"},
5221 {NULL, NULL}};
5222
5223 const char* data[] = {
5224 "`no-subst-template",
5225 "`template-head${a}",
5226 "`${a}template-tail",
5227 "`template-head${a}template-tail",
5228 "`${a}${b}${c}",
5229 "`a${a}b${b}c${c}",
5230 "`${a}a${b}b${c}c",
5231 "`foo\n\nbar\r\nbaz",
5232 "`foo\n\n${ bar }\r\nbaz",
5233 "`foo${a /* comment } */`",
5234 "`foo${a /* comment } `*/",
5235 "`foo${a // comment}`",
5236 "`foo${a \n`",
5237 "`foo${a \r\n`",
5238 "`foo${a \r`",
5239 "`foo${/* comment */ a`",
5240 "`foo${// commenta}`",
5241 "`foo${\n a`",
5242 "`foo${\r\n a`",
5243 "`foo${\r a`",
5244 "`foo${fn(}`",
5245 "`foo${1 if}`",
5246 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005247 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005248}
5249
5250
5251TEST(TemplateLiteralsIllegalTokens) {
5252 const char* context_data[][2] = {{"'use strict';", ""},
5253 {"function foo(){ 'use strict';"
5254 " var a, b, c; return ", "}"},
5255 {NULL, NULL}};
5256 const char* data[] = {
5257 "`hello\\x`",
5258 "`hello\\x${1}`",
5259 "`hello${1}\\x`",
5260 "`hello${1}\\x${2}`",
5261 "`hello\\x\n`",
5262 "`hello\\x\n${1}`",
5263 "`hello${1}\\x\n`",
5264 "`hello${1}\\x\n${2}`",
5265 NULL};
5266
Ben Murdochc5610432016-08-08 18:44:38 +01005267 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005268}
5269
5270
5271TEST(ParseRestParameters) {
5272 const char* context_data[][2] = {{"'use strict';(function(",
5273 "){ return args;})(1, [], /regexp/, 'str',"
5274 "function(){});"},
5275 {"(function(", "){ return args;})(1, [],"
5276 "/regexp/, 'str', function(){});"},
5277 {NULL, NULL}};
5278
5279 const char* data[] = {"...args",
5280 "a, ...args",
5281 "... args",
5282 "a, ... args",
5283 "...\targs",
5284 "a, ...\targs",
5285 "...\r\nargs",
5286 "a, ...\r\nargs",
5287 "...\rargs",
5288 "a, ...\rargs",
5289 "...\t\n\t\t\n args",
5290 "a, ... \n \n args",
5291 "...{ length, 0: a, 1: b}",
5292 "...{}",
5293 "...[a, b]",
5294 "...[]",
5295 "...[...[a, b, ...c]]",
5296 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01005297 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005298}
5299
5300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005301TEST(ParseRestParametersErrors) {
5302 const char* context_data[][2] = {{"'use strict';(function(",
5303 "){ return args;}(1, [], /regexp/, 'str',"
5304 "function(){});"},
5305 {"(function(", "){ return args;}(1, [],"
5306 "/regexp/, 'str', function(){});"},
5307 {NULL, NULL}};
5308
5309 const char* data[] = {
5310 "...args, b",
5311 "a, ...args, b",
5312 "...args, b",
5313 "a, ...args, b",
5314 "...args,\tb",
5315 "a,...args\t,b",
5316 "...args\r\n, b",
5317 "a, ... args,\r\nb",
5318 "...args\r,b",
5319 "a, ... args,\rb",
5320 "...args\t\n\t\t\n, b",
5321 "a, ... args, \n \n b",
5322 "a, a, ...args",
5323 "a,\ta, ...args",
5324 "a,\ra, ...args",
5325 "a,\na, ...args",
5326 NULL};
5327 RunParserSyncTest(context_data, data, kError);
5328}
5329
5330
5331TEST(RestParameterInSetterMethodError) {
5332 const char* context_data[][2] = {
5333 {"'use strict';({ set prop(", ") {} }).prop = 1;"},
5334 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
5335 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
5336 {"({ set prop(", ") {} }).prop = 1;"},
5337 {"(class { static set prop(", ") {} }).prop = 1;"},
5338 {"(new (class { set prop(", ") {} })).prop = 1;"},
5339 {nullptr, nullptr}};
5340 const char* data[] = {"...a", "...arguments", "...eval", nullptr};
5341
Ben Murdochc5610432016-08-08 18:44:38 +01005342 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005343}
5344
5345
5346TEST(RestParametersEvalArguments) {
Ben Murdochc5610432016-08-08 18:44:38 +01005347 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005348 const char* strict_context_data[][2] =
5349 {{"'use strict';(function(",
5350 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5351 {NULL, NULL}};
5352 const char* sloppy_context_data[][2] =
5353 {{"(function(",
5354 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5355 {NULL, NULL}};
5356
5357 const char* data[] = {
5358 "...eval",
5359 "eval, ...args",
5360 "...arguments",
Ben Murdochc5610432016-08-08 18:44:38 +01005361 // See https://bugs.chromium.org/p/v8/issues/detail?id=4577
5362 // "arguments, ...args",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005363 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005364 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005365
5366 // Fail in strict mode
5367 RunParserSyncTest(strict_context_data, data, kError);
5368
5369 // OK in sloppy mode
5370 RunParserSyncTest(sloppy_context_data, data, kSuccess);
5371}
5372
5373
5374TEST(RestParametersDuplicateEvalArguments) {
5375 const char* context_data[][2] =
5376 {{"'use strict';(function(",
5377 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5378 {"(function(",
5379 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5380 {NULL, NULL}};
5381
5382 const char* data[] = {
5383 "eval, ...eval",
5384 "eval, eval, ...args",
5385 "arguments, ...arguments",
5386 "arguments, arguments, ...args",
5387 NULL};
5388
5389 // In strict mode, the error is using "eval" or "arguments" as parameter names
5390 // In sloppy mode, the error is that eval / arguments are duplicated
5391 RunParserSyncTest(context_data, data, kError);
5392}
5393
5394
5395TEST(SpreadCall) {
5396 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5397 {"function fn() {} fn(", ");"},
5398 {NULL, NULL}};
5399
5400 const char* data[] = {
5401 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
5402 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
5403 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
5404 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
5405 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
5406 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
5407
5408 RunParserSyncTest(context_data, data, kSuccess);
5409}
5410
5411
5412TEST(SpreadCallErrors) {
5413 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5414 {"function fn() {} fn(", ");"},
5415 {NULL, NULL}};
5416
5417 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
5418
5419 RunParserSyncTest(context_data, data, kError);
5420}
5421
5422
5423TEST(BadRestSpread) {
5424 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
5425 {"function fn() { ", "} fn();"},
5426 {NULL, NULL}};
5427 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];",
5428 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
5429 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}",
5430 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005431 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005432}
5433
5434
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005435TEST(LexicalScopingSloppyMode) {
5436 const char* context_data[][2] = {
5437 {"", ""},
5438 {"function f() {", "}"},
5439 {"{", "}"},
5440 {NULL, NULL}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005441
5442 const char* good_data[] = {
5443 "let = 1;",
5444 "for(let = 1;;){}",
5445 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01005446 RunParserSyncTest(context_data, good_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005447}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005448
5449
5450TEST(ComputedPropertyName) {
5451 const char* context_data[][2] = {{"({[", "]: 1});"},
5452 {"({get [", "]() {}});"},
5453 {"({set [", "](_) {}});"},
5454 {"({[", "]() {}});"},
5455 {"({*[", "]() {}});"},
5456 {"(class {get [", "]() {}});"},
5457 {"(class {set [", "](_) {}});"},
5458 {"(class {[", "]() {}});"},
5459 {"(class {*[", "]() {}});"},
5460 {NULL, NULL}};
5461 const char* error_data[] = {
5462 "1, 2",
5463 "var name",
5464 NULL};
5465
Ben Murdochc5610432016-08-08 18:44:38 +01005466 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005467
5468 const char* name_data[] = {
5469 "1",
5470 "1 + 2",
5471 "'name'",
5472 "\"name\"",
5473 "[]",
5474 "{}",
5475 NULL};
5476
Ben Murdochc5610432016-08-08 18:44:38 +01005477 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005478}
5479
5480
5481TEST(ComputedPropertyNameShorthandError) {
5482 const char* context_data[][2] = {{"({", "});"},
5483 {NULL, NULL}};
5484 const char* error_data[] = {
5485 "a: 1, [2]",
5486 "[1], a: 1",
5487 NULL};
5488
Ben Murdochc5610432016-08-08 18:44:38 +01005489 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005490}
5491
5492
5493TEST(BasicImportExportParsing) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005494 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005495 const char* kSources[] = {
5496 "export let x = 0;",
5497 "export var y = 0;",
5498 "export const z = 0;",
5499 "export function func() { };",
5500 "export class C { };",
5501 "export { };",
5502 "function f() {}; f(); export { f };",
5503 "var a, b, c; export { a, b as baz, c };",
5504 "var d, e; export { d as dreary, e, };",
5505 "export default function f() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005506 "export default function() {}",
5507 "export default function*() {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005508 "export default class C {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005509 "export default class {}"
5510 "export default class extends C {}"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005511 "export default 42",
5512 "var x; export default x = 7",
5513 "export { Q } from 'somemodule.js';",
5514 "export * from 'somemodule.js';",
5515 "var foo; export { foo as for };",
5516 "export { arguments } from 'm.js';",
5517 "export { for } from 'm.js';",
5518 "export { yield } from 'm.js'",
5519 "export { static } from 'm.js'",
5520 "export { let } from 'm.js'",
5521 "var a; export { a as b, a as c };",
Ben Murdochc5610432016-08-08 18:44:38 +01005522 "var a; export { a as await };",
5523 "var a; export { a as enum };",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005524
5525 "import 'somemodule.js';",
5526 "import { } from 'm.js';",
5527 "import { a } from 'm.js';",
5528 "import { a, b as d, c, } from 'm.js';",
5529 "import * as thing from 'm.js';",
5530 "import thing from 'm.js';",
5531 "import thing, * as rest from 'm.js';",
5532 "import thing, { a, b, c } from 'm.js';",
5533 "import { arguments as a } from 'm.js';",
5534 "import { for as f } from 'm.js';",
5535 "import { yield as y } from 'm.js';",
5536 "import { static as s } from 'm.js';",
5537 "import { let as l } from 'm.js';",
5538 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005539 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005540
5541 i::Isolate* isolate = CcTest::i_isolate();
5542 i::Factory* factory = isolate->factory();
5543
5544 v8::HandleScope handles(CcTest::isolate());
5545 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5546 v8::Context::Scope context_scope(context);
5547
5548 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5549 128 * 1024);
5550
5551 for (unsigned i = 0; i < arraysize(kSources); ++i) {
5552 i::Handle<i::String> source =
5553 factory->NewStringFromAsciiChecked(kSources[i]);
5554
5555 // Show that parsing as a module works
5556 {
5557 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005558 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005559 i::ParseInfo info(&zone, script);
5560 i::Parser parser(&info);
5561 info.set_module();
5562 if (!parser.Parse(&info)) {
5563 i::Handle<i::JSObject> exception_handle(
5564 i::JSObject::cast(isolate->pending_exception()));
Ben Murdochda12d292016-06-02 14:46:10 +01005565 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
5566 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
5567 .ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005568
5569 v8::base::OS::Print(
5570 "Parser failed on:\n"
5571 "\t%s\n"
5572 "with error:\n"
5573 "\t%s\n"
5574 "However, we expected no error.",
5575 source->ToCString().get(), message_string->ToCString().get());
5576 CHECK(false);
5577 }
5578 }
5579
5580 // And that parsing a script does not.
5581 {
5582 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005583 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005584 i::ParseInfo info(&zone, script);
5585 i::Parser parser(&info);
5586 info.set_global();
5587 CHECK(!parser.Parse(&info));
5588 }
5589 }
5590}
5591
5592
5593TEST(ImportExportParsingErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005594 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005595 const char* kErrorSources[] = {
5596 "export {",
5597 "var a; export { a",
5598 "var a; export { a,",
5599 "var a; export { a, ;",
5600 "var a; export { a as };",
5601 "var a, b; export { a as , b};",
5602 "export }",
5603 "var foo, bar; export { foo bar };",
5604 "export { foo };",
5605 "export { , };",
5606 "export default;",
5607 "export default var x = 7;",
5608 "export default let x = 7;",
5609 "export default const x = 7;",
5610 "export *;",
5611 "export * from;",
5612 "export { Q } from;",
5613 "export default from 'module.js';",
5614 "export { for }",
5615 "export { for as foo }",
5616 "export { arguments }",
5617 "export { arguments as foo }",
5618 "var a; export { a, a };",
5619 "var a, b; export { a as b, b };",
5620 "var a, b; export { a as c, b as c };",
5621 "export default function f(){}; export default class C {};",
5622 "export default function f(){}; var a; export { a as default };",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005623 "export function() {}",
5624 "export function*() {}",
5625 "export class {}",
5626 "export class extends C {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005627
5628 "import from;",
5629 "import from 'm.js';",
5630 "import { };",
5631 "import {;",
5632 "import };",
5633 "import { , };",
5634 "import { , } from 'm.js';",
5635 "import { a } from;",
5636 "import { a } 'm.js';",
5637 "import , from 'm.js';",
5638 "import a , from 'm.js';",
5639 "import a { b, c } from 'm.js';",
5640 "import arguments from 'm.js';",
5641 "import eval from 'm.js';",
5642 "import { arguments } from 'm.js';",
5643 "import { eval } from 'm.js';",
5644 "import { a as arguments } from 'm.js';",
5645 "import { for } from 'm.js';",
5646 "import { y as yield } from 'm.js'",
5647 "import { s as static } from 'm.js'",
5648 "import { l as let } from 'm.js'",
Ben Murdochc5610432016-08-08 18:44:38 +01005649 "import { a as await } from 'm.js';",
5650 "import { a as enum } from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005651 "import { x }, def from 'm.js';",
5652 "import def, def2 from 'm.js';",
5653 "import * as x, def from 'm.js';",
5654 "import * as x, * as y from 'm.js';",
5655 "import {x}, {y} from 'm.js';",
5656 "import * as x, {y} from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005657 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005658 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005659
5660 i::Isolate* isolate = CcTest::i_isolate();
5661 i::Factory* factory = isolate->factory();
5662
5663 v8::HandleScope handles(CcTest::isolate());
5664 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5665 v8::Context::Scope context_scope(context);
5666
5667 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5668 128 * 1024);
5669
5670 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5671 i::Handle<i::String> source =
5672 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5673
5674 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005675 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005676 i::ParseInfo info(&zone, script);
5677 i::Parser parser(&info);
5678 info.set_module();
5679 CHECK(!parser.Parse(&info));
5680 }
5681}
5682
Ben Murdochc5610432016-08-08 18:44:38 +01005683TEST(ModuleTopLevelFunctionDecl) {
5684 // clang-format off
5685 const char* kErrorSources[] = {
5686 "function f() {} function f() {}",
5687 "var f; function f() {}",
5688 "function f() {} var f;",
5689 "function* f() {} function* f() {}",
5690 "var f; function* f() {}",
5691 "function* f() {} var f;",
5692 "function f() {} function* f() {}",
5693 "function* f() {} function f() {}",
5694 };
5695 // clang-format on
5696
5697 i::Isolate* isolate = CcTest::i_isolate();
5698 i::Factory* factory = isolate->factory();
5699
5700 v8::HandleScope handles(CcTest::isolate());
5701 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5702 v8::Context::Scope context_scope(context);
5703
5704 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5705 128 * 1024);
5706
5707 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5708 i::Handle<i::String> source =
5709 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5710
5711 i::Handle<i::Script> script = factory->NewScript(source);
5712 i::Zone zone(CcTest::i_isolate()->allocator());
5713 i::ParseInfo info(&zone, script);
5714 i::Parser parser(&info);
5715 info.set_module();
5716 CHECK(!parser.Parse(&info));
5717 }
5718}
5719
5720TEST(ModuleAwaitReserved) {
5721 // clang-format off
5722 const char* kErrorSources[] = {
5723 "await;",
5724 "await: ;",
5725 "var await;",
5726 "var [await] = [];",
5727 "var { await } = {};",
5728 "var { x: await } = {};",
5729 "{ var await; }",
5730 "let await;",
5731 "let [await] = [];",
5732 "let { await } = {};",
5733 "let { x: await } = {};",
5734 "{ let await; }",
5735 "const await = null;",
5736 "const [await] = [];",
5737 "const { await } = {};",
5738 "const { x: await } = {};",
5739 "{ const await = null; }",
5740 "function await() {}",
5741 "function f(await) {}",
5742 "function* await() {}",
5743 "function* g(await) {}",
5744 "(function await() {});",
5745 "(function (await) {});",
5746 "(function* await() {});",
5747 "(function* (await) {});",
5748 "(await) => {};",
5749 "await => {};",
5750 "class await {}",
5751 "class C { constructor(await) {} }",
5752 "class C { m(await) {} }",
5753 "class C { static m(await) {} }",
5754 "class C { *m(await) {} }",
5755 "class C { static *m(await) {} }",
5756 "(class await {})",
5757 "(class { constructor(await) {} });",
5758 "(class { m(await) {} });",
5759 "(class { static m(await) {} });",
5760 "(class { *m(await) {} });",
5761 "(class { static *m(await) {} });",
5762 "({ m(await) {} });",
5763 "({ *m(await) {} });",
5764 "({ set p(await) {} });",
5765 "try {} catch (await) {}",
5766 "try {} catch (await) {} finally {}",
5767 NULL
5768 };
5769 // clang-format on
5770 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5771
5772 RunModuleParserSyncTest(context_data, kErrorSources, kError);
5773}
5774
5775TEST(ModuleAwaitReservedPreParse) {
5776 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5777 const char* error_data[] = {"function f() { var await = 0; }", NULL};
5778
5779 RunModuleParserSyncTest(context_data, error_data, kError);
5780}
5781
5782TEST(ModuleAwaitPermitted) {
5783 // clang-format off
5784 const char* kValidSources[] = {
5785 "({}).await;",
5786 "({ await: null });",
5787 "({ await() {} });",
5788 "({ get await() {} });",
5789 "({ set await(x) {} });",
5790 "(class { await() {} });",
5791 "(class { static await() {} });",
5792 "(class { *await() {} });",
5793 "(class { static *await() {} });",
5794 NULL
5795 };
5796 // clang-format on
5797 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5798
5799 RunModuleParserSyncTest(context_data, kValidSources, kSuccess);
5800}
5801
5802TEST(EnumReserved) {
5803 // clang-format off
5804 const char* kErrorSources[] = {
5805 "enum;",
5806 "enum: ;",
5807 "var enum;",
5808 "var [enum] = [];",
5809 "var { enum } = {};",
5810 "var { x: enum } = {};",
5811 "{ var enum; }",
5812 "let enum;",
5813 "let [enum] = [];",
5814 "let { enum } = {};",
5815 "let { x: enum } = {};",
5816 "{ let enum; }",
5817 "const enum = null;",
5818 "const [enum] = [];",
5819 "const { enum } = {};",
5820 "const { x: enum } = {};",
5821 "{ const enum = null; }",
5822 "function enum() {}",
5823 "function f(enum) {}",
5824 "function* enum() {}",
5825 "function* g(enum) {}",
5826 "(function enum() {});",
5827 "(function (enum) {});",
5828 "(function* enum() {});",
5829 "(function* (enum) {});",
5830 "(enum) => {};",
5831 "enum => {};",
5832 "class enum {}",
5833 "class C { constructor(enum) {} }",
5834 "class C { m(enum) {} }",
5835 "class C { static m(enum) {} }",
5836 "class C { *m(enum) {} }",
5837 "class C { static *m(enum) {} }",
5838 "(class enum {})",
5839 "(class { constructor(enum) {} });",
5840 "(class { m(enum) {} });",
5841 "(class { static m(enum) {} });",
5842 "(class { *m(enum) {} });",
5843 "(class { static *m(enum) {} });",
5844 "({ m(enum) {} });",
5845 "({ *m(enum) {} });",
5846 "({ set p(enum) {} });",
5847 "try {} catch (enum) {}",
5848 "try {} catch (enum) {} finally {}",
5849 NULL
5850 };
5851 // clang-format on
5852 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5853
5854 RunModuleParserSyncTest(context_data, kErrorSources, kError);
5855}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005856
5857TEST(ModuleParsingInternals) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005858 i::Isolate* isolate = CcTest::i_isolate();
5859 i::Factory* factory = isolate->factory();
5860 v8::HandleScope handles(CcTest::isolate());
5861 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5862 v8::Context::Scope context_scope(context);
5863 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5864 128 * 1024);
5865
5866 static const char kSource[] =
5867 "let x = 5;"
5868 "export { x as y };"
5869 "import { q as z } from 'm.js';"
5870 "import n from 'n.js';"
5871 "export { a as b } from 'm.js';"
5872 "export * from 'p.js';"
5873 "import 'q.js'";
5874 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
5875 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005876 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005877 i::ParseInfo info(&zone, script);
5878 i::Parser parser(&info);
5879 info.set_module();
5880 CHECK(parser.Parse(&info));
5881 CHECK(i::Compiler::Analyze(&info));
5882 i::FunctionLiteral* func = info.literal();
5883 i::Scope* module_scope = func->scope();
5884 i::Scope* outer_scope = module_scope->outer_scope();
5885 CHECK(outer_scope->is_script_scope());
5886 CHECK_NULL(outer_scope->outer_scope());
5887 CHECK(module_scope->is_module_scope());
5888 i::ModuleDescriptor* descriptor = module_scope->module();
5889 CHECK_NOT_NULL(descriptor);
5890 CHECK_EQ(1, descriptor->Length());
5891 const i::AstRawString* export_name =
5892 info.ast_value_factory()->GetOneByteString("y");
5893 const i::AstRawString* local_name =
5894 descriptor->LookupLocalExport(export_name, &zone);
5895 CHECK_NOT_NULL(local_name);
5896 CHECK(local_name->IsOneByteEqualTo("x"));
5897 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
5898 CHECK_EQ(3, declarations->length());
5899 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
5900 i::ImportDeclaration* import_decl =
5901 declarations->at(1)->AsImportDeclaration();
5902 CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
5903 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
5904 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
5905 import_decl = declarations->at(2)->AsImportDeclaration();
5906 CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
5907 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
5908 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
5909 // TODO(adamk): Add test for indirect exports once they're fully implemented.
5910 // TODO(adamk): Add test for star exports once they're fully implemented.
5911 const i::ZoneList<const i::AstRawString*>& requested_modules =
5912 descriptor->requested_modules();
5913 CHECK_EQ(4, requested_modules.length());
5914 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
5915 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
5916 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
5917 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
5918}
5919
5920
5921TEST(DuplicateProtoError) {
5922 const char* context_data[][2] = {
5923 {"({", "});"},
5924 {"'use strict'; ({", "});"},
5925 {NULL, NULL}
5926 };
5927 const char* error_data[] = {
5928 "__proto__: {}, __proto__: {}",
5929 "__proto__: {}, \"__proto__\": {}",
5930 "__proto__: {}, \"__\x70roto__\": {}",
5931 "__proto__: {}, a: 1, __proto__: {}",
5932 NULL
5933 };
5934
5935 RunParserSyncTest(context_data, error_data, kError);
5936}
5937
5938
5939TEST(DuplicateProtoNoError) {
5940 const char* context_data[][2] = {
5941 {"({", "});"},
5942 {"'use strict'; ({", "});"},
5943 {NULL, NULL}
5944 };
5945 const char* error_data[] = {
5946 "__proto__: {}, ['__proto__']: {}",
5947 "__proto__: {}, __proto__() {}",
5948 "__proto__: {}, get __proto__() {}",
5949 "__proto__: {}, set __proto__(v) {}",
5950 "__proto__: {}, __proto__",
5951 NULL
5952 };
5953
5954 RunParserSyncTest(context_data, error_data, kSuccess);
5955}
5956
5957
5958TEST(DeclarationsError) {
5959 const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5960 {"'use strict'; if (false) {} else", ""},
5961 {"'use strict'; while (false)", ""},
5962 {"'use strict'; for (;;)", ""},
5963 {"'use strict'; for (x in y)", ""},
5964 {"'use strict'; do ", " while (false)"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005965 {NULL, NULL}};
5966
5967 const char* statement_data[] = {
5968 "let x = 1;",
5969 "const x = 1;",
5970 "class C {}",
5971 NULL};
5972
Ben Murdochda12d292016-06-02 14:46:10 +01005973 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005974}
5975
5976
5977void TestLanguageMode(const char* source,
5978 i::LanguageMode expected_language_mode) {
5979 i::Isolate* isolate = CcTest::i_isolate();
5980 i::Factory* factory = isolate->factory();
5981 v8::HandleScope handles(CcTest::isolate());
5982 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5983 v8::Context::Scope context_scope(context);
5984 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5985 128 * 1024);
5986
5987 i::Handle<i::Script> script =
5988 factory->NewScript(factory->NewStringFromAsciiChecked(source));
Ben Murdochda12d292016-06-02 14:46:10 +01005989 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005990 i::ParseInfo info(&zone, script);
5991 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005992 info.set_global();
5993 parser.Parse(&info);
5994 CHECK(info.literal() != NULL);
5995 CHECK_EQ(expected_language_mode, info.literal()->language_mode());
5996}
5997
5998
5999TEST(LanguageModeDirectives) {
6000 TestLanguageMode("\"use nothing\"", i::SLOPPY);
6001 TestLanguageMode("\"use strict\"", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006002
6003 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006004
6005 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006006}
6007
6008
6009TEST(PropertyNameEvalArguments) {
6010 const char* context_data[][2] = {{"'use strict';", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006011 {NULL, NULL}};
6012
6013 const char* statement_data[] = {
6014 "({eval: 1})",
6015 "({arguments: 1})",
6016 "({eval() {}})",
6017 "({arguments() {}})",
6018 "({*eval() {}})",
6019 "({*arguments() {}})",
6020 "({get eval() {}})",
6021 "({get arguments() {}})",
6022 "({set eval(_) {}})",
6023 "({set arguments(_) {}})",
6024
6025 "class C {eval() {}}",
6026 "class C {arguments() {}}",
6027 "class C {*eval() {}}",
6028 "class C {*arguments() {}}",
6029 "class C {get eval() {}}",
6030 "class C {get arguments() {}}",
6031 "class C {set eval(_) {}}",
6032 "class C {set arguments(_) {}}",
6033
6034 "class C {static eval() {}}",
6035 "class C {static arguments() {}}",
6036 "class C {static *eval() {}}",
6037 "class C {static *arguments() {}}",
6038 "class C {static get eval() {}}",
6039 "class C {static get arguments() {}}",
6040 "class C {static set eval(_) {}}",
6041 "class C {static set arguments(_) {}}",
6042
6043 NULL};
6044
Ben Murdochda12d292016-06-02 14:46:10 +01006045 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006046}
6047
6048
6049TEST(FunctionLiteralDuplicateParameters) {
6050 const char* strict_context_data[][2] =
6051 {{"'use strict';(function(", "){})();"},
6052 {"(function(", ") { 'use strict'; })();"},
6053 {"'use strict'; function fn(", ") {}; fn();"},
6054 {"function fn(", ") { 'use strict'; }; fn();"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006055 {NULL, NULL}};
6056
6057 const char* sloppy_context_data[][2] =
6058 {{"(function(", "){})();"},
6059 {"(function(", ") {})();"},
6060 {"function fn(", ") {}; fn();"},
6061 {"function fn(", ") {}; fn();"},
6062 {NULL, NULL}};
6063
6064 const char* data[] = {
6065 "a, a",
6066 "a, a, a",
6067 "b, a, a",
6068 "a, b, c, c",
6069 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
6070 NULL};
6071
Ben Murdochda12d292016-06-02 14:46:10 +01006072 RunParserSyncTest(strict_context_data, data, kError);
6073 RunParserSyncTest(sloppy_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006074}
6075
6076
6077TEST(ArrowFunctionASIErrors) {
6078 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
6079 {NULL, NULL}};
6080
6081 const char* data[] = {
6082 "(a\n=> a)(1)",
6083 "(a/*\n*/=> a)(1)",
6084 "((a)\n=> a)(1)",
6085 "((a)/*\n*/=> a)(1)",
6086 "((a, b)\n=> a + b)(1, 2)",
6087 "((a, b)/*\n*/=> a + b)(1, 2)",
6088 NULL};
6089 RunParserSyncTest(context_data, data, kError);
6090}
6091
6092
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006093TEST(DestructuringPositiveTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006094 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6095 {"var ", " = {};"},
6096 {"'use strict'; const ", " = {};"},
6097 {"function f(", ") {}"},
6098 {"function f(argument1, ", ") {}"},
6099 {"var f = (", ") => {};"},
6100 {"var f = (argument1,", ") => {};"},
6101 {"try {} catch(", ") {}"},
6102 {NULL, NULL}};
6103
6104 // clang-format off
6105 const char* data[] = {
6106 "a",
6107 "{ x : y }",
6108 "{ x : y = 1 }",
6109 "{ get, set }",
6110 "{ get = 1, set = 2 }",
6111 "[a]",
6112 "[a = 1]",
6113 "[a,b,c]",
6114 "[a, b = 42, c]",
6115 "{ x : x, y : y }",
6116 "{ x : x = 1, y : y }",
6117 "{ x : x, y : y = 42 }",
6118 "[]",
6119 "{}",
6120 "[{x:x, y:y}, [a,b,c]]",
6121 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
6122 "{x}",
6123 "{x, y}",
6124 "{x = 42, y = 15}",
6125 "[a,,b]",
6126 "{42 : x}",
6127 "{42 : x = 42}",
6128 "{42e-2 : x}",
6129 "{42e-2 : x = 42}",
6130 "{x : y, x : z}",
6131 "{'hi' : x}",
6132 "{'hi' : x = 42}",
6133 "{var: x}",
6134 "{var: x = 42}",
6135 "{[x] : z}",
6136 "{[1+1] : z}",
6137 "{[foo()] : z}",
6138 "{}",
6139 "[...rest]",
6140 "[a,b,...rest]",
6141 "[a,,...rest]",
6142 NULL};
6143 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006144 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006145}
6146
6147
6148TEST(DestructuringNegativeTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006149 { // All modes.
6150 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6151 {"var ", " = {};"},
6152 {"'use strict'; const ", " = {};"},
6153 {"function f(", ") {}"},
6154 {"function f(argument1, ", ") {}"},
6155 {"var f = (", ") => {};"},
6156 {"var f = ", " => {};"},
6157 {"var f = (argument1,", ") => {};"},
6158 {"try {} catch(", ") {}"},
6159 {NULL, NULL}};
6160
6161 // clang-format off
6162 const char* data[] = {
6163 "a++",
6164 "++a",
6165 "delete a",
6166 "void a",
6167 "typeof a",
6168 "--a",
6169 "+a",
6170 "-a",
6171 "~a",
6172 "!a",
6173 "{ x : y++ }",
6174 "[a++]",
6175 "(x => y)",
6176 "a[i]", "a()",
6177 "a.b",
6178 "new a",
6179 "a + 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 "function a() {}",
6190 "a`bcd`",
6191 "this",
6192 "null",
6193 "true",
6194 "false",
6195 "1",
6196 "'abc'",
6197 "/abc/",
6198 "`abc`",
6199 "class {}",
6200 "{+2 : x}",
6201 "{-2 : x}",
6202 "var",
6203 "[var]",
6204 "{x : {y : var}}",
6205 "{x : x = a+}",
6206 "{x : x = (a+)}",
6207 "{x : x += a}",
6208 "{m() {} = 0}",
6209 "{[1+1]}",
6210 "[...rest, x]",
6211 "[a,b,...rest, x]",
6212 "[a,,...rest, x]",
6213 "[...rest,]",
6214 "[a,b,...rest,]",
6215 "[a,,...rest,]",
6216 "[...rest,...rest1]",
6217 "[a,b,...rest,...rest1]",
6218 "[a,,..rest,...rest1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006219 "[x, y, ...z = 1]",
6220 "[...z = 1]",
6221 "[x, y, ...[z] = [1]]",
6222 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006223 "{ x : 3 }",
6224 "{ x : 'foo' }",
6225 "{ x : /foo/ }",
6226 "{ x : `foo` }",
6227 "{ get a() {} }",
6228 "{ set a() {} }",
6229 "{ method() {} }",
6230 "{ *method() {} }",
6231 NULL};
6232 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006233 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006234 }
6235
6236 { // All modes.
6237 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6238 {"var ", " = {};"},
6239 {"'use strict'; const ", " = {};"},
6240 {"function f(", ") {}"},
6241 {"function f(argument1, ", ") {}"},
6242 {"var f = (", ") => {};"},
6243 {"var f = (argument1,", ") => {};"},
6244 {NULL, NULL}};
6245
6246 // clang-format off
6247 const char* data[] = {
6248 "x => x",
6249 "() => x",
6250 NULL};
6251 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006252 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006253 }
6254
6255 { // Strict mode.
6256 const char* context_data[][2] = {
6257 {"'use strict'; let ", " = {};"},
6258 {"'use strict'; const ", " = {};"},
6259 {"'use strict'; function f(", ") {}"},
6260 {"'use strict'; function f(argument1, ", ") {}"},
6261 {NULL, NULL}};
6262
6263 // clang-format off
6264 const char* data[] = {
6265 "[eval]",
6266 "{ a : arguments }",
6267 "[public]",
6268 "{ x : private }",
6269 NULL};
6270 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006271 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006272 }
6273
6274 { // 'yield' in generators.
6275 const char* context_data[][2] = {
6276 {"function*() { var ", " = {};"},
6277 {"function*() { 'use strict'; let ", " = {};"},
6278 {"function*() { 'use strict'; const ", " = {};"},
6279 {NULL, NULL}};
6280
6281 // clang-format off
6282 const char* data[] = {
6283 "yield",
6284 "[yield]",
6285 "{ x : yield }",
6286 NULL};
6287 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006288 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006289 }
6290
6291 { // Declaration-specific errors
6292 const char* context_data[][2] = {{"'use strict'; var ", ""},
6293 {"'use strict'; let ", ""},
6294 {"'use strict'; const ", ""},
6295 {"'use strict'; for (var ", ";;) {}"},
6296 {"'use strict'; for (let ", ";;) {}"},
6297 {"'use strict'; for (const ", ";;) {}"},
6298 {"var ", ""},
6299 {"let ", ""},
6300 {"const ", ""},
6301 {"for (var ", ";;) {}"},
6302 {"for (let ", ";;) {}"},
6303 {"for (const ", ";;) {}"},
6304 {NULL, NULL}};
6305
6306 // clang-format off
6307 const char* data[] = {
6308 "{ a }",
6309 "[ a ]",
6310 NULL};
6311 // clang-format on
Ben Murdochc5610432016-08-08 18:44:38 +01006312 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006313 }
6314}
6315
6316
6317TEST(DestructuringAssignmentPositiveTests) {
6318 const char* context_data[][2] = {
6319 {"'use strict'; let x, y, z; (", " = {});"},
6320 {"var x, y, z; (", " = {});"},
6321 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6322 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6323 {"var x, y, z; for (x in ", " = {});"},
6324 {"var x, y, z; for (x of ", " = {});"},
6325 {"var x, y, z; for (", " in {});"},
6326 {"var x, y, z; for (", " of {});"},
6327 {"'use strict'; var x, y, z; for (", " in {});"},
6328 {"'use strict'; var x, y, z; for (", " of {});"},
6329 {NULL, NULL}};
6330
6331 const char* mixed_assignments_context_data[][2] = {
6332 {"'use strict'; let x, y, z; (", " = z = {});"},
6333 {"var x, y, z; (", " = z = {});"},
6334 {"'use strict'; let x, y, z; (x = ", " = z = {});"},
6335 {"var x, y, z; (x = ", " = z = {});"},
6336 {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
6337 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
6338 {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
6339 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
6340 {"var x, y, z; for (x in ", " = z = {});"},
6341 {"var x, y, z; for (x in x = ", " = z = {});"},
6342 {"var x, y, z; for (x of ", " = z = {});"},
6343 {"var x, y, z; for (x of x = ", " = z = {});"},
6344 {NULL, NULL}};
6345
6346 // clang-format off
6347 const char* data[] = {
6348 "x",
6349
6350 "{ x : y }",
6351 "{ x : foo().y }",
6352 "{ x : foo()[y] }",
6353 "{ x : y.z }",
6354 "{ x : y[z] }",
6355 "{ x : { y } }",
6356 "{ x : { foo: y } }",
6357 "{ x : { foo: foo().y } }",
6358 "{ x : { foo: foo()[y] } }",
6359 "{ x : { foo: y.z } }",
6360 "{ x : { foo: y[z] } }",
6361 "{ x : [ y ] }",
6362 "{ x : [ foo().y ] }",
6363 "{ x : [ foo()[y] ] }",
6364 "{ x : [ y.z ] }",
6365 "{ x : [ y[z] ] }",
6366
6367 "{ x : y = 10 }",
6368 "{ x : foo().y = 10 }",
6369 "{ x : foo()[y] = 10 }",
6370 "{ x : y.z = 10 }",
6371 "{ x : y[z] = 10 }",
6372 "{ x : { y = 10 } = {} }",
6373 "{ x : { foo: y = 10 } = {} }",
6374 "{ x : { foo: foo().y = 10 } = {} }",
6375 "{ x : { foo: foo()[y] = 10 } = {} }",
6376 "{ x : { foo: y.z = 10 } = {} }",
6377 "{ x : { foo: y[z] = 10 } = {} }",
6378 "{ x : [ y = 10 ] = {} }",
6379 "{ x : [ foo().y = 10 ] = {} }",
6380 "{ x : [ foo()[y] = 10 ] = {} }",
6381 "{ x : [ y.z = 10 ] = {} }",
6382 "{ x : [ y[z] = 10 ] = {} }",
6383
6384 "[ x ]",
6385 "[ foo().x ]",
6386 "[ foo()[x] ]",
6387 "[ x.y ]",
6388 "[ x[y] ]",
6389 "[ { x } ]",
6390 "[ { x : y } ]",
6391 "[ { x : foo().y } ]",
6392 "[ { x : foo()[y] } ]",
6393 "[ { x : x.y } ]",
6394 "[ { x : x[y] } ]",
6395 "[ [ x ] ]",
6396 "[ [ foo().x ] ]",
6397 "[ [ foo()[x] ] ]",
6398 "[ [ x.y ] ]",
6399 "[ [ x[y] ] ]",
6400
6401 "[ x = 10 ]",
6402 "[ foo().x = 10 ]",
6403 "[ foo()[x] = 10 ]",
6404 "[ x.y = 10 ]",
6405 "[ x[y] = 10 ]",
6406 "[ { x = 10 } = {} ]",
6407 "[ { x : y = 10 } = {} ]",
6408 "[ { x : foo().y = 10 } = {} ]",
6409 "[ { x : foo()[y] = 10 } = {} ]",
6410 "[ { x : x.y = 10 } = {} ]",
6411 "[ { x : x[y] = 10 } = {} ]",
6412 "[ [ x = 10 ] = {} ]",
6413 "[ [ foo().x = 10 ] = {} ]",
6414 "[ [ foo()[x] = 10 ] = {} ]",
6415 "[ [ x.y = 10 ] = {} ]",
6416 "[ [ x[y] = 10 ] = {} ]",
6417 "{ x : y = 1 }",
6418 "{ x }",
6419 "{ x, y, z }",
6420 "{ x = 1, y: z, z: y }",
6421 "{x = 42, y = 15}",
6422 "[x]",
6423 "[x = 1]",
6424 "[x,y,z]",
6425 "[x, y = 42, z]",
6426 "{ x : x, y : y }",
6427 "{ x : x = 1, y : y }",
6428 "{ x : x, y : y = 42 }",
6429 "[]",
6430 "{}",
6431 "[{x:x, y:y}, [,x,z,]]",
6432 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
6433 "[x,,y]",
6434 "[(x),,(y)]",
6435 "[(x)]",
6436 "{42 : x}",
6437 "{42 : x = 42}",
6438 "{42e-2 : x}",
6439 "{42e-2 : x = 42}",
6440 "{'hi' : x}",
6441 "{'hi' : x = 42}",
6442 "{var: x}",
6443 "{var: x = 42}",
6444 "{var: (x) = 42}",
6445 "{[x] : z}",
6446 "{[1+1] : z}",
6447 "{[1+1] : (z)}",
6448 "{[foo()] : z}",
6449 "{[foo()] : (z)}",
6450 "{[foo()] : foo().bar}",
6451 "{[foo()] : foo()['bar']}",
6452 "{[foo()] : this.bar}",
6453 "{[foo()] : this['bar']}",
6454 "{[foo()] : 'foo'.bar}",
6455 "{[foo()] : 'foo'['bar']}",
6456 "[...x]",
6457 "[x,y,...z]",
6458 "[x,,...z]",
6459 "{ x: y }",
6460 "[x, y]",
6461 "[((x, y) => z).x]",
6462 "{x: ((y, z) => z).x}",
6463 "[((x, y) => z)['x']]",
6464 "{x: ((y, z) => z)['x']}",
6465
6466 "{x: { y = 10 } }",
6467 "[(({ x } = { x: 1 }) => x).a]",
6468
6469 // v8:4662
6470 "{ x: (y) }",
6471 "{ x: (y) = [] }",
6472 "{ x: (foo.bar) }",
6473 "{ x: (foo['bar']) }",
6474 "[ ...(a) ]",
6475 "[ ...(foo['bar']) ]",
6476 "[ ...(foo.bar) ]",
6477 "[ (y) ]",
6478 "[ (foo.bar) ]",
6479 "[ (foo['bar']) ]",
6480
6481 NULL};
6482 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006483 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006484
Ben Murdochda12d292016-06-02 14:46:10 +01006485 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006486
6487 const char* empty_context_data[][2] = {
6488 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6489
6490 // CoverInitializedName ambiguity handling in various contexts
6491 const char* ambiguity_data[] = {
6492 "var foo = { x = 10 } = {};",
6493 "var foo = { q } = { x = 10 } = {};",
6494 "var foo; foo = { x = 10 } = {};",
6495 "var foo; foo = { q } = { x = 10 } = {};",
6496 "var x; ({ x = 10 } = {});",
6497 "var q, x; ({ q } = { x = 10 } = {});",
6498 "var x; [{ x = 10 } = {}]",
6499 "var x; (true ? { x = true } = {} : { x = false } = {})",
6500 "var q, x; (q, { x = 10 } = {});",
6501 "var { x = 10 } = { x = 20 } = {};",
6502 "var { x = 10 } = (o = { x = 20 } = {});",
6503 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
6504 NULL,
6505 };
Ben Murdochda12d292016-06-02 14:46:10 +01006506 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006507}
6508
6509
6510TEST(DestructuringAssignmentNegativeTests) {
6511 const char* context_data[][2] = {
6512 {"'use strict'; let x, y, z; (", " = {});"},
6513 {"var x, y, z; (", " = {});"},
6514 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6515 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6516 {"var x, y, z; for (x in ", " = {});"},
6517 {"var x, y, z; for (x of ", " = {});"},
6518 {NULL, NULL}};
6519
6520 // clang-format off
6521 const char* data[] = {
6522 "{ x : ++y }",
6523 "{ x : y * 2 }",
6524 "{ ...x }",
6525 "{ get x() {} }",
6526 "{ set x() {} }",
6527 "{ x: y() }",
6528 "{ this }",
6529 "{ x: this }",
6530 "{ x: this = 1 }",
6531 "{ super }",
6532 "{ x: super }",
6533 "{ x: super = 1 }",
6534 "{ new.target }",
6535 "{ x: new.target }",
6536 "{ x: new.target = 1 }",
6537 "[x--]",
6538 "[--x = 1]",
6539 "[x()]",
6540 "[this]",
6541 "[this = 1]",
6542 "[new.target]",
6543 "[new.target = 1]",
6544 "[super]",
6545 "[super = 1]",
6546 "[function f() {}]",
6547 "[50]",
6548 "[(50)]",
6549 "[(function() {})]",
6550 "[(foo())]",
6551 "{ x: 50 }",
6552 "{ x: (50) }",
6553 "['str']",
6554 "{ x: 'str' }",
6555 "{ x: ('str') }",
6556 "{ x: (foo()) }",
6557 "{ x: (function() {}) }",
6558 "{ x: y } = 'str'",
6559 "[x, y] = 'str'",
6560 "[(x,y) => z]",
6561 "{x: (y) => z}",
6562 "[x, ...y, z]",
6563 "[...x,]",
6564 "[x, y, ...z = 1]",
6565 "[...z = 1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006566 "[x, y, ...[z] = [1]]",
6567 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006568
6569 // v8:4657
6570 "({ x: x4, x: (x+=1e4) })",
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: y } = {})",
6576 "(({ x: y } = {}))",
6577 "(({ x: y }) = {})",
6578 "([a])",
6579 "(([a]))",
6580 "([a] = [])",
6581 "(([a] = []))",
6582 "(([a]) = [])",
6583
6584 // v8:4662
6585 "{ x: ([y]) }",
6586 "{ x: ([y] = []) }",
6587 "{ x: ({y}) }",
6588 "{ x: ({y} = {}) }",
6589 "{ x: (++y) }",
6590 "[ (...[a]) ]",
6591 "[ ...([a]) ]",
6592 "[ ...([a] = [])",
6593 "[ ...[ ( [ a ] ) ] ]",
6594 "[ ([a]) ]",
6595 "[ (...[a]) ]",
6596 "[ ([a] = []) ]",
6597 "[ (++y) ]",
6598 "[ ...(++y) ]",
6599
6600 "[ x += x ]",
6601 "{ foo: x += x }",
6602
6603 NULL};
6604 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006605 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006606
6607 const char* empty_context_data[][2] = {
6608 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6609
6610 // CoverInitializedName ambiguity handling in various contexts
6611 const char* ambiguity_data[] = {
6612 "var foo = { x = 10 };",
6613 "var foo = { q } = { x = 10 };",
6614 "var foo; foo = { x = 10 };",
6615 "var foo; foo = { q } = { x = 10 };",
6616 "var x; ({ x = 10 });",
6617 "var q, x; ({ q } = { x = 10 });",
6618 "var x; [{ x = 10 }]",
6619 "var x; (true ? { x = true } : { x = false })",
6620 "var q, x; (q, { x = 10 });",
6621 "var { x = 10 } = { x = 20 };",
6622 "var { x = 10 } = (o = { x = 20 });",
6623 "var x; (({ x = 10 } = { x = 20 }) => x)({})",
6624
6625 // Not ambiguous, but uses same context data
6626 "switch([window %= []] = []) { default: }",
6627
6628 NULL,
6629 };
Ben Murdochda12d292016-06-02 14:46:10 +01006630 RunParserSyncTest(empty_context_data, ambiguity_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006631
6632 // Strict mode errors
6633 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
6634 {"'use strict'; for (", " of {}) {}"},
6635 {"'use strict'; for (", " in {}) {}"},
6636 {NULL, NULL}};
6637 const char* strict_data[] = {"{ eval }",
6638 "{ arguments }",
6639 "{ foo: eval }",
6640 "{ foo: arguments }",
6641 "{ eval = 0 }",
6642 "{ arguments = 0 }",
6643 "{ foo: eval = 0 }",
6644 "{ foo: arguments = 0 }",
6645 "[ eval ]",
6646 "[ arguments ]",
6647 "[ eval = 0 ]",
6648 "[ arguments = 0 ]",
6649
6650 // v8:4662
6651 "{ x: (eval) }",
6652 "{ x: (arguments) }",
6653 "{ x: (eval = 0) }",
6654 "{ x: (arguments = 0) }",
6655 "{ x: (eval) = 0 }",
6656 "{ x: (arguments) = 0 }",
6657 "[ (eval) ]",
6658 "[ (arguments) ]",
6659 "[ (eval = 0) ]",
6660 "[ (arguments = 0) ]",
6661 "[ (eval) = 0 ]",
6662 "[ (arguments) = 0 ]",
6663 "[ ...(eval) ]",
6664 "[ ...(arguments) ]",
6665 "[ ...(eval = 0) ]",
6666 "[ ...(arguments = 0) ]",
6667 "[ ...(eval) = 0 ]",
6668 "[ ...(arguments) = 0 ]",
6669
6670 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01006671 RunParserSyncTest(strict_context_data, strict_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006672}
6673
6674
6675TEST(DestructuringDisallowPatternsInForVarIn) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006676 const char* context_data[][2] = {
6677 {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
6678 // clang-format off
6679 const char* error_data[] = {
6680 "for (let x = {} in null);",
6681 "for (let x = {} of null);",
6682 NULL};
6683 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006684 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006685
6686 // clang-format off
6687 const char* success_data[] = {
6688 "for (var x = {} in null);",
6689 NULL};
6690 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006691 RunParserSyncTest(context_data, success_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006692}
6693
6694
6695TEST(DestructuringDuplicateParams) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006696 const char* context_data[][2] = {{"'use strict';", ""},
6697 {"function outer() { 'use strict';", "}"},
6698 {nullptr, nullptr}};
6699
6700
6701 // clang-format off
6702 const char* error_data[] = {
6703 "function f(x,x){}",
6704 "function f(x, {x : x}){}",
6705 "function f(x, {x}){}",
6706 "function f({x,x}) {}",
6707 "function f([x,x]) {}",
6708 "function f(x, [y,{z:x}]) {}",
6709 "function f([x,{y:x}]) {}",
6710 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6711 "function f(x, x, {a}) {}",
6712 nullptr};
6713 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006714 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006715}
6716
6717
6718TEST(DestructuringDuplicateParamsSloppy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006719 const char* context_data[][2] = {
6720 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
6721
6722
6723 // clang-format off
6724 const char* error_data[] = {
6725 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6726 "function f(x, {x : x}){}",
6727 "function f(x, {x}){}",
6728 "function f({x,x}) {}",
6729 "function f(x, x, {a}) {}",
6730 nullptr};
6731 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006732 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006733}
6734
6735
6736TEST(DestructuringDisallowPatternsInSingleParamArrows) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006737 const char* context_data[][2] = {{"'use strict';", ""},
6738 {"function outer() { 'use strict';", "}"},
6739 {"", ""},
6740 {"function outer() { ", "}"},
6741 {nullptr, nullptr}};
6742
6743 // clang-format off
6744 const char* error_data[] = {
6745 "var f = {x} => {};",
6746 "var f = {x,y} => {};",
6747 nullptr};
6748 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006749 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006750}
6751
6752
6753TEST(DefaultParametersYieldInInitializers) {
6754 // clang-format off
6755 const char* sloppy_function_context_data[][2] = {
6756 {"(function f(", ") { });"},
6757 {NULL, NULL}
6758 };
6759
6760 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006761 {"'use strict'; (function f(", ") { });"},
6762 {NULL, NULL}
6763 };
6764
6765 const char* sloppy_arrow_context_data[][2] = {
6766 {"((", ")=>{});"},
6767 {NULL, NULL}
6768 };
6769
6770 const char* strict_arrow_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006771 {"'use strict'; ((", ")=>{});"},
6772 {NULL, NULL}
6773 };
6774
6775 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006776 {"'use strict'; (function *g(", ") { });"},
6777 {"(function *g(", ") { });"},
Ben Murdochda12d292016-06-02 14:46:10 +01006778 // Arrow function within generator has the same rules.
6779 {"'use strict'; (function *g() { (", ") => {} });"},
6780 {"(function *g() { (", ") => {} });"},
Ben Murdochc5610432016-08-08 18:44:38 +01006781 // And similarly for arrow functions in the parameter list.
6782 {"'use strict'; (function *g(z = (", ") => {}) { });"},
6783 {"(function *g(z = (", ") => {}) { });"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006784 {NULL, NULL}
6785 };
6786
6787 const char* parameter_data[] = {
6788 "x=yield",
6789 "x, y=yield",
6790 "{x=yield}",
6791 "[x=yield]",
6792
6793 "x=(yield)",
6794 "x, y=(yield)",
6795 "{x=(yield)}",
6796 "[x=(yield)]",
6797
6798 "x=f(yield)",
6799 "x, y=f(yield)",
6800 "{x=f(yield)}",
6801 "[x=f(yield)]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006802
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006803 "{x}=yield",
6804 "[x]=yield",
6805
6806 "{x}=(yield)",
6807 "[x]=(yield)",
6808
6809 "{x}=f(yield)",
6810 "[x]=f(yield)",
6811 NULL
6812 };
6813
Ben Murdochda12d292016-06-02 14:46:10 +01006814 // Because classes are always in strict mode, these are always errors.
6815 const char* always_error_param_data[] = {
6816 "x = class extends (yield) { }",
6817 "x = class extends f(yield) { }",
6818 "x = class extends (null, yield) { }",
6819 "x = class extends (a ? null : yield) { }",
6820 "[x] = [class extends (a ? null : yield) { }]",
6821 "[x = class extends (a ? null : yield) { }]",
6822 "[x = class extends (a ? null : yield) { }] = [null]",
6823 "x = class { [yield]() { } }",
6824 "x = class { static [yield]() { } }",
6825 "x = class { [(yield, 1)]() { } }",
6826 "x = class { [y = (yield, 1)]() { } }",
6827 NULL
6828 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006829 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006830
Ben Murdochda12d292016-06-02 14:46:10 +01006831 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
6832 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006833
Ben Murdochda12d292016-06-02 14:46:10 +01006834 RunParserSyncTest(strict_function_context_data, parameter_data, kError);
6835 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006836
Ben Murdochda12d292016-06-02 14:46:10 +01006837 RunParserSyncTest(generator_context_data, parameter_data, kError);
6838 RunParserSyncTest(generator_context_data, always_error_param_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006839}
6840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006841TEST(SpreadArray) {
6842 const char* context_data[][2] = {
6843 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6844
6845 // clang-format off
6846 const char* data[] = {
6847 "[...a]",
6848 "[a, ...b]",
6849 "[...a,]",
6850 "[...a, ,]",
6851 "[, ...a]",
6852 "[...a, ...b]",
6853 "[...a, , ...b]",
6854 "[...[...a]]",
6855 "[, ...a]",
6856 "[, , ...a]",
6857 NULL};
6858 // clang-format on
6859 RunParserSyncTest(context_data, data, kSuccess);
6860}
6861
6862
6863TEST(SpreadArrayError) {
6864 const char* context_data[][2] = {
6865 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6866
6867 // clang-format off
6868 const char* data[] = {
6869 "[...]",
6870 "[a, ...]",
6871 "[..., ]",
6872 "[..., ...]",
6873 "[ (...a)]",
6874 NULL};
6875 // clang-format on
6876 RunParserSyncTest(context_data, data, kError);
6877}
6878
6879
6880TEST(NewTarget) {
6881 // clang-format off
6882 const char* good_context_data[][2] = {
6883 {"function f() {", "}"},
6884 {"'use strict'; function f() {", "}"},
6885 {"var f = function() {", "}"},
6886 {"'use strict'; var f = function() {", "}"},
6887 {"({m: function() {", "}})"},
6888 {"'use strict'; ({m: function() {", "}})"},
6889 {"({m() {", "}})"},
6890 {"'use strict'; ({m() {", "}})"},
6891 {"({get x() {", "}})"},
6892 {"'use strict'; ({get x() {", "}})"},
6893 {"({set x(_) {", "}})"},
6894 {"'use strict'; ({set x(_) {", "}})"},
6895 {"class C {m() {", "}}"},
6896 {"class C {get x() {", "}}"},
6897 {"class C {set x(_) {", "}}"},
6898 {NULL}
6899 };
6900
6901 const char* bad_context_data[][2] = {
6902 {"", ""},
6903 {"'use strict';", ""},
6904 {NULL}
6905 };
6906
6907 const char* data[] = {
6908 "new.target",
6909 "{ new.target }",
6910 "() => { new.target }",
6911 "() => new.target",
6912 "if (1) { new.target }",
6913 "if (1) {} else { new.target }",
6914 "while (0) { new.target }",
6915 "do { new.target } while (0)",
6916 NULL
6917 };
6918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006919 // clang-format on
6920
Ben Murdochc5610432016-08-08 18:44:38 +01006921 RunParserSyncTest(good_context_data, data, kSuccess);
6922 RunParserSyncTest(bad_context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006923}
6924
6925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006926TEST(ConstSloppy) {
6927 // clang-format off
6928 const char* context_data[][2] = {
6929 {"", ""},
6930 {"{", "}"},
6931 {NULL, NULL}
6932 };
6933
6934 const char* data[] = {
6935 "const x = 1",
6936 "for (const x = 1; x < 1; x++) {}",
6937 "for (const x in {}) {}",
6938 "for (const x of []) {}",
6939 NULL
6940 };
6941 // clang-format on
Ben Murdochc5610432016-08-08 18:44:38 +01006942 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006943}
6944
6945
6946TEST(LetSloppy) {
6947 // clang-format off
6948 const char* context_data[][2] = {
6949 {"", ""},
6950 {"'use strict';", ""},
6951 {"{", "}"},
6952 {NULL, NULL}
6953 };
6954
6955 const char* data[] = {
6956 "let x",
6957 "let x = 1",
6958 "for (let x = 1; x < 1; x++) {}",
6959 "for (let x in {}) {}",
6960 "for (let x of []) {}",
6961 NULL
6962 };
6963 // clang-format on
6964
Ben Murdochc5610432016-08-08 18:44:38 +01006965 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006966}
6967
6968
6969TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
6970 // TC39 deemed "use strict" directives to be an error when occurring in the
6971 // body of a function with non-simple parameter list, on 29/7/2015.
6972 // https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006973 const char* context_data[][2] = {
6974 {"function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006975 {"function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006976 {"class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006977 {"var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006978 {"var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006979 {"var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006980 {"var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006981 {"var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006982
6983 {"'use strict'; function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006984 {"'use strict'; function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006985 {"'use strict'; class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006986 {"'use strict'; var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006987 {"'use strict'; var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006988 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006989 {"'use strict'; var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006990 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006991
6992 {NULL, NULL}};
6993
6994 const char* data[] = {
6995 // TODO(@caitp): support formal parameter initializers
6996 "{}",
6997 "[]",
6998 "[{}]",
6999 "{a}",
7000 "a, {b}",
7001 "a, b, {c, d, e}",
7002 "initializer = true",
7003 "a, b, c = 1",
7004 "...args",
7005 "a, b, ...rest",
7006 "[a, b, ...rest]",
7007 "{ bindingPattern = {} }",
7008 "{ initializedBindingPattern } = { initializedBindingPattern: true }",
7009 NULL};
7010
Ben Murdochc5610432016-08-08 18:44:38 +01007011 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007012}
7013
7014
7015TEST(LetSloppyOnly) {
7016 // clang-format off
7017 const char* context_data[][2] = {
7018 {"", ""},
7019 {"{", "}"},
7020 {"(function() {", "})()"},
7021 {NULL, NULL}
7022 };
7023
7024 const char* data[] = {
7025 "let",
7026 "let = 1",
7027 "for (let = 1; let < 1; let++) {}",
7028 "for (let in {}) {}",
7029 "for (var let = 1; let < 1; let++) {}",
7030 "for (var let in {}) {}",
7031 "for (var [let] = 1; let < 1; let++) {}",
7032 "for (var [let] in {}) {}",
7033 "var let",
7034 "var [let] = []",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007035 NULL
7036 };
7037 // clang-format on
7038
Ben Murdochc5610432016-08-08 18:44:38 +01007039 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007040
7041 // Some things should be rejected even in sloppy mode
7042 // This addresses BUG(v8:4403).
7043
7044 // clang-format off
7045 const char* fail_data[] = {
7046 "let let = 1",
7047 "for (let let = 1; let < 1; let++) {}",
7048 "for (let let in {}) {}",
7049 "for (let let of []) {}",
7050 "const let = 1",
7051 "for (const let = 1; let < 1; let++) {}",
7052 "for (const let in {}) {}",
7053 "for (const let of []) {}",
7054 "let [let] = 1",
7055 "for (let [let] = 1; let < 1; let++) {}",
7056 "for (let [let] in {}) {}",
7057 "for (let [let] of []) {}",
7058 "const [let] = 1",
7059 "for (const [let] = 1; let < 1; let++) {}",
7060 "for (const [let] in {}) {}",
7061 "for (const [let] of []) {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007062
7063 // Sprinkle in the escaped version too.
7064 "let l\\u0065t = 1",
7065 "const l\\u0065t = 1",
7066 "let [l\\u0065t] = 1",
7067 "const [l\\u0065t] = 1",
7068 "for (let l\\u0065t in {}) {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007069 NULL
7070 };
7071 // clang-format on
7072
Ben Murdochc5610432016-08-08 18:44:38 +01007073 RunParserSyncTest(context_data, fail_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007074}
7075
7076
7077TEST(EscapedKeywords) {
7078 // clang-format off
7079 const char* sloppy_context_data[][2] = {
7080 {"", ""},
7081 {NULL, NULL}
7082 };
7083
7084 const char* strict_context_data[][2] = {
7085 {"'use strict';", ""},
7086 {NULL, NULL}
7087 };
7088
7089 const char* fail_data[] = {
7090 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
7091 "cl\\u0061ss Foo {}",
7092 "var x = cl\\u0061ss {}",
7093 "\\u0063onst foo = 1;",
7094 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
7095 "d\\u0065bugger;",
7096 "d\\u0065lete this.a;",
7097 "\\u0063o { } while(0)",
7098 "if (d\\u006f { true }) {}",
7099 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
7100 "e\\u0078port var foo;",
7101 "try { } catch (e) {} f\\u0069nally { }",
7102 "f\\u006fr (var i = 0; i < 10; ++i);",
7103 "f\\u0075nction fn() {}",
7104 "var f = f\\u0075nction() {}",
7105 "\\u0069f (true) { }",
7106 "\\u0069mport blah from './foo.js';",
7107 "n\\u0065w function f() {}",
7108 "(function() { r\\u0065turn; })()",
7109 "class C extends function() {} { constructor() { sup\\u0065r() } }",
7110 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
7111 "sw\\u0069tch (this.a) {}",
7112 "var x = th\\u0069s;",
7113 "th\\u0069s.a = 1;",
7114 "thr\\u006fw 'boo';",
7115 "t\\u0072y { true } catch (e) {}",
7116 "var x = typ\\u0065of 'blah'",
7117 "v\\u0061r a = true",
7118 "var v\\u0061r = true",
7119 "(function() { return v\\u006fid 0; })()",
7120 "wh\\u0069le (true) { }",
7121 "w\\u0069th (this.scope) { }",
7122 "(function*() { y\\u0069eld 1; })()",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007123 "(function*() { var y\\u0069eld = 1; })()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007124
7125 "var \\u0065num = 1;",
7126 "var { \\u0065num } = {}",
7127 "(\\u0065num = 1);",
7128
7129 // Null / Boolean literals
7130 "(x === n\\u0075ll);",
7131 "var x = n\\u0075ll;",
7132 "var n\\u0075ll = 1;",
7133 "var { n\\u0075ll } = { 1 };",
7134 "n\\u0075ll = 1;",
7135 "(x === tr\\u0075e);",
7136 "var x = tr\\u0075e;",
7137 "var tr\\u0075e = 1;",
7138 "var { tr\\u0075e } = {};",
7139 "tr\\u0075e = 1;",
7140 "(x === f\\u0061lse);",
7141 "var x = f\\u0061lse;",
7142 "var f\\u0061lse = 1;",
7143 "var { f\\u0061lse } = {};",
7144 "f\\u0061lse = 1;",
7145
7146 // TODO(caitp): consistent error messages for labeled statements and
7147 // expressions
7148 "switch (this.a) { c\\u0061se 6: break; }",
7149 "try { } c\\u0061tch (e) {}",
7150 "switch (this.a) { d\\u0065fault: break; }",
7151 "class C \\u0065xtends function B() {} {}",
7152 "for (var a i\\u006e this) {}",
7153 "if ('foo' \\u0069n this) {}",
7154 "if (this \\u0069nstanceof Array) {}",
7155 "(n\\u0065w function f() {})",
7156 "(typ\\u0065of 123)",
7157 "(v\\u006fid 0)",
7158 "do { ; } wh\\u0069le (true) { }",
7159 "(function*() { return (n++, y\\u0069eld 1); })()",
7160 "class C { st\\u0061tic bar() {} }",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007161 "class C { st\\u0061tic *bar() {} }",
7162 "class C { st\\u0061tic get bar() {} }",
7163 "class C { st\\u0061tic set bar() {} }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007164
Ben Murdoch097c5b22016-05-18 11:27:45 +01007165 // TODO(adamk): These should not be errors in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007166 "(y\\u0069eld);",
7167 "var y\\u0069eld = 1;",
7168 "var { y\\u0069eld } = {};",
7169 NULL
7170 };
7171 // clang-format on
7172
Ben Murdochc5610432016-08-08 18:44:38 +01007173 RunParserSyncTest(sloppy_context_data, fail_data, kError);
7174 RunParserSyncTest(strict_context_data, fail_data, kError);
7175 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007176
7177 // clang-format off
7178 const char* let_data[] = {
7179 "var l\\u0065t = 1;",
7180 "l\\u0065t = 1;",
7181 "(l\\u0065t === 1);",
7182 NULL
7183 };
7184 // clang-format on
7185
Ben Murdochc5610432016-08-08 18:44:38 +01007186 RunParserSyncTest(sloppy_context_data, let_data, kSuccess);
7187 RunParserSyncTest(strict_context_data, let_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007188
7189 // Non-errors in sloppy mode
7190 const char* valid_data[] = {"(\\u0069mplements = 1);",
7191 "var impl\\u0065ments = 1;",
7192 "var { impl\\u0065ments } = {};",
7193 "(\\u0069nterface = 1);",
7194 "var int\\u0065rface = 1;",
7195 "var { int\\u0065rface } = {};",
7196 "(p\\u0061ckage = 1);",
7197 "var packa\\u0067e = 1;",
7198 "var { packa\\u0067e } = {};",
7199 "(p\\u0072ivate = 1);",
7200 "var p\\u0072ivate;",
7201 "var { p\\u0072ivate } = {};",
7202 "(prot\\u0065cted);",
7203 "var prot\\u0065cted = 1;",
7204 "var { prot\\u0065cted } = {};",
7205 "(publ\\u0069c);",
7206 "var publ\\u0069c = 1;",
7207 "var { publ\\u0069c } = {};",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007208 "(st\\u0061tic);",
7209 "var st\\u0061tic = 1;",
7210 "var { st\\u0061tic } = {};",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007211 NULL};
Ben Murdochc5610432016-08-08 18:44:38 +01007212 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess);
7213 RunParserSyncTest(strict_context_data, valid_data, kError);
7214 RunModuleParserSyncTest(strict_context_data, valid_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007215}
7216
7217
7218TEST(MiscSyntaxErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007219 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007220 const char* context_data[][2] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007221 { "'use strict'", "" },
7222 { "", "" },
7223 { NULL, NULL }
7224 };
7225 const char* error_data[] = {
7226 "for (();;) {}",
7227
7228 // crbug.com/582626
7229 "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
7230 NULL
7231 };
7232 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007233
Ben Murdochc5610432016-08-08 18:44:38 +01007234 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007235}
Ben Murdoch097c5b22016-05-18 11:27:45 +01007236
Ben Murdochda12d292016-06-02 14:46:10 +01007237
7238TEST(EscapeSequenceErrors) {
7239 // clang-format off
7240 const char* context_data[][2] = {
7241 { "'", "'" },
7242 { "\"", "\"" },
7243 { "`", "`" },
7244 { "`${'", "'}`" },
7245 { "`${\"", "\"}`" },
7246 { "`${`", "`}`" },
7247 { "f(tag`", "`);" },
7248 { NULL, NULL }
7249 };
7250 const char* error_data[] = {
7251 "\\uABCG",
7252 "\\u{ZZ}",
7253 "\\u{FFZ}",
7254 "\\u{FFFFFFFFFF }",
7255 "\\u{110000}",
7256 "\\u{110000",
7257 "\\u{FFFD }",
7258 "\\xZF",
7259 NULL
7260 };
7261 // clang-format on
7262
Ben Murdochc5610432016-08-08 18:44:38 +01007263 RunParserSyncTest(context_data, error_data, kError);
Ben Murdochda12d292016-06-02 14:46:10 +01007264}
7265
7266
Ben Murdoch097c5b22016-05-18 11:27:45 +01007267TEST(FunctionSentErrors) {
7268 // clang-format off
7269 const char* context_data[][2] = {
7270 { "'use strict'", "" },
7271 { "", "" },
7272 { NULL, NULL }
7273 };
7274 const char* error_data[] = {
7275 "var x = function.sent",
7276 "function* g() { yield function.s\\u0065nt; }",
7277 NULL
7278 };
7279 // clang-format on
7280
7281 static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
7282 RunParserSyncTest(context_data, error_data, kError, always_flags,
7283 arraysize(always_flags));
7284}
7285
7286TEST(NewTargetErrors) {
7287 // clang-format off
7288 const char* context_data[][2] = {
7289 { "'use strict'", "" },
7290 { "", "" },
7291 { NULL, NULL }
7292 };
7293 const char* error_data[] = {
7294 "var x = new.target",
7295 "function f() { return new.t\\u0061rget; }",
7296 NULL
7297 };
7298 // clang-format on
7299 RunParserSyncTest(context_data, error_data, kError);
7300}
Ben Murdochda12d292016-06-02 14:46:10 +01007301
7302TEST(FunctionDeclarationError) {
7303 // clang-format off
7304 const char* strict_context[][2] = {
7305 { "'use strict';", "" },
7306 { "'use strict'; { ", "}" },
7307 {"(function() { 'use strict';", "})()"},
7308 {"(function() { 'use strict'; {", "} })()"},
7309 { NULL, NULL }
7310 };
7311 const char* sloppy_context[][2] = {
7312 { "", "" },
7313 { "{", "}" },
7314 {"(function() {", "})()"},
7315 {"(function() { {", "} })()"},
7316 { NULL, NULL }
7317 };
7318 // Invalid in all contexts
7319 const char* error_data[] = {
7320 "try function foo() {} catch (e) {}",
7321 NULL
7322 };
7323 // Valid in sloppy mode only, and only when the
7324 // --harmony-restrictive-declarations flag is off
7325 const char* unrestricted_data[] = {
7326 "do function foo() {} while (0);",
7327 "for (;false;) function foo() {}",
7328 "for (var i = 0; i < 1; i++) function f() { };",
7329 "for (var x in {a: 1}) function f() { };",
7330 "for (var x in {}) function f() { };",
7331 "for (var x in {}) function foo() {}",
7332 "for (x in {a: 1}) function f() { };",
7333 "for (x in {}) function f() { };",
7334 "var x; for (x in {}) function foo() {}",
7335 "with ({}) function f() { };",
7336 "do label: function foo() {} while (0);",
7337 "for (;false;) label: function foo() {}",
7338 "for (var i = 0; i < 1; i++) label: function f() { };",
7339 "for (var x in {a: 1}) label: function f() { };",
7340 "for (var x in {}) label: function f() { };",
7341 "for (var x in {}) label: function foo() {}",
7342 "for (x in {a: 1}) label: function f() { };",
7343 "for (x in {}) label: function f() { };",
7344 "var x; for (x in {}) label: function foo() {}",
7345 "with ({}) label: function f() { };",
7346 "if (true) label: function f() {}",
7347 "if (true) {} else label: function f() {}",
Ben Murdochc5610432016-08-08 18:44:38 +01007348 "if (true) function* f() { }",
7349 "label: function* f() { }",
7350 // TODO(littledan, v8:4806): Ban duplicate generator declarations in
7351 // a block, maybe by tracking whether a Variable is a generator declaration
7352 // "{ function* f() {} function* f() {} }",
7353 // "{ function f() {} function* f() {} }",
7354 // "{ function* f() {} function f() {} }",
Ben Murdochda12d292016-06-02 14:46:10 +01007355 NULL
7356 };
7357 // Valid only in sloppy mode, with or without
7358 // --harmony-restrictive-declarations
7359 const char* sloppy_data[] = {
7360 "if (true) function foo() {}",
7361 "if (false) {} else function f() { };",
7362 "label: function f() { }",
7363 "label: if (true) function f() { }",
7364 "label: if (true) {} else function f() { }",
7365 NULL
7366 };
7367 // clang-format on
7368
7369 static const ParserFlag restrictive_flags[] = {
7370 kAllowHarmonyRestrictiveDeclarations};
7371
7372 // Nothing parses in strict mode without a SyntaxError
7373 RunParserSyncTest(strict_context, error_data, kError);
7374 RunParserSyncTest(strict_context, error_data, kError, NULL, 0,
7375 restrictive_flags, arraysize(restrictive_flags));
7376 RunParserSyncTest(strict_context, unrestricted_data, kError);
7377 RunParserSyncTest(strict_context, unrestricted_data, kError, NULL, 0,
7378 restrictive_flags, arraysize(restrictive_flags));
7379 RunParserSyncTest(strict_context, sloppy_data, kError);
7380 RunParserSyncTest(strict_context, sloppy_data, kError, NULL, 0,
7381 restrictive_flags, arraysize(restrictive_flags));
7382
7383 // In sloppy mode, some things are successful, depending on the flag
7384 RunParserSyncTest(sloppy_context, error_data, kError);
7385 RunParserSyncTest(sloppy_context, error_data, kError, NULL, 0,
7386 restrictive_flags, arraysize(restrictive_flags));
7387 RunParserSyncTest(sloppy_context, unrestricted_data, kSuccess);
7388 RunParserSyncTest(sloppy_context, unrestricted_data, kError, NULL, 0,
7389 restrictive_flags, arraysize(restrictive_flags));
7390 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
7391 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess, restrictive_flags,
7392 arraysize(restrictive_flags));
7393}
7394
7395TEST(ExponentiationOperator) {
7396 // clang-format off
7397 const char* context_data[][2] = {
7398 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7399 { "var O = { p: 1 }, x = 10; ; (", ")" },
7400 { "var O = { p: 1 }, x = 10; foo(", ")" },
7401 { NULL, NULL }
7402 };
7403 const char* data[] = {
7404 "(delete O.p) ** 10",
7405 "(delete x) ** 10",
7406 "(~O.p) ** 10",
7407 "(~x) ** 10",
7408 "(!O.p) ** 10",
7409 "(!x) ** 10",
7410 "(+O.p) ** 10",
7411 "(+x) ** 10",
7412 "(-O.p) ** 10",
7413 "(-x) ** 10",
7414 "(typeof O.p) ** 10",
7415 "(typeof x) ** 10",
7416 "(void 0) ** 10",
7417 "(void O.p) ** 10",
7418 "(void x) ** 10",
7419 "++O.p ** 10",
7420 "++x ** 10",
7421 "--O.p ** 10",
7422 "--x ** 10",
7423 "O.p++ ** 10",
7424 "x++ ** 10",
7425 "O.p-- ** 10",
7426 "x-- ** 10",
7427 NULL
7428 };
7429 // clang-format on
7430
7431 static const ParserFlag always_flags[] = {
7432 kAllowHarmonyExponentiationOperator};
7433 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7434 arraysize(always_flags));
7435}
7436
7437TEST(ExponentiationOperatorErrors) {
7438 // clang-format off
7439 const char* context_data[][2] = {
7440 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7441 { "var O = { p: 1 }, x = 10; ; (", ")" },
7442 { "var O = { p: 1 }, x = 10; foo(", ")" },
7443 { NULL, NULL }
7444 };
7445 const char* error_data[] = {
7446 "delete O.p ** 10",
7447 "delete x ** 10",
7448 "~O.p ** 10",
7449 "~x ** 10",
7450 "!O.p ** 10",
7451 "!x ** 10",
7452 "+O.p ** 10",
7453 "+x ** 10",
7454 "-O.p ** 10",
7455 "-x ** 10",
7456 "typeof O.p ** 10",
7457 "typeof x ** 10",
7458 "void ** 10",
7459 "void O.p ** 10",
7460 "void x ** 10",
7461 "++delete O.p ** 10",
7462 "--delete O.p ** 10",
7463 "++~O.p ** 10",
7464 "++~x ** 10",
7465 "--!O.p ** 10",
7466 "--!x ** 10",
7467 "++-O.p ** 10",
7468 "++-x ** 10",
7469 "--+O.p ** 10",
7470 "--+x ** 10",
7471 "[ x ] **= [ 2 ]",
7472 "[ x **= 2 ] = [ 2 ]",
7473 "{ x } **= { x: 2 }",
7474 "{ x: x **= 2 ] = { x: 2 }",
7475 // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
7476 // "Array() **= 10",
7477 NULL
7478 };
7479 // clang-format on
7480
7481 static const ParserFlag always_flags[] = {
7482 kAllowHarmonyExponentiationOperator};
7483 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7484 arraysize(always_flags));
7485}
Ben Murdochc5610432016-08-08 18:44:38 +01007486
7487TEST(AsyncAwait) {
7488 // clang-format off
7489 const char* context_data[][2] = {
7490 { "'use strict';", "" },
7491 { "", "" },
7492 { NULL, NULL }
7493 };
7494
7495 const char* data[] = {
7496 "var asyncFn = async function() { await 1; };",
7497 "var asyncFn = async function withName() { await 1; };",
7498 "var asyncFn = async () => await 'test';",
7499 "var asyncFn = async x => await x + 'test';",
7500 "async function asyncFn() { await 1; }",
7501 "var O = { async method() { await 1; } }",
7502 "var O = { async ['meth' + 'od']() { await 1; } }",
7503 "var O = { async 'method'() { await 1; } }",
7504 "var O = { async 0() { await 1; } }",
7505 "async function await() {}",
7506 NULL
7507 };
7508 // clang-format on
7509
7510 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7511 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7512 arraysize(always_flags));
7513
7514 // clang-format off
7515 const char* async_body_context_data[][2] = {
7516 { "async function f() {", "}" },
7517 { "var f = async function() {", "}" },
7518 { "var f = async() => {", "}" },
7519 { "var O = { async method() {", "} }" },
7520 { "'use strict'; async function f() {", "}" },
7521 { "'use strict'; var f = async function() {", "}" },
7522 { "'use strict'; var f = async() => {", "}" },
7523 { "'use strict'; var O = { async method() {", "} }" },
7524 { NULL, NULL }
7525 };
7526
7527 const char* body_context_data[][2] = {
7528 { "function f() {", "}" },
7529 { "function* g() {", "}" },
7530 { "var f = function() {", "}" },
7531 { "var g = function*() {", "}" },
7532 { "var O = { method() {", "} }" },
7533 { "var O = { *method() {", "} }" },
7534 { "var f = () => {", "}" },
7535 { "'use strict'; function f() {", "}" },
7536 { "'use strict'; function* g() {", "}" },
7537 { "'use strict'; var f = function() {", "}" },
7538 { "'use strict'; var g = function*() {", "}" },
7539 { "'use strict'; var O = { method() {", "} }" },
7540 { "'use strict'; var O = { *method() {", "} }" },
7541 { "'use strict'; var f = () => {", "}" },
7542 { NULL, NULL }
7543 };
7544
7545 const char* body_data[] = {
7546 "var async = 1; return async;",
7547 "let async = 1; return async;",
7548 "const async = 1; return async;",
7549 "function async() {} return async();",
7550 "var async = async => async; return async();",
7551 "function foo() { var await = 1; return await; }",
7552 "function foo(await) { return await; }",
7553 "function* foo() { var await = 1; return await; }",
7554 "function* foo(await) { return await; }",
7555 "var f = (await) => await;",
7556 "var f = () => { var await = 1; return await; }",
7557 "var O = { method() { var await = 1; return await; } };",
7558 "var O = { method(await) { return await; } };",
7559 "var O = { *method() { var await = 1; return await; } };",
7560 "var O = { *method(await) { return await; } };",
7561
7562 "(function await() {})",
7563 NULL
7564 };
7565 // clang-format on
7566
7567 RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0,
7568 always_flags, arraysize(always_flags));
7569 RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0,
7570 always_flags, arraysize(always_flags));
7571}
7572
7573TEST(AsyncAwaitErrors) {
7574 // clang-format off
7575 const char* context_data[][2] = {
7576 { "'use strict';", "" },
7577 { "", "" },
7578 { NULL, NULL }
7579 };
7580
7581 const char* strict_context_data[][2] = {
7582 { "'use strict';", "" },
7583 { NULL, NULL }
7584 };
7585
7586 const char* error_data[] = {
7587 "var asyncFn = async function() { var await = 1; };",
7588 "var asyncFn = async function() { var { await } = 1; };",
7589 "var asyncFn = async function() { var [ await ] = 1; };",
7590 "var asyncFn = async function await() {};",
7591 "var asyncFn = async () => var await = 'test';",
7592 "var asyncFn = async await => await + 'test';",
7593 "var asyncFn = async function(await) {};",
7594 "var asyncFn = async function() { return async (await) => {}; }",
7595 "var asyncFn = async (await) => 'test';",
7596 "var asyncFn = async x => { var await = 1; }",
7597 "var asyncFn = async x => { var { await } = 1; }",
7598 "var asyncFn = async x => { var [ await ] = 1; }",
7599 "async function f(await) {}",
7600 "async function f() { var await = 1; }",
7601 "async function f() { var { await } = 1; }",
7602 "async function f() { var [ await ] = 1; }",
7603
7604 "var O = { async method(a, a) {} }",
7605 "var O = { async ['meth' + 'od'](a, a) {} }",
7606 "var O = { async 'method'(a, a) {} }",
7607 "var O = { async 0(a, a) {} }",
7608
7609 "async function f() { var O = { async [await](a, a) {} } }",
7610
7611 "var asyncFn = async function() { await; }",
7612 "async function f() { await; }",
7613 "var O = { async method() { await; } };",
7614 "var f = async() => await;",
7615 "var f = async() => { await; };",
7616
7617 "var asyncFn = async function*() {}",
7618 "async function* f() {}",
7619 "var O = { *async method() {} };",
7620 "var O = { async *method() {} };",
7621 "var O = { async method*() {} };",
7622
7623 "var asyncFn = async function(x = await 1) { return x; }",
7624 "async function f(x = await 1) { return x; }",
7625 "var f = async(x = await 1) => x;",
7626 "var O = { async method(x = await 1) { return x; } };",
7627
7628 "var f = async(x = await) => 1;",
7629
7630 "class C { async constructor() {} }",
7631 "class C {}; class C2 extends C { async constructor() {} }",
7632 "class C { static async prototype() {} }",
7633 "class C {}; class C2 extends C { static async prototype() {} }",
7634
7635 "var f = async() => ((async(x = await 1) => x)();",
7636
7637 "var asyncFn = async function() { function await() {} }",
7638 "var asyncFn = async() => { function await() {} }",
7639 "var O = { async method() { function await() {} } }",
7640 "async function foo() { function await() {} }",
7641
7642 NULL
7643 };
7644
7645 const char* strict_error_data[] = {
7646 "var O = { async method(eval) {} }",
7647 "var O = { async ['meth' + 'od'](eval) {} }",
7648 "var O = { async 'method'(eval) {} }",
7649 "var O = { async 0(eval) {} }",
7650
7651 "var O = { async method(arguments) {} }",
7652 "var O = { async ['meth' + 'od'](arguments) {} }",
7653 "var O = { async 'method'(arguments) {} }",
7654 "var O = { async 0(arguments) {} }",
7655
7656 "var O = { async method(dupe, dupe) {} }",
7657
7658 // TODO(caitp): preparser needs to report duplicate parameter errors, too.
7659 // "var f = async(dupe, dupe) => {}",
7660
7661 NULL
7662 };
7663 // clang-format on
7664
7665 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7666 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7667 arraysize(always_flags));
7668 RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0,
7669 always_flags, arraysize(always_flags));
7670}
7671
7672TEST(AsyncAwaitModule) {
7673 // clang-format off
7674 const char* context_data[][2] = {
7675 { "", "" },
7676 { NULL, NULL }
7677 };
7678
7679 const char* data[] = {
7680 "export default async function() { await 1; }",
7681 "export default async function async() { await 1; }",
7682 "export async function async() { await 1; }",
7683 NULL
7684 };
7685 // clang-format on
7686
7687 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7688 RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7689 arraysize(always_flags), NULL, 0, false);
7690}
7691
7692TEST(AsyncAwaitModuleErrors) {
7693 // clang-format off
7694 const char* context_data[][2] = {
7695 { "", "" },
7696 { NULL, NULL }
7697 };
7698
7699 const char* error_data[] = {
7700 "export default (async function await() {})",
7701 "export default async function await() {}",
7702 "export async function await() {}",
7703 "export async function() {}",
7704 "export async",
7705 NULL
7706 };
7707 // clang-format on
7708
7709 static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait};
7710 RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0,
7711 always_flags, arraysize(always_flags), NULL, 0,
7712 false);
7713}
7714
7715TEST(RestrictiveForInErrors) {
7716 // clang-format off
7717 const char* context_data[][2] = {
7718 { "'use strict'", "" },
7719 { "", "" },
7720 { NULL, NULL }
7721 };
7722 const char* error_data[] = {
7723 "for (var x = 0 in {});",
7724 "for (const x = 0 in {});",
7725 "for (let x = 0 in {});",
7726 NULL
7727 };
7728 // clang-format on
7729
7730 static const ParserFlag always_flags[] = {kAllowHarmonyForIn};
7731 RunParserSyncTest(context_data, error_data, kError, nullptr, 0, always_flags,
7732 arraysize(always_flags));
7733}