blob: b04fb94d3ac92801f23ef9b44ecade040319e1a8 [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 Murdoch4a90d5f2016-03-22 12:00:34 +0000156 i::Zone zone;
157 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 Murdoch4a90d5f2016-03-22 12:00:34 +0000174 i::Zone zone;
175 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) {
203 v8::Isolate* isolate = CcTest::isolate();
204 v8::HandleScope handles(isolate);
205 v8::Local<v8::Context> context = v8::Context::New(isolate);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100206 v8::Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 CcTest::i_isolate()->stack_guard()->SetStackLimit(
208 i::GetCurrentStackPosition() - 128 * 1024);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100209
210 // Source containing functions that might be lazily compiled and all types
211 // of symbols (string, propertyName, regexp).
212 const char* source =
213 "var x = 42;"
214 "function foo(a) { return function nolazy(b) { return a + b; } }"
215 "function bar(a) { if (a) return function lazy(b) { return b; } }"
216 "var z = {'string': 'string literal', bareword: 'propertyName', "
217 " 42: 'number literal', for: 'keyword as propertyName', "
218 " f\\u006fr: 'keyword propertyname with escape'};"
219 "var v = /RegExp Literal/;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 "var w = /RegExp Literal\\u0020With Escape/gi;"
Iain Merrick9ac36c92010-09-13 15:29:50 +0100221 "var y = { get getter() { return 42; }, "
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 " set setter(v) { this.value = v; }};"
223 "var f = a => function (b) { return a + b; };"
224 "var g = a => b => a + b;";
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100225 int source_length = i::StrLength(source);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100226
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 // ScriptResource will be deleted when the corresponding String is GCd.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 v8::ScriptCompiler::Source script_source(
229 v8::String::NewExternalOneByte(isolate,
230 new ScriptResource(source, source_length))
231 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 i::FLAG_min_preparse_length = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
234 v8::ScriptCompiler::kProduceParserCache)
235 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 CHECK(script_source.GetCachedData());
237
238 // Compile the script again, using the cached data.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100239 bool lazy_flag = i::FLAG_lazy;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 i::FLAG_lazy = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
242 v8::ScriptCompiler::kConsumeParserCache)
243 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244 i::FLAG_lazy = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 v8::ScriptCompiler::CompileUnboundScript(
246 isolate, &script_source, v8::ScriptCompiler::kConsumeParserCache)
247 .ToLocalChecked();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100248 i::FLAG_lazy = lazy_flag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249}
Iain Merrick9ac36c92010-09-13 15:29:50 +0100250
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251
252TEST(PreparseFunctionDataIsUsed) {
253 // This tests that we actually do use the function data generated by the
254 // preparser.
255
256 // Make preparsing work for short scripts.
257 i::FLAG_min_preparse_length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258
259 v8::Isolate* isolate = CcTest::isolate();
260 v8::HandleScope handles(isolate);
261 v8::Local<v8::Context> context = v8::Context::New(isolate);
262 v8::Context::Scope context_scope(context);
263 CcTest::i_isolate()->stack_guard()->SetStackLimit(
264 i::GetCurrentStackPosition() - 128 * 1024);
265
266 const char* good_code[] = {
267 "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
268 "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
269 };
270
271 // Insert a syntax error inside the lazy function.
272 const char* bad_code[] = {
273 "function this_is_lazy() { if ( } function foo() { return 25; } foo();",
274 "var this_is_lazy = () => { if ( }; var foo = () => 25; foo();",
275 };
276
277 for (unsigned i = 0; i < arraysize(good_code); i++) {
278 v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &good_source,
280 v8::ScriptCompiler::kProduceParserCache)
281 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282
283 const v8::ScriptCompiler::CachedData* cached_data =
284 good_source.GetCachedData();
285 CHECK(cached_data->data != NULL);
286 CHECK_GT(cached_data->length, 0);
287
288 // Now compile the erroneous code with the good preparse data. If the
289 // preparse data is used, the lazy function is skipped and it should
290 // compile fine.
291 v8::ScriptCompiler::Source bad_source(
292 v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
293 cached_data->data, cached_data->length));
294 v8::Local<v8::Value> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 CompileRun(isolate->GetCurrentContext(), &bad_source,
296 v8::ScriptCompiler::kConsumeParserCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 CHECK_EQ(25, result->Int32Value(isolate->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100300}
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800301
302
303TEST(StandAlonePreParser) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000304 v8::V8::Initialize();
305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 CcTest::i_isolate()->stack_guard()->SetStackLimit(
307 i::GetCurrentStackPosition() - 128 * 1024);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800308
309 const char* programs[] = {
310 "{label: 42}",
311 "var x = 42;",
312 "function foo(x, y) { return x + y; }",
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000313 "%ArgleBargle(glop);",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800314 "var x = new new Function('this.x = 42');",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 "var f = (x, y) => x + y;",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800316 NULL
317 };
318
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800320 for (int i = 0; programs[i]; i++) {
321 const char* program = programs[i];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100322 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100323 reinterpret_cast<const i::byte*>(program),
324 static_cast<unsigned>(strlen(program)));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800325 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100327 scanner.Initialize(&stream);
328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 i::Zone zone;
330 i::AstValueFactory ast_value_factory(
331 &zone, CcTest::i_isolate()->heap()->HashSeed());
332 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
333 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 preparser.set_allow_lazy(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 preparser.set_allow_natives(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 i::PreParser::PreParseResult result = preparser.PreParseProgram();
337 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
338 CHECK(!log.HasError());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800339 }
340}
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800341
342
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100343TEST(StandAlonePreParserNoNatives) {
344 v8::V8::Initialize();
345
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 CcTest::i_isolate()->stack_guard()->SetStackLimit(
347 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100348
349 const char* programs[] = {
350 "%ArgleBargle(glop);",
351 "var x = %_IsSmi(42);",
352 NULL
353 };
354
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100356 for (int i = 0; programs[i]; i++) {
357 const char* program = programs[i];
358 i::Utf8ToUtf16CharacterStream stream(
359 reinterpret_cast<const i::byte*>(program),
360 static_cast<unsigned>(strlen(program)));
361 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100363 scanner.Initialize(&stream);
364
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 // Preparser defaults to disallowing natives syntax.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 i::Zone zone;
367 i::AstValueFactory ast_value_factory(
368 &zone, CcTest::i_isolate()->heap()->HashSeed());
369 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
370 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 preparser.set_allow_lazy(true);
372 i::PreParser::PreParseResult result = preparser.PreParseProgram();
373 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
374 CHECK(log.HasError());
375 }
376}
377
378
379TEST(PreparsingObjectLiterals) {
380 // Regression test for a bug where the symbol stream produced by PreParser
381 // didn't match what Parser wanted to consume.
382 v8::Isolate* isolate = CcTest::isolate();
383 v8::HandleScope handles(isolate);
384 v8::Local<v8::Context> context = v8::Context::New(isolate);
385 v8::Context::Scope context_scope(context);
386 CcTest::i_isolate()->stack_guard()->SetStackLimit(
387 i::GetCurrentStackPosition() - 128 * 1024);
388
389 {
390 const char* source = "var myo = {if: \"foo\"}; myo.if;";
391 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
392 CHECK(result->IsString());
393 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 }
396
397 {
398 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
399 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
400 CHECK(result->IsString());
401 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403 }
404
405 {
406 const char* source = "var myo = {1: \"foo\"}; myo[1];";
407 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
408 CHECK(result->IsString());
409 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100411 }
412}
413
414
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800415TEST(RegressChromium62639) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000416 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000418
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
420 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800421
422 const char* program = "var x = 'something';\n"
423 "escape: function() {}";
424 // Fails parsing expecting an identifier after "function".
425 // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
426 // and then used the invalid currently scanned literal. This always
427 // failed in debug mode, and sometimes crashed in release mode.
428
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100429 i::Utf8ToUtf16CharacterStream stream(
430 reinterpret_cast<const i::byte*>(program),
431 static_cast<unsigned>(strlen(program)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 i::CompleteParserRecorder log;
433 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
434 scanner.Initialize(&stream);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 i::Zone zone;
436 i::AstValueFactory ast_value_factory(&zone,
437 CcTest::i_isolate()->heap()->HashSeed());
438 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 CcTest::i_isolate()->stack_guard()->real_climit());
440 preparser.set_allow_lazy(true);
441 i::PreParser::PreParseResult result = preparser.PreParseProgram();
442 // Even in the case of a syntax error, kPreParseSuccess is returned.
443 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
444 CHECK(log.HasError());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800445}
446
447
448TEST(Regress928) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000449 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000450 i::Isolate* isolate = CcTest::i_isolate();
451 i::Factory* factory = isolate->factory();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000452
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800453 // Preparsing didn't consider the catch clause of a try statement
454 // as with-content, which made it assume that a function inside
455 // the block could be lazily compiled, and an extra, unexpected,
456 // entry was added to the data.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
458 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800459
460 const char* program =
461 "try { } catch (e) { var foo = function () { /* first */ } }"
462 "var bar = function () { /* second */ }";
463
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 v8::HandleScope handles(CcTest::isolate());
465 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
466 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
467 i::CompleteParserRecorder log;
468 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
469 scanner.Initialize(&stream);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 i::Zone zone;
471 i::AstValueFactory ast_value_factory(&zone,
472 CcTest::i_isolate()->heap()->HashSeed());
473 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474 CcTest::i_isolate()->stack_guard()->real_climit());
475 preparser.set_allow_lazy(true);
476 i::PreParser::PreParseResult result = preparser.PreParseProgram();
477 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
478 i::ScriptData* sd = log.GetScriptData();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400479 i::ParseData* pd = i::ParseData::FromCachedData(sd);
480 pd->Initialize();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800481
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100482 int first_function =
483 static_cast<int>(strstr(program, "function") - program);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100484 int first_lbrace = first_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800485 CHECK_EQ('{', program[first_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400486 i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800487 CHECK(!entry1.is_valid());
488
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100489 int second_function =
490 static_cast<int>(strstr(program + first_lbrace, "function") - program);
491 int second_lbrace =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100492 second_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800493 CHECK_EQ('{', program[second_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400494 i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800495 CHECK(entry2.is_valid());
496 CHECK_EQ('}', program[entry2.end_pos() - 1]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 delete pd;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800499}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500
501
502TEST(PreParseOverflow) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000503 v8::V8::Initialize();
504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 CcTest::i_isolate()->stack_guard()->SetStackLimit(
506 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100507
508 size_t kProgramSize = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 v8::base::SmartArrayPointer<char> program(
510 i::NewArray<char>(kProgramSize + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 memset(program.get(), '(', kProgramSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100512 program[kProgramSize] = '\0';
513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100515
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100516 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 reinterpret_cast<const i::byte*>(program.get()),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100518 static_cast<unsigned>(kProgramSize));
519 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521 scanner.Initialize(&stream);
522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 i::Zone zone;
524 i::AstValueFactory ast_value_factory(&zone,
525 CcTest::i_isolate()->heap()->HashSeed());
526 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
527 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 preparser.set_allow_lazy(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 i::PreParser::PreParseResult result = preparser.PreParseProgram();
530 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100531}
532
533
534class TestExternalResource: public v8::String::ExternalStringResource {
535 public:
536 explicit TestExternalResource(uint16_t* data, int length)
537 : data_(data), length_(static_cast<size_t>(length)) { }
538
539 ~TestExternalResource() { }
540
541 const uint16_t* data() const {
542 return data_;
543 }
544
545 size_t length() const {
546 return length_;
547 }
548 private:
549 uint16_t* data_;
550 size_t length_;
551};
552
553
554#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
555
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556void TestCharacterStream(const char* one_byte_source, unsigned length,
557 unsigned start = 0, unsigned end = 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100558 if (end == 0) end = length;
559 unsigned sub_length = end - start;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560 i::Isolate* isolate = CcTest::i_isolate();
561 i::Factory* factory = isolate->factory();
562 i::HandleScope test_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 v8::base::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100564 for (unsigned i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565 uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100566 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 i::Vector<const char> one_byte_vector(one_byte_source,
568 static_cast<int>(length));
569 i::Handle<i::String> one_byte_string =
570 factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
571 TestExternalResource resource(uc16_buffer.get(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100572 i::Handle<i::String> uc16_string(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100574
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100575 i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100576 i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
578 end);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100579 i::Utf8ToUtf16CharacterStream utf8_stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 reinterpret_cast<const i::byte*>(one_byte_source), end);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100581 utf8_stream.SeekForward(start);
582
583 unsigned i = start;
584 while (i < end) {
585 // Read streams one char at a time
586 CHECK_EQU(i, uc16_stream.pos());
587 CHECK_EQU(i, string_stream.pos());
588 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100590 int32_t c1 = uc16_stream.Advance();
591 int32_t c2 = string_stream.Advance();
592 int32_t c3 = utf8_stream.Advance();
593 i++;
594 CHECK_EQ(c0, c1);
595 CHECK_EQ(c0, c2);
596 CHECK_EQ(c0, c3);
597 CHECK_EQU(i, uc16_stream.pos());
598 CHECK_EQU(i, string_stream.pos());
599 CHECK_EQU(i, utf8_stream.pos());
600 }
601 while (i > start + sub_length / 4) {
602 // Pushback, re-read, pushback again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 int32_t c0 = one_byte_source[i - 1];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100604 CHECK_EQU(i, uc16_stream.pos());
605 CHECK_EQU(i, string_stream.pos());
606 CHECK_EQU(i, utf8_stream.pos());
607 uc16_stream.PushBack(c0);
608 string_stream.PushBack(c0);
609 utf8_stream.PushBack(c0);
610 i--;
611 CHECK_EQU(i, uc16_stream.pos());
612 CHECK_EQU(i, string_stream.pos());
613 CHECK_EQU(i, utf8_stream.pos());
614 int32_t c1 = uc16_stream.Advance();
615 int32_t c2 = string_stream.Advance();
616 int32_t c3 = utf8_stream.Advance();
617 i++;
618 CHECK_EQU(i, uc16_stream.pos());
619 CHECK_EQU(i, string_stream.pos());
620 CHECK_EQU(i, utf8_stream.pos());
621 CHECK_EQ(c0, c1);
622 CHECK_EQ(c0, c2);
623 CHECK_EQ(c0, c3);
624 uc16_stream.PushBack(c0);
625 string_stream.PushBack(c0);
626 utf8_stream.PushBack(c0);
627 i--;
628 CHECK_EQU(i, uc16_stream.pos());
629 CHECK_EQU(i, string_stream.pos());
630 CHECK_EQU(i, utf8_stream.pos());
631 }
632 unsigned halfway = start + sub_length / 2;
633 uc16_stream.SeekForward(halfway - i);
634 string_stream.SeekForward(halfway - i);
635 utf8_stream.SeekForward(halfway - i);
636 i = halfway;
637 CHECK_EQU(i, uc16_stream.pos());
638 CHECK_EQU(i, string_stream.pos());
639 CHECK_EQU(i, utf8_stream.pos());
640
641 while (i < end) {
642 // Read streams one char at a time
643 CHECK_EQU(i, uc16_stream.pos());
644 CHECK_EQU(i, string_stream.pos());
645 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100647 int32_t c1 = uc16_stream.Advance();
648 int32_t c2 = string_stream.Advance();
649 int32_t c3 = utf8_stream.Advance();
650 i++;
651 CHECK_EQ(c0, c1);
652 CHECK_EQ(c0, c2);
653 CHECK_EQ(c0, c3);
654 CHECK_EQU(i, uc16_stream.pos());
655 CHECK_EQU(i, string_stream.pos());
656 CHECK_EQU(i, utf8_stream.pos());
657 }
658
659 int32_t c1 = uc16_stream.Advance();
660 int32_t c2 = string_stream.Advance();
661 int32_t c3 = utf8_stream.Advance();
662 CHECK_LT(c1, 0);
663 CHECK_LT(c2, 0);
664 CHECK_LT(c3, 0);
665}
666
667
668TEST(CharacterStreams) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 v8::Isolate* isolate = CcTest::isolate();
670 v8::HandleScope handles(isolate);
671 v8::Local<v8::Context> context = v8::Context::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 v8::Context::Scope context_scope(context);
673
674 TestCharacterStream("abc\0\n\r\x7f", 7);
675 static const unsigned kBigStringSize = 4096;
676 char buffer[kBigStringSize + 1];
677 for (unsigned i = 0; i < kBigStringSize; i++) {
678 buffer[i] = static_cast<char>(i & 0x7f);
679 }
680 TestCharacterStream(buffer, kBigStringSize);
681
682 TestCharacterStream(buffer, kBigStringSize, 576, 3298);
683
684 TestCharacterStream("\0", 1);
685 TestCharacterStream("", 0);
686}
687
688
689TEST(Utf8CharacterStream) {
690 static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
691 static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
692
693 static const int kAllUtf8CharsSize =
694 (unibrow::Utf8::kMaxOneByteChar + 1) +
695 (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
696 (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
697 static const unsigned kAllUtf8CharsSizeU =
698 static_cast<unsigned>(kAllUtf8CharsSize);
699
700 char buffer[kAllUtf8CharsSizeU];
701 unsigned cursor = 0;
702 for (int i = 0; i <= kMaxUC16Char; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000703 cursor += unibrow::Utf8::Encode(buffer + cursor, i,
704 unibrow::Utf16::kNoPreviousCharacter, true);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 CHECK(cursor == kAllUtf8CharsSizeU);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100707
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100708 i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
709 kAllUtf8CharsSizeU);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 int32_t bad = unibrow::Utf8::kBadChar;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 for (int i = 0; i <= kMaxUC16Char; i++) {
712 CHECK_EQU(i, stream.pos());
713 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 if (i >= 0xd800 && i <= 0xdfff) {
715 CHECK_EQ(bad, c);
716 } else {
717 CHECK_EQ(i, c);
718 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719 CHECK_EQU(i + 1, stream.pos());
720 }
721 for (int i = kMaxUC16Char; i >= 0; i--) {
722 CHECK_EQU(i + 1, stream.pos());
723 stream.PushBack(i);
724 CHECK_EQU(i, stream.pos());
725 }
726 int i = 0;
727 while (stream.pos() < kMaxUC16CharU) {
728 CHECK_EQU(i, stream.pos());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 int progress = static_cast<int>(stream.SeekForward(12));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100730 i += progress;
731 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 if (i >= 0xd800 && i <= 0xdfff) {
733 CHECK_EQ(bad, c);
734 } else if (i <= kMaxUC16Char) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100735 CHECK_EQ(i, c);
736 } else {
737 CHECK_EQ(-1, c);
738 }
739 i += 1;
740 CHECK_EQU(i, stream.pos());
741 }
742}
743
744#undef CHECK_EQU
745
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100746void TestStreamScanner(i::Utf16CharacterStream* stream,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100747 i::Token::Value* expected_tokens,
748 int skip_pos = 0, // Zero means not skipping.
749 int skip_to = 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000750 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +0100751 scanner.Initialize(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100752
753 int i = 0;
754 do {
755 i::Token::Value expected = expected_tokens[i];
756 i::Token::Value actual = scanner.Next();
757 CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
758 if (scanner.location().end_pos == skip_pos) {
759 scanner.SeekForward(skip_to);
760 }
761 i++;
762 } while (expected_tokens[i] != i::Token::ILLEGAL);
763}
764
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765
Ben Murdochb0fe1622011-05-05 13:52:32 +0100766TEST(StreamScanner) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000767 v8::V8::Initialize();
768
Ben Murdochb0fe1622011-05-05 13:52:32 +0100769 const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100770 i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
771 static_cast<unsigned>(strlen(str1)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772 i::Token::Value expectations1[] = {
773 i::Token::LBRACE,
774 i::Token::IDENTIFIER,
775 i::Token::IDENTIFIER,
776 i::Token::FOR,
777 i::Token::COLON,
778 i::Token::MUL,
779 i::Token::DIV,
780 i::Token::LT,
781 i::Token::SUB,
782 i::Token::IDENTIFIER,
783 i::Token::EOS,
784 i::Token::ILLEGAL
785 };
786 TestStreamScanner(&stream1, expectations1, 0, 0);
787
788 const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100789 i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
790 static_cast<unsigned>(strlen(str2)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100791 i::Token::Value expectations2[] = {
792 i::Token::CASE,
793 i::Token::DEFAULT,
794 i::Token::CONST,
795 i::Token::LBRACE,
796 // Skipped part here
797 i::Token::RBRACE,
798 i::Token::DO,
799 i::Token::EOS,
800 i::Token::ILLEGAL
801 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 CHECK_EQ('{', str2[19]);
803 CHECK_EQ('}', str2[37]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100804 TestStreamScanner(&stream2, expectations2, 20, 37);
805
806 const char* str3 = "{}}}}";
807 i::Token::Value expectations3[] = {
808 i::Token::LBRACE,
809 i::Token::RBRACE,
810 i::Token::RBRACE,
811 i::Token::RBRACE,
812 i::Token::RBRACE,
813 i::Token::EOS,
814 i::Token::ILLEGAL
815 };
816 // Skip zero-four RBRACEs.
817 for (int i = 0; i <= 4; i++) {
818 expectations3[6 - i] = i::Token::ILLEGAL;
819 expectations3[5 - i] = i::Token::EOS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100820 i::Utf8ToUtf16CharacterStream stream3(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100821 reinterpret_cast<const i::byte*>(str3),
822 static_cast<unsigned>(strlen(str3)));
823 TestStreamScanner(&stream3, expectations3, 1, 1 + i);
824 }
825}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100826
827
828void TestScanRegExp(const char* re_source, const char* expected) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100829 i::Utf8ToUtf16CharacterStream stream(
Ben Murdoch086aeea2011-05-13 15:57:08 +0100830 reinterpret_cast<const i::byte*>(re_source),
831 static_cast<unsigned>(strlen(re_source)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 i::HandleScope scope(CcTest::i_isolate());
833 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100834 scanner.Initialize(&stream);
835
836 i::Token::Value start = scanner.peek();
837 CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
838 CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
839 scanner.Next(); // Current token is now the regexp literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 i::Zone zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 i::AstValueFactory ast_value_factory(&zone,
842 CcTest::i_isolate()->heap()->HashSeed());
843 ast_value_factory.Internalize(CcTest::i_isolate());
844 i::Handle<i::String> val =
845 scanner.CurrentSymbol(&ast_value_factory)->string();
846 i::DisallowHeapAllocation no_alloc;
847 i::String::FlatContent content = val->GetFlatContent();
848 CHECK(content.IsOneByte());
849 i::Vector<const uint8_t> actual = content.ToOneByteVector();
Ben Murdoch086aeea2011-05-13 15:57:08 +0100850 for (int i = 0; i < actual.length(); i++) {
851 CHECK_NE('\0', expected[i]);
852 CHECK_EQ(expected[i], actual[i]);
853 }
854}
855
856
857TEST(RegExpScanning) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000858 v8::V8::Initialize();
859
Ben Murdoch086aeea2011-05-13 15:57:08 +0100860 // RegExp token with added garbage at the end. The scanner should only
861 // scan the RegExp until the terminating slash just before "flipperwald".
862 TestScanRegExp("/b/flipperwald", "b");
863 // Incomplete escape sequences doesn't hide the terminating slash.
864 TestScanRegExp("/\\x/flipperwald", "\\x");
865 TestScanRegExp("/\\u/flipperwald", "\\u");
866 TestScanRegExp("/\\u1/flipperwald", "\\u1");
867 TestScanRegExp("/\\u12/flipperwald", "\\u12");
868 TestScanRegExp("/\\u123/flipperwald", "\\u123");
869 TestScanRegExp("/\\c/flipperwald", "\\c");
870 TestScanRegExp("/\\c//flipperwald", "\\c");
871 // Slashes inside character classes are not terminating.
872 TestScanRegExp("/[/]/flipperwald", "[/]");
873 TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
874 // Incomplete escape sequences inside a character class doesn't hide
875 // the end of the character class.
876 TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
877 TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
878 TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
879 TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
880 TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
881 TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
882 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
883 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
884 // Escaped ']'s wont end the character class.
885 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
886 // Escaped slashes are not terminating.
887 TestScanRegExp("/\\//flipperwald", "\\/");
888 // Starting with '=' works too.
889 TestScanRegExp("/=/", "=");
890 TestScanRegExp("/=?/", "=?");
891}
Ben Murdoch692be652012-01-10 18:47:50 +0000892
893
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100894static int Utf8LengthHelper(const char* s) {
895 int len = i::StrLength(s);
896 int character_length = len;
897 for (int i = 0; i < len; i++) {
898 unsigned char c = s[i];
899 int input_offset = 0;
900 int output_adjust = 0;
901 if (c > 0x7f) {
902 if (c < 0xc0) continue;
903 if (c >= 0xf0) {
904 if (c >= 0xf8) {
905 // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
906 // byte.
907 continue; // Handle first UTF-8 byte.
908 }
909 if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
910 // This 4 byte sequence could have been coded as a 3 byte sequence.
911 // Record a single kBadChar for the first byte and continue.
912 continue;
913 }
914 input_offset = 3;
915 // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
916 character_length -= 2;
917 } else if (c >= 0xe0) {
918 if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
919 // This 3 byte sequence could have been coded as a 2 byte sequence.
920 // Record a single kBadChar for the first byte and continue.
921 continue;
922 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 if (c == 0xed) {
924 unsigned char d = s[i + 1];
925 if ((d < 0x80) || (d > 0x9f)) {
926 // This 3 byte sequence is part of a surrogate pair which is not
927 // supported by UTF-8. Record a single kBadChar for the first byte
928 // and continue.
929 continue;
930 }
931 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100932 input_offset = 2;
933 // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
934 output_adjust = 2;
935 } else {
936 if ((c & 0x1e) == 0) {
937 // This 2 byte sequence could have been coded as a 1 byte sequence.
938 // Record a single kBadChar for the first byte and continue.
939 continue;
940 }
941 input_offset = 1;
942 // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
943 output_adjust = 1;
944 }
945 bool bad = false;
946 for (int j = 1; j <= input_offset; j++) {
947 if ((s[i + j] & 0xc0) != 0x80) {
948 // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
949 // which is a single UTF-16 code unit.
950 bad = true;
951 break;
952 }
953 }
954 if (!bad) {
955 i += input_offset;
956 character_length -= output_adjust;
957 }
958 }
959 }
960 return character_length;
961}
962
963
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400964TEST(ScopeUsesArgumentsSuperThis) {
965 static const struct {
966 const char* prefix;
967 const char* suffix;
968 } surroundings[] = {
969 { "function f() {", "}" },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 { "var f = () => {", "};" },
971 { "class C { constructor() {", "} }" },
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400972 };
973
974 enum Expected {
975 NONE = 0,
976 ARGUMENTS = 1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 SUPER_PROPERTY = 1 << 1,
978 THIS = 1 << 2,
979 EVAL = 1 << 4
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400980 };
981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982 // clang-format off
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400983 static const struct {
984 const char* body;
985 int expected;
986 } source_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 {"", NONE},
988 {"return this", THIS},
989 {"return arguments", ARGUMENTS},
990 {"return super.x", SUPER_PROPERTY},
991 {"return arguments[0]", ARGUMENTS},
992 {"return this + arguments[0]", ARGUMENTS | THIS},
993 {"return this + arguments[0] + super.x",
994 ARGUMENTS | SUPER_PROPERTY | THIS},
995 {"return x => this + x", THIS},
996 {"return x => super.f() + x", SUPER_PROPERTY},
997 {"this.foo = 42;", THIS},
998 {"this.foo();", THIS},
999 {"if (foo()) { this.f() }", THIS},
1000 {"if (foo()) { super.f() }", SUPER_PROPERTY},
1001 {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
1002 {"while (true) { this.f() }", THIS},
1003 {"while (true) { super.f() }", SUPER_PROPERTY},
1004 {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
1005 // Multiple nesting levels must work as well.
1006 {"while (true) { while (true) { while (true) return this } }", THIS},
1007 {"while (true) { while (true) { while (true) return super.f() } }",
1008 SUPER_PROPERTY},
1009 {"if (1) { return () => { while (true) new this() } }", THIS},
1010 {"return function (x) { return this + x }", NONE},
1011 {"return { m(x) { return super.m() + x } }", NONE},
1012 {"var x = function () { this.foo = 42 };", NONE},
1013 {"var x = { m() { super.foo = 42 } };", NONE},
1014 {"if (1) { return function () { while (true) new this() } }", NONE},
1015 {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1016 {"return function (x) { return () => this }", NONE},
1017 {"return { m(x) { return () => super.m() } }", NONE},
1018 // Flags must be correctly set when using block scoping.
1019 {"\"use strict\"; while (true) { let x; this, arguments; }",
1020 THIS},
1021 {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1022 SUPER_PROPERTY | THIS},
1023 {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
1024 {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
1025 {"\"use strict\"; if (1) {"
1026 " let x; return { m() { return this + super.m() + arguments } }"
1027 "}",
1028 NONE},
1029 {"eval(42)", EVAL},
1030 {"if (1) { eval(42) }", EVAL},
1031 {"eval('super.x')", EVAL},
1032 {"eval('this.x')", EVAL},
1033 {"eval('arguments')", EVAL},
1034 };
1035 // clang-format on
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036
1037 i::Isolate* isolate = CcTest::i_isolate();
1038 i::Factory* factory = isolate->factory();
1039
1040 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042 v8::Context::Scope context_scope(context);
1043
1044 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1045 128 * 1024);
1046
1047 for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1048 for (unsigned i = 0; i < arraysize(source_data); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 // Super property is only allowed in constructor and method.
1050 if (((source_data[i].expected & SUPER_PROPERTY) ||
1051 (source_data[i].expected == NONE)) && j != 2) {
1052 continue;
1053 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001054 int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1055 i::StrLength(surroundings[j].suffix) +
1056 i::StrLength(source_data[i].body);
1057 i::ScopedVector<char> program(kProgramByteSize + 1);
1058 i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1059 source_data[i].body, surroundings[j].suffix);
1060 i::Handle<i::String> source =
1061 factory->NewStringFromUtf8(i::CStrVector(program.start()))
1062 .ToHandleChecked();
1063 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 i::Zone zone;
1065 i::ParseInfo info(&zone, script);
1066 i::Parser parser(&info);
1067 parser.set_allow_harmony_sloppy(true);
1068 info.set_global();
1069 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001070 CHECK(i::Rewriter::Rewrite(&info));
1071 CHECK(i::Scope::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 CHECK(info.literal() != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 i::Scope* script_scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001075 CHECK(script_scope->is_script_scope());
1076 CHECK_EQ(1, script_scope->inner_scopes()->length());
1077
1078 i::Scope* scope = script_scope->inner_scopes()->at(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 // Adjust for constructor scope.
1080 if (j == 2) {
1081 CHECK_EQ(1, scope->inner_scopes()->length());
1082 scope = scope->inner_scopes()->at(0);
1083 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001084 CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
1085 scope->uses_arguments());
1086 CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1087 scope->uses_super_property());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 if ((source_data[i].expected & THIS) != 0) {
1089 // Currently the is_used() flag is conservative; all variables in a
1090 // script scope are marked as used.
1091 CHECK(
1092 scope->Lookup(info.ast_value_factory()->this_string())->is_used());
1093 }
1094 CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001095 }
1096 }
1097}
1098
1099
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100static void CheckParsesToNumber(const char* source, bool with_dot) {
1101 v8::V8::Initialize();
1102 HandleAndZoneScope handles;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 i::Isolate* isolate = CcTest::i_isolate();
1105 i::Factory* factory = isolate->factory();
1106
1107 std::string full_source = "function f() { return ";
1108 full_source += source;
1109 full_source += "; }";
1110
1111 i::Handle<i::String> source_code =
1112 factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1113 .ToHandleChecked();
1114
1115 i::Handle<i::Script> script = factory->NewScript(source_code);
1116
1117 i::ParseInfo info(handles.main_zone(), script);
1118 i::Parser parser(&info);
1119 parser.set_allow_harmony_sloppy(true);
1120 info.set_global();
1121 info.set_lazy(false);
1122 info.set_allow_lazy_parsing(false);
1123 info.set_toplevel(true);
1124
1125 i::CompilationInfo compilation_info(&info);
1126 CHECK(i::Compiler::ParseAndAnalyze(&info));
1127
1128 CHECK(info.scope()->declarations()->length() == 1);
1129 i::FunctionLiteral* fun =
1130 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
1131 CHECK(fun->body()->length() == 1);
1132 CHECK(fun->body()->at(0)->IsReturnStatement());
1133 i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1134 i::Literal* lit = ret->expression()->AsLiteral();
1135 if (lit != NULL) {
1136 const i::AstValue* val = lit->raw_value();
1137 CHECK(with_dot == val->ContainsDot());
1138 } else if (with_dot) {
1139 i::BinaryOperation* bin = ret->expression()->AsBinaryOperation();
1140 CHECK(bin != NULL);
1141 CHECK_EQ(i::Token::MUL, bin->op());
1142 i::Literal* rlit = bin->right()->AsLiteral();
1143 const i::AstValue* val = rlit->raw_value();
1144 CHECK(with_dot == val->ContainsDot());
1145 CHECK_EQ(1.0, val->AsNumber());
1146 }
1147}
1148
1149
1150TEST(ParseNumbers) {
1151 CheckParsesToNumber("1.", true);
1152 CheckParsesToNumber("1.34", true);
1153 CheckParsesToNumber("134", false);
1154 CheckParsesToNumber("134e44", false);
1155 CheckParsesToNumber("134.e44", true);
1156 CheckParsesToNumber("134.44e44", true);
1157 CheckParsesToNumber(".44", true);
1158
1159 CheckParsesToNumber("-1.", true);
1160 CheckParsesToNumber("-1.0", true);
1161 CheckParsesToNumber("-1.34", true);
1162 CheckParsesToNumber("-134", false);
1163 CheckParsesToNumber("-134e44", false);
1164 CheckParsesToNumber("-134.e44", true);
1165 CheckParsesToNumber("-134.44e44", true);
1166 CheckParsesToNumber("-.44", true);
1167
1168 CheckParsesToNumber("+x", true);
1169}
1170
1171
1172TEST(ScopePositions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001173 // Test the parser for correctly setting the start and end positions
1174 // of a scope. We check the scope positions of exactly one scope
1175 // nested in the global scope of a program. 'inner source' is the
1176 // source code that determines the part of the source belonging
1177 // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1178 // parts of the source that belong to the global scope.
1179 struct SourceData {
1180 const char* outer_prefix;
1181 const char* inner_source;
1182 const char* outer_suffix;
1183 i::ScopeType scope_type;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184 i::LanguageMode language_mode;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001185 };
1186
1187 const SourceData source_data[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001188 { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
1189 { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001190 { " with ({}) ", "{\n"
1191 " block;\n"
1192 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193 " more;", i::WITH_SCOPE, i::SLOPPY },
1194 { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001195 { " with ({}) ", "statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001197 { " with ({})\n"
1198 " ", "statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001200 { " try {} catch ", "(e) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001202 { " try {} catch ", "(e) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001203 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001204 { " try {} catch ", "(e) {\n"
1205 " block;\n"
1206 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207 " more;", i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001208 { " try {} catch ", "(e) { block; }", " finally { block; } more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001209 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001210 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211 " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001212 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213 " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001214 { " start;\n"
1215 " ", "{\n"
1216 " let block;\n"
1217 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001218 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001219 { " start;\n"
1220 " function fun", "(a,b) { infunction; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001222 { " start;\n"
1223 " function fun", "(a,b) {\n"
1224 " infunction;\n"
1225 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226 " more;", i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227 { " start;\n", "(a,b) => a + b", "; more;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001229 { " start;\n", "(a,b) => { return a+b; }", "\nmore;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001231 { " start;\n"
1232 " (function fun", "(a,b) { infunction; }", ")();",
1233 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001234 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001236 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001238 { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
1239 " block;\n"
1240 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001242 { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001244 { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001245 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001246 { " for ", "(let x = 1 ; x < 10; ++ x)\n"
1247 " 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 in {}) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001250 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001251 { " for ", "(let x in {}) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001253 { " for ", "(let x in {}) {\n"
1254 " block;\n"
1255 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001257 { " for ", "(let x in {}) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001258 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001259 { " for ", "(let x in {}) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001260 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001261 { " for ", "(let x in {})\n"
1262 " statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001264 // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1265 // the preparser off in terms of byte offsets.
1266 // 6 byte encoding.
1267 { " 'foo\355\240\201\355\260\211';\n"
1268 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001270 // 4 byte encoding.
1271 { " 'foo\360\220\220\212';\n"
1272 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001274 // 3 byte encoding of \u0fff.
1275 { " 'foo\340\277\277';\n"
1276 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001278 // Broken 6 byte encoding with missing last byte.
1279 { " 'foo\355\240\201\355\211';\n"
1280 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001282 // Broken 3 byte encoding of \u0fff with missing last byte.
1283 { " 'foo\340\277';\n"
1284 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001286 // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1287 { " 'foo\340';\n"
1288 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001290 // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1291 { " 'foo\340\203\277';\n"
1292 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001293 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001294 // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1295 { " 'foo\340\201\277';\n"
1296 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001298 // Unpaired lead surrogate.
1299 { " 'foo\355\240\201';\n"
1300 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001302 // Unpaired lead surrogate where following code point is a 3 byte sequence.
1303 { " 'foo\355\240\201\340\277\277';\n"
1304 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001306 // Unpaired lead surrogate where following code point is a 4 byte encoding
1307 // of a trail surrogate.
1308 { " 'foo\355\240\201\360\215\260\211';\n"
1309 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001311 // Unpaired trail surrogate.
1312 { " 'foo\355\260\211';\n"
1313 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001315 // 2 byte encoding of \u00ff.
1316 { " 'foo\303\277';\n"
1317 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001319 // Broken 2 byte encoding of \u00ff with missing last byte.
1320 { " 'foo\303';\n"
1321 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001323 // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1324 { " 'foo\301\277';\n"
1325 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001327 // Illegal 5 byte encoding.
1328 { " 'foo\370\277\277\277\277';\n"
1329 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001331 // Illegal 6 byte encoding.
1332 { " 'foo\374\277\277\277\277\277';\n"
1333 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001335 // Illegal 0xfe byte
1336 { " 'foo\376\277\277\277\277\277\277';\n"
1337 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001339 // Illegal 0xff byte
1340 { " 'foo\377\277\277\277\277\277\277\277';\n"
1341 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001342 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001343 { " 'foo';\n"
1344 " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
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\360\220\220\214'; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 i::FUNCTION_SCOPE, i::SLOPPY },
1349 { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001350 };
1351
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 i::Isolate* isolate = CcTest::i_isolate();
1353 i::Factory* factory = isolate->factory();
1354
1355 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001357 v8::Context::Scope context_scope(context);
1358
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1360 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001361
1362 for (int i = 0; source_data[i].outer_prefix; i++) {
1363 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1364 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1365 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1366 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1367 int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1368 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1369 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1370 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 i::ScopedVector<char> program(kProgramByteSize + 1);
1372 i::SNPrintF(program, "%s%s%s",
1373 source_data[i].outer_prefix,
1374 source_data[i].inner_source,
1375 source_data[i].outer_suffix);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001376
1377 // Parse program source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001378 i::Handle<i::String> source = factory->NewStringFromUtf8(
1379 i::CStrVector(program.start())).ToHandleChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001380 CHECK_EQ(source->length(), kProgramSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001382 i::Zone zone;
1383 i::ParseInfo info(&zone, script);
1384 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385 parser.set_allow_lazy(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 info.set_global();
1387 info.set_language_mode(source_data[i].language_mode);
1388 parser.Parse(&info);
1389 CHECK(info.literal() != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001390
1391 // Check scope types and positions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392 i::Scope* scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001393 CHECK(scope->is_script_scope());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001394 CHECK_EQ(scope->start_position(), 0);
1395 CHECK_EQ(scope->end_position(), kProgramSize);
1396 CHECK_EQ(scope->inner_scopes()->length(), 1);
1397
1398 i::Scope* inner_scope = scope->inner_scopes()->at(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399 CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001400 CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1401 // The end position of a token is one position after the last
1402 // character belonging to that token.
1403 CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1404 }
1405}
1406
1407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408TEST(DiscardFunctionBody) {
1409 // Test that inner function bodies are discarded if possible.
1410 // See comments in ParseFunctionLiteral in parser.cc.
1411 const char* discard_sources[] = {
1412 "(function f() { function g() { var a; } })();",
1413 "(function f() { function g() { { function h() { } } } })();",
1414 /* TODO(conradw): In future it may be possible to apply this optimisation
1415 * to these productions.
1416 "(function f() { 0, function g() { var a; } })();",
1417 "(function f() { 0, { g() { var a; } } })();",
1418 "(function f() { 0, class c { g() { var a; } } })();", */
1419 NULL};
1420
1421 i::Isolate* isolate = CcTest::i_isolate();
1422 i::Factory* factory = isolate->factory();
1423 v8::HandleScope handles(CcTest::isolate());
1424 i::FunctionLiteral* function;
1425
1426 for (int i = 0; discard_sources[i]; i++) {
1427 const char* source = discard_sources[i];
1428 i::Handle<i::String> source_code =
1429 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
1430 i::Handle<i::Script> script = factory->NewScript(source_code);
1431 i::Zone zone;
1432 i::ParseInfo info(&zone, script);
1433 info.set_allow_lazy_parsing();
1434 i::Parser parser(&info);
1435 parser.set_allow_harmony_sloppy(true);
1436 parser.Parse(&info);
1437 function = info.literal();
1438 CHECK_NOT_NULL(function);
1439 CHECK_NOT_NULL(function->body());
1440 CHECK_EQ(1, function->body()->length());
1441 i::FunctionLiteral* inner =
1442 function->body()->first()->AsExpressionStatement()->expression()->
1443 AsCall()->expression()->AsFunctionLiteral();
1444 i::Scope* inner_scope = inner->scope();
1445 i::FunctionLiteral* fun = nullptr;
1446 if (inner_scope->declarations()->length() > 1) {
1447 fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun();
1448 } else {
1449 // TODO(conradw): This path won't be hit until the other test cases can be
1450 // uncommented.
1451 UNREACHABLE();
1452 CHECK_NOT_NULL(inner->body());
1453 CHECK_GE(2, inner->body()->length());
1454 i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
1455 expression()->AsBinaryOperation()->right();
1456 if (exp->IsFunctionLiteral()) {
1457 fun = exp->AsFunctionLiteral();
1458 } else if (exp->IsObjectLiteral()) {
1459 fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
1460 AsFunctionLiteral();
1461 } else {
1462 fun = exp->AsClassLiteral()->properties()->at(0)->value()->
1463 AsFunctionLiteral();
1464 }
1465 }
1466 CHECK_NULL(fun->body());
1467 }
1468}
1469
1470
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001471const char* ReadString(unsigned* start) {
1472 int length = start[0];
1473 char* result = i::NewArray<char>(length + 1);
1474 for (int i = 0; i < length; i++) {
1475 result[i] = start[i + 1];
1476 }
1477 result[length] = '\0';
1478 return result;
1479}
1480
1481
1482i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
1483 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001484 int message = data[i::PreparseDataConstants::kMessageTemplatePos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485 int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486 i::Handle<i::Object> arg_object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 if (arg_count == 1) {
1488 // Position after text found by skipping past length field and
1489 // length field content words.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 const char* arg =
1491 ReadString(&data[i::PreparseDataConstants::kMessageArgPos]);
1492 arg_object = v8::Utils::OpenHandle(*v8_str(arg));
1493 i::DeleteArray(arg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494 } else {
1495 CHECK_EQ(0, arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001496 arg_object = isolate->factory()->undefined_value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001497 }
1498
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 data.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500 return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501}
1502
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503enum ParserFlag {
1504 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001505 kAllowNatives,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 kAllowHarmonyDefaultParameters,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001507 kAllowHarmonySloppy,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 kAllowHarmonySloppyLet,
1509 kAllowHarmonyDestructuring,
1510 kAllowHarmonyDestructuringAssignment,
1511 kAllowHarmonyNewTarget,
1512 kAllowStrongMode,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001513 kNoLegacyConst,
1514 kAllowHarmonyFunctionSent
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515};
1516
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001517enum ParserSyncTestResult {
1518 kSuccessOrError,
1519 kSuccess,
1520 kError
1521};
1522
1523template <typename Traits>
1524void SetParserFlags(i::ParserBase<Traits>* parser,
1525 i::EnumSet<ParserFlag> flags) {
1526 parser->set_allow_lazy(flags.Contains(kAllowLazy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001527 parser->set_allow_natives(flags.Contains(kAllowNatives));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 parser->set_allow_harmony_default_parameters(
1529 flags.Contains(kAllowHarmonyDefaultParameters));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001530 parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 parser->set_allow_harmony_sloppy_let(flags.Contains(kAllowHarmonySloppyLet));
1532 parser->set_allow_harmony_destructuring_bind(
1533 flags.Contains(kAllowHarmonyDestructuring));
1534 parser->set_allow_harmony_destructuring_assignment(
1535 flags.Contains(kAllowHarmonyDestructuringAssignment));
1536 parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
1537 parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001538 parser->set_allow_harmony_function_sent(
1539 flags.Contains(kAllowHarmonyFunctionSent));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540}
1541
1542
1543void TestParserSyncWithFlags(i::Handle<i::String> source,
1544 i::EnumSet<ParserFlag> flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 ParserSyncTestResult result,
1546 bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001547 i::Isolate* isolate = CcTest::i_isolate();
1548 i::Factory* factory = isolate->factory();
1549
1550 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001551 int preparser_materialized_literals = -1;
1552 int parser_materialized_literals = -2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 bool test_preparser = !is_module;
Ben Murdoch692be652012-01-10 18:47:50 +00001554
1555 // Preparse the data.
1556 i::CompleteParserRecorder log;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001557 if (test_preparser) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001558 i::Scanner scanner(isolate->unicode_cache());
1559 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 i::Zone zone;
1561 i::AstValueFactory ast_value_factory(
1562 &zone, CcTest::i_isolate()->heap()->HashSeed());
1563 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
1564 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565 SetParserFlags(&preparser, flags);
1566 scanner.Initialize(&stream);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001567 i::PreParser::PreParseResult result = preparser.PreParseProgram(
1568 &preparser_materialized_literals);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1570 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 bool preparse_error = log.HasError();
Ben Murdoch692be652012-01-10 18:47:50 +00001572
1573 // Parse the data
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574 i::FunctionLiteral* function;
1575 {
1576 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 i::Zone zone;
1578 i::ParseInfo info(&zone, script);
1579 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001580 SetParserFlags(&parser, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581 if (is_module) {
1582 info.set_module();
1583 } else {
1584 info.set_global();
1585 }
1586 parser.Parse(&info);
1587 function = info.literal();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001588 if (function) {
1589 parser_materialized_literals = function->materialized_literal_count();
1590 }
Ben Murdoch692be652012-01-10 18:47:50 +00001591 }
1592
1593 // Check that preparsing fails iff parsing fails.
Ben Murdoch692be652012-01-10 18:47:50 +00001594 if (function == NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001595 // Extract exception from the parser.
1596 CHECK(isolate->has_pending_exception());
1597 i::Handle<i::JSObject> exception_handle(
1598 i::JSObject::cast(isolate->pending_exception()));
1599 i::Handle<i::String> message_string =
1600 i::Handle<i::String>::cast(i::Object::GetProperty(
1601 isolate, exception_handle, "message").ToHandleChecked());
1602
1603 if (result == kSuccess) {
1604 v8::base::OS::Print(
1605 "Parser failed on:\n"
1606 "\t%s\n"
1607 "with error:\n"
1608 "\t%s\n"
1609 "However, we expected no error.",
1610 source->ToCString().get(), message_string->ToCString().get());
1611 CHECK(false);
1612 }
1613
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 if (test_preparser && !preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 v8::base::OS::Print(
1616 "Parser failed on:\n"
1617 "\t%s\n"
1618 "with error:\n"
1619 "\t%s\n"
1620 "However, the preparser succeeded",
1621 source->ToCString().get(), message_string->ToCString().get());
1622 CHECK(false);
1623 }
1624 // Check that preparser and parser produce the same error.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001625 if (test_preparser) {
1626 i::Handle<i::String> preparser_message =
1627 FormatMessage(log.ErrorMessageData());
1628 if (!i::String::Equals(message_string, preparser_message)) {
1629 v8::base::OS::Print(
1630 "Expected parser and preparser to produce the same error on:\n"
1631 "\t%s\n"
1632 "However, found the following error messages\n"
1633 "\tparser: %s\n"
1634 "\tpreparser: %s\n",
1635 source->ToCString().get(), message_string->ToCString().get(),
1636 preparser_message->ToCString().get());
1637 CHECK(false);
1638 }
Ben Murdoch692be652012-01-10 18:47:50 +00001639 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001640 } else if (test_preparser && preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 v8::base::OS::Print(
1642 "Preparser failed on:\n"
1643 "\t%s\n"
1644 "with error:\n"
1645 "\t%s\n"
1646 "However, the parser succeeded",
1647 source->ToCString().get(),
1648 FormatMessage(log.ErrorMessageData())->ToCString().get());
1649 CHECK(false);
1650 } else if (result == kError) {
1651 v8::base::OS::Print(
1652 "Expected error on:\n"
1653 "\t%s\n"
1654 "However, parser and preparser succeeded",
1655 source->ToCString().get());
1656 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657 } else if (test_preparser &&
1658 preparser_materialized_literals != parser_materialized_literals) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001659 v8::base::OS::Print(
1660 "Preparser materialized literals (%d) differ from Parser materialized "
1661 "literals (%d) on:\n"
1662 "\t%s\n"
1663 "However, parser and preparser succeeded",
1664 preparser_materialized_literals, parser_materialized_literals,
1665 source->ToCString().get());
1666 CHECK(false);
Ben Murdoch692be652012-01-10 18:47:50 +00001667 }
1668}
1669
1670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671void TestParserSync(const char* source, const ParserFlag* varying_flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001672 size_t varying_flags_length,
1673 ParserSyncTestResult result = kSuccessOrError,
1674 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001675 size_t always_true_flags_length = 0,
1676 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001677 size_t always_false_flags_length = 0,
1678 bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001679 i::Handle<i::String> str =
1680 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1681 for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1682 i::EnumSet<ParserFlag> flags;
1683 for (size_t flag_index = 0; flag_index < varying_flags_length;
1684 ++flag_index) {
1685 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1686 }
1687 for (size_t flag_index = 0; flag_index < always_true_flags_length;
1688 ++flag_index) {
1689 flags.Add(always_true_flags[flag_index]);
1690 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001691 for (size_t flag_index = 0; flag_index < always_false_flags_length;
1692 ++flag_index) {
1693 flags.Remove(always_false_flags[flag_index]);
1694 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001695 TestParserSyncWithFlags(str, flags, result, is_module);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001696 }
1697}
1698
1699
Ben Murdoch692be652012-01-10 18:47:50 +00001700TEST(ParserSync) {
1701 const char* context_data[][2] = {
1702 { "", "" },
1703 { "{", "}" },
1704 { "if (true) ", " else {}" },
1705 { "if (true) {} else ", "" },
1706 { "if (true) ", "" },
1707 { "do ", " while (false)" },
1708 { "while (false) ", "" },
1709 { "for (;;) ", "" },
1710 { "with ({})", "" },
1711 { "switch (12) { case 12: ", "}" },
1712 { "switch (12) { default: ", "}" },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 { "switch (12) { ", "case 12: }" },
Ben Murdoch692be652012-01-10 18:47:50 +00001714 { "label2: ", "" },
1715 { NULL, NULL }
1716 };
1717
1718 const char* statement_data[] = {
1719 "{}",
1720 "var x",
1721 "var x = 1",
1722 "const x",
1723 "const x = 1",
1724 ";",
1725 "12",
1726 "if (false) {} else ;",
1727 "if (false) {} else {}",
1728 "if (false) {} else 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001729 "if (false) ;",
Ben Murdoch692be652012-01-10 18:47:50 +00001730 "if (false) {}",
1731 "if (false) 12",
1732 "do {} while (false)",
1733 "for (;;) ;",
1734 "for (;;) {}",
1735 "for (;;) 12",
1736 "continue",
1737 "continue label",
1738 "continue\nlabel",
1739 "break",
1740 "break label",
1741 "break\nlabel",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1743 // "return",
1744 // "return 12",
1745 // "return\n12",
Ben Murdoch692be652012-01-10 18:47:50 +00001746 "with ({}) ;",
1747 "with ({}) {}",
1748 "with ({}) 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001749 "switch ({}) { default: }",
1750 "label3: ",
Ben Murdoch692be652012-01-10 18:47:50 +00001751 "throw",
1752 "throw 12",
1753 "throw\n12",
1754 "try {} catch(e) {}",
1755 "try {} finally {}",
1756 "try {} catch(e) {} finally {}",
1757 "debugger",
1758 NULL
1759 };
1760
1761 const char* termination_data[] = {
1762 "",
1763 ";",
1764 "\n",
1765 ";\n",
1766 "\n;",
1767 NULL
1768 };
1769
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001771 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch692be652012-01-10 18:47:50 +00001772 v8::Context::Scope context_scope(context);
1773
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001774 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1775 i::GetCurrentStackPosition() - 128 * 1024);
1776
Ben Murdoch692be652012-01-10 18:47:50 +00001777 for (int i = 0; context_data[i][0] != NULL; ++i) {
1778 for (int j = 0; statement_data[j] != NULL; ++j) {
1779 for (int k = 0; termination_data[k] != NULL; ++k) {
1780 int kPrefixLen = i::StrLength(context_data[i][0]);
1781 int kStatementLen = i::StrLength(statement_data[j]);
1782 int kTerminationLen = i::StrLength(termination_data[k]);
1783 int kSuffixLen = i::StrLength(context_data[i][1]);
1784 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1785 + kSuffixLen + i::StrLength("label: for (;;) { }");
1786
1787 // Plug the source code pieces together.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001788 i::ScopedVector<char> program(kProgramSize + 1);
1789 int length = i::SNPrintF(program,
Ben Murdoch692be652012-01-10 18:47:50 +00001790 "label: for (;;) { %s%s%s%s }",
1791 context_data[i][0],
1792 statement_data[j],
1793 termination_data[k],
1794 context_data[i][1]);
1795 CHECK(length == kProgramSize);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001796 TestParserSync(program.start(), NULL, 0);
Ben Murdoch692be652012-01-10 18:47:50 +00001797 }
1798 }
1799 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001800
1801 // Neither Harmony numeric literals nor our natives syntax have any
1802 // interaction with the flags above, so test these separately to reduce
1803 // the combinatorial explosion.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 TestParserSync("0o1234", NULL, 0);
1805 TestParserSync("0b1011", NULL, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001806
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001807 static const ParserFlag flags3[] = { kAllowNatives };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001808 TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1809}
1810
1811
1812TEST(StrictOctal) {
1813 // Test that syntax error caused by octal literal is reported correctly as
1814 // such (issue 2220).
1815 v8::V8::Initialize();
1816 v8::HandleScope scope(CcTest::isolate());
1817 v8::Context::Scope context_scope(
1818 v8::Context::New(CcTest::isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001819 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001820 const char* script =
1821 "\"use strict\"; \n"
1822 "a = function() { \n"
1823 " b = function() { \n"
1824 " 01; \n"
1825 " }; \n"
1826 "}; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001827 v8_compile(v8_str(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 CHECK(try_catch.HasCaught());
1829 v8::String::Utf8Value exception(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 CHECK_EQ(0,
1831 strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1832 *exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833}
1834
1835
1836void RunParserSyncTest(const char* context_data[][2],
1837 const char* statement_data[],
1838 ParserSyncTestResult result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 const ParserFlag* flags = NULL, int flags_len = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001841 int always_true_len = 0,
1842 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001843 int always_false_len = 0, bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001845 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001846 v8::Context::Scope context_scope(context);
1847
1848 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1849 i::GetCurrentStackPosition() - 128 * 1024);
1850
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001851 // Experimental feature flags should not go here; pass the flags as
1852 // always_true_flags if the test needs them.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001853 static const ParserFlag default_flags[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001854 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001855 kAllowNatives,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001856 };
1857 ParserFlag* generated_flags = NULL;
1858 if (flags == NULL) {
1859 flags = default_flags;
1860 flags_len = arraysize(default_flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001861 if (always_true_flags != NULL || always_false_flags != NULL) {
1862 // Remove always_true/false_flags from default_flags (if present).
1863 CHECK((always_true_flags != NULL) == (always_true_len > 0));
1864 CHECK((always_false_flags != NULL) == (always_false_len > 0));
1865 generated_flags = new ParserFlag[flags_len + always_true_len];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001866 int flag_index = 0;
1867 for (int i = 0; i < flags_len; ++i) {
1868 bool use_flag = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001869 for (int j = 0; use_flag && j < always_true_len; ++j) {
1870 if (flags[i] == always_true_flags[j]) use_flag = false;
1871 }
1872 for (int j = 0; use_flag && j < always_false_len; ++j) {
1873 if (flags[i] == always_false_flags[j]) use_flag = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001874 }
1875 if (use_flag) generated_flags[flag_index++] = flags[i];
1876 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001877 flags_len = flag_index;
1878 flags = generated_flags;
1879 }
1880 }
1881 for (int i = 0; context_data[i][0] != NULL; ++i) {
1882 for (int j = 0; statement_data[j] != NULL; ++j) {
1883 int kPrefixLen = i::StrLength(context_data[i][0]);
1884 int kStatementLen = i::StrLength(statement_data[j]);
1885 int kSuffixLen = i::StrLength(context_data[i][1]);
1886 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1887
1888 // Plug the source code pieces together.
1889 i::ScopedVector<char> program(kProgramSize + 1);
1890 int length = i::SNPrintF(program,
1891 "%s%s%s",
1892 context_data[i][0],
1893 statement_data[j],
1894 context_data[i][1]);
1895 CHECK(length == kProgramSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001896 TestParserSync(program.start(), flags, flags_len, result,
1897 always_true_flags, always_true_len, always_false_flags,
1898 always_false_len, is_module);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001899 }
1900 }
1901 delete[] generated_flags;
1902}
1903
1904
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001905void RunModuleParserSyncTest(const char* context_data[][2],
1906 const char* statement_data[],
1907 ParserSyncTestResult result,
1908 const ParserFlag* flags = NULL, int flags_len = 0,
1909 const ParserFlag* always_true_flags = NULL,
1910 int always_true_len = 0,
1911 const ParserFlag* always_false_flags = NULL,
1912 int always_false_len = 0) {
1913 bool flag = i::FLAG_harmony_modules;
1914 i::FLAG_harmony_modules = true;
1915 RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1916 always_true_flags, always_true_len, always_false_flags,
1917 always_false_len, true);
1918 i::FLAG_harmony_modules = flag;
1919}
1920
1921
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922TEST(ErrorsEvalAndArguments) {
1923 // Tests that both preparsing and parsing produce the right kind of errors for
1924 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1925 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1926 // isn't.
1927 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001928 {"\"use strict\";", ""},
1929 {"\"use strong\";", ""},
1930 {"var eval; function test_func() {\"use strict\"; ", "}"},
1931 {"var eval; function test_func() {\"use strong\"; ", "}"},
1932 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001933
1934 const char* statement_data[] = {
1935 "var eval;",
1936 "var arguments",
1937 "var foo, eval;",
1938 "var foo, arguments;",
1939 "try { } catch (eval) { }",
1940 "try { } catch (arguments) { }",
1941 "function eval() { }",
1942 "function arguments() { }",
1943 "function foo(eval) { }",
1944 "function foo(arguments) { }",
1945 "function foo(bar, eval) { }",
1946 "function foo(bar, arguments) { }",
1947 "(eval) => { }",
1948 "(arguments) => { }",
1949 "(foo, eval) => { }",
1950 "(foo, arguments) => { }",
1951 "eval = 1;",
1952 "arguments = 1;",
1953 "var foo = eval = 1;",
1954 "var foo = arguments = 1;",
1955 "++eval;",
1956 "++arguments;",
1957 "eval++;",
1958 "arguments++;",
1959 NULL
1960 };
1961
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 static const ParserFlag always_flags[] = {kAllowStrongMode};
1963 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1964 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001965}
1966
1967
1968TEST(NoErrorsEvalAndArgumentsSloppy) {
1969 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1970 // identifiers when needed.
1971 const char* context_data[][2] = {
1972 { "", "" },
1973 { "function test_func() {", "}"},
1974 { NULL, NULL }
1975 };
1976
1977 const char* statement_data[] = {
1978 "var eval;",
1979 "var arguments",
1980 "var foo, eval;",
1981 "var foo, arguments;",
1982 "try { } catch (eval) { }",
1983 "try { } catch (arguments) { }",
1984 "function eval() { }",
1985 "function arguments() { }",
1986 "function foo(eval) { }",
1987 "function foo(arguments) { }",
1988 "function foo(bar, eval) { }",
1989 "function foo(bar, arguments) { }",
1990 "eval = 1;",
1991 "arguments = 1;",
1992 "var foo = eval = 1;",
1993 "var foo = arguments = 1;",
1994 "++eval;",
1995 "++arguments;",
1996 "eval++;",
1997 "arguments++;",
1998 NULL
1999 };
2000
2001 RunParserSyncTest(context_data, statement_data, kSuccess);
2002}
2003
2004
2005TEST(NoErrorsEvalAndArgumentsStrict) {
2006 const char* context_data[][2] = {
2007 { "\"use strict\";", "" },
2008 { "function test_func() { \"use strict\";", "}" },
2009 { "() => { \"use strict\"; ", "}" },
2010 { NULL, NULL }
2011 };
2012
2013 const char* statement_data[] = {
2014 "eval;",
2015 "arguments;",
2016 "var foo = eval;",
2017 "var foo = arguments;",
2018 "var foo = { eval: 1 };",
2019 "var foo = { arguments: 1 };",
2020 "var foo = { }; foo.eval = {};",
2021 "var foo = { }; foo.arguments = {};",
2022 NULL
2023 };
2024
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002025 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002026}
2027
2028
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002029#define FUTURE_STRICT_RESERVED_WORDS(V) \
2030 V(implements) \
2031 V(interface) \
2032 V(let) \
2033 V(package) \
2034 V(private) \
2035 V(protected) \
2036 V(public) \
2037 V(static) \
2038 V(yield)
2039
2040
2041#define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
2042 V(implements) \
2043 V(let) \
2044 V(static) \
2045 V(yield)
2046
2047
2048#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2049 "var " #NAME ";", \
2050 "var foo, " #NAME ";", \
2051 "try { } catch (" #NAME ") { }", \
2052 "function " #NAME "() { }", \
2053 "(function " #NAME "() { })", \
2054 "function foo(" #NAME ") { }", \
2055 "function foo(bar, " #NAME ") { }", \
2056 #NAME " = 1;", \
2057 #NAME " += 1;", \
2058 "var foo = " #NAME " = 1;", \
2059 "++" #NAME ";", \
2060 #NAME " ++;",
2061
2062
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002063TEST(ErrorsFutureStrictReservedWords) {
2064 // Tests that both preparsing and parsing produce the right kind of errors for
2065 // using future strict reserved words as identifiers. Without the strict mode,
2066 // it's ok to use future strict reserved words as identifiers. With the strict
2067 // mode, it isn't.
2068 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002069 {"function test_func() {\"use strict\"; ", "}"},
2070 {"() => { \"use strict\"; ", "}"},
2071 {"function test_func() {\"use strong\"; ", "}"},
2072 {"() => { \"use strong\"; ", "}"},
2073 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002074
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002075 const char* statement_data[] {
2076 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002077 NULL
2078 };
2079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002080 static const ParserFlag always_flags[] = {kAllowStrongMode};
2081 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2082 arraysize(always_flags));
2083 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2084 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002085}
2086
2087
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002088#undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2089
2090
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002091TEST(NoErrorsFutureStrictReservedWords) {
2092 const char* context_data[][2] = {
2093 { "", "" },
2094 { "function test_func() {", "}"},
2095 { "() => {", "}" },
2096 { NULL, NULL }
2097 };
2098
2099 const char* statement_data[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002100 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002101 NULL
2102 };
2103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002104 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002105}
2106
2107
2108TEST(ErrorsReservedWords) {
2109 // Tests that both preparsing and parsing produce the right kind of errors for
2110 // using future reserved words as identifiers. These tests don't depend on the
2111 // strict mode.
2112 const char* context_data[][2] = {
2113 { "", "" },
2114 { "\"use strict\";", "" },
2115 { "var eval; function test_func() {", "}"},
2116 { "var eval; function test_func() {\"use strict\"; ", "}"},
2117 { "var eval; () => {", "}"},
2118 { "var eval; () => {\"use strict\"; ", "}"},
2119 { NULL, NULL }
2120 };
2121
2122 const char* statement_data[] = {
2123 "var super;",
2124 "var foo, super;",
2125 "try { } catch (super) { }",
2126 "function super() { }",
2127 "function foo(super) { }",
2128 "function foo(bar, super) { }",
2129 "(super) => { }",
2130 "(bar, super) => { }",
2131 "super = 1;",
2132 "var foo = super = 1;",
2133 "++super;",
2134 "super++;",
2135 "function foo super",
2136 NULL
2137 };
2138
2139 RunParserSyncTest(context_data, statement_data, kError);
2140}
2141
2142
2143TEST(NoErrorsLetSloppyAllModes) {
2144 // In sloppy mode, it's okay to use "let" as identifier.
2145 const char* context_data[][2] = {
2146 { "", "" },
2147 { "function f() {", "}" },
2148 { "(function f() {", "})" },
2149 { NULL, NULL }
2150 };
2151
2152 const char* statement_data[] = {
2153 "var let;",
2154 "var foo, let;",
2155 "try { } catch (let) { }",
2156 "function let() { }",
2157 "(function let() { })",
2158 "function foo(let) { }",
2159 "function foo(bar, let) { }",
2160 "let = 1;",
2161 "var foo = let = 1;",
2162 "let * 2;",
2163 "++let;",
2164 "let++;",
2165 "let: 34",
2166 "function let(let) { let: let(let + let(0)); }",
2167 "({ let: 1 })",
2168 "({ get let() { 1 } })",
2169 "let(100)",
2170 NULL
2171 };
2172
2173 RunParserSyncTest(context_data, statement_data, kSuccess);
2174}
2175
2176
2177TEST(NoErrorsYieldSloppyAllModes) {
2178 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2179 // generator (see other test).
2180 const char* context_data[][2] = {
2181 { "", "" },
2182 { "function not_gen() {", "}" },
2183 { "(function not_gen() {", "})" },
2184 { NULL, NULL }
2185 };
2186
2187 const char* statement_data[] = {
2188 "var yield;",
2189 "var foo, yield;",
2190 "try { } catch (yield) { }",
2191 "function yield() { }",
2192 "(function yield() { })",
2193 "function foo(yield) { }",
2194 "function foo(bar, yield) { }",
2195 "yield = 1;",
2196 "var foo = yield = 1;",
2197 "yield * 2;",
2198 "++yield;",
2199 "yield++;",
2200 "yield: 34",
2201 "function yield(yield) { yield: yield (yield + yield(0)); }",
2202 "({ yield: 1 })",
2203 "({ get yield() { 1 } })",
2204 "yield(100)",
2205 "yield[100]",
2206 NULL
2207 };
2208
2209 RunParserSyncTest(context_data, statement_data, kSuccess);
2210}
2211
2212
2213TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2214 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2215 // generator (see next test).
2216 const char* context_data[][2] = {
2217 { "", "" },
2218 { "function not_gen() {", "}" },
2219 { "function * gen() { function not_gen() {", "} }" },
2220 { "(function not_gen() {", "})" },
2221 { "(function * gen() { (function not_gen() {", "}) })" },
2222 { NULL, NULL }
2223 };
2224
2225 const char* statement_data[] = {
2226 "var yield;",
2227 "var foo, yield;",
2228 "try { } catch (yield) { }",
2229 "function yield() { }",
2230 "(function yield() { })",
2231 "function foo(yield) { }",
2232 "function foo(bar, yield) { }",
2233 "function * yield() { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002234 "yield = 1;",
2235 "var foo = yield = 1;",
2236 "yield * 2;",
2237 "++yield;",
2238 "yield++;",
2239 "yield: 34",
2240 "function yield(yield) { yield: yield (yield + yield(0)); }",
2241 "({ yield: 1 })",
2242 "({ get yield() { 1 } })",
2243 "yield(100)",
2244 "yield[100]",
2245 NULL
2246 };
2247
2248 RunParserSyncTest(context_data, statement_data, kSuccess);
2249}
2250
2251
2252TEST(ErrorsYieldStrict) {
2253 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002254 {"\"use strict\";", ""},
2255 {"\"use strict\"; function not_gen() {", "}"},
2256 {"function test_func() {\"use strict\"; ", "}"},
2257 {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2258 {"\"use strict\"; (function not_gen() {", "})"},
2259 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2260 {"() => {\"use strict\"; ", "}"},
2261 {"\"use strong\";", ""},
2262 {"\"use strong\"; function not_gen() {", "}"},
2263 {"function test_func() {\"use strong\"; ", "}"},
2264 {"\"use strong\"; function * gen() { function not_gen() {", "} }"},
2265 {"\"use strong\"; (function not_gen() {", "})"},
2266 {"\"use strong\"; (function * gen() { (function not_gen() {", "}) })"},
2267 {"() => {\"use strong\"; ", "}"},
2268 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002269
2270 const char* statement_data[] = {
2271 "var yield;",
2272 "var foo, yield;",
2273 "try { } catch (yield) { }",
2274 "function yield() { }",
2275 "(function yield() { })",
2276 "function foo(yield) { }",
2277 "function foo(bar, yield) { }",
2278 "function * yield() { }",
2279 "(function * yield() { })",
2280 "yield = 1;",
2281 "var foo = yield = 1;",
2282 "++yield;",
2283 "yield++;",
2284 "yield: 34;",
2285 NULL
2286 };
2287
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002288 static const ParserFlag always_flags[] = {kAllowStrongMode};
2289 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2290 arraysize(always_flags));
2291}
2292
2293
2294TEST(ErrorsYieldSloppy) {
2295 const char* context_data[][2] = {
2296 { "", "" },
2297 { "function not_gen() {", "}" },
2298 { "(function not_gen() {", "})" },
2299 { NULL, NULL }
2300 };
2301
2302 const char* statement_data[] = {
2303 "(function * yield() { })",
2304 NULL
2305 };
2306
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002307 RunParserSyncTest(context_data, statement_data, kError);
2308}
2309
2310
2311TEST(NoErrorsGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002312 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002313 const char* context_data[][2] = {
2314 { "function * gen() {", "}" },
2315 { "(function * gen() {", "})" },
2316 { "(function * () {", "})" },
2317 { NULL, NULL }
2318 };
2319
2320 const char* statement_data[] = {
2321 // A generator without a body is valid.
2322 ""
2323 // Valid yield expressions inside generators.
2324 "yield 2;",
2325 "yield * 2;",
2326 "yield * \n 2;",
2327 "yield yield 1;",
2328 "yield * yield * 1;",
2329 "yield 3 + (yield 4);",
2330 "yield * 3 + (yield * 4);",
2331 "(yield * 3) + (yield * 4);",
2332 "yield 3; yield 4;",
2333 "yield * 3; yield * 4;",
2334 "(function (yield) { })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002335 "(function yield() { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002336 "yield { yield: 12 }",
2337 "yield /* comment */ { yield: 12 }",
2338 "yield * \n { yield: 12 }",
2339 "yield /* comment */ * \n { yield: 12 }",
2340 // You can return in a generator.
2341 "yield 1; return",
2342 "yield * 1; return",
2343 "yield 1; return 37",
2344 "yield * 1; return 37",
2345 "yield 1; return 37; yield 'dead';",
2346 "yield * 1; return 37; yield * 'dead';",
2347 // Yield is still a valid key in object literals.
2348 "({ yield: 1 })",
2349 "({ get yield() { } })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 // And in assignment pattern computed properties
2351 "({ [yield]: x } = { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002352 // Yield without RHS.
2353 "yield;",
2354 "yield",
2355 "yield\n",
2356 "yield /* comment */"
2357 "yield // comment\n"
2358 "(yield)",
2359 "[yield]",
2360 "{yield}",
2361 "yield, yield",
2362 "yield; yield",
2363 "(yield) ? yield : yield",
2364 "(yield) \n ? yield : yield",
2365 // If there is a newline before the next token, we don't look for RHS.
2366 "yield\nfor (;;) {}",
2367 NULL
2368 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002369 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002371 static const ParserFlag always_flags[] = {
2372 kAllowHarmonyDestructuringAssignment};
2373 RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
2374 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002375}
2376
2377
2378TEST(ErrorsYieldGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002379 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002380 const char* context_data[][2] = {
2381 { "function * gen() {", "}" },
2382 { "\"use strict\"; function * gen() {", "}" },
2383 { NULL, NULL }
2384 };
2385
2386 const char* statement_data[] = {
2387 // Invalid yield expressions inside generators.
2388 "var yield;",
2389 "var foo, yield;",
2390 "try { } catch (yield) { }",
2391 "function yield() { }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002392 // The name of the NFE is bound in the generator, which does not permit
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002393 // yield to be an identifier.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002394 "(function * yield() { })",
2395 // Yield isn't valid as a formal parameter for generators.
2396 "function * foo(yield) { }",
2397 "(function * foo(yield) { })",
2398 "yield = 1;",
2399 "var foo = yield = 1;",
2400 "++yield;",
2401 "yield++;",
2402 "yield *",
2403 "(yield *)",
2404 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2405 // is invalid.
2406 "yield 3 + yield 4;",
2407 "yield: 34",
2408 "yield ? 1 : 2",
2409 // Parses as yield (/ yield): invalid.
2410 "yield / yield",
2411 "+ yield",
2412 "+ yield 3",
2413 // Invalid (no newline allowed between yield and *).
2414 "yield\n*3",
2415 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2416 // object literal, and yield is not a valid label).
2417 "yield\n{yield: 42}",
2418 "yield /* comment */\n {yield: 42}",
2419 "yield //comment\n {yield: 42}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002420 // Destructuring binding and assignment are both disallowed
2421 "var [yield] = [42];",
2422 "var {foo: yield} = {a: 42};",
2423 "[yield] = [42];",
2424 "({a: yield} = {a: 42});",
2425 // Also disallow full yield expressions on LHS
2426 "var [yield 24] = [42];",
2427 "var {foo: yield 24} = {a: 42};",
2428 "[yield 24] = [42];",
2429 "({a: yield 24} = {a: 42});",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002430 NULL
2431 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002433
2434 RunParserSyncTest(context_data, statement_data, kError);
2435}
2436
2437
2438TEST(ErrorsNameOfStrictFunction) {
2439 // Tests that illegal tokens as names of a strict function produce the correct
2440 // errors.
2441 const char* context_data[][2] = {
2442 { "function ", ""},
2443 { "\"use strict\"; function", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002444 { "\"use strong\"; function", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002445 { "function * ", ""},
2446 { "\"use strict\"; function * ", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002447 { "\"use strong\"; function * ", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002448 { NULL, NULL }
2449 };
2450
2451 const char* statement_data[] = {
2452 "eval() {\"use strict\";}",
2453 "arguments() {\"use strict\";}",
2454 "interface() {\"use strict\";}",
2455 "yield() {\"use strict\";}",
2456 // Future reserved words are always illegal
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002457 "super() { }",
2458 "super() {\"use strict\";}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002459 NULL
2460 };
2461
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002462 static const ParserFlag always_flags[] = {kAllowStrongMode};
2463 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2464 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002465}
2466
2467
2468TEST(NoErrorsNameOfStrictFunction) {
2469 const char* context_data[][2] = {
2470 { "function ", ""},
2471 { NULL, NULL }
2472 };
2473
2474 const char* statement_data[] = {
2475 "eval() { }",
2476 "arguments() { }",
2477 "interface() { }",
2478 "yield() { }",
2479 NULL
2480 };
2481
2482 RunParserSyncTest(context_data, statement_data, kSuccess);
2483}
2484
2485
2486TEST(NoErrorsNameOfStrictGenerator) {
2487 const char* context_data[][2] = {
2488 { "function * ", ""},
2489 { NULL, NULL }
2490 };
2491
2492 const char* statement_data[] = {
2493 "eval() { }",
2494 "arguments() { }",
2495 "interface() { }",
2496 "yield() { }",
2497 NULL
2498 };
2499
2500 RunParserSyncTest(context_data, statement_data, kSuccess);
2501}
2502
2503
2504TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2505 // Using future reserved words as labels is always an error.
2506 const char* context_data[][2] = {
2507 { "", ""},
2508 { "function test_func() {", "}" },
2509 { "() => {", "}" },
2510 { NULL, NULL }
2511 };
2512
2513 const char* statement_data[] = {
2514 "super: while(true) { break super; }",
2515 NULL
2516 };
2517
2518 RunParserSyncTest(context_data, statement_data, kError);
2519}
2520
2521
2522TEST(ErrorsIllegalWordsAsLabelsStrict) {
2523 // Tests that illegal tokens as labels produce the correct errors.
2524 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002525 {"\"use strict\";", ""},
2526 {"function test_func() {\"use strict\"; ", "}"},
2527 {"() => {\"use strict\"; ", "}"},
2528 {"\"use strong\";", ""},
2529 {"function test_func() {\"use strong\"; ", "}"},
2530 {"() => {\"use strong\"; ", "}"},
2531 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002532
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002533#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002534 const char* statement_data[] = {
2535 "super: while(true) { break super; }",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002536 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002537 NULL
2538 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002539#undef LABELLED_WHILE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 static const ParserFlag always_flags[] = {kAllowStrongMode};
2542 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2543 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544}
2545
2546
2547TEST(NoErrorsIllegalWordsAsLabels) {
2548 // Using eval and arguments as labels is legal even in strict mode.
2549 const char* context_data[][2] = {
2550 { "", ""},
2551 { "function test_func() {", "}" },
2552 { "() => {", "}" },
2553 { "\"use strict\";", "" },
2554 { "\"use strict\"; function test_func() {", "}" },
2555 { "\"use strict\"; () => {", "}" },
2556 { NULL, NULL }
2557 };
2558
2559 const char* statement_data[] = {
2560 "mylabel: while(true) { break mylabel; }",
2561 "eval: while(true) { break eval; }",
2562 "arguments: while(true) { break arguments; }",
2563 NULL
2564 };
2565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002566 RunParserSyncTest(context_data, statement_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002567}
2568
2569
2570TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2571 const char* context_data[][2] = {
2572 { "", ""},
2573 { "function test_func() {", "}" },
2574 { "() => {", "}" },
2575 { NULL, NULL }
2576 };
2577
2578#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2579 const char* statement_data[] {
2580 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2581 NULL
2582 };
2583#undef LABELLED_WHILE
2584
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002585 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002586}
2587
2588
2589TEST(ErrorsParenthesizedLabels) {
2590 // Parenthesized identifiers shouldn't be recognized as labels.
2591 const char* context_data[][2] = {
2592 { "", ""},
2593 { "function test_func() {", "}" },
2594 { "() => {", "}" },
2595 { NULL, NULL }
2596 };
2597
2598 const char* statement_data[] = {
2599 "(mylabel): while(true) { break mylabel; }",
2600 NULL
2601 };
2602
2603 RunParserSyncTest(context_data, statement_data, kError);
2604}
2605
2606
2607TEST(NoErrorsParenthesizedDirectivePrologue) {
2608 // Parenthesized directive prologue shouldn't be recognized.
2609 const char* context_data[][2] = {
2610 { "", ""},
2611 { NULL, NULL }
2612 };
2613
2614 const char* statement_data[] = {
2615 "(\"use strict\"); var eval;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002616 "(\"use strong\"); var eval;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002617 NULL
2618 };
2619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002620 static const ParserFlag always_flags[] = {kAllowStrongMode};
2621 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2622 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002623}
2624
2625
2626TEST(ErrorsNotAnIdentifierName) {
2627 const char* context_data[][2] = {
2628 { "", ""},
2629 { "\"use strict\";", ""},
2630 { NULL, NULL }
2631 };
2632
2633 const char* statement_data[] = {
2634 "var foo = {}; foo.{;",
2635 "var foo = {}; foo.};",
2636 "var foo = {}; foo.=;",
2637 "var foo = {}; foo.888;",
2638 "var foo = {}; foo.-;",
2639 "var foo = {}; foo.--;",
2640 NULL
2641 };
2642
2643 RunParserSyncTest(context_data, statement_data, kError);
2644}
2645
2646
2647TEST(NoErrorsIdentifierNames) {
2648 // Keywords etc. are valid as property names.
2649 const char* context_data[][2] = {
2650 { "", ""},
2651 { "\"use strict\";", ""},
2652 { NULL, NULL }
2653 };
2654
2655 const char* statement_data[] = {
2656 "var foo = {}; foo.if;",
2657 "var foo = {}; foo.yield;",
2658 "var foo = {}; foo.super;",
2659 "var foo = {}; foo.interface;",
2660 "var foo = {}; foo.eval;",
2661 "var foo = {}; foo.arguments;",
2662 NULL
2663 };
2664
2665 RunParserSyncTest(context_data, statement_data, kSuccess);
2666}
2667
2668
2669TEST(DontRegressPreParserDataSizes) {
2670 // These tests make sure that Parser doesn't start producing less "preparse
2671 // data" (data which the embedder can cache).
2672 v8::V8::Initialize();
2673 v8::Isolate* isolate = CcTest::isolate();
2674 v8::HandleScope handles(isolate);
2675
2676 CcTest::i_isolate()->stack_guard()->SetStackLimit(
2677 i::GetCurrentStackPosition() - 128 * 1024);
2678
2679 struct TestCase {
2680 const char* program;
2681 int functions;
2682 } test_cases[] = {
2683 // No functions.
2684 {"var x = 42;", 0},
2685 // Functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002686 {"function foo() {}", 1},
2687 {"function foo() {} function bar() {}", 2},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002688 // Getter / setter functions are recorded as functions if they're on the top
2689 // level.
2690 {"var x = {get foo(){} };", 1},
2691 // Functions insize lazy functions are not recorded.
2692 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2693 {"function lazy() { var x = {get foo(){} } }", 1},
2694 {NULL, 0}
2695 };
2696
2697 for (int i = 0; test_cases[i].program; i++) {
2698 const char* program = test_cases[i].program;
2699 i::Factory* factory = CcTest::i_isolate()->factory();
2700 i::Handle<i::String> source =
2701 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2702 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002703 i::Zone zone;
2704 i::ParseInfo info(&zone, script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002705 i::ScriptData* sd = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002706 info.set_cached_data(&sd);
2707 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
2708 info.set_allow_lazy_parsing();
2709 i::Parser::ParseStatic(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002710 i::ParseData* pd = i::ParseData::FromCachedData(sd);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002711
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002712 if (pd->FunctionCount() != test_cases[i].functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002713 v8::base::OS::Print(
2714 "Expected preparse data for program:\n"
2715 "\t%s\n"
2716 "to contain %d functions, however, received %d functions.\n",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002717 program, test_cases[i].functions, pd->FunctionCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002718 CHECK(false);
2719 }
2720 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002721 delete pd;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002722 }
2723}
2724
2725
2726TEST(FunctionDeclaresItselfStrict) {
2727 // Tests that we produce the right kinds of errors when a function declares
2728 // itself strict (we cannot produce there errors as soon as we see the
2729 // offending identifiers, because we don't know at that point whether the
2730 // function is strict or not).
2731 const char* context_data[][2] = {
2732 {"function eval() {", "}"},
2733 {"function arguments() {", "}"},
2734 {"function yield() {", "}"},
2735 {"function interface() {", "}"},
2736 {"function foo(eval) {", "}"},
2737 {"function foo(arguments) {", "}"},
2738 {"function foo(yield) {", "}"},
2739 {"function foo(interface) {", "}"},
2740 {"function foo(bar, eval) {", "}"},
2741 {"function foo(bar, arguments) {", "}"},
2742 {"function foo(bar, yield) {", "}"},
2743 {"function foo(bar, interface) {", "}"},
2744 {"function foo(bar, bar) {", "}"},
2745 { NULL, NULL }
2746 };
2747
2748 const char* strict_statement_data[] = {
2749 "\"use strict\";",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002750 "\"use strong\";",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002751 NULL
2752 };
2753
2754 const char* non_strict_statement_data[] = {
2755 ";",
2756 NULL
2757 };
2758
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002759 static const ParserFlag always_flags[] = {kAllowStrongMode};
2760 RunParserSyncTest(context_data, strict_statement_data, kError, NULL, 0,
2761 always_flags, arraysize(always_flags));
2762 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess, NULL, 0,
2763 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002764}
2765
2766
2767TEST(ErrorsTryWithoutCatchOrFinally) {
2768 const char* context_data[][2] = {
2769 {"", ""},
2770 { NULL, NULL }
2771 };
2772
2773 const char* statement_data[] = {
2774 "try { }",
2775 "try { } foo();",
2776 "try { } catch (e) foo();",
2777 "try { } catch { }",
2778 "try { } finally foo();",
2779 NULL
2780 };
2781
2782 RunParserSyncTest(context_data, statement_data, kError);
2783}
2784
2785
2786TEST(NoErrorsTryCatchFinally) {
2787 const char* context_data[][2] = {
2788 {"", ""},
2789 { NULL, NULL }
2790 };
2791
2792 const char* statement_data[] = {
2793 "try { } catch (e) { }",
2794 "try { } catch (e) { } finally { }",
2795 "try { } finally { }",
2796 NULL
2797 };
2798
2799 RunParserSyncTest(context_data, statement_data, kSuccess);
2800}
2801
2802
2803TEST(ErrorsRegexpLiteral) {
2804 const char* context_data[][2] = {
2805 {"var r = ", ""},
2806 { NULL, NULL }
2807 };
2808
2809 const char* statement_data[] = {
2810 "/unterminated",
2811 NULL
2812 };
2813
2814 RunParserSyncTest(context_data, statement_data, kError);
2815}
2816
2817
2818TEST(NoErrorsRegexpLiteral) {
2819 const char* context_data[][2] = {
2820 {"var r = ", ""},
2821 { NULL, NULL }
2822 };
2823
2824 const char* statement_data[] = {
2825 "/foo/",
2826 "/foo/g",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002827 NULL
2828 };
2829
2830 RunParserSyncTest(context_data, statement_data, kSuccess);
2831}
2832
2833
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002834TEST(NoErrorsNewExpression) {
2835 const char* context_data[][2] = {
2836 {"", ""},
2837 {"var f =", ""},
2838 { NULL, NULL }
2839 };
2840
2841 const char* statement_data[] = {
2842 "new foo",
2843 "new foo();",
2844 "new foo(1);",
2845 "new foo(1, 2);",
2846 // The first () will be processed as a part of the NewExpression and the
2847 // second () will be processed as part of LeftHandSideExpression.
2848 "new foo()();",
2849 // The first () will be processed as a part of the inner NewExpression and
2850 // the second () will be processed as a part of the outer NewExpression.
2851 "new new foo()();",
2852 "new foo.bar;",
2853 "new foo.bar();",
2854 "new foo.bar.baz;",
2855 "new foo.bar().baz;",
2856 "new foo[bar];",
2857 "new foo[bar]();",
2858 "new foo[bar][baz];",
2859 "new foo[bar]()[baz];",
2860 "new foo[bar].baz(baz)()[bar].baz;",
2861 "new \"foo\"", // Runtime error
2862 "new 1", // Runtime error
2863 // This even runs:
2864 "(new new Function(\"this.x = 1\")).x;",
2865 "new new Test_Two(String, 2).v(0123).length;",
2866 NULL
2867 };
2868
2869 RunParserSyncTest(context_data, statement_data, kSuccess);
2870}
2871
2872
2873TEST(ErrorsNewExpression) {
2874 const char* context_data[][2] = {
2875 {"", ""},
2876 {"var f =", ""},
2877 { NULL, NULL }
2878 };
2879
2880 const char* statement_data[] = {
2881 "new foo bar",
2882 "new ) foo",
2883 "new ++foo",
2884 "new foo ++",
2885 NULL
2886 };
2887
2888 RunParserSyncTest(context_data, statement_data, kError);
2889}
2890
2891
2892TEST(StrictObjectLiteralChecking) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002893 const char* context_data[][2] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002894 {"\"use strict\"; var myobject = {", "};"},
2895 {"\"use strict\"; var myobject = {", ",};"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002896 {"var myobject = {", "};"},
2897 {"var myobject = {", ",};"},
2898 { NULL, NULL }
2899 };
2900
2901 // These are only errors in strict mode.
2902 const char* statement_data[] = {
2903 "foo: 1, foo: 2",
2904 "\"foo\": 1, \"foo\": 2",
2905 "foo: 1, \"foo\": 2",
2906 "1: 1, 1: 2",
2907 "1: 1, \"1\": 2",
2908 "get: 1, get: 2", // Not a getter for real, just a property called get.
2909 "set: 1, set: 2", // Not a setter for real, just a property called set.
2910 NULL
2911 };
2912
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002913 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002914}
2915
2916
2917TEST(ErrorsObjectLiteralChecking) {
2918 const char* context_data[][2] = {
2919 {"\"use strict\"; var myobject = {", "};"},
2920 {"var myobject = {", "};"},
2921 { NULL, NULL }
2922 };
2923
2924 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002925 ",",
2926 // Wrong number of parameters
2927 "get bar(x) {}",
2928 "get bar(x, y) {}",
2929 "set bar() {}",
2930 "set bar(x, y) {}",
2931 // Parsing FunctionLiteral for getter or setter fails
2932 "get foo( +",
2933 "get foo() \"error\"",
2934 NULL
2935 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002936
2937 RunParserSyncTest(context_data, statement_data, kError);
2938}
2939
2940
2941TEST(NoErrorsObjectLiteralChecking) {
2942 const char* context_data[][2] = {
2943 {"var myobject = {", "};"},
2944 {"var myobject = {", ",};"},
2945 {"\"use strict\"; var myobject = {", "};"},
2946 {"\"use strict\"; var myobject = {", ",};"},
2947 { NULL, NULL }
2948 };
2949
2950 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002951 "foo: 1, get foo() {}",
2952 "foo: 1, set foo(v) {}",
2953 "\"foo\": 1, get \"foo\"() {}",
2954 "\"foo\": 1, set \"foo\"(v) {}",
2955 "1: 1, get 1() {}",
2956 "1: 1, set 1(v) {}",
2957 "get foo() {}, get foo() {}",
2958 "set foo(_) {}, set foo(v) {}",
2959 "foo: 1, get \"foo\"() {}",
2960 "foo: 1, set \"foo\"(v) {}",
2961 "\"foo\": 1, get foo() {}",
2962 "\"foo\": 1, set foo(v) {}",
2963 "1: 1, get \"1\"() {}",
2964 "1: 1, set \"1\"(v) {}",
2965 "\"1\": 1, get 1() {}",
2966 "\"1\": 1, set 1(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002967 "foo: 1, bar: 2",
2968 "\"foo\": 1, \"bar\": 2",
2969 "1: 1, 2: 2",
2970 // Syntax: IdentifierName ':' AssignmentExpression
2971 "foo: bar = 5 + baz",
2972 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2973 "get foo() {}",
2974 "get \"foo\"() {}",
2975 "get 1() {}",
2976 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2977 // '{' FunctionBody '}'
2978 "set foo(v) {}",
2979 "set \"foo\"(v) {}",
2980 "set 1(v) {}",
2981 // Non-colliding getters and setters -> no errors
2982 "foo: 1, get bar() {}",
2983 "foo: 1, set bar(v) {}",
2984 "\"foo\": 1, get \"bar\"() {}",
2985 "\"foo\": 1, set \"bar\"(v) {}",
2986 "1: 1, get 2() {}",
2987 "1: 1, set 2(v) {}",
2988 "get: 1, get foo() {}",
2989 "set: 1, set foo(_) {}",
2990 // Keywords, future reserved and strict future reserved are also allowed as
2991 // property names.
2992 "if: 4",
2993 "interface: 5",
2994 "super: 6",
2995 "eval: 7",
2996 "arguments: 8",
2997 NULL
2998 };
2999
3000 RunParserSyncTest(context_data, statement_data, kSuccess);
3001}
3002
3003
3004TEST(TooManyArguments) {
3005 const char* context_data[][2] = {
3006 {"foo(", "0)"},
3007 { NULL, NULL }
3008 };
3009
3010 using v8::internal::Code;
3011 char statement[Code::kMaxArguments * 2 + 1];
3012 for (int i = 0; i < Code::kMaxArguments; ++i) {
3013 statement[2 * i] = '0';
3014 statement[2 * i + 1] = ',';
3015 }
3016 statement[Code::kMaxArguments * 2] = 0;
3017
3018 const char* statement_data[] = {
3019 statement,
3020 NULL
3021 };
3022
3023 // The test is quite slow, so run it with a reduced set of flags.
3024 static const ParserFlag empty_flags[] = {kAllowLazy};
3025 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
3026}
3027
3028
3029TEST(StrictDelete) {
3030 // "delete <Identifier>" is not allowed in strict mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003031 const char* strong_context_data[][2] = {
3032 {"\"use strong\"; ", ""},
3033 { NULL, NULL }
3034 };
3035
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003036 const char* strict_context_data[][2] = {
3037 {"\"use strict\"; ", ""},
3038 { NULL, NULL }
3039 };
3040
3041 const char* sloppy_context_data[][2] = {
3042 {"", ""},
3043 { NULL, NULL }
3044 };
3045
3046 // These are errors in the strict mode.
3047 const char* sloppy_statement_data[] = {
3048 "delete foo;",
3049 "delete foo + 1;",
3050 "delete (foo);",
3051 "delete eval;",
3052 "delete interface;",
3053 NULL
3054 };
3055
3056 // These are always OK
3057 const char* good_statement_data[] = {
3058 "delete this;",
3059 "delete 1;",
3060 "delete 1 + 2;",
3061 "delete foo();",
3062 "delete foo.bar;",
3063 "delete foo[bar];",
3064 "delete foo--;",
3065 "delete --foo;",
3066 "delete new foo();",
3067 "delete new foo(bar);",
3068 NULL
3069 };
3070
3071 // These are always errors
3072 const char* bad_statement_data[] = {
3073 "delete if;",
3074 NULL
3075 };
3076
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003077 static const ParserFlag always_flags[] = {kAllowStrongMode};
3078 RunParserSyncTest(strong_context_data, sloppy_statement_data, kError, NULL, 0,
3079 always_flags, arraysize(always_flags));
3080 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError, NULL, 0,
3081 always_flags, arraysize(always_flags));
3082 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess, NULL,
3083 0, always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003084
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003085 RunParserSyncTest(strong_context_data, good_statement_data, kError, NULL, 0,
3086 always_flags, arraysize(always_flags));
3087 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess, NULL, 0,
3088 always_flags, arraysize(always_flags));
3089 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess, NULL, 0,
3090 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003091
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003092 RunParserSyncTest(strong_context_data, bad_statement_data, kError, NULL, 0,
3093 always_flags, arraysize(always_flags));
3094 RunParserSyncTest(strict_context_data, bad_statement_data, kError, NULL, 0,
3095 always_flags, arraysize(always_flags));
3096 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError, NULL, 0,
3097 always_flags, arraysize(always_flags));
3098}
3099
3100
3101TEST(NoErrorsDeclsInCase) {
3102 const char* context_data[][2] = {
3103 {"'use strict'; switch(x) { case 1:", "}"},
3104 {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3105 {"'use strict'; switch(x) { case 1: case 2:", "}"},
3106 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3107 {"'use strict'; switch(x) { default:", "}"},
3108 {"function foo() {'use strict'; switch(x) { default:", "}}"},
3109 {"'use strict'; switch(x) { case 1: default:", "}"},
3110 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3111 { nullptr, nullptr }
3112 };
3113
3114 const char* statement_data[] = {
3115 "function f() { }",
3116 "class C { }",
3117 "class C extends Q {}",
3118 "function f() { } class C {}",
3119 "function f() { }; class C {}",
3120 "class C {}; function f() {}",
3121 nullptr
3122 };
3123
3124 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003125}
3126
3127
3128TEST(InvalidLeftHandSide) {
3129 const char* assignment_context_data[][2] = {
3130 {"", " = 1;"},
3131 {"\"use strict\"; ", " = 1;"},
3132 { NULL, NULL }
3133 };
3134
3135 const char* prefix_context_data[][2] = {
3136 {"++", ";"},
3137 {"\"use strict\"; ++", ";"},
3138 {NULL, NULL},
3139 };
3140
3141 const char* postfix_context_data[][2] = {
3142 {"", "++;"},
3143 {"\"use strict\"; ", "++;"},
3144 { NULL, NULL }
3145 };
3146
3147 // Good left hand sides for assigment or prefix / postfix operations.
3148 const char* good_statement_data[] = {
3149 "foo",
3150 "foo.bar",
3151 "foo[bar]",
3152 "foo()[bar]",
3153 "foo().bar",
3154 "this.foo",
3155 "this[foo]",
3156 "new foo()[bar]",
3157 "new foo().bar",
3158 "foo()",
3159 "foo(bar)",
3160 "foo[bar]()",
3161 "foo.bar()",
3162 "this()",
3163 "this.foo()",
3164 "this[foo].bar()",
3165 "this.foo[foo].bar(this)(bar)[foo]()",
3166 NULL
3167 };
3168
3169 // Bad left hand sides for assigment or prefix / postfix operations.
3170 const char* bad_statement_data_common[] = {
3171 "2",
3172 "new foo",
3173 "new foo()",
3174 "null",
3175 "if", // Unexpected token
3176 "{x: 1}", // Unexpected token
3177 "this",
3178 "\"bar\"",
3179 "(foo + bar)",
3180 "new new foo()[bar]", // means: new (new foo()[bar])
3181 "new new foo().bar", // means: new (new foo()[bar])
3182 NULL
3183 };
3184
3185 // These are not okay for assignment, but okay for prefix / postix.
3186 const char* bad_statement_data_for_assignment[] = {
3187 "++foo",
3188 "foo++",
3189 "foo + bar",
3190 NULL
3191 };
3192
3193 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3194 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3195 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3196 kError);
3197
3198 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3199 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3200
3201 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3202 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3203}
3204
3205
3206TEST(FuncNameInferrerBasic) {
3207 // Tests that function names are inferred properly.
3208 i::FLAG_allow_natives_syntax = true;
3209 v8::Isolate* isolate = CcTest::isolate();
3210 v8::HandleScope scope(isolate);
3211 LocalContext env;
3212 CompileRun("var foo1 = function() {}; "
3213 "var foo2 = function foo3() {}; "
3214 "function not_ctor() { "
3215 " var foo4 = function() {}; "
3216 " return %FunctionGetInferredName(foo4); "
3217 "} "
3218 "function Ctor() { "
3219 " var foo5 = function() {}; "
3220 " return %FunctionGetInferredName(foo5); "
3221 "} "
3222 "var obj1 = { foo6: function() {} }; "
3223 "var obj2 = { 'foo7': function() {} }; "
3224 "var obj3 = {}; "
3225 "obj3[1] = function() {}; "
3226 "var obj4 = {}; "
3227 "obj4[1] = function foo8() {}; "
3228 "var obj5 = {}; "
3229 "obj5['foo9'] = function() {}; "
3230 "var obj6 = { obj7 : { foo10: function() {} } };");
3231 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3232 // foo2 is not unnamed -> its name is not inferred.
3233 ExpectString("%FunctionGetInferredName(foo2)", "");
3234 ExpectString("not_ctor()", "foo4");
3235 ExpectString("Ctor()", "Ctor.foo5");
3236 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3237 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3238 ExpectString("%FunctionGetInferredName(obj3[1])",
3239 "obj3.(anonymous function)");
3240 ExpectString("%FunctionGetInferredName(obj4[1])", "");
3241 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3242 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3243}
3244
3245
3246TEST(FuncNameInferrerTwoByte) {
3247 // Tests function name inferring in cases where some parts of the inferred
3248 // function name are two-byte strings.
3249 i::FLAG_allow_natives_syntax = true;
3250 v8::Isolate* isolate = CcTest::isolate();
3251 v8::HandleScope scope(isolate);
3252 LocalContext env;
3253 uint16_t* two_byte_source = AsciiToTwoByteString(
3254 "var obj1 = { oXj2 : { foo1: function() {} } }; "
3255 "%FunctionGetInferredName(obj1.oXj2.foo1)");
3256 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3257 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3258 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3259 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003260 v8::String::NewFromTwoByte(isolate, two_byte_source,
3261 v8::NewStringType::kNormal)
3262 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003263 v8::Local<v8::Value> result = CompileRun(source);
3264 CHECK(result->IsString());
3265 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003266 v8::String::NewFromTwoByte(isolate, two_byte_name,
3267 v8::NewStringType::kNormal)
3268 .ToLocalChecked();
3269 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003270 i::DeleteArray(two_byte_source);
3271 i::DeleteArray(two_byte_name);
3272}
3273
3274
3275TEST(FuncNameInferrerEscaped) {
3276 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3277 // character as a unicode escape.
3278 i::FLAG_allow_natives_syntax = true;
3279 v8::Isolate* isolate = CcTest::isolate();
3280 v8::HandleScope scope(isolate);
3281 LocalContext env;
3282 uint16_t* two_byte_source = AsciiToTwoByteString(
3283 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3284 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3285 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3286 // Fix to correspond to the non-ASCII name in two_byte_source.
3287 two_byte_name[6] = 0x010d;
3288 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003289 v8::String::NewFromTwoByte(isolate, two_byte_source,
3290 v8::NewStringType::kNormal)
3291 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003292 v8::Local<v8::Value> result = CompileRun(source);
3293 CHECK(result->IsString());
3294 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003295 v8::String::NewFromTwoByte(isolate, two_byte_name,
3296 v8::NewStringType::kNormal)
3297 .ToLocalChecked();
3298 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003299 i::DeleteArray(two_byte_source);
3300 i::DeleteArray(two_byte_name);
3301}
3302
3303
3304TEST(RegressionLazyFunctionWithErrorWithArg) {
3305 // The bug occurred when a lazy function had an error which requires a
3306 // parameter (such as "unknown label" here). The error message was processed
3307 // before the AstValueFactory containing the error message string was
3308 // internalized.
3309 v8::Isolate* isolate = CcTest::isolate();
3310 v8::HandleScope scope(isolate);
3311 LocalContext env;
3312 i::FLAG_lazy = true;
3313 i::FLAG_min_preparse_length = 0;
3314 CompileRun("function this_is_lazy() {\n"
3315 " break p;\n"
3316 "}\n"
3317 "this_is_lazy();\n");
3318}
3319
3320
3321TEST(SerializationOfMaybeAssignmentFlag) {
3322 i::Isolate* isolate = CcTest::i_isolate();
3323 i::Factory* factory = isolate->factory();
3324 i::HandleScope scope(isolate);
3325 LocalContext env;
3326
3327 const char* src =
3328 "function h() {"
3329 " var result = [];"
3330 " function f() {"
3331 " result.push(2);"
3332 " }"
3333 " function assertResult(r) {"
3334 " f();"
3335 " result = [];"
3336 " }"
3337 " assertResult([2]);"
3338 " assertResult([2]);"
3339 " return f;"
3340 "};"
3341 "h();";
3342
3343 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3344 i::SNPrintF(program, "%s", src);
3345 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3346 source->PrintOn(stdout);
3347 printf("\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003348 i::Zone zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003349 v8::Local<v8::Value> v = CompileRun(src);
3350 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3351 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3352 i::Context* context = f->context();
3353 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3354 avf.Internalize(isolate);
3355 const i::AstRawString* name = avf.GetOneByteString("result");
3356 i::Handle<i::String> str = name->string();
3357 CHECK(str->IsInternalizedString());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003358 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003359 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003360 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003361 i::Scope* s =
3362 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3363 CHECK(s != script_scope);
3364 CHECK(name != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003365
3366 // Get result from h's function context (that is f's context)
3367 i::Variable* var = s->Lookup(name);
3368
3369 CHECK(var != NULL);
3370 // Maybe assigned should survive deserialization
3371 CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3372 // TODO(sigurds) Figure out if is_used should survive context serialization.
3373}
3374
3375
3376TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3377 i::Isolate* isolate = CcTest::i_isolate();
3378 i::Factory* factory = isolate->factory();
3379 i::HandleScope scope(isolate);
3380 LocalContext env;
3381
3382
3383 const char* src =
3384 "function f(x) {"
3385 " var a = arguments;"
3386 " function g(i) {"
3387 " ++a[0];"
3388 " };"
3389 " return g;"
3390 " }"
3391 "f(0);";
3392
3393 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3394 i::SNPrintF(program, "%s", src);
3395 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3396 source->PrintOn(stdout);
3397 printf("\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003398 i::Zone zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003399 v8::Local<v8::Value> v = CompileRun(src);
3400 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3401 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3402 i::Context* context = f->context();
3403 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3404 avf.Internalize(isolate);
3405
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003406 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003407 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003408 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003409 i::Scope* s =
3410 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3411 CHECK(s != script_scope);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003412 const i::AstRawString* name_x = avf.GetOneByteString("x");
3413
3414 // Get result from f's function context (that is g's outer context)
3415 i::Variable* var_x = s->Lookup(name_x);
3416 CHECK(var_x != NULL);
3417 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3418}
3419
3420
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003421TEST(InnerAssignment) {
3422 i::Isolate* isolate = CcTest::i_isolate();
3423 i::Factory* factory = isolate->factory();
3424 i::HandleScope scope(isolate);
3425 LocalContext env;
3426
3427 const char* prefix = "function f() {";
3428 const char* midfix = " function g() {";
3429 const char* suffix = "}}";
3430 struct { const char* source; bool assigned; bool strict; } outers[] = {
3431 // Actual assignments.
3432 { "var x; var x = 5;", true, false },
3433 { "var x; { var x = 5; }", true, false },
3434 { "'use strict'; let x; x = 6;", true, true },
3435 { "var x = 5; function x() {}", true, false },
3436 // Actual non-assignments.
3437 { "var x;", false, false },
3438 { "var x = 5;", false, false },
3439 { "'use strict'; let x;", false, true },
3440 { "'use strict'; let x = 6;", false, true },
3441 { "'use strict'; var x = 0; { let x = 6; }", false, true },
3442 { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3443 { "'use strict'; let x = 0; { let x = 6; }", false, true },
3444 { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3445 { "var x; try {} catch (x) { x = 5; }", false, false },
3446 { "function x() {}", false, false },
3447 // Eval approximation.
3448 { "var x; eval('');", true, false },
3449 { "eval(''); var x;", true, false },
3450 { "'use strict'; let x; eval('');", true, true },
3451 { "'use strict'; eval(''); let x;", true, true },
3452 // Non-assignments not recognized, because the analysis is approximative.
3453 { "var x; var x;", true, false },
3454 { "var x = 5; var x;", true, false },
3455 { "var x; { var x; }", true, false },
3456 { "var x; function x() {}", true, false },
3457 { "function x() {}; var x;", true, false },
3458 { "var x; try {} catch (x) { var x = 5; }", true, false },
3459 };
3460 struct { const char* source; bool assigned; bool with; } inners[] = {
3461 // Actual assignments.
3462 { "x = 1;", true, false },
3463 { "x++;", true, false },
3464 { "++x;", true, false },
3465 { "x--;", true, false },
3466 { "--x;", true, false },
3467 { "{ x = 1; }", true, false },
3468 { "'use strict'; { let x; }; x = 0;", true, false },
3469 { "'use strict'; { const x = 1; }; x = 0;", true, false },
3470 { "'use strict'; { function x() {} }; x = 0;", true, false },
3471 { "with ({}) { x = 1; }", true, true },
3472 { "eval('');", true, false },
3473 { "'use strict'; { let y; eval('') }", true, false },
3474 { "function h() { x = 0; }", true, false },
3475 { "(function() { x = 0; })", true, false },
3476 { "(function() { x = 0; })", true, false },
3477 { "with ({}) (function() { x = 0; })", true, true },
3478 // Actual non-assignments.
3479 { "", false, false },
3480 { "x;", false, false },
3481 { "var x;", false, false },
3482 { "var x = 8;", false, false },
3483 { "var x; x = 8;", false, false },
3484 { "'use strict'; let x;", false, false },
3485 { "'use strict'; let x = 8;", false, false },
3486 { "'use strict'; let x; x = 8;", false, false },
3487 { "'use strict'; const x = 8;", false, false },
3488 { "function x() {}", false, false },
3489 { "function x() { x = 0; }", false, false },
3490 { "function h(x) { x = 0; }", false, false },
3491 { "'use strict'; { let x; x = 0; }", false, false },
3492 { "{ var x; }; x = 0;", false, false },
3493 { "with ({}) {}", false, true },
3494 { "var x; { with ({}) { x = 1; } }", false, true },
3495 { "try {} catch(x) { x = 0; }", false, false },
3496 { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3497 // Eval approximation.
3498 { "eval('');", true, false },
3499 { "function h() { eval(''); }", true, false },
3500 { "(function() { eval(''); })", true, false },
3501 // Shadowing not recognized because of eval approximation.
3502 { "var x; eval('');", true, false },
3503 { "'use strict'; let x; eval('');", true, false },
3504 { "try {} catch(x) { eval(''); }", true, false },
3505 { "function x() { eval(''); }", true, false },
3506 { "(function(x) { eval(''); })", true, false },
3507 };
3508
3509 // Used to trigger lazy compilation of function
3510 int comment_len = 2048;
3511 i::ScopedVector<char> comment(comment_len + 1);
3512 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3513 int prefix_len = Utf8LengthHelper(prefix);
3514 int midfix_len = Utf8LengthHelper(midfix);
3515 int suffix_len = Utf8LengthHelper(suffix);
3516 for (unsigned i = 0; i < arraysize(outers); ++i) {
3517 const char* outer = outers[i].source;
3518 int outer_len = Utf8LengthHelper(outer);
3519 for (unsigned j = 0; j < arraysize(inners); ++j) {
3520 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3521 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3522 if (outers[i].strict && inners[j].with) continue;
3523 const char* inner = inners[j].source;
3524 int inner_len = Utf8LengthHelper(inner);
3525
3526 int outer_comment_len = outer_lazy ? comment_len : 0;
3527 int inner_comment_len = inner_lazy ? comment_len : 0;
3528 const char* outer_comment = outer_lazy ? comment.start() : "";
3529 const char* inner_comment = inner_lazy ? comment.start() : "";
3530 int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3531 inner_comment_len + inner_len + suffix_len;
3532 i::ScopedVector<char> program(len + 1);
3533
3534 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3535 midfix, inner_comment, inner, suffix);
3536 i::Handle<i::String> source =
3537 factory->InternalizeUtf8String(program.start());
3538 source->PrintOn(stdout);
3539 printf("\n");
3540
3541 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003542 i::Zone zone;
3543 i::ParseInfo info(&zone, script);
3544 i::Parser parser(&info);
3545 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003546 CHECK(i::Compiler::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003547 CHECK(info.literal() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003548
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003549 i::Scope* scope = info.literal()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003550 CHECK_EQ(scope->inner_scopes()->length(), 1);
3551 i::Scope* inner_scope = scope->inner_scopes()->at(0);
3552 const i::AstRawString* var_name =
3553 info.ast_value_factory()->GetOneByteString("x");
3554 i::Variable* var = inner_scope->Lookup(var_name);
3555 bool expected = outers[i].assigned || inners[j].assigned;
3556 CHECK(var != NULL);
3557 CHECK(var->is_used() || !expected);
3558 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3559 }
3560 }
3561 }
3562 }
3563}
3564
3565namespace {
3566
3567int* global_use_counts = NULL;
3568
3569void MockUseCounterCallback(v8::Isolate* isolate,
3570 v8::Isolate::UseCounterFeature feature) {
3571 ++global_use_counts[feature];
3572}
3573
3574}
3575
3576
3577TEST(UseAsmUseCount) {
3578 i::Isolate* isolate = CcTest::i_isolate();
3579 i::HandleScope scope(isolate);
3580 LocalContext env;
3581 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3582 global_use_counts = use_counts;
3583 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3584 CompileRun("\"use asm\";\n"
3585 "var foo = 1;\n"
3586 "\"use asm\";\n" // Only the first one counts.
3587 "function bar() { \"use asm\"; var baz = 1; }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003588 // Optimizing will double-count because the source is parsed twice.
3589 CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
3590}
3591
3592
3593TEST(UseConstLegacyCount) {
3594 i::FLAG_legacy_const = true;
3595 i::Isolate* isolate = CcTest::i_isolate();
3596 i::HandleScope scope(isolate);
3597 LocalContext env;
3598 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3599 global_use_counts = use_counts;
3600 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3601 CompileRun(
3602 "const x = 1;\n"
3603 "var foo = 1;\n"
3604 "const y = 1;\n"
3605 "function bar() {\n"
3606 " const z = 1; var baz = 1;\n"
3607 " function q() { const k = 42; }\n"
3608 "}");
3609 // Optimizing will double-count because the source is parsed twice.
3610 CHECK_EQ(i::FLAG_always_opt ? 8 : 4, use_counts[v8::Isolate::kLegacyConst]);
3611}
3612
3613
3614TEST(StrictModeUseCount) {
3615 i::Isolate* isolate = CcTest::i_isolate();
3616 i::HandleScope scope(isolate);
3617 LocalContext env;
3618 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3619 global_use_counts = use_counts;
3620 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3621 CompileRun(
3622 "\"use strict\";\n"
3623 "function bar() { var baz = 1; }"); // strict mode inherits
3624 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3625 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
3626}
3627
3628
3629TEST(SloppyModeUseCount) {
3630 i::Isolate* isolate = CcTest::i_isolate();
3631 i::HandleScope scope(isolate);
3632 LocalContext env;
3633 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3634 global_use_counts = use_counts;
3635 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3636 CompileRun("function bar() { var baz = 1; }");
3637 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3638 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
3639}
3640
3641
3642TEST(BothModesUseCount) {
3643 i::Isolate* isolate = CcTest::i_isolate();
3644 i::HandleScope scope(isolate);
3645 LocalContext env;
3646 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3647 global_use_counts = use_counts;
3648 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3649 CompileRun("function bar() { 'use strict'; var baz = 1; }");
3650 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3651 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3652}
3653
3654
3655TEST(ErrorsArrowFormalParameters) {
3656 const char* context_data[][2] = {
3657 { "()", "=>{}" },
3658 { "()", "=>{};" },
3659 { "var x = ()", "=>{}" },
3660 { "var x = ()", "=>{};" },
3661
3662 { "a", "=>{}" },
3663 { "a", "=>{};" },
3664 { "var x = a", "=>{}" },
3665 { "var x = a", "=>{};" },
3666
3667 { "(a)", "=>{}" },
3668 { "(a)", "=>{};" },
3669 { "var x = (a)", "=>{}" },
3670 { "var x = (a)", "=>{};" },
3671
3672 { "(...a)", "=>{}" },
3673 { "(...a)", "=>{};" },
3674 { "var x = (...a)", "=>{}" },
3675 { "var x = (...a)", "=>{};" },
3676
3677 { "(a,b)", "=>{}" },
3678 { "(a,b)", "=>{};" },
3679 { "var x = (a,b)", "=>{}" },
3680 { "var x = (a,b)", "=>{};" },
3681
3682 { "(a,...b)", "=>{}" },
3683 { "(a,...b)", "=>{};" },
3684 { "var x = (a,...b)", "=>{}" },
3685 { "var x = (a,...b)", "=>{};" },
3686
3687 { nullptr, nullptr }
3688 };
3689 const char* assignment_expression_suffix_data[] = {
3690 "?c:d=>{}",
3691 "=c=>{}",
3692 "()",
3693 "(c)",
3694 "[1]",
3695 "[c]",
3696 ".c",
3697 "-c",
3698 "+c",
3699 "c++",
3700 "`c`",
3701 "`${c}`",
3702 "`template-head${c}`",
3703 "`${c}template-tail`",
3704 "`template-head${c}template-tail`",
3705 "`${c}template-tail`",
3706 nullptr
3707 };
3708
3709 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003710}
3711
3712
3713TEST(ErrorsArrowFunctions) {
3714 // Tests that parser and preparser generate the same kind of errors
3715 // on invalid arrow function syntax.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003716
3717 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003718 const char* context_data[][2] = {
3719 {"", ";"},
3720 {"v = ", ";"},
3721 {"bar ? (", ") : baz;"},
3722 {"bar ? baz : (", ");"},
3723 {"bar[", "];"},
3724 {"bar, ", ";"},
3725 {"", ", bar;"},
3726 {NULL, NULL}
3727 };
3728
3729 const char* statement_data[] = {
3730 "=> 0",
3731 "=>",
3732 "() =>",
3733 "=> {}",
3734 ") => {}",
3735 ", => {}",
3736 "(,) => {}",
3737 "return => {}",
3738 "() => {'value': 42}",
3739
3740 // Check that the early return introduced in ParsePrimaryExpression
3741 // does not accept stray closing parentheses.
3742 ")",
3743 ") => 0",
3744 "foo[()]",
3745 "()",
3746
3747 // Parameter lists with extra parens should be recognized as errors.
3748 "(()) => 0",
3749 "((x)) => 0",
3750 "((x, y)) => 0",
3751 "(x, (y)) => 0",
3752 "((x, y, z)) => 0",
3753 "(x, (y, z)) => 0",
3754 "((x, y), z) => 0",
3755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003756 // Arrow function formal parameters are parsed as StrictFormalParameters,
3757 // which confusingly only implies that there are no duplicates. Words
3758 // reserved in strict mode, and eval or arguments, are indeed valid in
3759 // sloppy mode.
3760 "eval => { 'use strict'; 0 }",
3761 "arguments => { 'use strict'; 0 }",
3762 "yield => { 'use strict'; 0 }",
3763 "interface => { 'use strict'; 0 }",
3764 "(eval) => { 'use strict'; 0 }",
3765 "(arguments) => { 'use strict'; 0 }",
3766 "(yield) => { 'use strict'; 0 }",
3767 "(interface) => { 'use strict'; 0 }",
3768 "(eval, bar) => { 'use strict'; 0 }",
3769 "(bar, eval) => { 'use strict'; 0 }",
3770 "(bar, arguments) => { 'use strict'; 0 }",
3771 "(bar, yield) => { 'use strict'; 0 }",
3772 "(bar, interface) => { 'use strict'; 0 }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003773 // TODO(aperez): Detecting duplicates does not work in PreParser.
3774 // "(bar, bar) => {}",
3775
3776 // The parameter list is parsed as an expression, but only
3777 // a comma-separated list of identifier is valid.
3778 "32 => {}",
3779 "(32) => {}",
3780 "(a, 32) => {}",
3781 "if => {}",
3782 "(if) => {}",
3783 "(a, if) => {}",
3784 "a + b => {}",
3785 "(a + b) => {}",
3786 "(a + b, c) => {}",
3787 "(a, b - c) => {}",
3788 "\"a\" => {}",
3789 "(\"a\") => {}",
3790 "(\"a\", b) => {}",
3791 "(a, \"b\") => {}",
3792 "-a => {}",
3793 "(-a) => {}",
3794 "(-a, b) => {}",
3795 "(a, -b) => {}",
3796 "{} => {}",
3797 "({}) => {}",
3798 "(a, {}) => {}",
3799 "({}, a) => {}",
3800 "a++ => {}",
3801 "(a++) => {}",
3802 "(a++, b) => {}",
3803 "(a, b++) => {}",
3804 "[] => {}",
3805 "([]) => {}",
3806 "(a, []) => {}",
3807 "([], a) => {}",
3808 "(a = b) => {}",
3809 "(a = b, c) => {}",
3810 "(a, b = c) => {}",
3811 "(foo ? bar : baz) => {}",
3812 "(a, foo ? bar : baz) => {}",
3813 "(foo ? bar : baz, a) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003814 "(a.b, c) => {}",
3815 "(c, a.b) => {}",
3816 "(a['b'], c) => {}",
3817 "(c, a['b']) => {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01003818
3819 // crbug.com/582626
3820 "(...rest - a) => b",
3821 "(a, ...b - 10) => b",
3822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003823 NULL
3824 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01003825 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003826
3827 // The test is quite slow, so run it with a reduced set of flags.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003828 static const ParserFlag flags[] = {kAllowLazy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003829 RunParserSyncTest(context_data, statement_data, kError, flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003830 arraysize(flags));
3831
3832 // In a context where a concise arrow body is parsed with [~In] variant,
3833 // ensure that an error is reported in both full parser and preparser.
3834 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3835 {nullptr, nullptr}};
3836 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
3837 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
3838 arraysize(flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003839}
3840
3841
3842TEST(NoErrorsArrowFunctions) {
3843 // Tests that parser and preparser accept valid arrow functions syntax.
3844 const char* context_data[][2] = {
3845 {"", ";"},
3846 {"bar ? (", ") : baz;"},
3847 {"bar ? baz : (", ");"},
3848 {"bar, ", ";"},
3849 {"", ", bar;"},
3850 {NULL, NULL}
3851 };
3852
3853 const char* statement_data[] = {
3854 "() => {}",
3855 "() => { return 42 }",
3856 "x => { return x; }",
3857 "(x) => { return x; }",
3858 "(x, y) => { return x + y; }",
3859 "(x, y, z) => { return x + y + z; }",
3860 "(x, y) => { x.a = y; }",
3861 "() => 42",
3862 "x => x",
3863 "x => x * x",
3864 "(x) => x",
3865 "(x) => x * x",
3866 "(x, y) => x + y",
3867 "(x, y, z) => x, y, z",
3868 "(x, y) => x.a = y",
3869 "() => ({'value': 42})",
3870 "x => y => x + y",
3871 "(x, y) => (u, v) => x*u + y*v",
3872 "(x, y) => z => z * (x + y)",
3873 "x => (y, z) => z * (x + y)",
3874
3875 // Those are comma-separated expressions, with arrow functions as items.
3876 // They stress the code for validating arrow function parameter lists.
3877 "a, b => 0",
3878 "a, b, (c, d) => 0",
3879 "(a, b, (c, d) => 0)",
3880 "(a, b) => 0, (c, d) => 1",
3881 "(a, b => {}, a => a + 1)",
3882 "((a, b) => {}, (a => a + 1))",
3883 "(a, (a, (b, c) => 0))",
3884
3885 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3886 "foo ? bar : baz => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003887
3888 // Arrows with non-simple parameters.
3889 "({a}) => {}",
3890 "(x = 9) => {}",
3891 "(x, y = 9) => {}",
3892 "(x = 9, y) => {}",
3893 "(x, y = 9, z) => {}",
3894 "(x, y = 9, z = 8) => {}",
3895 "(...a) => {}",
3896 "(x, ...a) => {}",
3897 "(x = 9, ...a) => {}",
3898 "(x, y = 9, ...a) => {}",
3899 "(x, y = 9, {b}, z = 8, ...a) => {}",
3900 // TODO(wingo, rossberg): This is not accepted right now.
3901 // "({a} = {}) => {}",
3902 // "([x] = []) => {}",
3903 "({a = 42}) => {}",
3904 "([x = 0]) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003905 NULL
3906 };
3907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003908 static const ParserFlag always_flags[] = {kAllowHarmonyDefaultParameters,
3909 kAllowHarmonyDestructuring};
3910 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3911 always_flags, arraysize(always_flags));
3912
3913 static const ParserFlag flags[] = {kAllowLazy};
3914 // In a context where a concise arrow body is parsed with [~In] variant,
3915 // ensure that nested expressions can still use the 'in' operator,
3916 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3917 {nullptr, nullptr}};
3918 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
3919 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
3920 arraysize(flags));
3921}
3922
3923
3924TEST(ArrowFunctionsSloppyParameterNames) {
3925 const char* strong_context_data[][2] = {
3926 {"'use strong'; ", ";"},
3927 {"'use strong'; bar ? (", ") : baz;"},
3928 {"'use strong'; bar ? baz : (", ");"},
3929 {"'use strong'; bar, ", ";"},
3930 {"'use strong'; ", ", bar;"},
3931 {NULL, NULL}
3932 };
3933
3934 const char* strict_context_data[][2] = {
3935 {"'use strict'; ", ";"},
3936 {"'use strict'; bar ? (", ") : baz;"},
3937 {"'use strict'; bar ? baz : (", ");"},
3938 {"'use strict'; bar, ", ";"},
3939 {"'use strict'; ", ", bar;"},
3940 {NULL, NULL}
3941 };
3942
3943 const char* sloppy_context_data[][2] = {
3944 {"", ";"},
3945 {"bar ? (", ") : baz;"},
3946 {"bar ? baz : (", ");"},
3947 {"bar, ", ";"},
3948 {"", ", bar;"},
3949 {NULL, NULL}
3950 };
3951
3952 const char* statement_data[] = {
3953 "eval => {}",
3954 "arguments => {}",
3955 "yield => {}",
3956 "interface => {}",
3957 "(eval) => {}",
3958 "(arguments) => {}",
3959 "(yield) => {}",
3960 "(interface) => {}",
3961 "(eval, bar) => {}",
3962 "(bar, eval) => {}",
3963 "(bar, arguments) => {}",
3964 "(bar, yield) => {}",
3965 "(bar, interface) => {}",
3966 "(interface, eval) => {}",
3967 "(interface, arguments) => {}",
3968 "(eval, interface) => {}",
3969 "(arguments, interface) => {}",
3970 NULL
3971 };
3972
3973 static const ParserFlag always_flags[] = {kAllowStrongMode};
3974 RunParserSyncTest(strong_context_data, statement_data, kError, NULL, 0,
3975 always_flags, arraysize(always_flags));
3976 RunParserSyncTest(strict_context_data, statement_data, kError, NULL, 0,
3977 always_flags, arraysize(always_flags));
3978 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess, NULL, 0,
3979 always_flags, arraysize(always_flags));
3980}
3981
3982
3983TEST(ArrowFunctionsYieldParameterNameInGenerator) {
3984 const char* sloppy_function_context_data[][2] = {
3985 {"(function f() { (", "); });"},
3986 {NULL, NULL}
3987 };
3988
3989 const char* strict_function_context_data[][2] = {
3990 {"(function f() {'use strong'; (", "); });"},
3991 {"(function f() {'use strict'; (", "); });"},
3992 {NULL, NULL}
3993 };
3994
3995 const char* generator_context_data[][2] = {
3996 {"(function *g() {'use strong'; (", "); });"},
3997 {"(function *g() {'use strict'; (", "); });"},
3998 {"(function *g() { (", "); });"},
3999 {NULL, NULL}
4000 };
4001
4002 const char* arrow_data[] = {
4003 "yield => {}",
4004 "(yield) => {}",
4005 "(a, yield) => {}",
4006 "(yield, a) => {}",
4007 "(yield, ...a) => {}",
4008 "(a, ...yield) => {}",
4009 "({yield}) => {}",
4010 "([yield]) => {}",
4011 NULL
4012 };
4013
4014 static const ParserFlag always_flags[] = { kAllowHarmonyDestructuring,
4015 kAllowStrongMode};
4016 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess, NULL, 0,
4017 always_flags, arraysize(always_flags));
4018 RunParserSyncTest(strict_function_context_data, arrow_data, kError, NULL, 0,
4019 always_flags, arraysize(always_flags));
4020 RunParserSyncTest(generator_context_data, arrow_data, kError, NULL, 0,
4021 always_flags, arraysize(always_flags));
4022}
4023
4024
4025TEST(SuperNoErrors) {
4026 // Tests that parser and preparser accept 'super' keyword in right places.
4027 const char* context_data[][2] = {
4028 {"class C { m() { ", "; } }"},
4029 {"class C { m() { k = ", "; } }"},
4030 {"class C { m() { foo(", "); } }"},
4031 {"class C { m() { () => ", "; } }"},
4032 {NULL, NULL}
4033 };
4034
4035 const char* statement_data[] = {
4036 "super.x",
4037 "super[27]",
4038 "new super.x",
4039 "new super.x()",
4040 "new super[27]",
4041 "new super[27]()",
4042 "z.super", // Ok, property lookup.
4043 NULL
4044 };
4045
4046 static const ParserFlag always_flags[] = {
4047 kAllowHarmonySloppy
4048 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004049 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
4050 always_flags, arraysize(always_flags));
4051}
4052
4053
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004054TEST(SuperErrors) {
4055 const char* context_data[][2] = {
4056 {"class C { m() { ", "; } }"},
4057 {"class C { m() { k = ", "; } }"},
4058 {"class C { m() { foo(", "); } }"},
4059 {"class C { m() { () => ", "; } }"},
4060 {NULL, NULL}
4061 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004062
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004063 const char* expression_data[] = {
4064 "super",
4065 "super = x",
4066 "y = super",
4067 "f(super)",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004068 "new super",
4069 "new super()",
4070 "new super(12, 45)",
4071 "new new super",
4072 "new new super()",
4073 "new new super()()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004074 NULL
4075 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004076
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004077 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4078 RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004079 always_flags, arraysize(always_flags));
4080}
4081
4082
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004083TEST(SuperCall) {
4084 const char* context_data[][2] = {{"", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004085 {NULL, NULL}};
4086
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004087 const char* success_data[] = {
4088 "class C extends B { constructor() { super(); } }",
4089 "class C extends B { constructor() { () => super(); } }",
4090 NULL
4091 };
4092
4093 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4094 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
4095 always_flags, arraysize(always_flags));
4096
4097 const char* error_data[] = {
4098 "class C { constructor() { super(); } }",
4099 "class C { method() { super(); } }",
4100 "class C { method() { () => super(); } }",
4101 "class C { *method() { super(); } }",
4102 "class C { get x() { super(); } }",
4103 "class C { set x(_) { super(); } }",
4104 "({ method() { super(); } })",
4105 "({ *method() { super(); } })",
4106 "({ get x() { super(); } })",
4107 "({ set x(_) { super(); } })",
4108 "({ f: function() { super(); } })",
4109 "(function() { super(); })",
4110 "var f = function() { super(); }",
4111 "({ f: function*() { super(); } })",
4112 "(function*() { super(); })",
4113 "var f = function*() { super(); }",
4114 NULL
4115 };
4116
4117 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
4118 always_flags, arraysize(always_flags));
4119}
4120
4121
4122TEST(SuperNewNoErrors) {
4123 const char* context_data[][2] = {
4124 {"class C { constructor() { ", " } }"},
4125 {"class C { *method() { ", " } }"},
4126 {"class C { get x() { ", " } }"},
4127 {"class C { set x(_) { ", " } }"},
4128 {"({ method() { ", " } })"},
4129 {"({ *method() { ", " } })"},
4130 {"({ get x() { ", " } })"},
4131 {"({ set x(_) { ", " } })"},
4132 {NULL, NULL}
4133 };
4134
4135 const char* expression_data[] = {
4136 "new super.x;",
4137 "new super.x();",
4138 "() => new super.x;",
4139 "() => new super.x();",
4140 NULL
4141 };
4142
4143 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4144 RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
4145 always_flags, arraysize(always_flags));
4146}
4147
4148
4149TEST(SuperNewErrors) {
4150 const char* context_data[][2] = {
4151 {"class C { method() { ", " } }"},
4152 {"class C { *method() { ", " } }"},
4153 {"class C { get x() { ", " } }"},
4154 {"class C { set x(_) { ", " } }"},
4155 {"({ method() { ", " } })"},
4156 {"({ *method() { ", " } })"},
4157 {"({ get x() { ", " } })"},
4158 {"({ set x(_) { ", " } })"},
4159 {"({ f: function() { ", " } })"},
4160 {"(function() { ", " })"},
4161 {"var f = function() { ", " }"},
4162 {"({ f: function*() { ", " } })"},
4163 {"(function*() { ", " })"},
4164 {"var f = function*() { ", " }"},
4165 {NULL, NULL}
4166 };
4167
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004168 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004169 "new super;",
4170 "new super();",
4171 "() => new super;",
4172 "() => new super();",
4173 NULL
4174 };
4175
4176 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4177 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4178 always_flags, arraysize(always_flags));
4179}
4180
4181
4182TEST(SuperErrorsNonMethods) {
4183 // super is only allowed in methods, accessors and constructors.
4184 const char* context_data[][2] = {
4185 {"", ";"},
4186 {"k = ", ";"},
4187 {"foo(", ");"},
4188 {"if (", ") {}"},
4189 {"if (true) {", "}"},
4190 {"if (false) {} else {", "}"},
4191 {"while (true) {", "}"},
4192 {"function f() {", "}"},
4193 {"class C extends (", ") {}"},
4194 {"class C { m() { function f() {", "} } }"},
4195 {"({ m() { function f() {", "} } })"},
4196 {NULL, NULL}
4197 };
4198
4199 const char* statement_data[] = {
4200 "super",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004201 "super = x",
4202 "y = super",
4203 "f(super)",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004204 "super.x",
4205 "super[27]",
4206 "super.x()",
4207 "super[27]()",
4208 "super()",
4209 "new super.x",
4210 "new super.x()",
4211 "new super[27]",
4212 "new super[27]()",
4213 NULL
4214 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004216 static const ParserFlag always_flags[] = {
4217 kAllowHarmonySloppy
4218 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004219 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4220 always_flags, arraysize(always_flags));
4221}
4222
4223
4224TEST(NoErrorsMethodDefinition) {
4225 const char* context_data[][2] = {{"({", "});"},
4226 {"'use strict'; ({", "});"},
4227 {"({*", "});"},
4228 {"'use strict'; ({*", "});"},
4229 {NULL, NULL}};
4230
4231 const char* object_literal_body_data[] = {
4232 "m() {}",
4233 "m(x) { return x; }",
4234 "m(x, y) {}, n() {}",
4235 "set(x, y) {}",
4236 "get(x, y) {}",
4237 NULL
4238 };
4239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004240 RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004241}
4242
4243
4244TEST(MethodDefinitionNames) {
4245 const char* context_data[][2] = {{"({", "(x, y) {}});"},
4246 {"'use strict'; ({", "(x, y) {}});"},
4247 {"({*", "(x, y) {}});"},
4248 {"'use strict'; ({*", "(x, y) {}});"},
4249 {NULL, NULL}};
4250
4251 const char* name_data[] = {
4252 "m",
4253 "'m'",
4254 "\"m\"",
4255 "\"m n\"",
4256 "true",
4257 "false",
4258 "null",
4259 "0",
4260 "1.2",
4261 "1e1",
4262 "1E1",
4263 "1e+1",
4264 "1e-1",
4265
4266 // Keywords
4267 "async",
4268 "await",
4269 "break",
4270 "case",
4271 "catch",
4272 "class",
4273 "const",
4274 "continue",
4275 "debugger",
4276 "default",
4277 "delete",
4278 "do",
4279 "else",
4280 "enum",
4281 "export",
4282 "extends",
4283 "finally",
4284 "for",
4285 "function",
4286 "if",
4287 "implements",
4288 "import",
4289 "in",
4290 "instanceof",
4291 "interface",
4292 "let",
4293 "new",
4294 "package",
4295 "private",
4296 "protected",
4297 "public",
4298 "return",
4299 "static",
4300 "super",
4301 "switch",
4302 "this",
4303 "throw",
4304 "try",
4305 "typeof",
4306 "var",
4307 "void",
4308 "while",
4309 "with",
4310 "yield",
4311 NULL
4312 };
4313
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004314 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004315}
4316
4317
4318TEST(MethodDefinitionStrictFormalParamereters) {
4319 const char* context_data[][2] = {{"({method(", "){}});"},
4320 {"'use strict'; ({method(", "){}});"},
4321 {"({*method(", "){}});"},
4322 {"'use strict'; ({*method(", "){}});"},
4323 {NULL, NULL}};
4324
4325 const char* params_data[] = {
4326 "x, x",
4327 "x, y, x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004328 "var",
4329 "const",
4330 NULL
4331 };
4332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004333 RunParserSyncTest(context_data, params_data, kError);
4334}
4335
4336
4337TEST(MethodDefinitionEvalArguments) {
4338 const char* strict_context_data[][2] =
4339 {{"'use strict'; ({method(", "){}});"},
4340 {"'use strict'; ({*method(", "){}});"},
4341 {NULL, NULL}};
4342 const char* sloppy_context_data[][2] =
4343 {{"({method(", "){}});"},
4344 {"({*method(", "){}});"},
4345 {NULL, NULL}};
4346
4347 const char* data[] = {
4348 "eval",
4349 "arguments",
4350 NULL};
4351
4352 // Fail in strict mode
4353 RunParserSyncTest(strict_context_data, data, kError);
4354
4355 // OK in sloppy mode
4356 RunParserSyncTest(sloppy_context_data, data, kSuccess);
4357}
4358
4359
4360TEST(MethodDefinitionDuplicateEvalArguments) {
4361 const char* context_data[][2] =
4362 {{"'use strict'; ({method(", "){}});"},
4363 {"'use strict'; ({*method(", "){}});"},
4364 {"({method(", "){}});"},
4365 {"({*method(", "){}});"},
4366 {NULL, NULL}};
4367
4368 const char* data[] = {
4369 "eval, eval",
4370 "eval, a, eval",
4371 "arguments, arguments",
4372 "arguments, a, arguments",
4373 NULL};
4374
4375 // In strict mode, the error is using "eval" or "arguments" as parameter names
4376 // In sloppy mode, the error is that eval / arguments are duplicated
4377 RunParserSyncTest(context_data, data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004378}
4379
4380
4381TEST(MethodDefinitionDuplicateProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004382 const char* context_data[][2] = {{"'use strict'; ({", "});"},
4383 {NULL, NULL}};
4384
4385 const char* params_data[] = {
4386 "x: 1, x() {}",
4387 "x() {}, x: 1",
4388 "x() {}, get x() {}",
4389 "x() {}, set x(_) {}",
4390 "x() {}, x() {}",
4391 "x() {}, y() {}, x() {}",
4392 "x() {}, \"x\"() {}",
4393 "x() {}, 'x'() {}",
4394 "0() {}, '0'() {}",
4395 "1.0() {}, 1: 1",
4396
4397 "x: 1, *x() {}",
4398 "*x() {}, x: 1",
4399 "*x() {}, get x() {}",
4400 "*x() {}, set x(_) {}",
4401 "*x() {}, *x() {}",
4402 "*x() {}, y() {}, *x() {}",
4403 "*x() {}, *\"x\"() {}",
4404 "*x() {}, *'x'() {}",
4405 "*0() {}, *'0'() {}",
4406 "*1.0() {}, 1: 1",
4407
4408 NULL
4409 };
4410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004411 RunParserSyncTest(context_data, params_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004412}
4413
4414
4415TEST(ClassExpressionNoErrors) {
4416 const char* context_data[][2] = {{"(", ");"},
4417 {"var C = ", ";"},
4418 {"bar, ", ";"},
4419 {NULL, NULL}};
4420 const char* class_data[] = {
4421 "class {}",
4422 "class name {}",
4423 "class extends F {}",
4424 "class name extends F {}",
4425 "class extends (F, G) {}",
4426 "class name extends (F, G) {}",
4427 "class extends class {} {}",
4428 "class name extends class {} {}",
4429 "class extends class base {} {}",
4430 "class name extends class base {} {}",
4431 NULL};
4432
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004433 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004434 RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
4435 always_flags, arraysize(always_flags));
4436}
4437
4438
4439TEST(ClassDeclarationNoErrors) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004440 const char* context_data[][2] = {{"'use strict'; ", ""},
4441 {"'use strict'; {", "}"},
4442 {"'use strict'; if (true) {", "}"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004443 {NULL, NULL}};
4444 const char* statement_data[] = {
4445 "class name {}",
4446 "class name extends F {}",
4447 "class name extends (F, G) {}",
4448 "class name extends class {} {}",
4449 "class name extends class base {} {}",
4450 NULL};
4451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004452 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004453}
4454
4455
4456TEST(ClassBodyNoErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004457 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004458 // Tests that parser and preparser accept valid class syntax.
4459 const char* context_data[][2] = {{"(class {", "});"},
4460 {"(class extends Base {", "});"},
4461 {"class C {", "}"},
4462 {"class C extends Base {", "}"},
4463 {NULL, NULL}};
4464 const char* class_body_data[] = {
4465 ";",
4466 ";;",
4467 "m() {}",
4468 "m() {};",
4469 "; m() {}",
4470 "m() {}; n(x) {}",
4471 "get x() {}",
4472 "set x(v) {}",
4473 "get() {}",
4474 "set() {}",
4475 "*g() {}",
4476 "*g() {};",
4477 "; *g() {}",
4478 "*g() {}; *h(x) {}",
4479 "static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004480 "get static() {}",
4481 "set static(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004482 "static m() {}",
4483 "static get x() {}",
4484 "static set x(v) {}",
4485 "static get() {}",
4486 "static set() {}",
4487 "static static() {}",
4488 "static get static() {}",
4489 "static set static(v) {}",
4490 "*static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004491 "static *static() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004492 "*get() {}",
4493 "*set() {}",
4494 "static *g() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004495
4496 // Escaped 'static' should be allowed anywhere
4497 // static-as-PropertyName is.
4498 "st\\u0061tic() {}",
4499 "get st\\u0061tic() {}",
4500 "set st\\u0061tic(v) {}",
4501 "static st\\u0061tic() {}",
4502 "static get st\\u0061tic() {}",
4503 "static set st\\u0061tic(v) {}",
4504 "*st\\u0061tic() {}",
4505 "static *st\\u0061tic() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004506 NULL};
Ben Murdoch097c5b22016-05-18 11:27:45 +01004507 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004508
4509 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004510 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004511 };
4512 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4513 always_flags, arraysize(always_flags));
4514}
4515
4516
4517TEST(ClassPropertyNameNoErrors) {
4518 const char* context_data[][2] = {{"(class {", "() {}});"},
4519 {"(class { get ", "() {}});"},
4520 {"(class { set ", "(v) {}});"},
4521 {"(class { static ", "() {}});"},
4522 {"(class { static get ", "() {}});"},
4523 {"(class { static set ", "(v) {}});"},
4524 {"(class { *", "() {}});"},
4525 {"(class { static *", "() {}});"},
4526 {"class C {", "() {}}"},
4527 {"class C { get ", "() {}}"},
4528 {"class C { set ", "(v) {}}"},
4529 {"class C { static ", "() {}}"},
4530 {"class C { static get ", "() {}}"},
4531 {"class C { static set ", "(v) {}}"},
4532 {"class C { *", "() {}}"},
4533 {"class C { static *", "() {}}"},
4534 {NULL, NULL}};
4535 const char* name_data[] = {
4536 "42",
4537 "42.5",
4538 "42e2",
4539 "42e+2",
4540 "42e-2",
4541 "null",
4542 "false",
4543 "true",
4544 "'str'",
4545 "\"str\"",
4546 "static",
4547 "get",
4548 "set",
4549 "var",
4550 "const",
4551 "let",
4552 "this",
4553 "class",
4554 "function",
4555 "yield",
4556 "if",
4557 "else",
4558 "for",
4559 "while",
4560 "do",
4561 "try",
4562 "catch",
4563 "finally",
4564 NULL};
4565
4566 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004567 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004568 };
4569 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
4570 always_flags, arraysize(always_flags));
4571}
4572
4573
4574TEST(ClassExpressionErrors) {
4575 const char* context_data[][2] = {{"(", ");"},
4576 {"var C = ", ";"},
4577 {"bar, ", ";"},
4578 {NULL, NULL}};
4579 const char* class_data[] = {
4580 "class",
4581 "class name",
4582 "class name extends",
4583 "class extends",
4584 "class {",
4585 "class { m }",
4586 "class { m; n }",
4587 "class { m: 1 }",
4588 "class { m(); n() }",
4589 "class { get m }",
4590 "class { get m() }",
4591 "class { get m() { }",
4592 "class { set m() {} }", // Missing required parameter.
4593 "class { m() {}, n() {} }", // No commas allowed.
4594 NULL};
4595
4596 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004597 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004598 };
4599 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4600 always_flags, arraysize(always_flags));
4601}
4602
4603
4604TEST(ClassDeclarationErrors) {
4605 const char* context_data[][2] = {{"", ""},
4606 {"{", "}"},
4607 {"if (true) {", "}"},
4608 {NULL, NULL}};
4609 const char* class_data[] = {
4610 "class",
4611 "class name",
4612 "class name extends",
4613 "class extends",
4614 "class name {",
4615 "class name { m }",
4616 "class name { m; n }",
4617 "class name { m: 1 }",
4618 "class name { m(); n() }",
4619 "class name { get x }",
4620 "class name { get x() }",
4621 "class name { set x() {) }", // missing required param
4622 "class {}", // Name is required for declaration
4623 "class extends base {}",
4624 "class name { *",
4625 "class name { * }",
4626 "class name { *; }",
4627 "class name { *get x() {} }",
4628 "class name { *set x(_) {} }",
4629 "class name { *static m() {} }",
4630 NULL};
4631
4632 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004633 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004634 };
4635 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4636 always_flags, arraysize(always_flags));
4637}
4638
4639
4640TEST(ClassNameErrors) {
4641 const char* context_data[][2] = {{"class ", "{}"},
4642 {"(class ", "{});"},
4643 {"'use strict'; class ", "{}"},
4644 {"'use strict'; (class ", "{});"},
4645 {NULL, NULL}};
4646 const char* class_name[] = {
4647 "arguments",
4648 "eval",
4649 "implements",
4650 "interface",
4651 "let",
4652 "package",
4653 "private",
4654 "protected",
4655 "public",
4656 "static",
4657 "var",
4658 "yield",
4659 NULL};
4660
4661 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004662 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004663 };
4664 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4665 always_flags, arraysize(always_flags));
4666}
4667
4668
4669TEST(ClassGetterParamNameErrors) {
4670 const char* context_data[][2] = {
4671 {"class C { get name(", ") {} }"},
4672 {"(class { get name(", ") {} });"},
4673 {"'use strict'; class C { get name(", ") {} }"},
4674 {"'use strict'; (class { get name(", ") {} })"},
4675 {NULL, NULL}
4676 };
4677
4678 const char* class_name[] = {
4679 "arguments",
4680 "eval",
4681 "implements",
4682 "interface",
4683 "let",
4684 "package",
4685 "private",
4686 "protected",
4687 "public",
4688 "static",
4689 "var",
4690 "yield",
4691 NULL};
4692
4693 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004694 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004695 };
4696 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4697 always_flags, arraysize(always_flags));
4698}
4699
4700
4701TEST(ClassStaticPrototypeErrors) {
4702 const char* context_data[][2] = {{"class C {", "}"},
4703 {"(class {", "});"},
4704 {NULL, NULL}};
4705
4706 const char* class_body_data[] = {
4707 "static prototype() {}",
4708 "static get prototype() {}",
4709 "static set prototype(_) {}",
4710 "static *prototype() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004711 "static 'prototype'() {}",
4712 "static *'prototype'() {}",
4713 "static prot\\u006ftype() {}",
4714 "static 'prot\\u006ftype'() {}",
4715 "static get 'prot\\u006ftype'() {}",
4716 "static set 'prot\\u006ftype'(_) {}",
4717 "static *'prot\\u006ftype'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004718 NULL};
4719
4720 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004721 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004722 };
4723 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4724 always_flags, arraysize(always_flags));
4725}
4726
4727
4728TEST(ClassSpecialConstructorErrors) {
4729 const char* context_data[][2] = {{"class C {", "}"},
4730 {"(class {", "});"},
4731 {NULL, NULL}};
4732
4733 const char* class_body_data[] = {
4734 "get constructor() {}",
4735 "get constructor(_) {}",
4736 "*constructor() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004737 "get 'constructor'() {}",
4738 "*'constructor'() {}",
4739 "get c\\u006fnstructor() {}",
4740 "*c\\u006fnstructor() {}",
4741 "get 'c\\u006fnstructor'() {}",
4742 "get 'c\\u006fnstructor'(_) {}",
4743 "*'c\\u006fnstructor'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004744 NULL};
4745
4746 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004747 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004748 };
4749 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4750 always_flags, arraysize(always_flags));
4751}
4752
4753
4754TEST(ClassConstructorNoErrors) {
4755 const char* context_data[][2] = {{"class C {", "}"},
4756 {"(class {", "});"},
4757 {NULL, NULL}};
4758
4759 const char* class_body_data[] = {
4760 "constructor() {}",
4761 "static constructor() {}",
4762 "static get constructor() {}",
4763 "static set constructor(_) {}",
4764 "static *constructor() {}",
4765 NULL};
4766
4767 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004768 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004769 };
4770 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4771 always_flags, arraysize(always_flags));
4772}
4773
4774
4775TEST(ClassMultipleConstructorErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004776 const char* context_data[][2] = {{"class C {", "}"},
4777 {"(class {", "});"},
4778 {NULL, NULL}};
4779
4780 const char* class_body_data[] = {
4781 "constructor() {}; constructor() {}",
4782 NULL};
4783
4784 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004785 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004786 };
4787 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4788 always_flags, arraysize(always_flags));
4789}
4790
4791
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004792TEST(ClassMultiplePropertyNamesNoErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004793 const char* context_data[][2] = {{"class C {", "}"},
4794 {"(class {", "});"},
4795 {NULL, NULL}};
4796
4797 const char* class_body_data[] = {
4798 "constructor() {}; static constructor() {}",
4799 "m() {}; static m() {}",
4800 "m() {}; m() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004801 "static m() {}; static m() {}",
4802 "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004803 NULL};
4804
4805 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004806 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004807 };
4808 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4809 always_flags, arraysize(always_flags));
4810}
4811
4812
4813TEST(ClassesAreStrictErrors) {
4814 const char* context_data[][2] = {{"", ""},
4815 {"(", ");"},
4816 {NULL, NULL}};
4817
4818 const char* class_body_data[] = {
4819 "class C { method() { with ({}) {} } }",
4820 "class C extends function() { with ({}) {} } {}",
4821 "class C { *method() { with ({}) {} } }",
4822 NULL};
4823
4824 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004825 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004826 };
4827 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4828 always_flags, arraysize(always_flags));
Ben Murdoch692be652012-01-10 18:47:50 +00004829}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004830
4831
4832TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4833 const char* context_data[][2] = {{"({", "});"},
4834 {"'use strict'; ({", "});"},
4835 {NULL, NULL}};
4836
4837 const char* name_data[] = {
4838 "break",
4839 "case",
4840 "catch",
4841 "class",
4842 "const",
4843 "continue",
4844 "debugger",
4845 "default",
4846 "delete",
4847 "do",
4848 "else",
4849 "enum",
4850 "export",
4851 "extends",
4852 "false",
4853 "finally",
4854 "for",
4855 "function",
4856 "if",
4857 "import",
4858 "in",
4859 "instanceof",
4860 "new",
4861 "null",
4862 "return",
4863 "super",
4864 "switch",
4865 "this",
4866 "throw",
4867 "true",
4868 "try",
4869 "typeof",
4870 "var",
4871 "void",
4872 "while",
4873 "with",
4874 NULL
4875 };
4876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004877 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004878}
4879
4880
4881TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4882 const char* context_data[][2] = {{"({", "});"},
4883 {NULL, NULL}};
4884
4885 const char* name_data[] = {
4886 "implements",
4887 "interface",
4888 "let",
4889 "package",
4890 "private",
4891 "protected",
4892 "public",
4893 "static",
4894 "yield",
4895 NULL
4896 };
4897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004898 RunParserSyncTest(context_data, name_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004899
4900 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4901 {NULL, NULL}};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004902 RunParserSyncTest(context_strict_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004903}
4904
4905
4906TEST(ObjectLiteralPropertyShorthandError) {
4907 const char* context_data[][2] = {{"({", "});"},
4908 {"'use strict'; ({", "});"},
4909 {NULL, NULL}};
4910
4911 const char* name_data[] = {
4912 "1",
4913 "1.2",
4914 "0",
4915 "0.1",
4916 "1.0",
4917 "1e1",
4918 "0x1",
4919 "\"s\"",
4920 "'s'",
4921 NULL
4922 };
4923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004924 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004925}
4926
4927
4928TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4929 const char* context_data[][2] = {{"", ""},
4930 {NULL, NULL}};
4931
4932 const char* name_data[] = {
4933 "function* g() { ({yield}); }",
4934 NULL
4935 };
4936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004937 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004938}
4939
4940
4941TEST(ConstParsingInForIn) {
4942 const char* context_data[][2] = {{"'use strict';", ""},
4943 {"function foo(){ 'use strict';", "}"},
4944 {NULL, NULL}};
4945
4946 const char* data[] = {
4947 "for(const x = 1; ; ) {}",
4948 "for(const x = 1, y = 2;;){}",
4949 "for(const x in [1,2,3]) {}",
4950 "for(const x of [1,2,3]) {}",
4951 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004952 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004953}
4954
4955
Ben Murdoch097c5b22016-05-18 11:27:45 +01004956TEST(StatementParsingInForIn) {
4957 const char* context_data[][2] = {{"", ""},
4958 {"'use strict';", ""},
4959 {"function foo(){ 'use strict';", "}"},
4960 {NULL, NULL}};
4961
4962 const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
4963 "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
4964 NULL};
4965
4966 static const ParserFlag always_flags[] = {
4967 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
4968 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
4969 arraysize(always_flags));
4970}
4971
4972
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004973TEST(ConstParsingInForInError) {
4974 const char* context_data[][2] = {{"'use strict';", ""},
4975 {"function foo(){ 'use strict';", "}"},
4976 {NULL, NULL}};
4977
4978 const char* data[] = {
4979 "for(const x,y = 1; ; ) {}",
4980 "for(const x = 4 in [1,2,3]) {}",
4981 "for(const x = 4, y in [1,2,3]) {}",
4982 "for(const x = 4 of [1,2,3]) {}",
4983 "for(const x = 4, y of [1,2,3]) {}",
4984 "for(const x = 1, y = 2 in []) {}",
4985 "for(const x,y in []) {}",
4986 "for(const x = 1, y = 2 of []) {}",
4987 "for(const x,y of []) {}",
4988 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004989 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
4990}
4991
4992
4993TEST(InitializedDeclarationsInStrictForInError) {
4994 const char* context_data[][2] = {{"'use strict';", ""},
4995 {"function foo(){ 'use strict';", "}"},
4996 {NULL, NULL}};
4997
4998 const char* data[] = {
4999 "for (var i = 1 in {}) {}",
5000 "for (var i = void 0 in [1, 2, 3]) {}",
5001 "for (let i = 1 in {}) {}",
5002 "for (let i = void 0 in [1, 2, 3]) {}",
5003 "for (const i = 1 in {}) {}",
5004 "for (const i = void 0 in [1, 2, 3]) {}",
5005 NULL};
5006 RunParserSyncTest(context_data, data, kError);
5007}
5008
5009
5010TEST(InitializedDeclarationsInStrictForOfError) {
5011 const char* context_data[][2] = {{"'use strict';", ""},
5012 {"function foo(){ 'use strict';", "}"},
5013 {NULL, NULL}};
5014
5015 const char* data[] = {
5016 "for (var i = 1 of {}) {}",
5017 "for (var i = void 0 of [1, 2, 3]) {}",
5018 "for (let i = 1 of {}) {}",
5019 "for (let i = void 0 of [1, 2, 3]) {}",
5020 "for (const i = 1 of {}) {}",
5021 "for (const i = void 0 of [1, 2, 3]) {}",
5022 NULL};
5023 RunParserSyncTest(context_data, data, kError);
5024}
5025
5026
5027TEST(InitializedDeclarationsInSloppyForInError) {
5028 const char* context_data[][2] = {{"", ""},
5029 {"function foo(){", "}"},
5030 {NULL, NULL}};
5031
5032 const char* data[] = {
5033 "for (var i = 1 in {}) {}",
5034 "for (var i = void 0 in [1, 2, 3]) {}",
5035 NULL};
5036 // TODO(caitp): This should be an error in sloppy mode.
5037 RunParserSyncTest(context_data, data, kSuccess);
5038}
5039
5040
5041TEST(InitializedDeclarationsInSloppyForOfError) {
5042 const char* context_data[][2] = {{"", ""},
5043 {"function foo(){", "}"},
5044 {NULL, NULL}};
5045
5046 const char* data[] = {
5047 "for (var i = 1 of {}) {}",
5048 "for (var i = void 0 of [1, 2, 3]) {}",
5049 NULL};
5050 RunParserSyncTest(context_data, data, kError);
5051}
5052
5053
5054TEST(ForInMultipleDeclarationsError) {
5055 const char* context_data[][2] = {{"", ""},
5056 {"function foo(){", "}"},
5057 {"'use strict';", ""},
5058 {"function foo(){ 'use strict';", "}"},
5059 {NULL, NULL}};
5060
5061 const char* data[] = {
5062 "for (var i, j in {}) {}",
5063 "for (var i, j in [1, 2, 3]) {}",
5064 "for (var i, j = 1 in {}) {}",
5065 "for (var i, j = void 0 in [1, 2, 3]) {}",
5066
5067 "for (let i, j in {}) {}",
5068 "for (let i, j in [1, 2, 3]) {}",
5069 "for (let i, j = 1 in {}) {}",
5070 "for (let i, j = void 0 in [1, 2, 3]) {}",
5071
5072 "for (const i, j in {}) {}",
5073 "for (const i, j in [1, 2, 3]) {}",
5074 "for (const i, j = 1 in {}) {}",
5075 "for (const i, j = void 0 in [1, 2, 3]) {}",
5076 NULL};
5077 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5078 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5079 arraysize(always_flags));
5080}
5081
5082
5083TEST(ForOfMultipleDeclarationsError) {
5084 const char* context_data[][2] = {{"", ""},
5085 {"function foo(){", "}"},
5086 {"'use strict';", ""},
5087 {"function foo(){ 'use strict';", "}"},
5088 {NULL, NULL}};
5089
5090 const char* data[] = {
5091 "for (var i, j of {}) {}",
5092 "for (var i, j of [1, 2, 3]) {}",
5093 "for (var i, j = 1 of {}) {}",
5094 "for (var i, j = void 0 of [1, 2, 3]) {}",
5095
5096 "for (let i, j of {}) {}",
5097 "for (let i, j of [1, 2, 3]) {}",
5098 "for (let i, j = 1 of {}) {}",
5099 "for (let i, j = void 0 of [1, 2, 3]) {}",
5100
5101 "for (const i, j of {}) {}",
5102 "for (const i, j of [1, 2, 3]) {}",
5103 "for (const i, j = 1 of {}) {}",
5104 "for (const i, j = void 0 of [1, 2, 3]) {}",
5105 NULL};
5106 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5107 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5108 arraysize(always_flags));
5109}
5110
5111
5112TEST(ForInNoDeclarationsError) {
5113 const char* context_data[][2] = {{"", ""},
5114 {"function foo(){", "}"},
5115 {"'use strict';", ""},
5116 {"function foo(){ 'use strict';", "}"},
5117 {NULL, NULL}};
5118
5119 const char* data[] = {
5120 "for (var in {}) {}",
5121 "for (const in {}) {}",
5122 NULL};
5123 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5124 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5125 arraysize(always_flags));
5126}
5127
5128
5129TEST(ForOfNoDeclarationsError) {
5130 const char* context_data[][2] = {{"", ""},
5131 {"function foo(){", "}"},
5132 {"'use strict';", ""},
5133 {"function foo(){ 'use strict';", "}"},
5134 {NULL, NULL}};
5135
5136 const char* data[] = {
5137 "for (var of [1, 2, 3]) {}",
5138 "for (const of [1, 2, 3]) {}",
5139 NULL};
5140 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5141 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005142 arraysize(always_flags));
5143}
5144
5145
Ben Murdoch097c5b22016-05-18 11:27:45 +01005146TEST(ForOfInOperator) {
5147 const char* context_data[][2] = {{"", ""},
5148 {"'use strict';", ""},
5149 {"function foo(){ 'use strict';", "}"},
5150 {NULL, NULL}};
5151
5152 const char* data[] = {
5153 "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
5154 "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
5155
5156 static const ParserFlag always_flags[] = {
5157 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
5158 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5159 arraysize(always_flags));
5160}
5161
5162
5163TEST(ForOfYieldIdentifier) {
5164 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5165
5166 const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
5167 "for(let x of yield) {}", "for(const x of yield) {}",
5168 NULL};
5169
5170 static const ParserFlag always_flags[] = {
5171 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
5172 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5173 arraysize(always_flags));
5174}
5175
5176
5177TEST(ForOfYieldExpression) {
5178 const char* context_data[][2] = {{"", ""},
5179 {"'use strict';", ""},
5180 {"function foo(){ 'use strict';", "}"},
5181 {NULL, NULL}};
5182
5183 const char* data[] = {"function* g() { for(x of yield) {} }",
5184 "function* g() { for(var x of yield) {} }",
5185 "function* g() { for(let x of yield) {} }",
5186 "function* g() { for(const x of yield) {} }", NULL};
5187
5188 static const ParserFlag always_flags[] = {
5189 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
5190 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5191 arraysize(always_flags));
5192}
5193
5194
5195TEST(ForOfExpressionError) {
5196 const char* context_data[][2] = {{"", ""},
5197 {"'use strict';", ""},
5198 {"function foo(){ 'use strict';", "}"},
5199 {NULL, NULL}};
5200
5201 const char* data[] = {
5202 "for(x of [], []) {}", "for(var x of [], []) {}",
5203 "for(let x of [], []) {}", "for(const x of [], []) {}",
5204
5205 // AssignmentExpression should be validated statically:
5206 "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
5207 "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
5208
5209 static const ParserFlag always_flags[] = {
5210 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
5211 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5212 arraysize(always_flags));
5213}
5214
5215
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005216TEST(InvalidUnicodeEscapes) {
5217 const char* context_data[][2] = {{"", ""},
5218 {"'use strict';", ""},
5219 {NULL, NULL}};
5220 const char* data[] = {
5221 "var foob\\u123r = 0;",
5222 "var \\u123roo = 0;",
5223 "\"foob\\u123rr\"",
5224 // No escapes allowed in regexp flags
5225 "/regex/\\u0069g",
5226 "/regex/\\u006g",
5227 // Braces gone wrong
5228 "var foob\\u{c481r = 0;",
5229 "var foob\\uc481}r = 0;",
5230 "var \\u{0052oo = 0;",
5231 "var \\u0052}oo = 0;",
5232 "\"foob\\u{c481r\"",
5233 "var foob\\u{}ar = 0;",
5234 // Too high value for the unicode escape
5235 "\"\\u{110000}\"",
5236 // Not an unicode escape
5237 "var foob\\v1234r = 0;",
5238 "var foob\\U1234r = 0;",
5239 "var foob\\v{1234}r = 0;",
5240 "var foob\\U{1234}r = 0;",
5241 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005242 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005243}
5244
5245
5246TEST(UnicodeEscapes) {
5247 const char* context_data[][2] = {{"", ""},
5248 {"'use strict';", ""},
5249 {NULL, NULL}};
5250 const char* data[] = {
5251 // Identifier starting with escape
5252 "var \\u0052oo = 0;",
5253 "var \\u{0052}oo = 0;",
5254 "var \\u{52}oo = 0;",
5255 "var \\u{00000000052}oo = 0;",
5256 // Identifier with an escape but not starting with an escape
5257 "var foob\\uc481r = 0;",
5258 "var foob\\u{c481}r = 0;",
5259 // String with an escape
5260 "\"foob\\uc481r\"",
5261 "\"foob\\{uc481}r\"",
5262 // This character is a valid unicode character, representable as a surrogate
5263 // pair, not representable as 4 hex digits.
5264 "\"foo\\u{10e6d}\"",
5265 // Max value for the unicode escape
5266 "\"\\u{10ffff}\"",
5267 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005268 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005269}
5270
5271
5272TEST(ScanTemplateLiterals) {
5273 const char* context_data[][2] = {{"'use strict';", ""},
5274 {"function foo(){ 'use strict';"
5275 " var a, b, c; return ", "}"},
5276 {NULL, NULL}};
5277
5278 const char* data[] = {
5279 "``",
5280 "`no-subst-template`",
5281 "`template-head${a}`",
5282 "`${a}`",
5283 "`${a}template-tail`",
5284 "`template-head${a}template-tail`",
5285 "`${a}${b}${c}`",
5286 "`a${a}b${b}c${c}`",
5287 "`${a}a${b}b${c}c`",
5288 "`foo\n\nbar\r\nbaz`",
5289 "`foo\n\n${ bar }\r\nbaz`",
5290 "`foo${a /* comment */}`",
5291 "`foo${a // comment\n}`",
5292 "`foo${a \n}`",
5293 "`foo${a \r\n}`",
5294 "`foo${a \r}`",
5295 "`foo${/* comment */ a}`",
5296 "`foo${// comment\na}`",
5297 "`foo${\n a}`",
5298 "`foo${\r\n a}`",
5299 "`foo${\r a}`",
5300 "`foo${'a' in a}`",
5301 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005302 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005303}
5304
5305
5306TEST(ScanTaggedTemplateLiterals) {
5307 const char* context_data[][2] = {{"'use strict';", ""},
5308 {"function foo(){ 'use strict';"
5309 " function tag() {}"
5310 " var a, b, c; return ", "}"},
5311 {NULL, NULL}};
5312
5313 const char* data[] = {
5314 "tag ``",
5315 "tag `no-subst-template`",
5316 "tag`template-head${a}`",
5317 "tag `${a}`",
5318 "tag `${a}template-tail`",
5319 "tag `template-head${a}template-tail`",
5320 "tag\n`${a}${b}${c}`",
5321 "tag\r\n`a${a}b${b}c${c}`",
5322 "tag `${a}a${b}b${c}c`",
5323 "tag\t`foo\n\nbar\r\nbaz`",
5324 "tag\r`foo\n\n${ bar }\r\nbaz`",
5325 "tag`foo${a /* comment */}`",
5326 "tag`foo${a // comment\n}`",
5327 "tag`foo${a \n}`",
5328 "tag`foo${a \r\n}`",
5329 "tag`foo${a \r}`",
5330 "tag`foo${/* comment */ a}`",
5331 "tag`foo${// comment\na}`",
5332 "tag`foo${\n a}`",
5333 "tag`foo${\r\n a}`",
5334 "tag`foo${\r a}`",
5335 "tag`foo${'a' in a}`",
5336 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005337 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005338}
5339
5340
5341TEST(TemplateMaterializedLiterals) {
5342 const char* context_data[][2] = {
5343 {
5344 "'use strict';\n"
5345 "function tag() {}\n"
5346 "var a, b, c;\n"
5347 "(", ")"
5348 },
5349 {NULL, NULL}
5350 };
5351
5352 const char* data[] = {
5353 "tag``",
5354 "tag`a`",
5355 "tag`a${1}b`",
5356 "tag`a${1}b${2}c`",
5357 "``",
5358 "`a`",
5359 "`a${1}b`",
5360 "`a${1}b${2}c`",
5361 NULL
5362 };
5363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005364 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005365}
5366
5367
5368TEST(ScanUnterminatedTemplateLiterals) {
5369 const char* context_data[][2] = {{"'use strict';", ""},
5370 {"function foo(){ 'use strict';"
5371 " var a, b, c; return ", "}"},
5372 {NULL, NULL}};
5373
5374 const char* data[] = {
5375 "`no-subst-template",
5376 "`template-head${a}",
5377 "`${a}template-tail",
5378 "`template-head${a}template-tail",
5379 "`${a}${b}${c}",
5380 "`a${a}b${b}c${c}",
5381 "`${a}a${b}b${c}c",
5382 "`foo\n\nbar\r\nbaz",
5383 "`foo\n\n${ bar }\r\nbaz",
5384 "`foo${a /* comment } */`",
5385 "`foo${a /* comment } `*/",
5386 "`foo${a // comment}`",
5387 "`foo${a \n`",
5388 "`foo${a \r\n`",
5389 "`foo${a \r`",
5390 "`foo${/* comment */ a`",
5391 "`foo${// commenta}`",
5392 "`foo${\n a`",
5393 "`foo${\r\n a`",
5394 "`foo${\r a`",
5395 "`foo${fn(}`",
5396 "`foo${1 if}`",
5397 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005398 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005399}
5400
5401
5402TEST(TemplateLiteralsIllegalTokens) {
5403 const char* context_data[][2] = {{"'use strict';", ""},
5404 {"function foo(){ 'use strict';"
5405 " var a, b, c; return ", "}"},
5406 {NULL, NULL}};
5407 const char* data[] = {
5408 "`hello\\x`",
5409 "`hello\\x${1}`",
5410 "`hello${1}\\x`",
5411 "`hello${1}\\x${2}`",
5412 "`hello\\x\n`",
5413 "`hello\\x\n${1}`",
5414 "`hello${1}\\x\n`",
5415 "`hello${1}\\x\n${2}`",
5416 NULL};
5417
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005418 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5419}
5420
5421
5422TEST(ParseRestParameters) {
5423 const char* context_data[][2] = {{"'use strict';(function(",
5424 "){ return args;})(1, [], /regexp/, 'str',"
5425 "function(){});"},
5426 {"(function(", "){ return args;})(1, [],"
5427 "/regexp/, 'str', function(){});"},
5428 {NULL, NULL}};
5429
5430 const char* data[] = {"...args",
5431 "a, ...args",
5432 "... args",
5433 "a, ... args",
5434 "...\targs",
5435 "a, ...\targs",
5436 "...\r\nargs",
5437 "a, ...\r\nargs",
5438 "...\rargs",
5439 "a, ...\rargs",
5440 "...\t\n\t\t\n args",
5441 "a, ... \n \n args",
5442 "...{ length, 0: a, 1: b}",
5443 "...{}",
5444 "...[a, b]",
5445 "...[]",
5446 "...[...[a, b, ...c]]",
5447 NULL};
5448 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
5449 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005450 arraysize(always_flags));
5451}
5452
5453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005454TEST(ParseRestParametersErrors) {
5455 const char* context_data[][2] = {{"'use strict';(function(",
5456 "){ return args;}(1, [], /regexp/, 'str',"
5457 "function(){});"},
5458 {"(function(", "){ return args;}(1, [],"
5459 "/regexp/, 'str', function(){});"},
5460 {NULL, NULL}};
5461
5462 const char* data[] = {
5463 "...args, b",
5464 "a, ...args, b",
5465 "...args, b",
5466 "a, ...args, b",
5467 "...args,\tb",
5468 "a,...args\t,b",
5469 "...args\r\n, b",
5470 "a, ... args,\r\nb",
5471 "...args\r,b",
5472 "a, ... args,\rb",
5473 "...args\t\n\t\t\n, b",
5474 "a, ... args, \n \n b",
5475 "a, a, ...args",
5476 "a,\ta, ...args",
5477 "a,\ra, ...args",
5478 "a,\na, ...args",
5479 NULL};
5480 RunParserSyncTest(context_data, data, kError);
5481}
5482
5483
5484TEST(RestParameterInSetterMethodError) {
5485 const char* context_data[][2] = {
5486 {"'use strict';({ set prop(", ") {} }).prop = 1;"},
5487 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
5488 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
5489 {"({ set prop(", ") {} }).prop = 1;"},
5490 {"(class { static set prop(", ") {} }).prop = 1;"},
5491 {"(new (class { set prop(", ") {} })).prop = 1;"},
5492 {nullptr, nullptr}};
5493 const char* data[] = {"...a", "...arguments", "...eval", nullptr};
5494
5495 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5496 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5497 arraysize(always_flags));
5498}
5499
5500
5501TEST(RestParametersEvalArguments) {
5502 const char* strict_context_data[][2] =
5503 {{"'use strict';(function(",
5504 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5505 {NULL, NULL}};
5506 const char* sloppy_context_data[][2] =
5507 {{"(function(",
5508 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5509 {NULL, NULL}};
5510
5511 const char* data[] = {
5512 "...eval",
5513 "eval, ...args",
5514 "...arguments",
5515 "arguments, ...args",
5516 NULL};
5517
5518 // Fail in strict mode
5519 RunParserSyncTest(strict_context_data, data, kError);
5520
5521 // OK in sloppy mode
5522 RunParserSyncTest(sloppy_context_data, data, kSuccess);
5523}
5524
5525
5526TEST(RestParametersDuplicateEvalArguments) {
5527 const char* context_data[][2] =
5528 {{"'use strict';(function(",
5529 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5530 {"(function(",
5531 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5532 {NULL, NULL}};
5533
5534 const char* data[] = {
5535 "eval, ...eval",
5536 "eval, eval, ...args",
5537 "arguments, ...arguments",
5538 "arguments, arguments, ...args",
5539 NULL};
5540
5541 // In strict mode, the error is using "eval" or "arguments" as parameter names
5542 // In sloppy mode, the error is that eval / arguments are duplicated
5543 RunParserSyncTest(context_data, data, kError);
5544}
5545
5546
5547TEST(SpreadCall) {
5548 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5549 {"function fn() {} fn(", ");"},
5550 {NULL, NULL}};
5551
5552 const char* data[] = {
5553 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
5554 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
5555 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
5556 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
5557 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
5558 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
5559
5560 RunParserSyncTest(context_data, data, kSuccess);
5561}
5562
5563
5564TEST(SpreadCallErrors) {
5565 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5566 {"function fn() {} fn(", ");"},
5567 {NULL, NULL}};
5568
5569 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
5570
5571 RunParserSyncTest(context_data, data, kError);
5572}
5573
5574
5575TEST(BadRestSpread) {
5576 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
5577 {"function fn() { ", "} fn();"},
5578 {NULL, NULL}};
5579 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];",
5580 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
5581 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}",
5582 NULL};
5583 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5584}
5585
5586
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005587TEST(LexicalScopingSloppyMode) {
5588 const char* context_data[][2] = {
5589 {"", ""},
5590 {"function f() {", "}"},
5591 {"{", "}"},
5592 {NULL, NULL}};
5593 const char* bad_data[] = {
5594 "let x = 1;",
5595 "for(let x = 1;;){}",
5596 "for(let x of []){}",
5597 "for(let x in []){}",
5598 "class C {}",
5599 "class C extends D {}",
5600 "(class {})",
5601 "(class extends D {})",
5602 "(class C {})",
5603 "(class C extends D {})",
5604 NULL};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005605 static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005606 RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005607 always_false_flags, arraysize(always_false_flags));
5608
5609 const char* good_data[] = {
5610 "let = 1;",
5611 "for(let = 1;;){}",
5612 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005613 RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005614 always_false_flags, arraysize(always_false_flags));
5615}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005616
5617
5618TEST(ComputedPropertyName) {
5619 const char* context_data[][2] = {{"({[", "]: 1});"},
5620 {"({get [", "]() {}});"},
5621 {"({set [", "](_) {}});"},
5622 {"({[", "]() {}});"},
5623 {"({*[", "]() {}});"},
5624 {"(class {get [", "]() {}});"},
5625 {"(class {set [", "](_) {}});"},
5626 {"(class {[", "]() {}});"},
5627 {"(class {*[", "]() {}});"},
5628 {NULL, NULL}};
5629 const char* error_data[] = {
5630 "1, 2",
5631 "var name",
5632 NULL};
5633
5634 static const ParserFlag always_flags[] = {
5635 kAllowHarmonySloppy,
5636 };
5637 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5638 always_flags, arraysize(always_flags));
5639
5640 const char* name_data[] = {
5641 "1",
5642 "1 + 2",
5643 "'name'",
5644 "\"name\"",
5645 "[]",
5646 "{}",
5647 NULL};
5648
5649 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
5650 always_flags, arraysize(always_flags));
5651}
5652
5653
5654TEST(ComputedPropertyNameShorthandError) {
5655 const char* context_data[][2] = {{"({", "});"},
5656 {NULL, NULL}};
5657 const char* error_data[] = {
5658 "a: 1, [2]",
5659 "[1], a: 1",
5660 NULL};
5661
5662 static const ParserFlag always_flags[] = {
5663 kAllowHarmonySloppy,
5664 };
5665 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5666 always_flags, arraysize(always_flags));
5667}
5668
5669
5670TEST(BasicImportExportParsing) {
5671 i::FLAG_harmony_modules = true;
5672
Ben Murdoch097c5b22016-05-18 11:27:45 +01005673 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005674 const char* kSources[] = {
5675 "export let x = 0;",
5676 "export var y = 0;",
5677 "export const z = 0;",
5678 "export function func() { };",
5679 "export class C { };",
5680 "export { };",
5681 "function f() {}; f(); export { f };",
5682 "var a, b, c; export { a, b as baz, c };",
5683 "var d, e; export { d as dreary, e, };",
5684 "export default function f() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005685 "export default function() {}",
5686 "export default function*() {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005687 "export default class C {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005688 "export default class {}"
5689 "export default class extends C {}"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005690 "export default 42",
5691 "var x; export default x = 7",
5692 "export { Q } from 'somemodule.js';",
5693 "export * from 'somemodule.js';",
5694 "var foo; export { foo as for };",
5695 "export { arguments } from 'm.js';",
5696 "export { for } from 'm.js';",
5697 "export { yield } from 'm.js'",
5698 "export { static } from 'm.js'",
5699 "export { let } from 'm.js'",
5700 "var a; export { a as b, a as c };",
5701
5702 "import 'somemodule.js';",
5703 "import { } from 'm.js';",
5704 "import { a } from 'm.js';",
5705 "import { a, b as d, c, } from 'm.js';",
5706 "import * as thing from 'm.js';",
5707 "import thing from 'm.js';",
5708 "import thing, * as rest from 'm.js';",
5709 "import thing, { a, b, c } from 'm.js';",
5710 "import { arguments as a } from 'm.js';",
5711 "import { for as f } from 'm.js';",
5712 "import { yield as y } from 'm.js';",
5713 "import { static as s } from 'm.js';",
5714 "import { let as l } from 'm.js';",
5715 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005716 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005717
5718 i::Isolate* isolate = CcTest::i_isolate();
5719 i::Factory* factory = isolate->factory();
5720
5721 v8::HandleScope handles(CcTest::isolate());
5722 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5723 v8::Context::Scope context_scope(context);
5724
5725 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5726 128 * 1024);
5727
5728 for (unsigned i = 0; i < arraysize(kSources); ++i) {
5729 i::Handle<i::String> source =
5730 factory->NewStringFromAsciiChecked(kSources[i]);
5731
5732 // Show that parsing as a module works
5733 {
5734 i::Handle<i::Script> script = factory->NewScript(source);
5735 i::Zone zone;
5736 i::ParseInfo info(&zone, script);
5737 i::Parser parser(&info);
5738 info.set_module();
5739 if (!parser.Parse(&info)) {
5740 i::Handle<i::JSObject> exception_handle(
5741 i::JSObject::cast(isolate->pending_exception()));
5742 i::Handle<i::String> message_string =
5743 i::Handle<i::String>::cast(i::Object::GetProperty(
5744 isolate, exception_handle, "message").ToHandleChecked());
5745
5746 v8::base::OS::Print(
5747 "Parser failed on:\n"
5748 "\t%s\n"
5749 "with error:\n"
5750 "\t%s\n"
5751 "However, we expected no error.",
5752 source->ToCString().get(), message_string->ToCString().get());
5753 CHECK(false);
5754 }
5755 }
5756
5757 // And that parsing a script does not.
5758 {
5759 i::Handle<i::Script> script = factory->NewScript(source);
5760 i::Zone zone;
5761 i::ParseInfo info(&zone, script);
5762 i::Parser parser(&info);
5763 info.set_global();
5764 CHECK(!parser.Parse(&info));
5765 }
5766 }
5767}
5768
5769
5770TEST(ImportExportParsingErrors) {
5771 i::FLAG_harmony_modules = true;
5772
Ben Murdoch097c5b22016-05-18 11:27:45 +01005773 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005774 const char* kErrorSources[] = {
5775 "export {",
5776 "var a; export { a",
5777 "var a; export { a,",
5778 "var a; export { a, ;",
5779 "var a; export { a as };",
5780 "var a, b; export { a as , b};",
5781 "export }",
5782 "var foo, bar; export { foo bar };",
5783 "export { foo };",
5784 "export { , };",
5785 "export default;",
5786 "export default var x = 7;",
5787 "export default let x = 7;",
5788 "export default const x = 7;",
5789 "export *;",
5790 "export * from;",
5791 "export { Q } from;",
5792 "export default from 'module.js';",
5793 "export { for }",
5794 "export { for as foo }",
5795 "export { arguments }",
5796 "export { arguments as foo }",
5797 "var a; export { a, a };",
5798 "var a, b; export { a as b, b };",
5799 "var a, b; export { a as c, b as c };",
5800 "export default function f(){}; export default class C {};",
5801 "export default function f(){}; var a; export { a as default };",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005802 "export function() {}",
5803 "export function*() {}",
5804 "export class {}",
5805 "export class extends C {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005806
5807 "import from;",
5808 "import from 'm.js';",
5809 "import { };",
5810 "import {;",
5811 "import };",
5812 "import { , };",
5813 "import { , } from 'm.js';",
5814 "import { a } from;",
5815 "import { a } 'm.js';",
5816 "import , from 'm.js';",
5817 "import a , from 'm.js';",
5818 "import a { b, c } from 'm.js';",
5819 "import arguments from 'm.js';",
5820 "import eval from 'm.js';",
5821 "import { arguments } from 'm.js';",
5822 "import { eval } from 'm.js';",
5823 "import { a as arguments } from 'm.js';",
5824 "import { for } from 'm.js';",
5825 "import { y as yield } from 'm.js'",
5826 "import { s as static } from 'm.js'",
5827 "import { l as let } from 'm.js'",
5828 "import { x }, def from 'm.js';",
5829 "import def, def2 from 'm.js';",
5830 "import * as x, def from 'm.js';",
5831 "import * as x, * as y from 'm.js';",
5832 "import {x}, {y} from 'm.js';",
5833 "import * as x, {y} from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005834 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005835 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005836
5837 i::Isolate* isolate = CcTest::i_isolate();
5838 i::Factory* factory = isolate->factory();
5839
5840 v8::HandleScope handles(CcTest::isolate());
5841 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5842 v8::Context::Scope context_scope(context);
5843
5844 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5845 128 * 1024);
5846
5847 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5848 i::Handle<i::String> source =
5849 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5850
5851 i::Handle<i::Script> script = factory->NewScript(source);
5852 i::Zone zone;
5853 i::ParseInfo info(&zone, script);
5854 i::Parser parser(&info);
5855 info.set_module();
5856 CHECK(!parser.Parse(&info));
5857 }
5858}
5859
5860
5861TEST(ModuleParsingInternals) {
5862 i::FLAG_harmony_modules = true;
5863
5864 i::Isolate* isolate = CcTest::i_isolate();
5865 i::Factory* factory = isolate->factory();
5866 v8::HandleScope handles(CcTest::isolate());
5867 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5868 v8::Context::Scope context_scope(context);
5869 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5870 128 * 1024);
5871
5872 static const char kSource[] =
5873 "let x = 5;"
5874 "export { x as y };"
5875 "import { q as z } from 'm.js';"
5876 "import n from 'n.js';"
5877 "export { a as b } from 'm.js';"
5878 "export * from 'p.js';"
5879 "import 'q.js'";
5880 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
5881 i::Handle<i::Script> script = factory->NewScript(source);
5882 i::Zone zone;
5883 i::ParseInfo info(&zone, script);
5884 i::Parser parser(&info);
5885 info.set_module();
5886 CHECK(parser.Parse(&info));
5887 CHECK(i::Compiler::Analyze(&info));
5888 i::FunctionLiteral* func = info.literal();
5889 i::Scope* module_scope = func->scope();
5890 i::Scope* outer_scope = module_scope->outer_scope();
5891 CHECK(outer_scope->is_script_scope());
5892 CHECK_NULL(outer_scope->outer_scope());
5893 CHECK(module_scope->is_module_scope());
5894 i::ModuleDescriptor* descriptor = module_scope->module();
5895 CHECK_NOT_NULL(descriptor);
5896 CHECK_EQ(1, descriptor->Length());
5897 const i::AstRawString* export_name =
5898 info.ast_value_factory()->GetOneByteString("y");
5899 const i::AstRawString* local_name =
5900 descriptor->LookupLocalExport(export_name, &zone);
5901 CHECK_NOT_NULL(local_name);
5902 CHECK(local_name->IsOneByteEqualTo("x"));
5903 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
5904 CHECK_EQ(3, declarations->length());
5905 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
5906 i::ImportDeclaration* import_decl =
5907 declarations->at(1)->AsImportDeclaration();
5908 CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
5909 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
5910 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
5911 import_decl = declarations->at(2)->AsImportDeclaration();
5912 CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
5913 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
5914 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
5915 // TODO(adamk): Add test for indirect exports once they're fully implemented.
5916 // TODO(adamk): Add test for star exports once they're fully implemented.
5917 const i::ZoneList<const i::AstRawString*>& requested_modules =
5918 descriptor->requested_modules();
5919 CHECK_EQ(4, requested_modules.length());
5920 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
5921 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
5922 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
5923 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
5924}
5925
5926
5927TEST(DuplicateProtoError) {
5928 const char* context_data[][2] = {
5929 {"({", "});"},
5930 {"'use strict'; ({", "});"},
5931 {NULL, NULL}
5932 };
5933 const char* error_data[] = {
5934 "__proto__: {}, __proto__: {}",
5935 "__proto__: {}, \"__proto__\": {}",
5936 "__proto__: {}, \"__\x70roto__\": {}",
5937 "__proto__: {}, a: 1, __proto__: {}",
5938 NULL
5939 };
5940
5941 RunParserSyncTest(context_data, error_data, kError);
5942}
5943
5944
5945TEST(DuplicateProtoNoError) {
5946 const char* context_data[][2] = {
5947 {"({", "});"},
5948 {"'use strict'; ({", "});"},
5949 {NULL, NULL}
5950 };
5951 const char* error_data[] = {
5952 "__proto__: {}, ['__proto__']: {}",
5953 "__proto__: {}, __proto__() {}",
5954 "__proto__: {}, get __proto__() {}",
5955 "__proto__: {}, set __proto__(v) {}",
5956 "__proto__: {}, __proto__",
5957 NULL
5958 };
5959
5960 RunParserSyncTest(context_data, error_data, kSuccess);
5961}
5962
5963
5964TEST(DeclarationsError) {
5965 const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5966 {"'use strict'; if (false) {} else", ""},
5967 {"'use strict'; while (false)", ""},
5968 {"'use strict'; for (;;)", ""},
5969 {"'use strict'; for (x in y)", ""},
5970 {"'use strict'; do ", " while (false)"},
5971 {"'use strong'; if (true)", ""},
5972 {"'use strong'; if (false) {} else", ""},
5973 {"'use strong'; while (false)", ""},
5974 {"'use strong'; for (;;)", ""},
5975 {"'use strong'; for (x in y)", ""},
5976 {"'use strong'; do ", " while (false)"},
5977 {NULL, NULL}};
5978
5979 const char* statement_data[] = {
5980 "let x = 1;",
5981 "const x = 1;",
5982 "class C {}",
5983 NULL};
5984
5985 static const ParserFlag always_flags[] = {kAllowStrongMode};
5986 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
5987 always_flags, arraysize(always_flags));
5988}
5989
5990
5991void TestLanguageMode(const char* source,
5992 i::LanguageMode expected_language_mode) {
5993 i::Isolate* isolate = CcTest::i_isolate();
5994 i::Factory* factory = isolate->factory();
5995 v8::HandleScope handles(CcTest::isolate());
5996 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5997 v8::Context::Scope context_scope(context);
5998 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5999 128 * 1024);
6000
6001 i::Handle<i::Script> script =
6002 factory->NewScript(factory->NewStringFromAsciiChecked(source));
6003 i::Zone zone;
6004 i::ParseInfo info(&zone, script);
6005 i::Parser parser(&info);
6006 parser.set_allow_strong_mode(true);
6007 info.set_global();
6008 parser.Parse(&info);
6009 CHECK(info.literal() != NULL);
6010 CHECK_EQ(expected_language_mode, info.literal()->language_mode());
6011}
6012
6013
6014TEST(LanguageModeDirectives) {
6015 TestLanguageMode("\"use nothing\"", i::SLOPPY);
6016 TestLanguageMode("\"use strict\"", i::STRICT);
6017 TestLanguageMode("\"use strong\"", i::STRONG);
6018
6019 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
6020 TestLanguageMode("var x = 1; \"use strong\"", i::SLOPPY);
6021
6022 // Test that multiple directives ("use strict" / "use strong") put the parser
6023 // into the correct mode.
6024 TestLanguageMode("\"use strict\"; \"use strong\";", i::STRONG);
6025 TestLanguageMode("\"use strong\"; \"use strict\";", i::STRONG);
6026
6027 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
6028 TestLanguageMode("\"use some future directive\"; \"use strong\";", i::STRONG);
6029}
6030
6031
6032TEST(PropertyNameEvalArguments) {
6033 const char* context_data[][2] = {{"'use strict';", ""},
6034 {"'use strong';", ""},
6035 {NULL, NULL}};
6036
6037 const char* statement_data[] = {
6038 "({eval: 1})",
6039 "({arguments: 1})",
6040 "({eval() {}})",
6041 "({arguments() {}})",
6042 "({*eval() {}})",
6043 "({*arguments() {}})",
6044 "({get eval() {}})",
6045 "({get arguments() {}})",
6046 "({set eval(_) {}})",
6047 "({set arguments(_) {}})",
6048
6049 "class C {eval() {}}",
6050 "class C {arguments() {}}",
6051 "class C {*eval() {}}",
6052 "class C {*arguments() {}}",
6053 "class C {get eval() {}}",
6054 "class C {get arguments() {}}",
6055 "class C {set eval(_) {}}",
6056 "class C {set arguments(_) {}}",
6057
6058 "class C {static eval() {}}",
6059 "class C {static arguments() {}}",
6060 "class C {static *eval() {}}",
6061 "class C {static *arguments() {}}",
6062 "class C {static get eval() {}}",
6063 "class C {static get arguments() {}}",
6064 "class C {static set eval(_) {}}",
6065 "class C {static set arguments(_) {}}",
6066
6067 NULL};
6068
6069 static const ParserFlag always_flags[] = {kAllowStrongMode};
6070 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
6071 always_flags, arraysize(always_flags));
6072}
6073
6074
6075TEST(FunctionLiteralDuplicateParameters) {
6076 const char* strict_context_data[][2] =
6077 {{"'use strict';(function(", "){})();"},
6078 {"(function(", ") { 'use strict'; })();"},
6079 {"'use strict'; function fn(", ") {}; fn();"},
6080 {"function fn(", ") { 'use strict'; }; fn();"},
6081 {"'use strong';(function(", "){})();"},
6082 {"(function(", ") { 'use strong'; })();"},
6083 {"'use strong'; function fn(", ") {}; fn();"},
6084 {"function fn(", ") { 'use strong'; }; fn();"},
6085 {NULL, NULL}};
6086
6087 const char* sloppy_context_data[][2] =
6088 {{"(function(", "){})();"},
6089 {"(function(", ") {})();"},
6090 {"function fn(", ") {}; fn();"},
6091 {"function fn(", ") {}; fn();"},
6092 {NULL, NULL}};
6093
6094 const char* data[] = {
6095 "a, a",
6096 "a, a, a",
6097 "b, a, a",
6098 "a, b, c, c",
6099 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
6100 NULL};
6101
6102 static const ParserFlag always_flags[] = { kAllowStrongMode };
6103 RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
6104 arraysize(always_flags));
6105 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, NULL, 0);
6106}
6107
6108
6109TEST(VarForbiddenInStrongMode) {
6110 const char* strong_context_data[][2] =
6111 {{"'use strong'; ", ""},
6112 {"function f() {'use strong'; ", "}"},
6113 {"function f() {'use strong'; while (true) { ", "} }"},
6114 {NULL, NULL}};
6115
6116 const char* strict_context_data[][2] =
6117 {{"'use strict'; ", ""},
6118 {"function f() {'use strict'; ", "}"},
6119 {"function f() {'use strict'; while (true) { ", "} }"},
6120 {NULL, NULL}};
6121
6122 const char* sloppy_context_data[][2] =
6123 {{"", ""},
6124 {"function f() { ", "}"},
6125 {NULL, NULL}};
6126
6127 const char* var_declarations[] = {
6128 "var x = 0;",
6129 "for (var i = 0; i < 10; i++) { }",
6130 NULL};
6131
6132 const char* let_declarations[] = {
6133 "let x = 0;",
6134 "for (let i = 0; i < 10; i++) { }",
6135 NULL};
6136
6137 const char* const_declarations[] = {
6138 "const x = 0;",
6139 NULL};
6140
6141 static const ParserFlag always_flags[] = {kAllowStrongMode};
6142 RunParserSyncTest(strong_context_data, var_declarations, kError, NULL, 0,
6143 always_flags, arraysize(always_flags));
6144 RunParserSyncTest(strong_context_data, let_declarations, kSuccess, NULL, 0,
6145 always_flags, arraysize(always_flags));
6146 RunParserSyncTest(strong_context_data, const_declarations, kSuccess, NULL, 0,
6147 always_flags, arraysize(always_flags));
6148
6149 RunParserSyncTest(strict_context_data, var_declarations, kSuccess, NULL, 0,
6150 always_flags, arraysize(always_flags));
6151 RunParserSyncTest(strict_context_data, let_declarations, kSuccess, NULL, 0,
6152 always_flags, arraysize(always_flags));
6153
6154 RunParserSyncTest(sloppy_context_data, var_declarations, kSuccess, NULL, 0,
6155 always_flags, arraysize(always_flags));
6156 // At the moment, let declarations are only available in strict mode.
6157 RunParserSyncTest(sloppy_context_data, let_declarations, kError, NULL, 0,
6158 always_flags, arraysize(always_flags));
6159}
6160
6161
6162TEST(StrongEmptySubStatements) {
6163 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6164 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6165 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6166
6167 const char* data_error[] = {
6168 "if (1);",
6169 "if (1) {} else;",
6170 "while (1);",
6171 "do; while (1);",
6172 "for (;;);",
6173 "for (x in []);",
6174 "for (x of []);",
6175 "for (const x = 0;;);",
6176 "for (const x in []);",
6177 "for (const x of []);",
6178 NULL};
6179
6180 const char* data_success[] = {
6181 "if (1) {} else {}",
6182 "switch(1) {}",
6183 "1+1;;",
6184 "1+1; ;",
6185 NULL};
6186
6187 static const ParserFlag always_flags[] = {
6188 kAllowStrongMode,
6189 };
6190 RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
6191 always_flags, arraysize(always_flags));
6192 RunParserSyncTest(strict_context_data, data_error, kSuccess, NULL, 0,
6193 always_flags, arraysize(always_flags));
6194 RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
6195 always_flags, arraysize(always_flags));
6196 RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
6197 always_flags, arraysize(always_flags));
6198}
6199
6200
6201TEST(StrongForIn) {
6202 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6203 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6204 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6205
6206 const char* data[] = {
6207 "for (x in []) {}",
6208 "for (const x in []) {}",
6209 NULL};
6210
6211 static const ParserFlag always_flags[] = {
6212 kAllowStrongMode,
6213 };
6214 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
6215 arraysize(always_flags));
6216 RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
6217 arraysize(always_flags));
6218 RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
6219 arraysize(always_flags));
6220}
6221
6222
6223TEST(StrongConstructorThis) {
6224 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6225 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6226 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6227
6228 const char* error_data[] = {
6229 "class C { constructor() { this; } }",
6230 "class C { constructor() { this.a; } }",
6231 "class C { constructor() { this['a']; } }",
6232 "class C { constructor() { (this); } }",
6233 "class C { constructor() { this(); } }",
6234 // TODO(rossberg): arrow functions not handled yet.
6235 // "class C { constructor() { () => this; } }",
6236 "class C { constructor() { this.a = 0, 0; } }",
6237 "class C { constructor() { (this.a = 0); } }",
6238 // "class C { constructor() { (() => this.a = 0)(); } }",
6239 "class C { constructor() { { this.a = 0; } } }",
6240 "class C { constructor() { if (1) this.a = 0; } }",
6241 "class C { constructor() { label: this.a = 0; } }",
6242 "class C { constructor() { this.a = this.b; } }",
6243 "class C { constructor() { this.a = {b: 1}; this.a.b } }",
6244 "class C { constructor() { this.a = {b: 1}; this.a.b = 0 } }",
6245 "class C { constructor() { this.a = function(){}; this.a() } }",
6246 NULL};
6247
6248 const char* success_data[] = {
6249 "class C { constructor() { this.a = 0; } }",
6250 "class C { constructor() { label: 0; this.a = 0; this.b = 6; } }",
6251 NULL};
6252
6253 static const ParserFlag always_flags[] = {kAllowStrongMode};
6254 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6255 always_flags, arraysize(always_flags));
6256 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6257 always_flags, arraysize(always_flags));
6258 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6259 always_flags, arraysize(always_flags));
6260
6261 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6262 always_flags, arraysize(always_flags));
6263 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6264 always_flags, arraysize(always_flags));
6265 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6266 always_flags, arraysize(always_flags));
6267}
6268
6269
6270TEST(StrongConstructorSuper) {
6271 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6272 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6273 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6274
6275 const char* error_data[] = {
6276 "class C extends Object { constructor() {} }",
6277 "class C extends Object { constructor() { super.a; } }",
6278 "class C extends Object { constructor() { super['a']; } }",
6279 "class C extends Object { constructor() { super.a = 0; } }",
6280 "class C extends Object { constructor() { (super.a); } }",
6281 // TODO(rossberg): arrow functions do not handle super yet.
6282 // "class C extends Object { constructor() { () => super.a; } }",
6283 "class C extends Object { constructor() { super(), 0; } }",
6284 "class C extends Object { constructor() { (super()); } }",
6285 // "class C extends Object { constructor() { (() => super())(); } }",
6286 "class C extends Object { constructor() { { super(); } } }",
6287 "class C extends Object { constructor() { if (1) super(); } }",
6288 "class C extends Object { constructor() { label: super(); } }",
6289 "class C extends Object { constructor() { super(), super(); } }",
6290 "class C extends Object { constructor() { super(); super(); } }",
6291 "class C extends Object { constructor() { super(); (super()); } }",
6292 "class C extends Object { constructor() { super(); { super() } } }",
6293 "class C extends Object { constructor() { this.a = 0, super(); } }",
6294 "class C extends Object { constructor() { this.a = 0; super(); } }",
6295 "class C extends Object { constructor() { super(this.a = 0); } }",
6296 "class C extends Object { constructor() { super().a; } }",
6297 NULL};
6298
6299 const char* success_data[] = {
6300 "class C extends Object { constructor() { super(); } }",
6301 "class C extends Object { constructor() { label: 66; super(); } }",
6302 "class C extends Object { constructor() { super(3); this.x = 0; } }",
6303 "class C extends Object { constructor() { 3; super(3); this.x = 0; } }",
6304 NULL};
6305
6306 static const ParserFlag always_flags[] = {kAllowStrongMode};
6307 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6308 always_flags, arraysize(always_flags));
6309 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6310 always_flags, arraysize(always_flags));
6311 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6312 always_flags, arraysize(always_flags));
6313
6314 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6315 always_flags, arraysize(always_flags));
6316 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6317 always_flags, arraysize(always_flags));
6318 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6319 always_flags, arraysize(always_flags));
6320}
6321
6322
6323TEST(StrongConstructorReturns) {
6324 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6325 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6326 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6327
6328 const char* error_data[] = {
6329 "class C extends Object { constructor() { super(); return {}; } }",
6330 "class C extends Object { constructor() { super(); { return {}; } } }",
6331 "class C extends Object { constructor() { super(); if (1) return {}; } }",
6332 "class C extends Object { constructor() { return; super(); } }",
6333 "class C extends Object { constructor() { { return; } super(); } }",
6334 "class C extends Object { constructor() { if (0) return; super(); } }",
6335 "class C { constructor() { return; this.a = 0; } }",
6336 "class C { constructor() { { return; } this.a = 0; } }",
6337 "class C { constructor() { if (0) return; this.a = 0; } }",
6338 "class C { constructor() { this.a = 0; if (0) return; this.b = 0; } }",
6339 NULL};
6340
6341 const char* success_data[] = {
6342 "class C extends Object { constructor() { super(); return; } }",
6343 "class C extends Object { constructor() { super(); { return } } }",
6344 "class C extends Object { constructor() { super(); if (1) return; } }",
6345 "class C { constructor() { this.a = 0; return; } }",
6346 "class C { constructor() { this.a = 0; { return; } } }",
6347 "class C { constructor() { this.a = 0; if (0) return; 65; } }",
6348 "class C extends Array { constructor() { super(); this.a = 9; return } }",
6349 NULL};
6350
6351 static const ParserFlag always_flags[] = {kAllowStrongMode};
6352 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6353 always_flags, arraysize(always_flags));
6354 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6355 always_flags, arraysize(always_flags));
6356 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6357 always_flags, arraysize(always_flags));
6358
6359 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6360 always_flags, arraysize(always_flags));
6361 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6362 always_flags, arraysize(always_flags));
6363 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6364 always_flags, arraysize(always_flags));
6365}
6366
6367
6368TEST(StrongConstructorDirective) {
6369 const char* context_data[][2] = {{"class c { ", " }"},
6370 {"(class c { ", " });"},
6371 {"let a = (class c { ", " });"},
6372 {NULL}};
6373
6374 const char* error_data[] = {
6375 "constructor() { \"use strong\" }",
6376 "constructor(...rest) { \"use strong\" }",
6377 "foo() {} constructor() { \"use strong\" }",
6378 "foo(...rest) { \"use strict\" } constructor() { \"use strong\" }", NULL};
6379
6380 const char* success_data[] = {
6381 "constructor() { \"use strict\" }", "foo() { \"use strong\" }",
6382 "foo() { \"use strong\" } constructor() {}", NULL};
6383
6384 static const ParserFlag always_flags[] = {
6385 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowStrongMode};
6386
6387 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
6388 arraysize(always_flags));
6389 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
6390 arraysize(always_flags));
6391}
6392
6393
6394TEST(StrongUndefinedLocal) {
6395 const char* context_data[][2] = {{"", ""}, {NULL}};
6396
6397 const char* data[] = {
6398 "function undefined() {'use strong';}",
6399 "function* undefined() {'use strong';}",
6400 "(function undefined() {'use strong';});",
6401 "{foo: (function undefined(){'use strong';})};",
6402 "(function* undefined() {'use strong';})",
6403 "{foo: (function* undefined(){'use strong';})};",
6404 "function foo(a, b, undefined, c, d) {'use strong';}",
6405 "function* foo(a, b, undefined, c, d) {'use strong';}",
6406 "(function foo(a, b, undefined, c, d) {'use strong';})",
6407 "{foo: (function foo(a, b, undefined, c, d) {'use strong';})};",
6408 "(function* foo(a, b, undefined, c, d) {'use strong';})",
6409 "{foo: (function* foo(a, b, undefined, c, d) {'use strong';})};",
6410 "class C { foo(a, b, undefined, c, d) {'use strong';} }",
6411 "class C { *foo(a, b, undefined, c, d) {'use strong';} }",
6412 "({ foo(a, b, undefined, c, d) {'use strong';} });",
6413 "{ *foo(a, b, undefined, c, d) {'use strong';} });",
6414 "class undefined {'use strong'}",
6415 "(class undefined {'use strong'});",
6416 NULL};
6417
6418 static const ParserFlag always_flags[] = {
6419 kAllowStrongMode, kAllowHarmonySloppy
6420 };
6421
6422 RunParserSyncTest(context_data, data, kError, NULL, 0,
6423 always_flags, arraysize(always_flags));
6424}
6425
6426
6427TEST(StrongUndefinedArrow) {
6428 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6429 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6430 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6431
6432 const char* data[] = {
6433 "(undefined => {return});",
6434 "((undefined, b, c) => {return});",
6435 "((a, undefined, c) => {return});",
6436 "((a, b, undefined) => {return});",
6437 NULL};
6438
6439 const char* local_strong[] = {
6440 "(undefined => {'use strong';});",
6441 "((undefined, b, c) => {'use strong';});",
6442 "((a, undefined, c) => {'use strong';});",
6443 "((a, b, undefined) => {'use strong';});",
6444 NULL};
6445
6446 static const ParserFlag always_flags[] = {kAllowStrongMode};
6447 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
6448 arraysize(always_flags));
6449 RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
6450 arraysize(always_flags));
6451 RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
6452 arraysize(always_flags));
6453 RunParserSyncTest(sloppy_context_data, local_strong, kError, NULL, 0,
6454 always_flags, arraysize(always_flags));
6455}
6456
6457
6458TEST(StrongDirectEval) {
6459 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6460 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6461
6462 const char* error_data[] = {
6463 "eval();",
6464 "eval([]);",
6465 "(eval)();",
6466 "(((eval)))();",
6467 "eval('function f() {}');",
6468 "function f() {eval()}",
6469 NULL};
6470
6471 const char* success_data[] = {
6472 "eval;",
6473 "eval`foo`;",
6474 "let foo = eval; foo();",
6475 "(1, eval)();",
6476 NULL};
6477
6478 static const ParserFlag always_flags[] = {
6479 kAllowStrongMode
6480 };
6481
6482 RunParserSyncTest(sloppy_context_data, error_data, kSuccess, NULL, 0,
6483 always_flags, arraysize(always_flags));
6484 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6485 always_flags, arraysize(always_flags));
6486 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6487 always_flags, arraysize(always_flags));
6488}
6489
6490
6491TEST(StrongSwitchFallthrough) {
6492 const char* sloppy_context_data[][2] = {
6493 {"function f() { foo:for(;;) { switch(1) {", "};}}"},
6494 {NULL, NULL}
6495 };
6496 const char* strong_context_data[][2] = {
6497 {"function f() { 'use strong'; foo:for(;;) { switch(1) {", "};}}"},
6498 {NULL, NULL}
6499 };
6500
6501 const char* data_success[] = {
6502 "",
6503 "case 1:",
6504 "case 1: case 2:",
6505 "case 1: break;",
6506 "default: throw new TypeError();",
6507 "case 1: case 2: null",
6508 "case 1: case 2: default: 1+1",
6509 "case 1: break; case 2: return; default:",
6510 "case 1: break foo; case 2: return; default:",
6511 "case 1: case 2: break; case 3: continue; case 4: default:",
6512 "case 1: case 2: break; case 3: continue foo; case 4: default:",
6513 "case 1: case 2: {{return;}} case 3: default:",
6514 "case 1: case 2: case 3: default: {1+1;{continue;}}",
6515 "case 1: case 2: {1+1;{1+1;{continue;}}} case 3: default:",
6516 "case 1: if (1) break; else continue; case 2: case 3: default:",
6517 "case 1: case 2: if (1) {{break;}} else break; case 3: default:",
6518 "case 1: if (1) break; else {if (1) break; else break;} case 2: default:",
6519 "case 1: if (1) {if (1) break; else break;} else break; case 2: default:",
6520 NULL};
6521
6522 const char* data_error[] = {
6523 "case 1: case 2: (function(){return}); default:",
6524 "case 1: 1+1; case 2:",
6525 "case 1: bar: break bar; case 2: break;",
6526 "case 1: bar:return; case 2:",
6527 "case 1: bar:{ continue;} case 2:",
6528 "case 1: break; case 2: bar:{ throw new TypeError() } default:",
6529 "case 1: case 2: { bar:{ { break;} } } default: break;",
6530 "case 1: if (1) break; else {}; case 2: default:",
6531 "case 1: case 2: if (1) break; default:",
6532 "case 1: case 2: if (1) break; else 0; default:",
6533 "case 1: case 2: if (1) 0; else break; default:",
6534 "case 1: case 2: case 3: if (1) {} default:",
6535 "case 1: bar:if (1) break; else continue; case 2: case 3: default:",
6536 NULL};
6537
6538 static const ParserFlag always_flags[] = {
6539 kAllowStrongMode
6540 };
6541 RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
6542 always_flags, arraysize(always_flags));
6543 RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
6544 always_flags, arraysize(always_flags));
6545 RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
6546 always_flags, arraysize(always_flags));
6547}
6548
6549
6550TEST(ArrowFunctionASIErrors) {
6551 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
6552 {NULL, NULL}};
6553
6554 const char* data[] = {
6555 "(a\n=> a)(1)",
6556 "(a/*\n*/=> a)(1)",
6557 "((a)\n=> a)(1)",
6558 "((a)/*\n*/=> a)(1)",
6559 "((a, b)\n=> a + b)(1, 2)",
6560 "((a, b)/*\n*/=> a + b)(1, 2)",
6561 NULL};
6562 RunParserSyncTest(context_data, data, kError);
6563}
6564
6565
6566TEST(StrongModeFreeVariablesDeclaredByPreviousScript) {
6567 i::FLAG_strong_mode = true;
6568 i::FLAG_legacy_const = true;
6569 v8::V8::Initialize();
6570 v8::HandleScope scope(CcTest::isolate());
6571 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6572 v8::TryCatch try_catch(CcTest::isolate());
6573
6574 // Introduce a bunch of variables, in all language modes.
6575 const char* script1 =
6576 "var my_var1 = 0; \n"
6577 "function my_func1() { } \n"
6578 "const my_const1 = 0; \n";
6579 CompileRun(v8_str(script1));
6580 CHECK(!try_catch.HasCaught());
6581
6582 const char* script2 =
6583 "\"use strict\"; \n"
6584 "let my_var2 = 0; \n"
6585 "function my_func2() { } \n"
6586 "const my_const2 = 0 \n";
6587 CompileRun(v8_str(script2));
6588 CHECK(!try_catch.HasCaught());
6589
6590 const char* script3 =
6591 "\"use strong\"; \n"
6592 "let my_var3 = 0; \n"
6593 "function my_func3() { } \n"
6594 "const my_const3 = 0; \n";
6595 CompileRun(v8_str(script3));
6596 CHECK(!try_catch.HasCaught());
6597
6598 // Sloppy eval introduces variables in the surrounding scope.
6599 const char* script4 =
6600 "eval('var my_var4 = 0;') \n"
6601 "eval('function my_func4() { }') \n"
6602 "eval('const my_const4 = 0;') \n";
6603 CompileRun(v8_str(script4));
6604 CHECK(!try_catch.HasCaught());
6605
6606 // Test that referencing these variables work.
6607 const char* script5 =
6608 "\"use strong\"; \n"
6609 "my_var1; \n"
6610 "my_func1; \n"
6611 "my_const1; \n"
6612 "my_var2; \n"
6613 "my_func2; \n"
6614 "my_const2; \n"
6615 "my_var3; \n"
6616 "my_func3; \n"
6617 "my_const3; \n"
6618 "my_var4; \n"
6619 "my_func4; \n"
6620 "my_const4; \n";
6621 CompileRun(v8_str(script5));
6622 CHECK(!try_catch.HasCaught());
6623}
6624
6625
6626TEST(StrongModeFreeVariablesDeclaredByLanguage) {
6627 i::FLAG_strong_mode = true;
6628 v8::V8::Initialize();
6629 v8::HandleScope scope(CcTest::isolate());
6630 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6631 v8::TryCatch try_catch(CcTest::isolate());
6632
6633 const char* script1 =
6634 "\"use strong\"; \n"
6635 "Math; \n"
6636 "RegExp; \n";
6637 CompileRun(v8_str(script1));
6638 CHECK(!try_catch.HasCaught());
6639}
6640
6641
6642TEST(StrongModeFreeVariablesDeclaredInGlobalPrototype) {
6643 i::FLAG_strong_mode = true;
6644 v8::V8::Initialize();
6645 v8::HandleScope scope(CcTest::isolate());
6646 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6647 v8::TryCatch try_catch(CcTest::isolate());
6648
6649 const char* script1 = "this.__proto__.my_var = 0;\n";
6650 CompileRun(v8_str(script1));
6651 CHECK(!try_catch.HasCaught());
6652
6653 const char* script2 =
6654 "\"use strong\"; \n"
6655 "my_var; \n";
6656 CompileRun(v8_str(script2));
6657 CHECK(!try_catch.HasCaught());
6658}
6659
6660
Ben Murdoch097c5b22016-05-18 11:27:45 +01006661static const ParserFlag kAllDestructuringFlags[] = {
6662 kAllowHarmonyDestructuring, kAllowHarmonyDestructuringAssignment,
6663 kAllowHarmonyDefaultParameters};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006664
6665TEST(DestructuringPositiveTests) {
6666 i::FLAG_harmony_destructuring_bind = true;
6667
6668 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6669 {"var ", " = {};"},
6670 {"'use strict'; const ", " = {};"},
6671 {"function f(", ") {}"},
6672 {"function f(argument1, ", ") {}"},
6673 {"var f = (", ") => {};"},
6674 {"var f = (argument1,", ") => {};"},
6675 {"try {} catch(", ") {}"},
6676 {NULL, NULL}};
6677
6678 // clang-format off
6679 const char* data[] = {
6680 "a",
6681 "{ x : y }",
6682 "{ x : y = 1 }",
6683 "{ get, set }",
6684 "{ get = 1, set = 2 }",
6685 "[a]",
6686 "[a = 1]",
6687 "[a,b,c]",
6688 "[a, b = 42, c]",
6689 "{ x : x, y : y }",
6690 "{ x : x = 1, y : y }",
6691 "{ x : x, y : y = 42 }",
6692 "[]",
6693 "{}",
6694 "[{x:x, y:y}, [a,b,c]]",
6695 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
6696 "{x}",
6697 "{x, y}",
6698 "{x = 42, y = 15}",
6699 "[a,,b]",
6700 "{42 : x}",
6701 "{42 : x = 42}",
6702 "{42e-2 : x}",
6703 "{42e-2 : x = 42}",
6704 "{x : y, x : z}",
6705 "{'hi' : x}",
6706 "{'hi' : x = 42}",
6707 "{var: x}",
6708 "{var: x = 42}",
6709 "{[x] : z}",
6710 "{[1+1] : z}",
6711 "{[foo()] : z}",
6712 "{}",
6713 "[...rest]",
6714 "[a,b,...rest]",
6715 "[a,,...rest]",
6716 NULL};
6717 // clang-format on
6718 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
6719 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
6720 arraysize(always_flags));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006721 RunParserSyncTest(context_data, data, kSuccess, NULL, 0,
6722 kAllDestructuringFlags, arraysize(kAllDestructuringFlags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006723}
6724
6725
6726TEST(DestructuringNegativeTests) {
6727 i::FLAG_harmony_destructuring_bind = true;
6728 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
6729
6730 { // All modes.
6731 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6732 {"var ", " = {};"},
6733 {"'use strict'; const ", " = {};"},
6734 {"function f(", ") {}"},
6735 {"function f(argument1, ", ") {}"},
6736 {"var f = (", ") => {};"},
6737 {"var f = ", " => {};"},
6738 {"var f = (argument1,", ") => {};"},
6739 {"try {} catch(", ") {}"},
6740 {NULL, NULL}};
6741
6742 // clang-format off
6743 const char* data[] = {
6744 "a++",
6745 "++a",
6746 "delete a",
6747 "void a",
6748 "typeof a",
6749 "--a",
6750 "+a",
6751 "-a",
6752 "~a",
6753 "!a",
6754 "{ x : y++ }",
6755 "[a++]",
6756 "(x => y)",
6757 "a[i]", "a()",
6758 "a.b",
6759 "new a",
6760 "a + a",
6761 "a - a",
6762 "a * a",
6763 "a / a",
6764 "a == a",
6765 "a != a",
6766 "a > a",
6767 "a < a",
6768 "a <<< a",
6769 "a >>> a",
6770 "function a() {}",
6771 "a`bcd`",
6772 "this",
6773 "null",
6774 "true",
6775 "false",
6776 "1",
6777 "'abc'",
6778 "/abc/",
6779 "`abc`",
6780 "class {}",
6781 "{+2 : x}",
6782 "{-2 : x}",
6783 "var",
6784 "[var]",
6785 "{x : {y : var}}",
6786 "{x : x = a+}",
6787 "{x : x = (a+)}",
6788 "{x : x += a}",
6789 "{m() {} = 0}",
6790 "{[1+1]}",
6791 "[...rest, x]",
6792 "[a,b,...rest, x]",
6793 "[a,,...rest, x]",
6794 "[...rest,]",
6795 "[a,b,...rest,]",
6796 "[a,,...rest,]",
6797 "[...rest,...rest1]",
6798 "[a,b,...rest,...rest1]",
6799 "[a,,..rest,...rest1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006800 "[x, y, ...z = 1]",
6801 "[...z = 1]",
6802 "[x, y, ...[z] = [1]]",
6803 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006804 "{ x : 3 }",
6805 "{ x : 'foo' }",
6806 "{ x : /foo/ }",
6807 "{ x : `foo` }",
6808 "{ get a() {} }",
6809 "{ set a() {} }",
6810 "{ method() {} }",
6811 "{ *method() {} }",
6812 NULL};
6813 // clang-format on
6814 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6815 arraysize(always_flags));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006816 RunParserSyncTest(context_data, data, kError, NULL, 0,
6817 kAllDestructuringFlags,
6818 arraysize(kAllDestructuringFlags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006819 }
6820
6821 { // All modes.
6822 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6823 {"var ", " = {};"},
6824 {"'use strict'; const ", " = {};"},
6825 {"function f(", ") {}"},
6826 {"function f(argument1, ", ") {}"},
6827 {"var f = (", ") => {};"},
6828 {"var f = (argument1,", ") => {};"},
6829 {NULL, NULL}};
6830
6831 // clang-format off
6832 const char* data[] = {
6833 "x => x",
6834 "() => x",
6835 NULL};
6836 // clang-format on
6837 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6838 arraysize(always_flags));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006839 RunParserSyncTest(context_data, data, kError, NULL, 0,
6840 kAllDestructuringFlags,
6841 arraysize(kAllDestructuringFlags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006842 }
6843
6844 { // Strict mode.
6845 const char* context_data[][2] = {
6846 {"'use strict'; let ", " = {};"},
6847 {"'use strict'; const ", " = {};"},
6848 {"'use strict'; function f(", ") {}"},
6849 {"'use strict'; function f(argument1, ", ") {}"},
6850 {NULL, NULL}};
6851
6852 // clang-format off
6853 const char* data[] = {
6854 "[eval]",
6855 "{ a : arguments }",
6856 "[public]",
6857 "{ x : private }",
6858 NULL};
6859 // clang-format on
6860 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6861 arraysize(always_flags));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006862 RunParserSyncTest(context_data, data, kError, NULL, 0,
6863 kAllDestructuringFlags,
6864 arraysize(kAllDestructuringFlags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006865 }
6866
6867 { // 'yield' in generators.
6868 const char* context_data[][2] = {
6869 {"function*() { var ", " = {};"},
6870 {"function*() { 'use strict'; let ", " = {};"},
6871 {"function*() { 'use strict'; const ", " = {};"},
6872 {NULL, NULL}};
6873
6874 // clang-format off
6875 const char* data[] = {
6876 "yield",
6877 "[yield]",
6878 "{ x : yield }",
6879 NULL};
6880 // clang-format on
6881 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6882 arraysize(always_flags));
Ben Murdoch097c5b22016-05-18 11:27:45 +01006883 RunParserSyncTest(context_data, data, kError, NULL, 0,
6884 kAllDestructuringFlags,
6885 arraysize(kAllDestructuringFlags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006886 }
6887
6888 { // Declaration-specific errors
6889 const char* context_data[][2] = {{"'use strict'; var ", ""},
6890 {"'use strict'; let ", ""},
6891 {"'use strict'; const ", ""},
6892 {"'use strict'; for (var ", ";;) {}"},
6893 {"'use strict'; for (let ", ";;) {}"},
6894 {"'use strict'; for (const ", ";;) {}"},
6895 {"var ", ""},
6896 {"let ", ""},
6897 {"const ", ""},
6898 {"for (var ", ";;) {}"},
6899 {"for (let ", ";;) {}"},
6900 {"for (const ", ";;) {}"},
6901 {NULL, NULL}};
6902
6903 // clang-format off
6904 const char* data[] = {
6905 "{ a }",
6906 "[ a ]",
6907 NULL};
6908 // clang-format on
6909 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
6910 kAllowHarmonySloppyLet};
6911 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6912 arraysize(always_flags));
6913 }
6914}
6915
6916
6917TEST(DestructuringAssignmentPositiveTests) {
6918 const char* context_data[][2] = {
6919 {"'use strict'; let x, y, z; (", " = {});"},
6920 {"var x, y, z; (", " = {});"},
6921 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6922 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6923 {"var x, y, z; for (x in ", " = {});"},
6924 {"var x, y, z; for (x of ", " = {});"},
6925 {"var x, y, z; for (", " in {});"},
6926 {"var x, y, z; for (", " of {});"},
6927 {"'use strict'; var x, y, z; for (", " in {});"},
6928 {"'use strict'; var x, y, z; for (", " of {});"},
6929 {NULL, NULL}};
6930
6931 const char* mixed_assignments_context_data[][2] = {
6932 {"'use strict'; let x, y, z; (", " = z = {});"},
6933 {"var x, y, z; (", " = z = {});"},
6934 {"'use strict'; let x, y, z; (x = ", " = z = {});"},
6935 {"var x, y, z; (x = ", " = z = {});"},
6936 {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
6937 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
6938 {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
6939 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
6940 {"var x, y, z; for (x in ", " = z = {});"},
6941 {"var x, y, z; for (x in x = ", " = z = {});"},
6942 {"var x, y, z; for (x of ", " = z = {});"},
6943 {"var x, y, z; for (x of x = ", " = z = {});"},
6944 {NULL, NULL}};
6945
6946 // clang-format off
6947 const char* data[] = {
6948 "x",
6949
6950 "{ x : y }",
6951 "{ x : foo().y }",
6952 "{ x : foo()[y] }",
6953 "{ x : y.z }",
6954 "{ x : y[z] }",
6955 "{ x : { y } }",
6956 "{ x : { foo: y } }",
6957 "{ x : { foo: foo().y } }",
6958 "{ x : { foo: foo()[y] } }",
6959 "{ x : { foo: y.z } }",
6960 "{ x : { foo: y[z] } }",
6961 "{ x : [ y ] }",
6962 "{ x : [ foo().y ] }",
6963 "{ x : [ foo()[y] ] }",
6964 "{ x : [ y.z ] }",
6965 "{ x : [ y[z] ] }",
6966
6967 "{ x : y = 10 }",
6968 "{ x : foo().y = 10 }",
6969 "{ x : foo()[y] = 10 }",
6970 "{ x : y.z = 10 }",
6971 "{ x : y[z] = 10 }",
6972 "{ x : { y = 10 } = {} }",
6973 "{ x : { foo: y = 10 } = {} }",
6974 "{ x : { foo: foo().y = 10 } = {} }",
6975 "{ x : { foo: foo()[y] = 10 } = {} }",
6976 "{ x : { foo: y.z = 10 } = {} }",
6977 "{ x : { foo: y[z] = 10 } = {} }",
6978 "{ x : [ y = 10 ] = {} }",
6979 "{ x : [ foo().y = 10 ] = {} }",
6980 "{ x : [ foo()[y] = 10 ] = {} }",
6981 "{ x : [ y.z = 10 ] = {} }",
6982 "{ x : [ y[z] = 10 ] = {} }",
6983
6984 "[ x ]",
6985 "[ foo().x ]",
6986 "[ foo()[x] ]",
6987 "[ x.y ]",
6988 "[ x[y] ]",
6989 "[ { x } ]",
6990 "[ { x : y } ]",
6991 "[ { x : foo().y } ]",
6992 "[ { x : foo()[y] } ]",
6993 "[ { x : x.y } ]",
6994 "[ { x : x[y] } ]",
6995 "[ [ x ] ]",
6996 "[ [ foo().x ] ]",
6997 "[ [ foo()[x] ] ]",
6998 "[ [ x.y ] ]",
6999 "[ [ x[y] ] ]",
7000
7001 "[ x = 10 ]",
7002 "[ foo().x = 10 ]",
7003 "[ foo()[x] = 10 ]",
7004 "[ x.y = 10 ]",
7005 "[ x[y] = 10 ]",
7006 "[ { x = 10 } = {} ]",
7007 "[ { x : y = 10 } = {} ]",
7008 "[ { x : foo().y = 10 } = {} ]",
7009 "[ { x : foo()[y] = 10 } = {} ]",
7010 "[ { x : x.y = 10 } = {} ]",
7011 "[ { x : x[y] = 10 } = {} ]",
7012 "[ [ x = 10 ] = {} ]",
7013 "[ [ foo().x = 10 ] = {} ]",
7014 "[ [ foo()[x] = 10 ] = {} ]",
7015 "[ [ x.y = 10 ] = {} ]",
7016 "[ [ x[y] = 10 ] = {} ]",
7017 "{ x : y = 1 }",
7018 "{ x }",
7019 "{ x, y, z }",
7020 "{ x = 1, y: z, z: y }",
7021 "{x = 42, y = 15}",
7022 "[x]",
7023 "[x = 1]",
7024 "[x,y,z]",
7025 "[x, y = 42, z]",
7026 "{ x : x, y : y }",
7027 "{ x : x = 1, y : y }",
7028 "{ x : x, y : y = 42 }",
7029 "[]",
7030 "{}",
7031 "[{x:x, y:y}, [,x,z,]]",
7032 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
7033 "[x,,y]",
7034 "[(x),,(y)]",
7035 "[(x)]",
7036 "{42 : x}",
7037 "{42 : x = 42}",
7038 "{42e-2 : x}",
7039 "{42e-2 : x = 42}",
7040 "{'hi' : x}",
7041 "{'hi' : x = 42}",
7042 "{var: x}",
7043 "{var: x = 42}",
7044 "{var: (x) = 42}",
7045 "{[x] : z}",
7046 "{[1+1] : z}",
7047 "{[1+1] : (z)}",
7048 "{[foo()] : z}",
7049 "{[foo()] : (z)}",
7050 "{[foo()] : foo().bar}",
7051 "{[foo()] : foo()['bar']}",
7052 "{[foo()] : this.bar}",
7053 "{[foo()] : this['bar']}",
7054 "{[foo()] : 'foo'.bar}",
7055 "{[foo()] : 'foo'['bar']}",
7056 "[...x]",
7057 "[x,y,...z]",
7058 "[x,,...z]",
7059 "{ x: y }",
7060 "[x, y]",
7061 "[((x, y) => z).x]",
7062 "{x: ((y, z) => z).x}",
7063 "[((x, y) => z)['x']]",
7064 "{x: ((y, z) => z)['x']}",
7065
7066 "{x: { y = 10 } }",
7067 "[(({ x } = { x: 1 }) => x).a]",
7068
7069 // v8:4662
7070 "{ x: (y) }",
7071 "{ x: (y) = [] }",
7072 "{ x: (foo.bar) }",
7073 "{ x: (foo['bar']) }",
7074 "[ ...(a) ]",
7075 "[ ...(foo['bar']) ]",
7076 "[ ...(foo.bar) ]",
7077 "[ (y) ]",
7078 "[ (foo.bar) ]",
7079 "[ (foo['bar']) ]",
7080
7081 NULL};
7082 // clang-format on
7083 static const ParserFlag always_flags[] = {
7084 kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
7085 kAllowHarmonyDefaultParameters};
7086 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7087 arraysize(always_flags));
7088
7089 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess, NULL, 0,
7090 always_flags, arraysize(always_flags));
7091
7092 const char* empty_context_data[][2] = {
7093 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7094
7095 // CoverInitializedName ambiguity handling in various contexts
7096 const char* ambiguity_data[] = {
7097 "var foo = { x = 10 } = {};",
7098 "var foo = { q } = { x = 10 } = {};",
7099 "var foo; foo = { x = 10 } = {};",
7100 "var foo; foo = { q } = { x = 10 } = {};",
7101 "var x; ({ x = 10 } = {});",
7102 "var q, x; ({ q } = { x = 10 } = {});",
7103 "var x; [{ x = 10 } = {}]",
7104 "var x; (true ? { x = true } = {} : { x = false } = {})",
7105 "var q, x; (q, { x = 10 } = {});",
7106 "var { x = 10 } = { x = 20 } = {};",
7107 "var { x = 10 } = (o = { x = 20 } = {});",
7108 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
7109 NULL,
7110 };
7111 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess, NULL, 0,
7112 always_flags, arraysize(always_flags));
7113}
7114
7115
7116TEST(DestructuringAssignmentNegativeTests) {
7117 const char* context_data[][2] = {
7118 {"'use strict'; let x, y, z; (", " = {});"},
7119 {"var x, y, z; (", " = {});"},
7120 {"'use strict'; let x, y, z; for (x in ", " = {});"},
7121 {"'use strict'; let x, y, z; for (x of ", " = {});"},
7122 {"var x, y, z; for (x in ", " = {});"},
7123 {"var x, y, z; for (x of ", " = {});"},
7124 {NULL, NULL}};
7125
7126 // clang-format off
7127 const char* data[] = {
7128 "{ x : ++y }",
7129 "{ x : y * 2 }",
7130 "{ ...x }",
7131 "{ get x() {} }",
7132 "{ set x() {} }",
7133 "{ x: y() }",
7134 "{ this }",
7135 "{ x: this }",
7136 "{ x: this = 1 }",
7137 "{ super }",
7138 "{ x: super }",
7139 "{ x: super = 1 }",
7140 "{ new.target }",
7141 "{ x: new.target }",
7142 "{ x: new.target = 1 }",
7143 "[x--]",
7144 "[--x = 1]",
7145 "[x()]",
7146 "[this]",
7147 "[this = 1]",
7148 "[new.target]",
7149 "[new.target = 1]",
7150 "[super]",
7151 "[super = 1]",
7152 "[function f() {}]",
7153 "[50]",
7154 "[(50)]",
7155 "[(function() {})]",
7156 "[(foo())]",
7157 "{ x: 50 }",
7158 "{ x: (50) }",
7159 "['str']",
7160 "{ x: 'str' }",
7161 "{ x: ('str') }",
7162 "{ x: (foo()) }",
7163 "{ x: (function() {}) }",
7164 "{ x: y } = 'str'",
7165 "[x, y] = 'str'",
7166 "[(x,y) => z]",
7167 "{x: (y) => z}",
7168 "[x, ...y, z]",
7169 "[...x,]",
7170 "[x, y, ...z = 1]",
7171 "[...z = 1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007172 "[x, y, ...[z] = [1]]",
7173 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007174
7175 // v8:4657
7176 "({ x: x4, x: (x+=1e4) })",
7177 "(({ x: x4, x: (x+=1e4) }))",
7178 "({ x: x4, x: (x+=1e4) } = {})",
7179 "(({ x: x4, x: (x+=1e4) } = {}))",
7180 "(({ x: x4, x: (x+=1e4) }) = {})",
7181 "({ x: y } = {})",
7182 "(({ x: y } = {}))",
7183 "(({ x: y }) = {})",
7184 "([a])",
7185 "(([a]))",
7186 "([a] = [])",
7187 "(([a] = []))",
7188 "(([a]) = [])",
7189
7190 // v8:4662
7191 "{ x: ([y]) }",
7192 "{ x: ([y] = []) }",
7193 "{ x: ({y}) }",
7194 "{ x: ({y} = {}) }",
7195 "{ x: (++y) }",
7196 "[ (...[a]) ]",
7197 "[ ...([a]) ]",
7198 "[ ...([a] = [])",
7199 "[ ...[ ( [ a ] ) ] ]",
7200 "[ ([a]) ]",
7201 "[ (...[a]) ]",
7202 "[ ([a] = []) ]",
7203 "[ (++y) ]",
7204 "[ ...(++y) ]",
7205
7206 "[ x += x ]",
7207 "{ foo: x += x }",
7208
7209 NULL};
7210 // clang-format on
7211 static const ParserFlag always_flags[] = {
7212 kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
7213 kAllowHarmonyDefaultParameters};
7214 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7215 arraysize(always_flags));
7216
7217 const char* empty_context_data[][2] = {
7218 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7219
7220 // CoverInitializedName ambiguity handling in various contexts
7221 const char* ambiguity_data[] = {
7222 "var foo = { x = 10 };",
7223 "var foo = { q } = { x = 10 };",
7224 "var foo; foo = { x = 10 };",
7225 "var foo; foo = { q } = { x = 10 };",
7226 "var x; ({ x = 10 });",
7227 "var q, x; ({ q } = { x = 10 });",
7228 "var x; [{ x = 10 }]",
7229 "var x; (true ? { x = true } : { x = false })",
7230 "var q, x; (q, { x = 10 });",
7231 "var { x = 10 } = { x = 20 };",
7232 "var { x = 10 } = (o = { x = 20 });",
7233 "var x; (({ x = 10 } = { x = 20 }) => x)({})",
7234
7235 // Not ambiguous, but uses same context data
7236 "switch([window %= []] = []) { default: }",
7237
7238 NULL,
7239 };
7240 RunParserSyncTest(empty_context_data, ambiguity_data, kError, NULL, 0,
7241 always_flags, arraysize(always_flags));
7242
7243 // Strict mode errors
7244 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
7245 {"'use strict'; for (", " of {}) {}"},
7246 {"'use strict'; for (", " in {}) {}"},
7247 {NULL, NULL}};
7248 const char* strict_data[] = {"{ eval }",
7249 "{ arguments }",
7250 "{ foo: eval }",
7251 "{ foo: arguments }",
7252 "{ eval = 0 }",
7253 "{ arguments = 0 }",
7254 "{ foo: eval = 0 }",
7255 "{ foo: arguments = 0 }",
7256 "[ eval ]",
7257 "[ arguments ]",
7258 "[ eval = 0 ]",
7259 "[ arguments = 0 ]",
7260
7261 // v8:4662
7262 "{ x: (eval) }",
7263 "{ x: (arguments) }",
7264 "{ x: (eval = 0) }",
7265 "{ x: (arguments = 0) }",
7266 "{ x: (eval) = 0 }",
7267 "{ x: (arguments) = 0 }",
7268 "[ (eval) ]",
7269 "[ (arguments) ]",
7270 "[ (eval = 0) ]",
7271 "[ (arguments = 0) ]",
7272 "[ (eval) = 0 ]",
7273 "[ (arguments) = 0 ]",
7274 "[ ...(eval) ]",
7275 "[ ...(arguments) ]",
7276 "[ ...(eval = 0) ]",
7277 "[ ...(arguments = 0) ]",
7278 "[ ...(eval) = 0 ]",
7279 "[ ...(arguments) = 0 ]",
7280
7281 NULL};
7282 RunParserSyncTest(strict_context_data, strict_data, kError, NULL, 0,
7283 always_flags, arraysize(always_flags));
7284}
7285
7286
7287TEST(DestructuringDisallowPatternsInForVarIn) {
7288 i::FLAG_harmony_destructuring_bind = true;
7289 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7290 const char* context_data[][2] = {
7291 {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
7292 // clang-format off
7293 const char* error_data[] = {
7294 "for (let x = {} in null);",
7295 "for (let x = {} of null);",
7296 NULL};
7297 // clang-format on
7298 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7299 arraysize(always_flags));
7300
7301 // clang-format off
7302 const char* success_data[] = {
7303 "for (var x = {} in null);",
7304 NULL};
7305 // clang-format on
7306 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
7307 arraysize(always_flags));
7308}
7309
7310
7311TEST(DestructuringDuplicateParams) {
7312 i::FLAG_harmony_destructuring_bind = true;
7313 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7314 const char* context_data[][2] = {{"'use strict';", ""},
7315 {"function outer() { 'use strict';", "}"},
7316 {nullptr, nullptr}};
7317
7318
7319 // clang-format off
7320 const char* error_data[] = {
7321 "function f(x,x){}",
7322 "function f(x, {x : x}){}",
7323 "function f(x, {x}){}",
7324 "function f({x,x}) {}",
7325 "function f([x,x]) {}",
7326 "function f(x, [y,{z:x}]) {}",
7327 "function f([x,{y:x}]) {}",
7328 // non-simple parameter list causes duplicates to be errors in sloppy mode.
7329 "function f(x, x, {a}) {}",
7330 nullptr};
7331 // clang-format on
7332 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7333 arraysize(always_flags));
7334}
7335
7336
7337TEST(DestructuringDuplicateParamsSloppy) {
7338 i::FLAG_harmony_destructuring_bind = true;
7339 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7340 const char* context_data[][2] = {
7341 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
7342
7343
7344 // clang-format off
7345 const char* error_data[] = {
7346 // non-simple parameter list causes duplicates to be errors in sloppy mode.
7347 "function f(x, {x : x}){}",
7348 "function f(x, {x}){}",
7349 "function f({x,x}) {}",
7350 "function f(x, x, {a}) {}",
7351 nullptr};
7352 // clang-format on
7353 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7354 arraysize(always_flags));
7355}
7356
7357
7358TEST(DestructuringDisallowPatternsInSingleParamArrows) {
7359 i::FLAG_harmony_destructuring_bind = true;
7360 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7361 const char* context_data[][2] = {{"'use strict';", ""},
7362 {"function outer() { 'use strict';", "}"},
7363 {"", ""},
7364 {"function outer() { ", "}"},
7365 {nullptr, nullptr}};
7366
7367 // clang-format off
7368 const char* error_data[] = {
7369 "var f = {x} => {};",
7370 "var f = {x,y} => {};",
7371 nullptr};
7372 // clang-format on
7373 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7374 arraysize(always_flags));
7375}
7376
7377
7378TEST(DefaultParametersYieldInInitializers) {
7379 // clang-format off
7380 const char* sloppy_function_context_data[][2] = {
7381 {"(function f(", ") { });"},
7382 {NULL, NULL}
7383 };
7384
7385 const char* strict_function_context_data[][2] = {
7386 {"'use strong'; (function f(", ") { });"},
7387 {"'use strict'; (function f(", ") { });"},
7388 {NULL, NULL}
7389 };
7390
7391 const char* sloppy_arrow_context_data[][2] = {
7392 {"((", ")=>{});"},
7393 {NULL, NULL}
7394 };
7395
7396 const char* strict_arrow_context_data[][2] = {
7397 {"'use strong'; ((", ")=>{});"},
7398 {"'use strict'; ((", ")=>{});"},
7399 {NULL, NULL}
7400 };
7401
7402 const char* generator_context_data[][2] = {
7403 {"'use strong'; (function *g(", ") { });"},
7404 {"'use strict'; (function *g(", ") { });"},
7405 {"(function *g(", ") { });"},
7406 {NULL, NULL}
7407 };
7408
7409 const char* parameter_data[] = {
7410 "x=yield",
7411 "x, y=yield",
7412 "{x=yield}",
7413 "[x=yield]",
7414
7415 "x=(yield)",
7416 "x, y=(yield)",
7417 "{x=(yield)}",
7418 "[x=(yield)]",
7419
7420 "x=f(yield)",
7421 "x, y=f(yield)",
7422 "{x=f(yield)}",
7423 "[x=f(yield)]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007425 "{x}=yield",
7426 "[x]=yield",
7427
7428 "{x}=(yield)",
7429 "[x]=(yield)",
7430
7431 "{x}=f(yield)",
7432 "[x]=f(yield)",
7433 NULL
7434 };
7435
7436 // clang-format on
7437 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
7438 kAllowHarmonyDefaultParameters,
7439 kAllowStrongMode};
7440
7441 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess,
7442 NULL, 0, always_flags, arraysize(always_flags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007443 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess, NULL,
7444 0, always_flags, arraysize(always_flags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007445
7446 RunParserSyncTest(strict_function_context_data, parameter_data, kError, NULL,
7447 0, always_flags, arraysize(always_flags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007448 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError, NULL, 0,
7449 always_flags, arraysize(always_flags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007450
7451 RunParserSyncTest(generator_context_data, parameter_data, kError, NULL, 0,
7452 always_flags, arraysize(always_flags));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007453}
7454
7455
7456TEST(SpreadArray) {
7457 const char* context_data[][2] = {
7458 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7459
7460 // clang-format off
7461 const char* data[] = {
7462 "[...a]",
7463 "[a, ...b]",
7464 "[...a,]",
7465 "[...a, ,]",
7466 "[, ...a]",
7467 "[...a, ...b]",
7468 "[...a, , ...b]",
7469 "[...[...a]]",
7470 "[, ...a]",
7471 "[, , ...a]",
7472 NULL};
7473 // clang-format on
7474 RunParserSyncTest(context_data, data, kSuccess);
7475}
7476
7477
7478TEST(SpreadArrayError) {
7479 const char* context_data[][2] = {
7480 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7481
7482 // clang-format off
7483 const char* data[] = {
7484 "[...]",
7485 "[a, ...]",
7486 "[..., ]",
7487 "[..., ...]",
7488 "[ (...a)]",
7489 NULL};
7490 // clang-format on
7491 RunParserSyncTest(context_data, data, kError);
7492}
7493
7494
7495TEST(NewTarget) {
7496 // clang-format off
7497 const char* good_context_data[][2] = {
7498 {"function f() {", "}"},
7499 {"'use strict'; function f() {", "}"},
7500 {"var f = function() {", "}"},
7501 {"'use strict'; var f = function() {", "}"},
7502 {"({m: function() {", "}})"},
7503 {"'use strict'; ({m: function() {", "}})"},
7504 {"({m() {", "}})"},
7505 {"'use strict'; ({m() {", "}})"},
7506 {"({get x() {", "}})"},
7507 {"'use strict'; ({get x() {", "}})"},
7508 {"({set x(_) {", "}})"},
7509 {"'use strict'; ({set x(_) {", "}})"},
7510 {"class C {m() {", "}}"},
7511 {"class C {get x() {", "}}"},
7512 {"class C {set x(_) {", "}}"},
7513 {NULL}
7514 };
7515
7516 const char* bad_context_data[][2] = {
7517 {"", ""},
7518 {"'use strict';", ""},
7519 {NULL}
7520 };
7521
7522 const char* data[] = {
7523 "new.target",
7524 "{ new.target }",
7525 "() => { new.target }",
7526 "() => new.target",
7527 "if (1) { new.target }",
7528 "if (1) {} else { new.target }",
7529 "while (0) { new.target }",
7530 "do { new.target } while (0)",
7531 NULL
7532 };
7533
7534 static const ParserFlag always_flags[] = {
7535 kAllowHarmonyNewTarget,
7536 kAllowHarmonySloppy,
7537 };
7538 // clang-format on
7539
7540 RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags,
7541 arraysize(always_flags));
7542 RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags,
7543 arraysize(always_flags));
7544}
7545
7546
7547TEST(ConstLegacy) {
7548 // clang-format off
7549 const char* context_data[][2] = {
7550 {"", ""},
7551 {"{", "}"},
7552 {NULL, NULL}
7553 };
7554
7555 const char* data[] = {
7556 "const x",
7557 "const x = 1",
7558 "for (const x = 1; x < 1; x++) {}",
7559 "for (const x in {}) {}",
7560 "for (const x of []) {}",
7561 NULL
7562 };
7563 // clang-format on
7564
7565
7566 static const ParserFlag always_flags[] = {kNoLegacyConst};
7567 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7568 arraysize(always_flags));
7569 RunParserSyncTest(context_data, data, kSuccess);
7570}
7571
7572
7573TEST(ConstSloppy) {
7574 // clang-format off
7575 const char* context_data[][2] = {
7576 {"", ""},
7577 {"{", "}"},
7578 {NULL, NULL}
7579 };
7580
7581 const char* data[] = {
7582 "const x = 1",
7583 "for (const x = 1; x < 1; x++) {}",
7584 "for (const x in {}) {}",
7585 "for (const x of []) {}",
7586 NULL
7587 };
7588 // clang-format on
7589 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7590 kNoLegacyConst};
7591 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7592 arraysize(always_flags));
7593}
7594
7595
7596TEST(LetSloppy) {
7597 // clang-format off
7598 const char* context_data[][2] = {
7599 {"", ""},
7600 {"'use strict';", ""},
7601 {"{", "}"},
7602 {NULL, NULL}
7603 };
7604
7605 const char* data[] = {
7606 "let x",
7607 "let x = 1",
7608 "for (let x = 1; x < 1; x++) {}",
7609 "for (let x in {}) {}",
7610 "for (let x of []) {}",
7611 NULL
7612 };
7613 // clang-format on
7614
7615 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7616 kAllowHarmonySloppyLet};
7617 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7618 arraysize(always_flags));
7619}
7620
7621
7622TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
7623 // TC39 deemed "use strict" directives to be an error when occurring in the
7624 // body of a function with non-simple parameter list, on 29/7/2015.
7625 // https://goo.gl/ueA7Ln
7626 //
7627 // In V8, this also applies to "use strong " directives.
7628 const char* context_data[][2] = {
7629 {"function f(", ") { 'use strict'; }"},
7630 {"function f(", ") { 'use strong'; }"},
7631 {"function* g(", ") { 'use strict'; }"},
7632 {"function* g(", ") { 'use strong'; }"},
7633 {"class c { foo(", ") { 'use strict' }"},
7634 {"class c { foo(", ") { 'use strong' }"},
7635 {"var a = (", ") => { 'use strict'; }"},
7636 {"var a = (", ") => { 'use strong'; }"},
7637 {"var o = { m(", ") { 'use strict'; }"},
7638 {"var o = { m(", ") { 'use strong'; }"},
7639 {"var o = { *gm(", ") { 'use strict'; }"},
7640 {"var o = { *gm(", ") { 'use strong'; }"},
7641 {"var c = { m(", ") { 'use strict'; }"},
7642 {"var c = { m(", ") { 'use strong'; }"},
7643 {"var c = { *gm(", ") { 'use strict'; }"},
7644 {"var c = { *gm(", ") { 'use strong'; }"},
7645
7646 {"'use strict'; function f(", ") { 'use strict'; }"},
7647 {"'use strict'; function f(", ") { 'use strong'; }"},
7648 {"'use strict'; function* g(", ") { 'use strict'; }"},
7649 {"'use strict'; function* g(", ") { 'use strong'; }"},
7650 {"'use strict'; class c { foo(", ") { 'use strict' }"},
7651 {"'use strict'; class c { foo(", ") { 'use strong' }"},
7652 {"'use strict'; var a = (", ") => { 'use strict'; }"},
7653 {"'use strict'; var a = (", ") => { 'use strong'; }"},
7654 {"'use strict'; var o = { m(", ") { 'use strict'; }"},
7655 {"'use strict'; var o = { m(", ") { 'use strong'; }"},
7656 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
7657 {"'use strict'; var o = { *gm(", ") { 'use strong'; }"},
7658 {"'use strict'; var c = { m(", ") { 'use strict'; }"},
7659 {"'use strict'; var c = { m(", ") { 'use strong'; }"},
7660 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
7661 {"'use strict'; var c = { *gm(", ") { 'use strong'; }"},
7662
7663 {"'use strong'; function f(", ") { 'use strict'; }"},
7664 {"'use strong'; function f(", ") { 'use strong'; }"},
7665 {"'use strong'; function* g(", ") { 'use strict'; }"},
7666 {"'use strong'; function* g(", ") { 'use strong'; }"},
7667 {"'use strong'; class c { foo(", ") { 'use strict' }"},
7668 {"'use strong'; class c { foo(", ") { 'use strong' }"},
7669 {"'use strong'; var a = (", ") => { 'use strict'; }"},
7670 {"'use strong'; var a = (", ") => { 'use strong'; }"},
7671 {"'use strong'; var o = { m(", ") { 'use strict'; }"},
7672 {"'use strong'; var o = { m(", ") { 'use strong'; }"},
7673 {"'use strong'; var o = { *gm(", ") { 'use strict'; }"},
7674 {"'use strong'; var o = { *gm(", ") { 'use strong'; }"},
7675 {"'use strong'; var c = { m(", ") { 'use strict'; }"},
7676 {"'use strong'; var c = { m(", ") { 'use strong'; }"},
7677 {"'use strong'; var c = { *gm(", ") { 'use strict'; }"},
7678 {"'use strong'; var c = { *gm(", ") { 'use strong'; }"},
7679
7680 {NULL, NULL}};
7681
7682 const char* data[] = {
7683 // TODO(@caitp): support formal parameter initializers
7684 "{}",
7685 "[]",
7686 "[{}]",
7687 "{a}",
7688 "a, {b}",
7689 "a, b, {c, d, e}",
7690 "initializer = true",
7691 "a, b, c = 1",
7692 "...args",
7693 "a, b, ...rest",
7694 "[a, b, ...rest]",
7695 "{ bindingPattern = {} }",
7696 "{ initializedBindingPattern } = { initializedBindingPattern: true }",
7697 NULL};
7698
7699 static const ParserFlag always_flags[] = {
7700 kAllowHarmonyDefaultParameters, kAllowHarmonyDestructuring,
7701 kAllowHarmonySloppy, kAllowStrongMode};
7702 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7703 arraysize(always_flags));
7704}
7705
7706
7707TEST(LetSloppyOnly) {
7708 // clang-format off
7709 const char* context_data[][2] = {
7710 {"", ""},
7711 {"{", "}"},
7712 {"(function() {", "})()"},
7713 {NULL, NULL}
7714 };
7715
7716 const char* data[] = {
7717 "let",
7718 "let = 1",
7719 "for (let = 1; let < 1; let++) {}",
7720 "for (let in {}) {}",
7721 "for (var let = 1; let < 1; let++) {}",
7722 "for (var let in {}) {}",
7723 "for (var [let] = 1; let < 1; let++) {}",
7724 "for (var [let] in {}) {}",
7725 "var let",
7726 "var [let] = []",
7727 "for (const let = 1; let < 1; let++) {}",
7728 "for (const let in {}) {}",
7729 "for (const [let] = 1; let < 1; let++) {}",
7730 "for (const [let] in {}) {}",
7731 "const let",
7732 "const [let] = []",
7733 NULL
7734 };
7735 // clang-format on
7736
7737 static const ParserFlag always_flags[] = {
7738 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
7739 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7740 arraysize(always_flags));
7741
7742 // Some things should be rejected even in sloppy mode
7743 // This addresses BUG(v8:4403).
7744
7745 // clang-format off
7746 const char* fail_data[] = {
7747 "let let = 1",
7748 "for (let let = 1; let < 1; let++) {}",
7749 "for (let let in {}) {}",
7750 "for (let let of []) {}",
7751 "const let = 1",
7752 "for (const let = 1; let < 1; let++) {}",
7753 "for (const let in {}) {}",
7754 "for (const let of []) {}",
7755 "let [let] = 1",
7756 "for (let [let] = 1; let < 1; let++) {}",
7757 "for (let [let] in {}) {}",
7758 "for (let [let] of []) {}",
7759 "const [let] = 1",
7760 "for (const [let] = 1; let < 1; let++) {}",
7761 "for (const [let] in {}) {}",
7762 "for (const [let] of []) {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007763
7764 // Sprinkle in the escaped version too.
7765 "let l\\u0065t = 1",
7766 "const l\\u0065t = 1",
7767 "let [l\\u0065t] = 1",
7768 "const [l\\u0065t] = 1",
7769 "for (let l\\u0065t in {}) {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007770 NULL
7771 };
7772 // clang-format on
7773
7774 static const ParserFlag fail_flags[] = {
7775 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst,
7776 kAllowHarmonyDestructuring};
7777 RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags,
7778 arraysize(fail_flags));
7779}
7780
7781
7782TEST(EscapedKeywords) {
7783 // clang-format off
7784 const char* sloppy_context_data[][2] = {
7785 {"", ""},
7786 {NULL, NULL}
7787 };
7788
7789 const char* strict_context_data[][2] = {
7790 {"'use strict';", ""},
7791 {NULL, NULL}
7792 };
7793
7794 const char* fail_data[] = {
7795 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
7796 "cl\\u0061ss Foo {}",
7797 "var x = cl\\u0061ss {}",
7798 "\\u0063onst foo = 1;",
7799 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
7800 "d\\u0065bugger;",
7801 "d\\u0065lete this.a;",
7802 "\\u0063o { } while(0)",
7803 "if (d\\u006f { true }) {}",
7804 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
7805 "e\\u0078port var foo;",
7806 "try { } catch (e) {} f\\u0069nally { }",
7807 "f\\u006fr (var i = 0; i < 10; ++i);",
7808 "f\\u0075nction fn() {}",
7809 "var f = f\\u0075nction() {}",
7810 "\\u0069f (true) { }",
7811 "\\u0069mport blah from './foo.js';",
7812 "n\\u0065w function f() {}",
7813 "(function() { r\\u0065turn; })()",
7814 "class C extends function() {} { constructor() { sup\\u0065r() } }",
7815 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
7816 "sw\\u0069tch (this.a) {}",
7817 "var x = th\\u0069s;",
7818 "th\\u0069s.a = 1;",
7819 "thr\\u006fw 'boo';",
7820 "t\\u0072y { true } catch (e) {}",
7821 "var x = typ\\u0065of 'blah'",
7822 "v\\u0061r a = true",
7823 "var v\\u0061r = true",
7824 "(function() { return v\\u006fid 0; })()",
7825 "wh\\u0069le (true) { }",
7826 "w\\u0069th (this.scope) { }",
7827 "(function*() { y\\u0069eld 1; })()",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007828 "(function*() { var y\\u0069eld = 1; })()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007829
7830 "var \\u0065num = 1;",
7831 "var { \\u0065num } = {}",
7832 "(\\u0065num = 1);",
7833
7834 // Null / Boolean literals
7835 "(x === n\\u0075ll);",
7836 "var x = n\\u0075ll;",
7837 "var n\\u0075ll = 1;",
7838 "var { n\\u0075ll } = { 1 };",
7839 "n\\u0075ll = 1;",
7840 "(x === tr\\u0075e);",
7841 "var x = tr\\u0075e;",
7842 "var tr\\u0075e = 1;",
7843 "var { tr\\u0075e } = {};",
7844 "tr\\u0075e = 1;",
7845 "(x === f\\u0061lse);",
7846 "var x = f\\u0061lse;",
7847 "var f\\u0061lse = 1;",
7848 "var { f\\u0061lse } = {};",
7849 "f\\u0061lse = 1;",
7850
7851 // TODO(caitp): consistent error messages for labeled statements and
7852 // expressions
7853 "switch (this.a) { c\\u0061se 6: break; }",
7854 "try { } c\\u0061tch (e) {}",
7855 "switch (this.a) { d\\u0065fault: break; }",
7856 "class C \\u0065xtends function B() {} {}",
7857 "for (var a i\\u006e this) {}",
7858 "if ('foo' \\u0069n this) {}",
7859 "if (this \\u0069nstanceof Array) {}",
7860 "(n\\u0065w function f() {})",
7861 "(typ\\u0065of 123)",
7862 "(v\\u006fid 0)",
7863 "do { ; } wh\\u0069le (true) { }",
7864 "(function*() { return (n++, y\\u0069eld 1); })()",
7865 "class C { st\\u0061tic bar() {} }",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007866 "class C { st\\u0061tic *bar() {} }",
7867 "class C { st\\u0061tic get bar() {} }",
7868 "class C { st\\u0061tic set bar() {} }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007869
Ben Murdoch097c5b22016-05-18 11:27:45 +01007870 // TODO(adamk): These should not be errors in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007871 "(y\\u0069eld);",
7872 "var y\\u0069eld = 1;",
7873 "var { y\\u0069eld } = {};",
7874 NULL
7875 };
7876 // clang-format on
7877
7878 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7879 kAllowHarmonyDestructuring};
7880 RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7881 always_flags, arraysize(always_flags));
7882 RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0,
7883 always_flags, arraysize(always_flags));
7884 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7885 always_flags, arraysize(always_flags));
7886
7887 // clang-format off
7888 const char* let_data[] = {
7889 "var l\\u0065t = 1;",
7890 "l\\u0065t = 1;",
7891 "(l\\u0065t === 1);",
7892 NULL
7893 };
7894 // clang-format on
7895
Ben Murdoch097c5b22016-05-18 11:27:45 +01007896 RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007897 always_flags, arraysize(always_flags));
7898 RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
7899 always_flags, arraysize(always_flags));
7900
7901 static const ParserFlag sloppy_let_flags[] = {
7902 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
Ben Murdoch097c5b22016-05-18 11:27:45 +01007903 RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007904 sloppy_let_flags, arraysize(sloppy_let_flags));
7905
7906 // Non-errors in sloppy mode
7907 const char* valid_data[] = {"(\\u0069mplements = 1);",
7908 "var impl\\u0065ments = 1;",
7909 "var { impl\\u0065ments } = {};",
7910 "(\\u0069nterface = 1);",
7911 "var int\\u0065rface = 1;",
7912 "var { int\\u0065rface } = {};",
7913 "(p\\u0061ckage = 1);",
7914 "var packa\\u0067e = 1;",
7915 "var { packa\\u0067e } = {};",
7916 "(p\\u0072ivate = 1);",
7917 "var p\\u0072ivate;",
7918 "var { p\\u0072ivate } = {};",
7919 "(prot\\u0065cted);",
7920 "var prot\\u0065cted = 1;",
7921 "var { prot\\u0065cted } = {};",
7922 "(publ\\u0069c);",
7923 "var publ\\u0069c = 1;",
7924 "var { publ\\u0069c } = {};",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007925 "(st\\u0061tic);",
7926 "var st\\u0061tic = 1;",
7927 "var { st\\u0061tic } = {};",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007928 NULL};
7929 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
7930 always_flags, arraysize(always_flags));
7931 RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7932 always_flags, arraysize(always_flags));
7933 RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7934 always_flags, arraysize(always_flags));
7935}
7936
7937
7938TEST(MiscSyntaxErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007939 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007940 const char* context_data[][2] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007941 { "'use strict'", "" },
7942 { "", "" },
7943 { NULL, NULL }
7944 };
7945 const char* error_data[] = {
7946 "for (();;) {}",
7947
7948 // crbug.com/582626
7949 "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
7950 NULL
7951 };
7952 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007953
7954 RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
7955}
Ben Murdoch097c5b22016-05-18 11:27:45 +01007956
7957TEST(FunctionSentErrors) {
7958 // clang-format off
7959 const char* context_data[][2] = {
7960 { "'use strict'", "" },
7961 { "", "" },
7962 { NULL, NULL }
7963 };
7964 const char* error_data[] = {
7965 "var x = function.sent",
7966 "function* g() { yield function.s\\u0065nt; }",
7967 NULL
7968 };
7969 // clang-format on
7970
7971 static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
7972 RunParserSyncTest(context_data, error_data, kError, always_flags,
7973 arraysize(always_flags));
7974}
7975
7976TEST(NewTargetErrors) {
7977 // clang-format off
7978 const char* context_data[][2] = {
7979 { "'use strict'", "" },
7980 { "", "" },
7981 { NULL, NULL }
7982 };
7983 const char* error_data[] = {
7984 "var x = new.target",
7985 "function f() { return new.t\\u0061rget; }",
7986 NULL
7987 };
7988 // clang-format on
7989 RunParserSyncTest(context_data, error_data, kError);
7990}