blob: 52493145dc4b34cfe5004cdd5c616c729999b490 [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
1503
1504enum ParserFlag {
1505 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001506 kAllowNatives,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001507 kAllowHarmonyDefaultParameters,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001508 kAllowHarmonySloppy,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509 kAllowHarmonySloppyLet,
1510 kAllowHarmonyDestructuring,
1511 kAllowHarmonyDestructuringAssignment,
1512 kAllowHarmonyNewTarget,
1513 kAllowStrongMode,
1514 kNoLegacyConst
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001515};
1516
1517
1518enum ParserSyncTestResult {
1519 kSuccessOrError,
1520 kSuccess,
1521 kError
1522};
1523
1524template <typename Traits>
1525void SetParserFlags(i::ParserBase<Traits>* parser,
1526 i::EnumSet<ParserFlag> flags) {
1527 parser->set_allow_lazy(flags.Contains(kAllowLazy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001528 parser->set_allow_natives(flags.Contains(kAllowNatives));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001529 parser->set_allow_harmony_default_parameters(
1530 flags.Contains(kAllowHarmonyDefaultParameters));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001531 parser->set_allow_harmony_sloppy(flags.Contains(kAllowHarmonySloppy));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001532 parser->set_allow_harmony_sloppy_let(flags.Contains(kAllowHarmonySloppyLet));
1533 parser->set_allow_harmony_destructuring_bind(
1534 flags.Contains(kAllowHarmonyDestructuring));
1535 parser->set_allow_harmony_destructuring_assignment(
1536 flags.Contains(kAllowHarmonyDestructuringAssignment));
1537 parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
1538 parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539}
1540
1541
1542void TestParserSyncWithFlags(i::Handle<i::String> source,
1543 i::EnumSet<ParserFlag> flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 ParserSyncTestResult result,
1545 bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546 i::Isolate* isolate = CcTest::i_isolate();
1547 i::Factory* factory = isolate->factory();
1548
1549 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001550 int preparser_materialized_literals = -1;
1551 int parser_materialized_literals = -2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 bool test_preparser = !is_module;
Ben Murdoch692be652012-01-10 18:47:50 +00001553
1554 // Preparse the data.
1555 i::CompleteParserRecorder log;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556 if (test_preparser) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001557 i::Scanner scanner(isolate->unicode_cache());
1558 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 i::Zone zone;
1560 i::AstValueFactory ast_value_factory(
1561 &zone, CcTest::i_isolate()->heap()->HashSeed());
1562 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
1563 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001564 SetParserFlags(&preparser, flags);
1565 scanner.Initialize(&stream);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001566 i::PreParser::PreParseResult result = preparser.PreParseProgram(
1567 &preparser_materialized_literals);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1569 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001570 bool preparse_error = log.HasError();
Ben Murdoch692be652012-01-10 18:47:50 +00001571
1572 // Parse the data
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 i::FunctionLiteral* function;
1574 {
1575 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 i::Zone zone;
1577 i::ParseInfo info(&zone, script);
1578 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579 SetParserFlags(&parser, flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 if (is_module) {
1581 info.set_module();
1582 } else {
1583 info.set_global();
1584 }
1585 parser.Parse(&info);
1586 function = info.literal();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001587 if (function) {
1588 parser_materialized_literals = function->materialized_literal_count();
1589 }
Ben Murdoch692be652012-01-10 18:47:50 +00001590 }
1591
1592 // Check that preparsing fails iff parsing fails.
Ben Murdoch692be652012-01-10 18:47:50 +00001593 if (function == NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001594 // Extract exception from the parser.
1595 CHECK(isolate->has_pending_exception());
1596 i::Handle<i::JSObject> exception_handle(
1597 i::JSObject::cast(isolate->pending_exception()));
1598 i::Handle<i::String> message_string =
1599 i::Handle<i::String>::cast(i::Object::GetProperty(
1600 isolate, exception_handle, "message").ToHandleChecked());
1601
1602 if (result == kSuccess) {
1603 v8::base::OS::Print(
1604 "Parser failed on:\n"
1605 "\t%s\n"
1606 "with error:\n"
1607 "\t%s\n"
1608 "However, we expected no error.",
1609 source->ToCString().get(), message_string->ToCString().get());
1610 CHECK(false);
1611 }
1612
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 if (test_preparser && !preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614 v8::base::OS::Print(
1615 "Parser failed on:\n"
1616 "\t%s\n"
1617 "with error:\n"
1618 "\t%s\n"
1619 "However, the preparser succeeded",
1620 source->ToCString().get(), message_string->ToCString().get());
1621 CHECK(false);
1622 }
1623 // Check that preparser and parser produce the same error.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 if (test_preparser) {
1625 i::Handle<i::String> preparser_message =
1626 FormatMessage(log.ErrorMessageData());
1627 if (!i::String::Equals(message_string, preparser_message)) {
1628 v8::base::OS::Print(
1629 "Expected parser and preparser to produce the same error on:\n"
1630 "\t%s\n"
1631 "However, found the following error messages\n"
1632 "\tparser: %s\n"
1633 "\tpreparser: %s\n",
1634 source->ToCString().get(), message_string->ToCString().get(),
1635 preparser_message->ToCString().get());
1636 CHECK(false);
1637 }
Ben Murdoch692be652012-01-10 18:47:50 +00001638 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001639 } else if (test_preparser && preparse_error) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001640 v8::base::OS::Print(
1641 "Preparser failed on:\n"
1642 "\t%s\n"
1643 "with error:\n"
1644 "\t%s\n"
1645 "However, the parser succeeded",
1646 source->ToCString().get(),
1647 FormatMessage(log.ErrorMessageData())->ToCString().get());
1648 CHECK(false);
1649 } else if (result == kError) {
1650 v8::base::OS::Print(
1651 "Expected error on:\n"
1652 "\t%s\n"
1653 "However, parser and preparser succeeded",
1654 source->ToCString().get());
1655 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 } else if (test_preparser &&
1657 preparser_materialized_literals != parser_materialized_literals) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001658 v8::base::OS::Print(
1659 "Preparser materialized literals (%d) differ from Parser materialized "
1660 "literals (%d) on:\n"
1661 "\t%s\n"
1662 "However, parser and preparser succeeded",
1663 preparser_materialized_literals, parser_materialized_literals,
1664 source->ToCString().get());
1665 CHECK(false);
Ben Murdoch692be652012-01-10 18:47:50 +00001666 }
1667}
1668
1669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670void TestParserSync(const char* source, const ParserFlag* varying_flags,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671 size_t varying_flags_length,
1672 ParserSyncTestResult result = kSuccessOrError,
1673 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001674 size_t always_true_flags_length = 0,
1675 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676 size_t always_false_flags_length = 0,
1677 bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001678 i::Handle<i::String> str =
1679 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1680 for (int bits = 0; bits < (1 << varying_flags_length); bits++) {
1681 i::EnumSet<ParserFlag> flags;
1682 for (size_t flag_index = 0; flag_index < varying_flags_length;
1683 ++flag_index) {
1684 if ((bits & (1 << flag_index)) != 0) flags.Add(varying_flags[flag_index]);
1685 }
1686 for (size_t flag_index = 0; flag_index < always_true_flags_length;
1687 ++flag_index) {
1688 flags.Add(always_true_flags[flag_index]);
1689 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001690 for (size_t flag_index = 0; flag_index < always_false_flags_length;
1691 ++flag_index) {
1692 flags.Remove(always_false_flags[flag_index]);
1693 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001694 TestParserSyncWithFlags(str, flags, result, is_module);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001695 }
1696}
1697
1698
Ben Murdoch692be652012-01-10 18:47:50 +00001699TEST(ParserSync) {
1700 const char* context_data[][2] = {
1701 { "", "" },
1702 { "{", "}" },
1703 { "if (true) ", " else {}" },
1704 { "if (true) {} else ", "" },
1705 { "if (true) ", "" },
1706 { "do ", " while (false)" },
1707 { "while (false) ", "" },
1708 { "for (;;) ", "" },
1709 { "with ({})", "" },
1710 { "switch (12) { case 12: ", "}" },
1711 { "switch (12) { default: ", "}" },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001712 { "switch (12) { ", "case 12: }" },
Ben Murdoch692be652012-01-10 18:47:50 +00001713 { "label2: ", "" },
1714 { NULL, NULL }
1715 };
1716
1717 const char* statement_data[] = {
1718 "{}",
1719 "var x",
1720 "var x = 1",
1721 "const x",
1722 "const x = 1",
1723 ";",
1724 "12",
1725 "if (false) {} else ;",
1726 "if (false) {} else {}",
1727 "if (false) {} else 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001728 "if (false) ;",
Ben Murdoch692be652012-01-10 18:47:50 +00001729 "if (false) {}",
1730 "if (false) 12",
1731 "do {} while (false)",
1732 "for (;;) ;",
1733 "for (;;) {}",
1734 "for (;;) 12",
1735 "continue",
1736 "continue label",
1737 "continue\nlabel",
1738 "break",
1739 "break label",
1740 "break\nlabel",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741 // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1742 // "return",
1743 // "return 12",
1744 // "return\n12",
Ben Murdoch692be652012-01-10 18:47:50 +00001745 "with ({}) ;",
1746 "with ({}) {}",
1747 "with ({}) 12",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001748 "switch ({}) { default: }",
1749 "label3: ",
Ben Murdoch692be652012-01-10 18:47:50 +00001750 "throw",
1751 "throw 12",
1752 "throw\n12",
1753 "try {} catch(e) {}",
1754 "try {} finally {}",
1755 "try {} catch(e) {} finally {}",
1756 "debugger",
1757 NULL
1758 };
1759
1760 const char* termination_data[] = {
1761 "",
1762 ";",
1763 "\n",
1764 ";\n",
1765 "\n;",
1766 NULL
1767 };
1768
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001769 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch692be652012-01-10 18:47:50 +00001771 v8::Context::Scope context_scope(context);
1772
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1774 i::GetCurrentStackPosition() - 128 * 1024);
1775
Ben Murdoch692be652012-01-10 18:47:50 +00001776 for (int i = 0; context_data[i][0] != NULL; ++i) {
1777 for (int j = 0; statement_data[j] != NULL; ++j) {
1778 for (int k = 0; termination_data[k] != NULL; ++k) {
1779 int kPrefixLen = i::StrLength(context_data[i][0]);
1780 int kStatementLen = i::StrLength(statement_data[j]);
1781 int kTerminationLen = i::StrLength(termination_data[k]);
1782 int kSuffixLen = i::StrLength(context_data[i][1]);
1783 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1784 + kSuffixLen + i::StrLength("label: for (;;) { }");
1785
1786 // Plug the source code pieces together.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001787 i::ScopedVector<char> program(kProgramSize + 1);
1788 int length = i::SNPrintF(program,
Ben Murdoch692be652012-01-10 18:47:50 +00001789 "label: for (;;) { %s%s%s%s }",
1790 context_data[i][0],
1791 statement_data[j],
1792 termination_data[k],
1793 context_data[i][1]);
1794 CHECK(length == kProgramSize);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001795 TestParserSync(program.start(), NULL, 0);
Ben Murdoch692be652012-01-10 18:47:50 +00001796 }
1797 }
1798 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001799
1800 // Neither Harmony numeric literals nor our natives syntax have any
1801 // interaction with the flags above, so test these separately to reduce
1802 // the combinatorial explosion.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001803 TestParserSync("0o1234", NULL, 0);
1804 TestParserSync("0b1011", NULL, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001805
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001806 static const ParserFlag flags3[] = { kAllowNatives };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001807 TestParserSync("%DebugPrint(123)", flags3, arraysize(flags3));
1808}
1809
1810
1811TEST(StrictOctal) {
1812 // Test that syntax error caused by octal literal is reported correctly as
1813 // such (issue 2220).
1814 v8::V8::Initialize();
1815 v8::HandleScope scope(CcTest::isolate());
1816 v8::Context::Scope context_scope(
1817 v8::Context::New(CcTest::isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 const char* script =
1820 "\"use strict\"; \n"
1821 "a = function() { \n"
1822 " b = function() { \n"
1823 " 01; \n"
1824 " }; \n"
1825 "}; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001826 v8_compile(v8_str(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001827 CHECK(try_catch.HasCaught());
1828 v8::String::Utf8Value exception(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001829 CHECK_EQ(0,
1830 strcmp("SyntaxError: Octal literals are not allowed in strict mode.",
1831 *exception));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001832}
1833
1834
1835void RunParserSyncTest(const char* context_data[][2],
1836 const char* statement_data[],
1837 ParserSyncTestResult result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001838 const ParserFlag* flags = NULL, int flags_len = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001839 const ParserFlag* always_true_flags = NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001840 int always_true_len = 0,
1841 const ParserFlag* always_false_flags = NULL,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001842 int always_false_len = 0, bool is_module = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001843 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001844 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 v8::Context::Scope context_scope(context);
1846
1847 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1848 i::GetCurrentStackPosition() - 128 * 1024);
1849
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001850 // Experimental feature flags should not go here; pass the flags as
1851 // always_true_flags if the test needs them.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001852 static const ParserFlag default_flags[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001853 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001854 kAllowNatives,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001855 };
1856 ParserFlag* generated_flags = NULL;
1857 if (flags == NULL) {
1858 flags = default_flags;
1859 flags_len = arraysize(default_flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001860 if (always_true_flags != NULL || always_false_flags != NULL) {
1861 // Remove always_true/false_flags from default_flags (if present).
1862 CHECK((always_true_flags != NULL) == (always_true_len > 0));
1863 CHECK((always_false_flags != NULL) == (always_false_len > 0));
1864 generated_flags = new ParserFlag[flags_len + always_true_len];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 int flag_index = 0;
1866 for (int i = 0; i < flags_len; ++i) {
1867 bool use_flag = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001868 for (int j = 0; use_flag && j < always_true_len; ++j) {
1869 if (flags[i] == always_true_flags[j]) use_flag = false;
1870 }
1871 for (int j = 0; use_flag && j < always_false_len; ++j) {
1872 if (flags[i] == always_false_flags[j]) use_flag = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 }
1874 if (use_flag) generated_flags[flag_index++] = flags[i];
1875 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 flags_len = flag_index;
1877 flags = generated_flags;
1878 }
1879 }
1880 for (int i = 0; context_data[i][0] != NULL; ++i) {
1881 for (int j = 0; statement_data[j] != NULL; ++j) {
1882 int kPrefixLen = i::StrLength(context_data[i][0]);
1883 int kStatementLen = i::StrLength(statement_data[j]);
1884 int kSuffixLen = i::StrLength(context_data[i][1]);
1885 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1886
1887 // Plug the source code pieces together.
1888 i::ScopedVector<char> program(kProgramSize + 1);
1889 int length = i::SNPrintF(program,
1890 "%s%s%s",
1891 context_data[i][0],
1892 statement_data[j],
1893 context_data[i][1]);
1894 CHECK(length == kProgramSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001895 TestParserSync(program.start(), flags, flags_len, result,
1896 always_true_flags, always_true_len, always_false_flags,
1897 always_false_len, is_module);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001898 }
1899 }
1900 delete[] generated_flags;
1901}
1902
1903
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001904void RunModuleParserSyncTest(const char* context_data[][2],
1905 const char* statement_data[],
1906 ParserSyncTestResult result,
1907 const ParserFlag* flags = NULL, int flags_len = 0,
1908 const ParserFlag* always_true_flags = NULL,
1909 int always_true_len = 0,
1910 const ParserFlag* always_false_flags = NULL,
1911 int always_false_len = 0) {
1912 bool flag = i::FLAG_harmony_modules;
1913 i::FLAG_harmony_modules = true;
1914 RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1915 always_true_flags, always_true_len, always_false_flags,
1916 always_false_len, true);
1917 i::FLAG_harmony_modules = flag;
1918}
1919
1920
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001921TEST(ErrorsEvalAndArguments) {
1922 // Tests that both preparsing and parsing produce the right kind of errors for
1923 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1924 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1925 // isn't.
1926 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001927 {"\"use strict\";", ""},
1928 {"\"use strong\";", ""},
1929 {"var eval; function test_func() {\"use strict\"; ", "}"},
1930 {"var eval; function test_func() {\"use strong\"; ", "}"},
1931 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001932
1933 const char* statement_data[] = {
1934 "var eval;",
1935 "var arguments",
1936 "var foo, eval;",
1937 "var foo, arguments;",
1938 "try { } catch (eval) { }",
1939 "try { } catch (arguments) { }",
1940 "function eval() { }",
1941 "function arguments() { }",
1942 "function foo(eval) { }",
1943 "function foo(arguments) { }",
1944 "function foo(bar, eval) { }",
1945 "function foo(bar, arguments) { }",
1946 "(eval) => { }",
1947 "(arguments) => { }",
1948 "(foo, eval) => { }",
1949 "(foo, arguments) => { }",
1950 "eval = 1;",
1951 "arguments = 1;",
1952 "var foo = eval = 1;",
1953 "var foo = arguments = 1;",
1954 "++eval;",
1955 "++arguments;",
1956 "eval++;",
1957 "arguments++;",
1958 NULL
1959 };
1960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001961 static const ParserFlag always_flags[] = {kAllowStrongMode};
1962 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
1963 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001964}
1965
1966
1967TEST(NoErrorsEvalAndArgumentsSloppy) {
1968 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1969 // identifiers when needed.
1970 const char* context_data[][2] = {
1971 { "", "" },
1972 { "function test_func() {", "}"},
1973 { NULL, NULL }
1974 };
1975
1976 const char* statement_data[] = {
1977 "var eval;",
1978 "var arguments",
1979 "var foo, eval;",
1980 "var foo, arguments;",
1981 "try { } catch (eval) { }",
1982 "try { } catch (arguments) { }",
1983 "function eval() { }",
1984 "function arguments() { }",
1985 "function foo(eval) { }",
1986 "function foo(arguments) { }",
1987 "function foo(bar, eval) { }",
1988 "function foo(bar, arguments) { }",
1989 "eval = 1;",
1990 "arguments = 1;",
1991 "var foo = eval = 1;",
1992 "var foo = arguments = 1;",
1993 "++eval;",
1994 "++arguments;",
1995 "eval++;",
1996 "arguments++;",
1997 NULL
1998 };
1999
2000 RunParserSyncTest(context_data, statement_data, kSuccess);
2001}
2002
2003
2004TEST(NoErrorsEvalAndArgumentsStrict) {
2005 const char* context_data[][2] = {
2006 { "\"use strict\";", "" },
2007 { "function test_func() { \"use strict\";", "}" },
2008 { "() => { \"use strict\"; ", "}" },
2009 { NULL, NULL }
2010 };
2011
2012 const char* statement_data[] = {
2013 "eval;",
2014 "arguments;",
2015 "var foo = eval;",
2016 "var foo = arguments;",
2017 "var foo = { eval: 1 };",
2018 "var foo = { arguments: 1 };",
2019 "var foo = { }; foo.eval = {};",
2020 "var foo = { }; foo.arguments = {};",
2021 NULL
2022 };
2023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002024 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002025}
2026
2027
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002028#define FUTURE_STRICT_RESERVED_WORDS(V) \
2029 V(implements) \
2030 V(interface) \
2031 V(let) \
2032 V(package) \
2033 V(private) \
2034 V(protected) \
2035 V(public) \
2036 V(static) \
2037 V(yield)
2038
2039
2040#define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
2041 V(implements) \
2042 V(let) \
2043 V(static) \
2044 V(yield)
2045
2046
2047#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2048 "var " #NAME ";", \
2049 "var foo, " #NAME ";", \
2050 "try { } catch (" #NAME ") { }", \
2051 "function " #NAME "() { }", \
2052 "(function " #NAME "() { })", \
2053 "function foo(" #NAME ") { }", \
2054 "function foo(bar, " #NAME ") { }", \
2055 #NAME " = 1;", \
2056 #NAME " += 1;", \
2057 "var foo = " #NAME " = 1;", \
2058 "++" #NAME ";", \
2059 #NAME " ++;",
2060
2061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062TEST(ErrorsFutureStrictReservedWords) {
2063 // Tests that both preparsing and parsing produce the right kind of errors for
2064 // using future strict reserved words as identifiers. Without the strict mode,
2065 // it's ok to use future strict reserved words as identifiers. With the strict
2066 // mode, it isn't.
2067 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002068 {"function test_func() {\"use strict\"; ", "}"},
2069 {"() => { \"use strict\"; ", "}"},
2070 {"function test_func() {\"use strong\"; ", "}"},
2071 {"() => { \"use strong\"; ", "}"},
2072 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002073
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002074 const char* statement_data[] {
2075 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076 NULL
2077 };
2078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002079 static const ParserFlag always_flags[] = {kAllowStrongMode};
2080 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2081 arraysize(always_flags));
2082 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2083 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002084}
2085
2086
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002087#undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2088
2089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090TEST(NoErrorsFutureStrictReservedWords) {
2091 const char* context_data[][2] = {
2092 { "", "" },
2093 { "function test_func() {", "}"},
2094 { "() => {", "}" },
2095 { NULL, NULL }
2096 };
2097
2098 const char* statement_data[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002099 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002100 NULL
2101 };
2102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002103 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002104}
2105
2106
2107TEST(ErrorsReservedWords) {
2108 // Tests that both preparsing and parsing produce the right kind of errors for
2109 // using future reserved words as identifiers. These tests don't depend on the
2110 // strict mode.
2111 const char* context_data[][2] = {
2112 { "", "" },
2113 { "\"use strict\";", "" },
2114 { "var eval; function test_func() {", "}"},
2115 { "var eval; function test_func() {\"use strict\"; ", "}"},
2116 { "var eval; () => {", "}"},
2117 { "var eval; () => {\"use strict\"; ", "}"},
2118 { NULL, NULL }
2119 };
2120
2121 const char* statement_data[] = {
2122 "var super;",
2123 "var foo, super;",
2124 "try { } catch (super) { }",
2125 "function super() { }",
2126 "function foo(super) { }",
2127 "function foo(bar, super) { }",
2128 "(super) => { }",
2129 "(bar, super) => { }",
2130 "super = 1;",
2131 "var foo = super = 1;",
2132 "++super;",
2133 "super++;",
2134 "function foo super",
2135 NULL
2136 };
2137
2138 RunParserSyncTest(context_data, statement_data, kError);
2139}
2140
2141
2142TEST(NoErrorsLetSloppyAllModes) {
2143 // In sloppy mode, it's okay to use "let" as identifier.
2144 const char* context_data[][2] = {
2145 { "", "" },
2146 { "function f() {", "}" },
2147 { "(function f() {", "})" },
2148 { NULL, NULL }
2149 };
2150
2151 const char* statement_data[] = {
2152 "var let;",
2153 "var foo, let;",
2154 "try { } catch (let) { }",
2155 "function let() { }",
2156 "(function let() { })",
2157 "function foo(let) { }",
2158 "function foo(bar, let) { }",
2159 "let = 1;",
2160 "var foo = let = 1;",
2161 "let * 2;",
2162 "++let;",
2163 "let++;",
2164 "let: 34",
2165 "function let(let) { let: let(let + let(0)); }",
2166 "({ let: 1 })",
2167 "({ get let() { 1 } })",
2168 "let(100)",
2169 NULL
2170 };
2171
2172 RunParserSyncTest(context_data, statement_data, kSuccess);
2173}
2174
2175
2176TEST(NoErrorsYieldSloppyAllModes) {
2177 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2178 // generator (see other test).
2179 const char* context_data[][2] = {
2180 { "", "" },
2181 { "function not_gen() {", "}" },
2182 { "(function not_gen() {", "})" },
2183 { NULL, NULL }
2184 };
2185
2186 const char* statement_data[] = {
2187 "var yield;",
2188 "var foo, yield;",
2189 "try { } catch (yield) { }",
2190 "function yield() { }",
2191 "(function yield() { })",
2192 "function foo(yield) { }",
2193 "function foo(bar, yield) { }",
2194 "yield = 1;",
2195 "var foo = yield = 1;",
2196 "yield * 2;",
2197 "++yield;",
2198 "yield++;",
2199 "yield: 34",
2200 "function yield(yield) { yield: yield (yield + yield(0)); }",
2201 "({ yield: 1 })",
2202 "({ get yield() { 1 } })",
2203 "yield(100)",
2204 "yield[100]",
2205 NULL
2206 };
2207
2208 RunParserSyncTest(context_data, statement_data, kSuccess);
2209}
2210
2211
2212TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2213 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2214 // generator (see next test).
2215 const char* context_data[][2] = {
2216 { "", "" },
2217 { "function not_gen() {", "}" },
2218 { "function * gen() { function not_gen() {", "} }" },
2219 { "(function not_gen() {", "})" },
2220 { "(function * gen() { (function not_gen() {", "}) })" },
2221 { NULL, NULL }
2222 };
2223
2224 const char* statement_data[] = {
2225 "var yield;",
2226 "var foo, yield;",
2227 "try { } catch (yield) { }",
2228 "function yield() { }",
2229 "(function yield() { })",
2230 "function foo(yield) { }",
2231 "function foo(bar, yield) { }",
2232 "function * yield() { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002233 "yield = 1;",
2234 "var foo = yield = 1;",
2235 "yield * 2;",
2236 "++yield;",
2237 "yield++;",
2238 "yield: 34",
2239 "function yield(yield) { yield: yield (yield + yield(0)); }",
2240 "({ yield: 1 })",
2241 "({ get yield() { 1 } })",
2242 "yield(100)",
2243 "yield[100]",
2244 NULL
2245 };
2246
2247 RunParserSyncTest(context_data, statement_data, kSuccess);
2248}
2249
2250
2251TEST(ErrorsYieldStrict) {
2252 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002253 {"\"use strict\";", ""},
2254 {"\"use strict\"; function not_gen() {", "}"},
2255 {"function test_func() {\"use strict\"; ", "}"},
2256 {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2257 {"\"use strict\"; (function not_gen() {", "})"},
2258 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2259 {"() => {\"use strict\"; ", "}"},
2260 {"\"use strong\";", ""},
2261 {"\"use strong\"; function not_gen() {", "}"},
2262 {"function test_func() {\"use strong\"; ", "}"},
2263 {"\"use strong\"; function * gen() { function not_gen() {", "} }"},
2264 {"\"use strong\"; (function not_gen() {", "})"},
2265 {"\"use strong\"; (function * gen() { (function not_gen() {", "}) })"},
2266 {"() => {\"use strong\"; ", "}"},
2267 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002268
2269 const char* statement_data[] = {
2270 "var yield;",
2271 "var foo, yield;",
2272 "try { } catch (yield) { }",
2273 "function yield() { }",
2274 "(function yield() { })",
2275 "function foo(yield) { }",
2276 "function foo(bar, yield) { }",
2277 "function * yield() { }",
2278 "(function * yield() { })",
2279 "yield = 1;",
2280 "var foo = yield = 1;",
2281 "++yield;",
2282 "yield++;",
2283 "yield: 34;",
2284 NULL
2285 };
2286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002287 static const ParserFlag always_flags[] = {kAllowStrongMode};
2288 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2289 arraysize(always_flags));
2290}
2291
2292
2293TEST(ErrorsYieldSloppy) {
2294 const char* context_data[][2] = {
2295 { "", "" },
2296 { "function not_gen() {", "}" },
2297 { "(function not_gen() {", "})" },
2298 { NULL, NULL }
2299 };
2300
2301 const char* statement_data[] = {
2302 "(function * yield() { })",
2303 NULL
2304 };
2305
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002306 RunParserSyncTest(context_data, statement_data, kError);
2307}
2308
2309
2310TEST(NoErrorsGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002311 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002312 const char* context_data[][2] = {
2313 { "function * gen() {", "}" },
2314 { "(function * gen() {", "})" },
2315 { "(function * () {", "})" },
2316 { NULL, NULL }
2317 };
2318
2319 const char* statement_data[] = {
2320 // A generator without a body is valid.
2321 ""
2322 // Valid yield expressions inside generators.
2323 "yield 2;",
2324 "yield * 2;",
2325 "yield * \n 2;",
2326 "yield yield 1;",
2327 "yield * yield * 1;",
2328 "yield 3 + (yield 4);",
2329 "yield * 3 + (yield * 4);",
2330 "(yield * 3) + (yield * 4);",
2331 "yield 3; yield 4;",
2332 "yield * 3; yield * 4;",
2333 "(function (yield) { })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002334 "(function yield() { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002335 "yield { yield: 12 }",
2336 "yield /* comment */ { yield: 12 }",
2337 "yield * \n { yield: 12 }",
2338 "yield /* comment */ * \n { yield: 12 }",
2339 // You can return in a generator.
2340 "yield 1; return",
2341 "yield * 1; return",
2342 "yield 1; return 37",
2343 "yield * 1; return 37",
2344 "yield 1; return 37; yield 'dead';",
2345 "yield * 1; return 37; yield * 'dead';",
2346 // Yield is still a valid key in object literals.
2347 "({ yield: 1 })",
2348 "({ get yield() { } })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002349 // And in assignment pattern computed properties
2350 "({ [yield]: x } = { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002351 // Yield without RHS.
2352 "yield;",
2353 "yield",
2354 "yield\n",
2355 "yield /* comment */"
2356 "yield // comment\n"
2357 "(yield)",
2358 "[yield]",
2359 "{yield}",
2360 "yield, yield",
2361 "yield; yield",
2362 "(yield) ? yield : yield",
2363 "(yield) \n ? yield : yield",
2364 // If there is a newline before the next token, we don't look for RHS.
2365 "yield\nfor (;;) {}",
2366 NULL
2367 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002368 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002369
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002370 static const ParserFlag always_flags[] = {
2371 kAllowHarmonyDestructuringAssignment};
2372 RunParserSyncTest(context_data, statement_data, kSuccess, nullptr, 0,
2373 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002374}
2375
2376
2377TEST(ErrorsYieldGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002378 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002379 const char* context_data[][2] = {
2380 { "function * gen() {", "}" },
2381 { "\"use strict\"; function * gen() {", "}" },
2382 { NULL, NULL }
2383 };
2384
2385 const char* statement_data[] = {
2386 // Invalid yield expressions inside generators.
2387 "var yield;",
2388 "var foo, yield;",
2389 "try { } catch (yield) { }",
2390 "function yield() { }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002391 // The name of the NFE is bound in the generator, which does not permit
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002392 // yield to be an identifier.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002393 "(function * yield() { })",
2394 // Yield isn't valid as a formal parameter for generators.
2395 "function * foo(yield) { }",
2396 "(function * foo(yield) { })",
2397 "yield = 1;",
2398 "var foo = yield = 1;",
2399 "++yield;",
2400 "yield++;",
2401 "yield *",
2402 "(yield *)",
2403 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2404 // is invalid.
2405 "yield 3 + yield 4;",
2406 "yield: 34",
2407 "yield ? 1 : 2",
2408 // Parses as yield (/ yield): invalid.
2409 "yield / yield",
2410 "+ yield",
2411 "+ yield 3",
2412 // Invalid (no newline allowed between yield and *).
2413 "yield\n*3",
2414 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2415 // object literal, and yield is not a valid label).
2416 "yield\n{yield: 42}",
2417 "yield /* comment */\n {yield: 42}",
2418 "yield //comment\n {yield: 42}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002419 // Destructuring binding and assignment are both disallowed
2420 "var [yield] = [42];",
2421 "var {foo: yield} = {a: 42};",
2422 "[yield] = [42];",
2423 "({a: yield} = {a: 42});",
2424 // Also disallow full yield expressions on LHS
2425 "var [yield 24] = [42];",
2426 "var {foo: yield 24} = {a: 42};",
2427 "[yield 24] = [42];",
2428 "({a: yield 24} = {a: 42});",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002429 NULL
2430 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002431 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002432
2433 RunParserSyncTest(context_data, statement_data, kError);
2434}
2435
2436
2437TEST(ErrorsNameOfStrictFunction) {
2438 // Tests that illegal tokens as names of a strict function produce the correct
2439 // errors.
2440 const char* context_data[][2] = {
2441 { "function ", ""},
2442 { "\"use strict\"; function", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002443 { "\"use strong\"; function", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002444 { "function * ", ""},
2445 { "\"use strict\"; function * ", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002446 { "\"use strong\"; function * ", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002447 { NULL, NULL }
2448 };
2449
2450 const char* statement_data[] = {
2451 "eval() {\"use strict\";}",
2452 "arguments() {\"use strict\";}",
2453 "interface() {\"use strict\";}",
2454 "yield() {\"use strict\";}",
2455 // Future reserved words are always illegal
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002456 "super() { }",
2457 "super() {\"use strict\";}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002458 NULL
2459 };
2460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002461 static const ParserFlag always_flags[] = {kAllowStrongMode};
2462 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2463 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002464}
2465
2466
2467TEST(NoErrorsNameOfStrictFunction) {
2468 const char* context_data[][2] = {
2469 { "function ", ""},
2470 { NULL, NULL }
2471 };
2472
2473 const char* statement_data[] = {
2474 "eval() { }",
2475 "arguments() { }",
2476 "interface() { }",
2477 "yield() { }",
2478 NULL
2479 };
2480
2481 RunParserSyncTest(context_data, statement_data, kSuccess);
2482}
2483
2484
2485TEST(NoErrorsNameOfStrictGenerator) {
2486 const char* context_data[][2] = {
2487 { "function * ", ""},
2488 { NULL, NULL }
2489 };
2490
2491 const char* statement_data[] = {
2492 "eval() { }",
2493 "arguments() { }",
2494 "interface() { }",
2495 "yield() { }",
2496 NULL
2497 };
2498
2499 RunParserSyncTest(context_data, statement_data, kSuccess);
2500}
2501
2502
2503TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2504 // Using future reserved words as labels is always an error.
2505 const char* context_data[][2] = {
2506 { "", ""},
2507 { "function test_func() {", "}" },
2508 { "() => {", "}" },
2509 { NULL, NULL }
2510 };
2511
2512 const char* statement_data[] = {
2513 "super: while(true) { break super; }",
2514 NULL
2515 };
2516
2517 RunParserSyncTest(context_data, statement_data, kError);
2518}
2519
2520
2521TEST(ErrorsIllegalWordsAsLabelsStrict) {
2522 // Tests that illegal tokens as labels produce the correct errors.
2523 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002524 {"\"use strict\";", ""},
2525 {"function test_func() {\"use strict\"; ", "}"},
2526 {"() => {\"use strict\"; ", "}"},
2527 {"\"use strong\";", ""},
2528 {"function test_func() {\"use strong\"; ", "}"},
2529 {"() => {\"use strong\"; ", "}"},
2530 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002531
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002532#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002533 const char* statement_data[] = {
2534 "super: while(true) { break super; }",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002535 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002536 NULL
2537 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002538#undef LABELLED_WHILE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002540 static const ParserFlag always_flags[] = {kAllowStrongMode};
2541 RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
2542 arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002543}
2544
2545
2546TEST(NoErrorsIllegalWordsAsLabels) {
2547 // Using eval and arguments as labels is legal even in strict mode.
2548 const char* context_data[][2] = {
2549 { "", ""},
2550 { "function test_func() {", "}" },
2551 { "() => {", "}" },
2552 { "\"use strict\";", "" },
2553 { "\"use strict\"; function test_func() {", "}" },
2554 { "\"use strict\"; () => {", "}" },
2555 { NULL, NULL }
2556 };
2557
2558 const char* statement_data[] = {
2559 "mylabel: while(true) { break mylabel; }",
2560 "eval: while(true) { break eval; }",
2561 "arguments: while(true) { break arguments; }",
2562 NULL
2563 };
2564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002565 RunParserSyncTest(context_data, statement_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002566}
2567
2568
2569TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2570 const char* context_data[][2] = {
2571 { "", ""},
2572 { "function test_func() {", "}" },
2573 { "() => {", "}" },
2574 { NULL, NULL }
2575 };
2576
2577#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2578 const char* statement_data[] {
2579 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2580 NULL
2581 };
2582#undef LABELLED_WHILE
2583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002584 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002585}
2586
2587
2588TEST(ErrorsParenthesizedLabels) {
2589 // Parenthesized identifiers shouldn't be recognized as labels.
2590 const char* context_data[][2] = {
2591 { "", ""},
2592 { "function test_func() {", "}" },
2593 { "() => {", "}" },
2594 { NULL, NULL }
2595 };
2596
2597 const char* statement_data[] = {
2598 "(mylabel): while(true) { break mylabel; }",
2599 NULL
2600 };
2601
2602 RunParserSyncTest(context_data, statement_data, kError);
2603}
2604
2605
2606TEST(NoErrorsParenthesizedDirectivePrologue) {
2607 // Parenthesized directive prologue shouldn't be recognized.
2608 const char* context_data[][2] = {
2609 { "", ""},
2610 { NULL, NULL }
2611 };
2612
2613 const char* statement_data[] = {
2614 "(\"use strict\"); var eval;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002615 "(\"use strong\"); var eval;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002616 NULL
2617 };
2618
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002619 static const ParserFlag always_flags[] = {kAllowStrongMode};
2620 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
2621 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002622}
2623
2624
2625TEST(ErrorsNotAnIdentifierName) {
2626 const char* context_data[][2] = {
2627 { "", ""},
2628 { "\"use strict\";", ""},
2629 { NULL, NULL }
2630 };
2631
2632 const char* statement_data[] = {
2633 "var foo = {}; foo.{;",
2634 "var foo = {}; foo.};",
2635 "var foo = {}; foo.=;",
2636 "var foo = {}; foo.888;",
2637 "var foo = {}; foo.-;",
2638 "var foo = {}; foo.--;",
2639 NULL
2640 };
2641
2642 RunParserSyncTest(context_data, statement_data, kError);
2643}
2644
2645
2646TEST(NoErrorsIdentifierNames) {
2647 // Keywords etc. are valid as property names.
2648 const char* context_data[][2] = {
2649 { "", ""},
2650 { "\"use strict\";", ""},
2651 { NULL, NULL }
2652 };
2653
2654 const char* statement_data[] = {
2655 "var foo = {}; foo.if;",
2656 "var foo = {}; foo.yield;",
2657 "var foo = {}; foo.super;",
2658 "var foo = {}; foo.interface;",
2659 "var foo = {}; foo.eval;",
2660 "var foo = {}; foo.arguments;",
2661 NULL
2662 };
2663
2664 RunParserSyncTest(context_data, statement_data, kSuccess);
2665}
2666
2667
2668TEST(DontRegressPreParserDataSizes) {
2669 // These tests make sure that Parser doesn't start producing less "preparse
2670 // data" (data which the embedder can cache).
2671 v8::V8::Initialize();
2672 v8::Isolate* isolate = CcTest::isolate();
2673 v8::HandleScope handles(isolate);
2674
2675 CcTest::i_isolate()->stack_guard()->SetStackLimit(
2676 i::GetCurrentStackPosition() - 128 * 1024);
2677
2678 struct TestCase {
2679 const char* program;
2680 int functions;
2681 } test_cases[] = {
2682 // No functions.
2683 {"var x = 42;", 0},
2684 // Functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002685 {"function foo() {}", 1},
2686 {"function foo() {} function bar() {}", 2},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002687 // Getter / setter functions are recorded as functions if they're on the top
2688 // level.
2689 {"var x = {get foo(){} };", 1},
2690 // Functions insize lazy functions are not recorded.
2691 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2692 {"function lazy() { var x = {get foo(){} } }", 1},
2693 {NULL, 0}
2694 };
2695
2696 for (int i = 0; test_cases[i].program; i++) {
2697 const char* program = test_cases[i].program;
2698 i::Factory* factory = CcTest::i_isolate()->factory();
2699 i::Handle<i::String> source =
2700 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2701 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002702 i::Zone zone;
2703 i::ParseInfo info(&zone, script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002704 i::ScriptData* sd = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002705 info.set_cached_data(&sd);
2706 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
2707 info.set_allow_lazy_parsing();
2708 i::Parser::ParseStatic(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002709 i::ParseData* pd = i::ParseData::FromCachedData(sd);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002710
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002711 if (pd->FunctionCount() != test_cases[i].functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002712 v8::base::OS::Print(
2713 "Expected preparse data for program:\n"
2714 "\t%s\n"
2715 "to contain %d functions, however, received %d functions.\n",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002716 program, test_cases[i].functions, pd->FunctionCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002717 CHECK(false);
2718 }
2719 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002720 delete pd;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002721 }
2722}
2723
2724
2725TEST(FunctionDeclaresItselfStrict) {
2726 // Tests that we produce the right kinds of errors when a function declares
2727 // itself strict (we cannot produce there errors as soon as we see the
2728 // offending identifiers, because we don't know at that point whether the
2729 // function is strict or not).
2730 const char* context_data[][2] = {
2731 {"function eval() {", "}"},
2732 {"function arguments() {", "}"},
2733 {"function yield() {", "}"},
2734 {"function interface() {", "}"},
2735 {"function foo(eval) {", "}"},
2736 {"function foo(arguments) {", "}"},
2737 {"function foo(yield) {", "}"},
2738 {"function foo(interface) {", "}"},
2739 {"function foo(bar, eval) {", "}"},
2740 {"function foo(bar, arguments) {", "}"},
2741 {"function foo(bar, yield) {", "}"},
2742 {"function foo(bar, interface) {", "}"},
2743 {"function foo(bar, bar) {", "}"},
2744 { NULL, NULL }
2745 };
2746
2747 const char* strict_statement_data[] = {
2748 "\"use strict\";",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 "\"use strong\";",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002750 NULL
2751 };
2752
2753 const char* non_strict_statement_data[] = {
2754 ";",
2755 NULL
2756 };
2757
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002758 static const ParserFlag always_flags[] = {kAllowStrongMode};
2759 RunParserSyncTest(context_data, strict_statement_data, kError, NULL, 0,
2760 always_flags, arraysize(always_flags));
2761 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess, NULL, 0,
2762 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002763}
2764
2765
2766TEST(ErrorsTryWithoutCatchOrFinally) {
2767 const char* context_data[][2] = {
2768 {"", ""},
2769 { NULL, NULL }
2770 };
2771
2772 const char* statement_data[] = {
2773 "try { }",
2774 "try { } foo();",
2775 "try { } catch (e) foo();",
2776 "try { } catch { }",
2777 "try { } finally foo();",
2778 NULL
2779 };
2780
2781 RunParserSyncTest(context_data, statement_data, kError);
2782}
2783
2784
2785TEST(NoErrorsTryCatchFinally) {
2786 const char* context_data[][2] = {
2787 {"", ""},
2788 { NULL, NULL }
2789 };
2790
2791 const char* statement_data[] = {
2792 "try { } catch (e) { }",
2793 "try { } catch (e) { } finally { }",
2794 "try { } finally { }",
2795 NULL
2796 };
2797
2798 RunParserSyncTest(context_data, statement_data, kSuccess);
2799}
2800
2801
2802TEST(ErrorsRegexpLiteral) {
2803 const char* context_data[][2] = {
2804 {"var r = ", ""},
2805 { NULL, NULL }
2806 };
2807
2808 const char* statement_data[] = {
2809 "/unterminated",
2810 NULL
2811 };
2812
2813 RunParserSyncTest(context_data, statement_data, kError);
2814}
2815
2816
2817TEST(NoErrorsRegexpLiteral) {
2818 const char* context_data[][2] = {
2819 {"var r = ", ""},
2820 { NULL, NULL }
2821 };
2822
2823 const char* statement_data[] = {
2824 "/foo/",
2825 "/foo/g",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002826 NULL
2827 };
2828
2829 RunParserSyncTest(context_data, statement_data, kSuccess);
2830}
2831
2832
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002833TEST(NoErrorsNewExpression) {
2834 const char* context_data[][2] = {
2835 {"", ""},
2836 {"var f =", ""},
2837 { NULL, NULL }
2838 };
2839
2840 const char* statement_data[] = {
2841 "new foo",
2842 "new foo();",
2843 "new foo(1);",
2844 "new foo(1, 2);",
2845 // The first () will be processed as a part of the NewExpression and the
2846 // second () will be processed as part of LeftHandSideExpression.
2847 "new foo()();",
2848 // The first () will be processed as a part of the inner NewExpression and
2849 // the second () will be processed as a part of the outer NewExpression.
2850 "new new foo()();",
2851 "new foo.bar;",
2852 "new foo.bar();",
2853 "new foo.bar.baz;",
2854 "new foo.bar().baz;",
2855 "new foo[bar];",
2856 "new foo[bar]();",
2857 "new foo[bar][baz];",
2858 "new foo[bar]()[baz];",
2859 "new foo[bar].baz(baz)()[bar].baz;",
2860 "new \"foo\"", // Runtime error
2861 "new 1", // Runtime error
2862 // This even runs:
2863 "(new new Function(\"this.x = 1\")).x;",
2864 "new new Test_Two(String, 2).v(0123).length;",
2865 NULL
2866 };
2867
2868 RunParserSyncTest(context_data, statement_data, kSuccess);
2869}
2870
2871
2872TEST(ErrorsNewExpression) {
2873 const char* context_data[][2] = {
2874 {"", ""},
2875 {"var f =", ""},
2876 { NULL, NULL }
2877 };
2878
2879 const char* statement_data[] = {
2880 "new foo bar",
2881 "new ) foo",
2882 "new ++foo",
2883 "new foo ++",
2884 NULL
2885 };
2886
2887 RunParserSyncTest(context_data, statement_data, kError);
2888}
2889
2890
2891TEST(StrictObjectLiteralChecking) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002892 const char* context_data[][2] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002893 {"\"use strict\"; var myobject = {", "};"},
2894 {"\"use strict\"; var myobject = {", ",};"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002895 {"var myobject = {", "};"},
2896 {"var myobject = {", ",};"},
2897 { NULL, NULL }
2898 };
2899
2900 // These are only errors in strict mode.
2901 const char* statement_data[] = {
2902 "foo: 1, foo: 2",
2903 "\"foo\": 1, \"foo\": 2",
2904 "foo: 1, \"foo\": 2",
2905 "1: 1, 1: 2",
2906 "1: 1, \"1\": 2",
2907 "get: 1, get: 2", // Not a getter for real, just a property called get.
2908 "set: 1, set: 2", // Not a setter for real, just a property called set.
2909 NULL
2910 };
2911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002912 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002913}
2914
2915
2916TEST(ErrorsObjectLiteralChecking) {
2917 const char* context_data[][2] = {
2918 {"\"use strict\"; var myobject = {", "};"},
2919 {"var myobject = {", "};"},
2920 { NULL, NULL }
2921 };
2922
2923 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002924 ",",
2925 // Wrong number of parameters
2926 "get bar(x) {}",
2927 "get bar(x, y) {}",
2928 "set bar() {}",
2929 "set bar(x, y) {}",
2930 // Parsing FunctionLiteral for getter or setter fails
2931 "get foo( +",
2932 "get foo() \"error\"",
2933 NULL
2934 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002935
2936 RunParserSyncTest(context_data, statement_data, kError);
2937}
2938
2939
2940TEST(NoErrorsObjectLiteralChecking) {
2941 const char* context_data[][2] = {
2942 {"var myobject = {", "};"},
2943 {"var myobject = {", ",};"},
2944 {"\"use strict\"; var myobject = {", "};"},
2945 {"\"use strict\"; var myobject = {", ",};"},
2946 { NULL, NULL }
2947 };
2948
2949 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002950 "foo: 1, get foo() {}",
2951 "foo: 1, set foo(v) {}",
2952 "\"foo\": 1, get \"foo\"() {}",
2953 "\"foo\": 1, set \"foo\"(v) {}",
2954 "1: 1, get 1() {}",
2955 "1: 1, set 1(v) {}",
2956 "get foo() {}, get foo() {}",
2957 "set foo(_) {}, set foo(v) {}",
2958 "foo: 1, get \"foo\"() {}",
2959 "foo: 1, set \"foo\"(v) {}",
2960 "\"foo\": 1, get foo() {}",
2961 "\"foo\": 1, set foo(v) {}",
2962 "1: 1, get \"1\"() {}",
2963 "1: 1, set \"1\"(v) {}",
2964 "\"1\": 1, get 1() {}",
2965 "\"1\": 1, set 1(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002966 "foo: 1, bar: 2",
2967 "\"foo\": 1, \"bar\": 2",
2968 "1: 1, 2: 2",
2969 // Syntax: IdentifierName ':' AssignmentExpression
2970 "foo: bar = 5 + baz",
2971 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2972 "get foo() {}",
2973 "get \"foo\"() {}",
2974 "get 1() {}",
2975 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2976 // '{' FunctionBody '}'
2977 "set foo(v) {}",
2978 "set \"foo\"(v) {}",
2979 "set 1(v) {}",
2980 // Non-colliding getters and setters -> no errors
2981 "foo: 1, get bar() {}",
2982 "foo: 1, set bar(v) {}",
2983 "\"foo\": 1, get \"bar\"() {}",
2984 "\"foo\": 1, set \"bar\"(v) {}",
2985 "1: 1, get 2() {}",
2986 "1: 1, set 2(v) {}",
2987 "get: 1, get foo() {}",
2988 "set: 1, set foo(_) {}",
2989 // Keywords, future reserved and strict future reserved are also allowed as
2990 // property names.
2991 "if: 4",
2992 "interface: 5",
2993 "super: 6",
2994 "eval: 7",
2995 "arguments: 8",
2996 NULL
2997 };
2998
2999 RunParserSyncTest(context_data, statement_data, kSuccess);
3000}
3001
3002
3003TEST(TooManyArguments) {
3004 const char* context_data[][2] = {
3005 {"foo(", "0)"},
3006 { NULL, NULL }
3007 };
3008
3009 using v8::internal::Code;
3010 char statement[Code::kMaxArguments * 2 + 1];
3011 for (int i = 0; i < Code::kMaxArguments; ++i) {
3012 statement[2 * i] = '0';
3013 statement[2 * i + 1] = ',';
3014 }
3015 statement[Code::kMaxArguments * 2] = 0;
3016
3017 const char* statement_data[] = {
3018 statement,
3019 NULL
3020 };
3021
3022 // The test is quite slow, so run it with a reduced set of flags.
3023 static const ParserFlag empty_flags[] = {kAllowLazy};
3024 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
3025}
3026
3027
3028TEST(StrictDelete) {
3029 // "delete <Identifier>" is not allowed in strict mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003030 const char* strong_context_data[][2] = {
3031 {"\"use strong\"; ", ""},
3032 { NULL, NULL }
3033 };
3034
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003035 const char* strict_context_data[][2] = {
3036 {"\"use strict\"; ", ""},
3037 { NULL, NULL }
3038 };
3039
3040 const char* sloppy_context_data[][2] = {
3041 {"", ""},
3042 { NULL, NULL }
3043 };
3044
3045 // These are errors in the strict mode.
3046 const char* sloppy_statement_data[] = {
3047 "delete foo;",
3048 "delete foo + 1;",
3049 "delete (foo);",
3050 "delete eval;",
3051 "delete interface;",
3052 NULL
3053 };
3054
3055 // These are always OK
3056 const char* good_statement_data[] = {
3057 "delete this;",
3058 "delete 1;",
3059 "delete 1 + 2;",
3060 "delete foo();",
3061 "delete foo.bar;",
3062 "delete foo[bar];",
3063 "delete foo--;",
3064 "delete --foo;",
3065 "delete new foo();",
3066 "delete new foo(bar);",
3067 NULL
3068 };
3069
3070 // These are always errors
3071 const char* bad_statement_data[] = {
3072 "delete if;",
3073 NULL
3074 };
3075
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003076 static const ParserFlag always_flags[] = {kAllowStrongMode};
3077 RunParserSyncTest(strong_context_data, sloppy_statement_data, kError, NULL, 0,
3078 always_flags, arraysize(always_flags));
3079 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError, NULL, 0,
3080 always_flags, arraysize(always_flags));
3081 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess, NULL,
3082 0, always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003083
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003084 RunParserSyncTest(strong_context_data, good_statement_data, kError, NULL, 0,
3085 always_flags, arraysize(always_flags));
3086 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess, NULL, 0,
3087 always_flags, arraysize(always_flags));
3088 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess, NULL, 0,
3089 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003091 RunParserSyncTest(strong_context_data, bad_statement_data, kError, NULL, 0,
3092 always_flags, arraysize(always_flags));
3093 RunParserSyncTest(strict_context_data, bad_statement_data, kError, NULL, 0,
3094 always_flags, arraysize(always_flags));
3095 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError, NULL, 0,
3096 always_flags, arraysize(always_flags));
3097}
3098
3099
3100TEST(NoErrorsDeclsInCase) {
3101 const char* context_data[][2] = {
3102 {"'use strict'; switch(x) { case 1:", "}"},
3103 {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3104 {"'use strict'; switch(x) { case 1: case 2:", "}"},
3105 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3106 {"'use strict'; switch(x) { default:", "}"},
3107 {"function foo() {'use strict'; switch(x) { default:", "}}"},
3108 {"'use strict'; switch(x) { case 1: default:", "}"},
3109 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3110 { nullptr, nullptr }
3111 };
3112
3113 const char* statement_data[] = {
3114 "function f() { }",
3115 "class C { }",
3116 "class C extends Q {}",
3117 "function f() { } class C {}",
3118 "function f() { }; class C {}",
3119 "class C {}; function f() {}",
3120 nullptr
3121 };
3122
3123 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003124}
3125
3126
3127TEST(InvalidLeftHandSide) {
3128 const char* assignment_context_data[][2] = {
3129 {"", " = 1;"},
3130 {"\"use strict\"; ", " = 1;"},
3131 { NULL, NULL }
3132 };
3133
3134 const char* prefix_context_data[][2] = {
3135 {"++", ";"},
3136 {"\"use strict\"; ++", ";"},
3137 {NULL, NULL},
3138 };
3139
3140 const char* postfix_context_data[][2] = {
3141 {"", "++;"},
3142 {"\"use strict\"; ", "++;"},
3143 { NULL, NULL }
3144 };
3145
3146 // Good left hand sides for assigment or prefix / postfix operations.
3147 const char* good_statement_data[] = {
3148 "foo",
3149 "foo.bar",
3150 "foo[bar]",
3151 "foo()[bar]",
3152 "foo().bar",
3153 "this.foo",
3154 "this[foo]",
3155 "new foo()[bar]",
3156 "new foo().bar",
3157 "foo()",
3158 "foo(bar)",
3159 "foo[bar]()",
3160 "foo.bar()",
3161 "this()",
3162 "this.foo()",
3163 "this[foo].bar()",
3164 "this.foo[foo].bar(this)(bar)[foo]()",
3165 NULL
3166 };
3167
3168 // Bad left hand sides for assigment or prefix / postfix operations.
3169 const char* bad_statement_data_common[] = {
3170 "2",
3171 "new foo",
3172 "new foo()",
3173 "null",
3174 "if", // Unexpected token
3175 "{x: 1}", // Unexpected token
3176 "this",
3177 "\"bar\"",
3178 "(foo + bar)",
3179 "new new foo()[bar]", // means: new (new foo()[bar])
3180 "new new foo().bar", // means: new (new foo()[bar])
3181 NULL
3182 };
3183
3184 // These are not okay for assignment, but okay for prefix / postix.
3185 const char* bad_statement_data_for_assignment[] = {
3186 "++foo",
3187 "foo++",
3188 "foo + bar",
3189 NULL
3190 };
3191
3192 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3193 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3194 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3195 kError);
3196
3197 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3198 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3199
3200 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3201 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3202}
3203
3204
3205TEST(FuncNameInferrerBasic) {
3206 // Tests that function names are inferred properly.
3207 i::FLAG_allow_natives_syntax = true;
3208 v8::Isolate* isolate = CcTest::isolate();
3209 v8::HandleScope scope(isolate);
3210 LocalContext env;
3211 CompileRun("var foo1 = function() {}; "
3212 "var foo2 = function foo3() {}; "
3213 "function not_ctor() { "
3214 " var foo4 = function() {}; "
3215 " return %FunctionGetInferredName(foo4); "
3216 "} "
3217 "function Ctor() { "
3218 " var foo5 = function() {}; "
3219 " return %FunctionGetInferredName(foo5); "
3220 "} "
3221 "var obj1 = { foo6: function() {} }; "
3222 "var obj2 = { 'foo7': function() {} }; "
3223 "var obj3 = {}; "
3224 "obj3[1] = function() {}; "
3225 "var obj4 = {}; "
3226 "obj4[1] = function foo8() {}; "
3227 "var obj5 = {}; "
3228 "obj5['foo9'] = function() {}; "
3229 "var obj6 = { obj7 : { foo10: function() {} } };");
3230 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3231 // foo2 is not unnamed -> its name is not inferred.
3232 ExpectString("%FunctionGetInferredName(foo2)", "");
3233 ExpectString("not_ctor()", "foo4");
3234 ExpectString("Ctor()", "Ctor.foo5");
3235 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3236 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3237 ExpectString("%FunctionGetInferredName(obj3[1])",
3238 "obj3.(anonymous function)");
3239 ExpectString("%FunctionGetInferredName(obj4[1])", "");
3240 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3241 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3242}
3243
3244
3245TEST(FuncNameInferrerTwoByte) {
3246 // Tests function name inferring in cases where some parts of the inferred
3247 // function name are two-byte strings.
3248 i::FLAG_allow_natives_syntax = true;
3249 v8::Isolate* isolate = CcTest::isolate();
3250 v8::HandleScope scope(isolate);
3251 LocalContext env;
3252 uint16_t* two_byte_source = AsciiToTwoByteString(
3253 "var obj1 = { oXj2 : { foo1: function() {} } }; "
3254 "%FunctionGetInferredName(obj1.oXj2.foo1)");
3255 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3256 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3257 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3258 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003259 v8::String::NewFromTwoByte(isolate, two_byte_source,
3260 v8::NewStringType::kNormal)
3261 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003262 v8::Local<v8::Value> result = CompileRun(source);
3263 CHECK(result->IsString());
3264 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003265 v8::String::NewFromTwoByte(isolate, two_byte_name,
3266 v8::NewStringType::kNormal)
3267 .ToLocalChecked();
3268 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003269 i::DeleteArray(two_byte_source);
3270 i::DeleteArray(two_byte_name);
3271}
3272
3273
3274TEST(FuncNameInferrerEscaped) {
3275 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3276 // character as a unicode escape.
3277 i::FLAG_allow_natives_syntax = true;
3278 v8::Isolate* isolate = CcTest::isolate();
3279 v8::HandleScope scope(isolate);
3280 LocalContext env;
3281 uint16_t* two_byte_source = AsciiToTwoByteString(
3282 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3283 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3284 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3285 // Fix to correspond to the non-ASCII name in two_byte_source.
3286 two_byte_name[6] = 0x010d;
3287 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003288 v8::String::NewFromTwoByte(isolate, two_byte_source,
3289 v8::NewStringType::kNormal)
3290 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003291 v8::Local<v8::Value> result = CompileRun(source);
3292 CHECK(result->IsString());
3293 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003294 v8::String::NewFromTwoByte(isolate, two_byte_name,
3295 v8::NewStringType::kNormal)
3296 .ToLocalChecked();
3297 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003298 i::DeleteArray(two_byte_source);
3299 i::DeleteArray(two_byte_name);
3300}
3301
3302
3303TEST(RegressionLazyFunctionWithErrorWithArg) {
3304 // The bug occurred when a lazy function had an error which requires a
3305 // parameter (such as "unknown label" here). The error message was processed
3306 // before the AstValueFactory containing the error message string was
3307 // internalized.
3308 v8::Isolate* isolate = CcTest::isolate();
3309 v8::HandleScope scope(isolate);
3310 LocalContext env;
3311 i::FLAG_lazy = true;
3312 i::FLAG_min_preparse_length = 0;
3313 CompileRun("function this_is_lazy() {\n"
3314 " break p;\n"
3315 "}\n"
3316 "this_is_lazy();\n");
3317}
3318
3319
3320TEST(SerializationOfMaybeAssignmentFlag) {
3321 i::Isolate* isolate = CcTest::i_isolate();
3322 i::Factory* factory = isolate->factory();
3323 i::HandleScope scope(isolate);
3324 LocalContext env;
3325
3326 const char* src =
3327 "function h() {"
3328 " var result = [];"
3329 " function f() {"
3330 " result.push(2);"
3331 " }"
3332 " function assertResult(r) {"
3333 " f();"
3334 " result = [];"
3335 " }"
3336 " assertResult([2]);"
3337 " assertResult([2]);"
3338 " return f;"
3339 "};"
3340 "h();";
3341
3342 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3343 i::SNPrintF(program, "%s", src);
3344 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3345 source->PrintOn(stdout);
3346 printf("\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003347 i::Zone zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003348 v8::Local<v8::Value> v = CompileRun(src);
3349 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3350 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3351 i::Context* context = f->context();
3352 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3353 avf.Internalize(isolate);
3354 const i::AstRawString* name = avf.GetOneByteString("result");
3355 i::Handle<i::String> str = name->string();
3356 CHECK(str->IsInternalizedString());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003357 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003358 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003359 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003360 i::Scope* s =
3361 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3362 CHECK(s != script_scope);
3363 CHECK(name != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003364
3365 // Get result from h's function context (that is f's context)
3366 i::Variable* var = s->Lookup(name);
3367
3368 CHECK(var != NULL);
3369 // Maybe assigned should survive deserialization
3370 CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3371 // TODO(sigurds) Figure out if is_used should survive context serialization.
3372}
3373
3374
3375TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3376 i::Isolate* isolate = CcTest::i_isolate();
3377 i::Factory* factory = isolate->factory();
3378 i::HandleScope scope(isolate);
3379 LocalContext env;
3380
3381
3382 const char* src =
3383 "function f(x) {"
3384 " var a = arguments;"
3385 " function g(i) {"
3386 " ++a[0];"
3387 " };"
3388 " return g;"
3389 " }"
3390 "f(0);";
3391
3392 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3393 i::SNPrintF(program, "%s", src);
3394 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3395 source->PrintOn(stdout);
3396 printf("\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003397 i::Zone zone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003398 v8::Local<v8::Value> v = CompileRun(src);
3399 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3400 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3401 i::Context* context = f->context();
3402 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3403 avf.Internalize(isolate);
3404
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003405 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003406 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003407 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003408 i::Scope* s =
3409 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3410 CHECK(s != script_scope);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003411 const i::AstRawString* name_x = avf.GetOneByteString("x");
3412
3413 // Get result from f's function context (that is g's outer context)
3414 i::Variable* var_x = s->Lookup(name_x);
3415 CHECK(var_x != NULL);
3416 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3417}
3418
3419
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003420TEST(InnerAssignment) {
3421 i::Isolate* isolate = CcTest::i_isolate();
3422 i::Factory* factory = isolate->factory();
3423 i::HandleScope scope(isolate);
3424 LocalContext env;
3425
3426 const char* prefix = "function f() {";
3427 const char* midfix = " function g() {";
3428 const char* suffix = "}}";
3429 struct { const char* source; bool assigned; bool strict; } outers[] = {
3430 // Actual assignments.
3431 { "var x; var x = 5;", true, false },
3432 { "var x; { var x = 5; }", true, false },
3433 { "'use strict'; let x; x = 6;", true, true },
3434 { "var x = 5; function x() {}", true, false },
3435 // Actual non-assignments.
3436 { "var x;", false, false },
3437 { "var x = 5;", false, false },
3438 { "'use strict'; let x;", false, true },
3439 { "'use strict'; let x = 6;", false, true },
3440 { "'use strict'; var x = 0; { let x = 6; }", false, true },
3441 { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3442 { "'use strict'; let x = 0; { let x = 6; }", false, true },
3443 { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3444 { "var x; try {} catch (x) { x = 5; }", false, false },
3445 { "function x() {}", false, false },
3446 // Eval approximation.
3447 { "var x; eval('');", true, false },
3448 { "eval(''); var x;", true, false },
3449 { "'use strict'; let x; eval('');", true, true },
3450 { "'use strict'; eval(''); let x;", true, true },
3451 // Non-assignments not recognized, because the analysis is approximative.
3452 { "var x; var x;", true, false },
3453 { "var x = 5; var x;", true, false },
3454 { "var x; { var x; }", true, false },
3455 { "var x; function x() {}", true, false },
3456 { "function x() {}; var x;", true, false },
3457 { "var x; try {} catch (x) { var x = 5; }", true, false },
3458 };
3459 struct { const char* source; bool assigned; bool with; } inners[] = {
3460 // Actual assignments.
3461 { "x = 1;", true, false },
3462 { "x++;", true, false },
3463 { "++x;", true, false },
3464 { "x--;", true, false },
3465 { "--x;", true, false },
3466 { "{ x = 1; }", true, false },
3467 { "'use strict'; { let x; }; x = 0;", true, false },
3468 { "'use strict'; { const x = 1; }; x = 0;", true, false },
3469 { "'use strict'; { function x() {} }; x = 0;", true, false },
3470 { "with ({}) { x = 1; }", true, true },
3471 { "eval('');", true, false },
3472 { "'use strict'; { let y; eval('') }", true, false },
3473 { "function h() { x = 0; }", true, false },
3474 { "(function() { x = 0; })", true, false },
3475 { "(function() { x = 0; })", true, false },
3476 { "with ({}) (function() { x = 0; })", true, true },
3477 // Actual non-assignments.
3478 { "", false, false },
3479 { "x;", false, false },
3480 { "var x;", false, false },
3481 { "var x = 8;", false, false },
3482 { "var x; x = 8;", false, false },
3483 { "'use strict'; let x;", false, false },
3484 { "'use strict'; let x = 8;", false, false },
3485 { "'use strict'; let x; x = 8;", false, false },
3486 { "'use strict'; const x = 8;", false, false },
3487 { "function x() {}", false, false },
3488 { "function x() { x = 0; }", false, false },
3489 { "function h(x) { x = 0; }", false, false },
3490 { "'use strict'; { let x; x = 0; }", false, false },
3491 { "{ var x; }; x = 0;", false, false },
3492 { "with ({}) {}", false, true },
3493 { "var x; { with ({}) { x = 1; } }", false, true },
3494 { "try {} catch(x) { x = 0; }", false, false },
3495 { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3496 // Eval approximation.
3497 { "eval('');", true, false },
3498 { "function h() { eval(''); }", true, false },
3499 { "(function() { eval(''); })", true, false },
3500 // Shadowing not recognized because of eval approximation.
3501 { "var x; eval('');", true, false },
3502 { "'use strict'; let x; eval('');", true, false },
3503 { "try {} catch(x) { eval(''); }", true, false },
3504 { "function x() { eval(''); }", true, false },
3505 { "(function(x) { eval(''); })", true, false },
3506 };
3507
3508 // Used to trigger lazy compilation of function
3509 int comment_len = 2048;
3510 i::ScopedVector<char> comment(comment_len + 1);
3511 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3512 int prefix_len = Utf8LengthHelper(prefix);
3513 int midfix_len = Utf8LengthHelper(midfix);
3514 int suffix_len = Utf8LengthHelper(suffix);
3515 for (unsigned i = 0; i < arraysize(outers); ++i) {
3516 const char* outer = outers[i].source;
3517 int outer_len = Utf8LengthHelper(outer);
3518 for (unsigned j = 0; j < arraysize(inners); ++j) {
3519 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3520 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3521 if (outers[i].strict && inners[j].with) continue;
3522 const char* inner = inners[j].source;
3523 int inner_len = Utf8LengthHelper(inner);
3524
3525 int outer_comment_len = outer_lazy ? comment_len : 0;
3526 int inner_comment_len = inner_lazy ? comment_len : 0;
3527 const char* outer_comment = outer_lazy ? comment.start() : "";
3528 const char* inner_comment = inner_lazy ? comment.start() : "";
3529 int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3530 inner_comment_len + inner_len + suffix_len;
3531 i::ScopedVector<char> program(len + 1);
3532
3533 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3534 midfix, inner_comment, inner, suffix);
3535 i::Handle<i::String> source =
3536 factory->InternalizeUtf8String(program.start());
3537 source->PrintOn(stdout);
3538 printf("\n");
3539
3540 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003541 i::Zone zone;
3542 i::ParseInfo info(&zone, script);
3543 i::Parser parser(&info);
3544 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003545 CHECK(i::Compiler::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003546 CHECK(info.literal() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003548 i::Scope* scope = info.literal()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003549 CHECK_EQ(scope->inner_scopes()->length(), 1);
3550 i::Scope* inner_scope = scope->inner_scopes()->at(0);
3551 const i::AstRawString* var_name =
3552 info.ast_value_factory()->GetOneByteString("x");
3553 i::Variable* var = inner_scope->Lookup(var_name);
3554 bool expected = outers[i].assigned || inners[j].assigned;
3555 CHECK(var != NULL);
3556 CHECK(var->is_used() || !expected);
3557 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3558 }
3559 }
3560 }
3561 }
3562}
3563
3564namespace {
3565
3566int* global_use_counts = NULL;
3567
3568void MockUseCounterCallback(v8::Isolate* isolate,
3569 v8::Isolate::UseCounterFeature feature) {
3570 ++global_use_counts[feature];
3571}
3572
3573}
3574
3575
3576TEST(UseAsmUseCount) {
3577 i::Isolate* isolate = CcTest::i_isolate();
3578 i::HandleScope scope(isolate);
3579 LocalContext env;
3580 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3581 global_use_counts = use_counts;
3582 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3583 CompileRun("\"use asm\";\n"
3584 "var foo = 1;\n"
3585 "\"use asm\";\n" // Only the first one counts.
3586 "function bar() { \"use asm\"; var baz = 1; }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003587 // Optimizing will double-count because the source is parsed twice.
3588 CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
3589}
3590
3591
3592TEST(UseConstLegacyCount) {
3593 i::FLAG_legacy_const = true;
3594 i::Isolate* isolate = CcTest::i_isolate();
3595 i::HandleScope scope(isolate);
3596 LocalContext env;
3597 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3598 global_use_counts = use_counts;
3599 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3600 CompileRun(
3601 "const x = 1;\n"
3602 "var foo = 1;\n"
3603 "const y = 1;\n"
3604 "function bar() {\n"
3605 " const z = 1; var baz = 1;\n"
3606 " function q() { const k = 42; }\n"
3607 "}");
3608 // Optimizing will double-count because the source is parsed twice.
3609 CHECK_EQ(i::FLAG_always_opt ? 8 : 4, use_counts[v8::Isolate::kLegacyConst]);
3610}
3611
3612
3613TEST(StrictModeUseCount) {
3614 i::Isolate* isolate = CcTest::i_isolate();
3615 i::HandleScope scope(isolate);
3616 LocalContext env;
3617 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3618 global_use_counts = use_counts;
3619 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3620 CompileRun(
3621 "\"use strict\";\n"
3622 "function bar() { var baz = 1; }"); // strict mode inherits
3623 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3624 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
3625}
3626
3627
3628TEST(SloppyModeUseCount) {
3629 i::Isolate* isolate = CcTest::i_isolate();
3630 i::HandleScope scope(isolate);
3631 LocalContext env;
3632 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3633 global_use_counts = use_counts;
3634 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3635 CompileRun("function bar() { var baz = 1; }");
3636 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3637 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
3638}
3639
3640
3641TEST(BothModesUseCount) {
3642 i::Isolate* isolate = CcTest::i_isolate();
3643 i::HandleScope scope(isolate);
3644 LocalContext env;
3645 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3646 global_use_counts = use_counts;
3647 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3648 CompileRun("function bar() { 'use strict'; var baz = 1; }");
3649 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3650 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3651}
3652
3653
3654TEST(ErrorsArrowFormalParameters) {
3655 const char* context_data[][2] = {
3656 { "()", "=>{}" },
3657 { "()", "=>{};" },
3658 { "var x = ()", "=>{}" },
3659 { "var x = ()", "=>{};" },
3660
3661 { "a", "=>{}" },
3662 { "a", "=>{};" },
3663 { "var x = a", "=>{}" },
3664 { "var x = a", "=>{};" },
3665
3666 { "(a)", "=>{}" },
3667 { "(a)", "=>{};" },
3668 { "var x = (a)", "=>{}" },
3669 { "var x = (a)", "=>{};" },
3670
3671 { "(...a)", "=>{}" },
3672 { "(...a)", "=>{};" },
3673 { "var x = (...a)", "=>{}" },
3674 { "var x = (...a)", "=>{};" },
3675
3676 { "(a,b)", "=>{}" },
3677 { "(a,b)", "=>{};" },
3678 { "var x = (a,b)", "=>{}" },
3679 { "var x = (a,b)", "=>{};" },
3680
3681 { "(a,...b)", "=>{}" },
3682 { "(a,...b)", "=>{};" },
3683 { "var x = (a,...b)", "=>{}" },
3684 { "var x = (a,...b)", "=>{};" },
3685
3686 { nullptr, nullptr }
3687 };
3688 const char* assignment_expression_suffix_data[] = {
3689 "?c:d=>{}",
3690 "=c=>{}",
3691 "()",
3692 "(c)",
3693 "[1]",
3694 "[c]",
3695 ".c",
3696 "-c",
3697 "+c",
3698 "c++",
3699 "`c`",
3700 "`${c}`",
3701 "`template-head${c}`",
3702 "`${c}template-tail`",
3703 "`template-head${c}template-tail`",
3704 "`${c}template-tail`",
3705 nullptr
3706 };
3707
3708 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003709}
3710
3711
3712TEST(ErrorsArrowFunctions) {
3713 // Tests that parser and preparser generate the same kind of errors
3714 // on invalid arrow function syntax.
3715 const char* context_data[][2] = {
3716 {"", ";"},
3717 {"v = ", ";"},
3718 {"bar ? (", ") : baz;"},
3719 {"bar ? baz : (", ");"},
3720 {"bar[", "];"},
3721 {"bar, ", ";"},
3722 {"", ", bar;"},
3723 {NULL, NULL}
3724 };
3725
3726 const char* statement_data[] = {
3727 "=> 0",
3728 "=>",
3729 "() =>",
3730 "=> {}",
3731 ") => {}",
3732 ", => {}",
3733 "(,) => {}",
3734 "return => {}",
3735 "() => {'value': 42}",
3736
3737 // Check that the early return introduced in ParsePrimaryExpression
3738 // does not accept stray closing parentheses.
3739 ")",
3740 ") => 0",
3741 "foo[()]",
3742 "()",
3743
3744 // Parameter lists with extra parens should be recognized as errors.
3745 "(()) => 0",
3746 "((x)) => 0",
3747 "((x, y)) => 0",
3748 "(x, (y)) => 0",
3749 "((x, y, z)) => 0",
3750 "(x, (y, z)) => 0",
3751 "((x, y), z) => 0",
3752
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003753 // Arrow function formal parameters are parsed as StrictFormalParameters,
3754 // which confusingly only implies that there are no duplicates. Words
3755 // reserved in strict mode, and eval or arguments, are indeed valid in
3756 // sloppy mode.
3757 "eval => { 'use strict'; 0 }",
3758 "arguments => { 'use strict'; 0 }",
3759 "yield => { 'use strict'; 0 }",
3760 "interface => { 'use strict'; 0 }",
3761 "(eval) => { 'use strict'; 0 }",
3762 "(arguments) => { 'use strict'; 0 }",
3763 "(yield) => { 'use strict'; 0 }",
3764 "(interface) => { 'use strict'; 0 }",
3765 "(eval, bar) => { 'use strict'; 0 }",
3766 "(bar, eval) => { 'use strict'; 0 }",
3767 "(bar, arguments) => { 'use strict'; 0 }",
3768 "(bar, yield) => { 'use strict'; 0 }",
3769 "(bar, interface) => { 'use strict'; 0 }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003770 // TODO(aperez): Detecting duplicates does not work in PreParser.
3771 // "(bar, bar) => {}",
3772
3773 // The parameter list is parsed as an expression, but only
3774 // a comma-separated list of identifier is valid.
3775 "32 => {}",
3776 "(32) => {}",
3777 "(a, 32) => {}",
3778 "if => {}",
3779 "(if) => {}",
3780 "(a, if) => {}",
3781 "a + b => {}",
3782 "(a + b) => {}",
3783 "(a + b, c) => {}",
3784 "(a, b - c) => {}",
3785 "\"a\" => {}",
3786 "(\"a\") => {}",
3787 "(\"a\", b) => {}",
3788 "(a, \"b\") => {}",
3789 "-a => {}",
3790 "(-a) => {}",
3791 "(-a, b) => {}",
3792 "(a, -b) => {}",
3793 "{} => {}",
3794 "({}) => {}",
3795 "(a, {}) => {}",
3796 "({}, a) => {}",
3797 "a++ => {}",
3798 "(a++) => {}",
3799 "(a++, b) => {}",
3800 "(a, b++) => {}",
3801 "[] => {}",
3802 "([]) => {}",
3803 "(a, []) => {}",
3804 "([], a) => {}",
3805 "(a = b) => {}",
3806 "(a = b, c) => {}",
3807 "(a, b = c) => {}",
3808 "(foo ? bar : baz) => {}",
3809 "(a, foo ? bar : baz) => {}",
3810 "(foo ? bar : baz, a) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003811 "(a.b, c) => {}",
3812 "(c, a.b) => {}",
3813 "(a['b'], c) => {}",
3814 "(c, a['b']) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003815 NULL
3816 };
3817
3818 // The test is quite slow, so run it with a reduced set of flags.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003819 static const ParserFlag flags[] = {kAllowLazy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003820 RunParserSyncTest(context_data, statement_data, kError, flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003821 arraysize(flags));
3822
3823 // In a context where a concise arrow body is parsed with [~In] variant,
3824 // ensure that an error is reported in both full parser and preparser.
3825 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3826 {nullptr, nullptr}};
3827 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
3828 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
3829 arraysize(flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003830}
3831
3832
3833TEST(NoErrorsArrowFunctions) {
3834 // Tests that parser and preparser accept valid arrow functions syntax.
3835 const char* context_data[][2] = {
3836 {"", ";"},
3837 {"bar ? (", ") : baz;"},
3838 {"bar ? baz : (", ");"},
3839 {"bar, ", ";"},
3840 {"", ", bar;"},
3841 {NULL, NULL}
3842 };
3843
3844 const char* statement_data[] = {
3845 "() => {}",
3846 "() => { return 42 }",
3847 "x => { return x; }",
3848 "(x) => { return x; }",
3849 "(x, y) => { return x + y; }",
3850 "(x, y, z) => { return x + y + z; }",
3851 "(x, y) => { x.a = y; }",
3852 "() => 42",
3853 "x => x",
3854 "x => x * x",
3855 "(x) => x",
3856 "(x) => x * x",
3857 "(x, y) => x + y",
3858 "(x, y, z) => x, y, z",
3859 "(x, y) => x.a = y",
3860 "() => ({'value': 42})",
3861 "x => y => x + y",
3862 "(x, y) => (u, v) => x*u + y*v",
3863 "(x, y) => z => z * (x + y)",
3864 "x => (y, z) => z * (x + y)",
3865
3866 // Those are comma-separated expressions, with arrow functions as items.
3867 // They stress the code for validating arrow function parameter lists.
3868 "a, b => 0",
3869 "a, b, (c, d) => 0",
3870 "(a, b, (c, d) => 0)",
3871 "(a, b) => 0, (c, d) => 1",
3872 "(a, b => {}, a => a + 1)",
3873 "((a, b) => {}, (a => a + 1))",
3874 "(a, (a, (b, c) => 0))",
3875
3876 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3877 "foo ? bar : baz => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003878
3879 // Arrows with non-simple parameters.
3880 "({a}) => {}",
3881 "(x = 9) => {}",
3882 "(x, y = 9) => {}",
3883 "(x = 9, y) => {}",
3884 "(x, y = 9, z) => {}",
3885 "(x, y = 9, z = 8) => {}",
3886 "(...a) => {}",
3887 "(x, ...a) => {}",
3888 "(x = 9, ...a) => {}",
3889 "(x, y = 9, ...a) => {}",
3890 "(x, y = 9, {b}, z = 8, ...a) => {}",
3891 // TODO(wingo, rossberg): This is not accepted right now.
3892 // "({a} = {}) => {}",
3893 // "([x] = []) => {}",
3894 "({a = 42}) => {}",
3895 "([x = 0]) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003896 NULL
3897 };
3898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003899 static const ParserFlag always_flags[] = {kAllowHarmonyDefaultParameters,
3900 kAllowHarmonyDestructuring};
3901 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3902 always_flags, arraysize(always_flags));
3903
3904 static const ParserFlag flags[] = {kAllowLazy};
3905 // In a context where a concise arrow body is parsed with [~In] variant,
3906 // ensure that nested expressions can still use the 'in' operator,
3907 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3908 {nullptr, nullptr}};
3909 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
3910 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
3911 arraysize(flags));
3912}
3913
3914
3915TEST(ArrowFunctionsSloppyParameterNames) {
3916 const char* strong_context_data[][2] = {
3917 {"'use strong'; ", ";"},
3918 {"'use strong'; bar ? (", ") : baz;"},
3919 {"'use strong'; bar ? baz : (", ");"},
3920 {"'use strong'; bar, ", ";"},
3921 {"'use strong'; ", ", bar;"},
3922 {NULL, NULL}
3923 };
3924
3925 const char* strict_context_data[][2] = {
3926 {"'use strict'; ", ";"},
3927 {"'use strict'; bar ? (", ") : baz;"},
3928 {"'use strict'; bar ? baz : (", ");"},
3929 {"'use strict'; bar, ", ";"},
3930 {"'use strict'; ", ", bar;"},
3931 {NULL, NULL}
3932 };
3933
3934 const char* sloppy_context_data[][2] = {
3935 {"", ";"},
3936 {"bar ? (", ") : baz;"},
3937 {"bar ? baz : (", ");"},
3938 {"bar, ", ";"},
3939 {"", ", bar;"},
3940 {NULL, NULL}
3941 };
3942
3943 const char* statement_data[] = {
3944 "eval => {}",
3945 "arguments => {}",
3946 "yield => {}",
3947 "interface => {}",
3948 "(eval) => {}",
3949 "(arguments) => {}",
3950 "(yield) => {}",
3951 "(interface) => {}",
3952 "(eval, bar) => {}",
3953 "(bar, eval) => {}",
3954 "(bar, arguments) => {}",
3955 "(bar, yield) => {}",
3956 "(bar, interface) => {}",
3957 "(interface, eval) => {}",
3958 "(interface, arguments) => {}",
3959 "(eval, interface) => {}",
3960 "(arguments, interface) => {}",
3961 NULL
3962 };
3963
3964 static const ParserFlag always_flags[] = {kAllowStrongMode};
3965 RunParserSyncTest(strong_context_data, statement_data, kError, NULL, 0,
3966 always_flags, arraysize(always_flags));
3967 RunParserSyncTest(strict_context_data, statement_data, kError, NULL, 0,
3968 always_flags, arraysize(always_flags));
3969 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess, NULL, 0,
3970 always_flags, arraysize(always_flags));
3971}
3972
3973
3974TEST(ArrowFunctionsYieldParameterNameInGenerator) {
3975 const char* sloppy_function_context_data[][2] = {
3976 {"(function f() { (", "); });"},
3977 {NULL, NULL}
3978 };
3979
3980 const char* strict_function_context_data[][2] = {
3981 {"(function f() {'use strong'; (", "); });"},
3982 {"(function f() {'use strict'; (", "); });"},
3983 {NULL, NULL}
3984 };
3985
3986 const char* generator_context_data[][2] = {
3987 {"(function *g() {'use strong'; (", "); });"},
3988 {"(function *g() {'use strict'; (", "); });"},
3989 {"(function *g() { (", "); });"},
3990 {NULL, NULL}
3991 };
3992
3993 const char* arrow_data[] = {
3994 "yield => {}",
3995 "(yield) => {}",
3996 "(a, yield) => {}",
3997 "(yield, a) => {}",
3998 "(yield, ...a) => {}",
3999 "(a, ...yield) => {}",
4000 "({yield}) => {}",
4001 "([yield]) => {}",
4002 NULL
4003 };
4004
4005 static const ParserFlag always_flags[] = { kAllowHarmonyDestructuring,
4006 kAllowStrongMode};
4007 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess, NULL, 0,
4008 always_flags, arraysize(always_flags));
4009 RunParserSyncTest(strict_function_context_data, arrow_data, kError, NULL, 0,
4010 always_flags, arraysize(always_flags));
4011 RunParserSyncTest(generator_context_data, arrow_data, kError, NULL, 0,
4012 always_flags, arraysize(always_flags));
4013}
4014
4015
4016TEST(SuperNoErrors) {
4017 // Tests that parser and preparser accept 'super' keyword in right places.
4018 const char* context_data[][2] = {
4019 {"class C { m() { ", "; } }"},
4020 {"class C { m() { k = ", "; } }"},
4021 {"class C { m() { foo(", "); } }"},
4022 {"class C { m() { () => ", "; } }"},
4023 {NULL, NULL}
4024 };
4025
4026 const char* statement_data[] = {
4027 "super.x",
4028 "super[27]",
4029 "new super.x",
4030 "new super.x()",
4031 "new super[27]",
4032 "new super[27]()",
4033 "z.super", // Ok, property lookup.
4034 NULL
4035 };
4036
4037 static const ParserFlag always_flags[] = {
4038 kAllowHarmonySloppy
4039 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004040 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
4041 always_flags, arraysize(always_flags));
4042}
4043
4044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004045TEST(SuperErrors) {
4046 const char* context_data[][2] = {
4047 {"class C { m() { ", "; } }"},
4048 {"class C { m() { k = ", "; } }"},
4049 {"class C { m() { foo(", "); } }"},
4050 {"class C { m() { () => ", "; } }"},
4051 {NULL, NULL}
4052 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004053
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004054 const char* expression_data[] = {
4055 "super",
4056 "super = x",
4057 "y = super",
4058 "f(super)",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004059 "new super",
4060 "new super()",
4061 "new super(12, 45)",
4062 "new new super",
4063 "new new super()",
4064 "new new super()()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004065 NULL
4066 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004068 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4069 RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004070 always_flags, arraysize(always_flags));
4071}
4072
4073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004074TEST(SuperCall) {
4075 const char* context_data[][2] = {{"", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004076 {NULL, NULL}};
4077
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004078 const char* success_data[] = {
4079 "class C extends B { constructor() { super(); } }",
4080 "class C extends B { constructor() { () => super(); } }",
4081 NULL
4082 };
4083
4084 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4085 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
4086 always_flags, arraysize(always_flags));
4087
4088 const char* error_data[] = {
4089 "class C { constructor() { super(); } }",
4090 "class C { method() { super(); } }",
4091 "class C { method() { () => super(); } }",
4092 "class C { *method() { super(); } }",
4093 "class C { get x() { super(); } }",
4094 "class C { set x(_) { super(); } }",
4095 "({ method() { super(); } })",
4096 "({ *method() { super(); } })",
4097 "({ get x() { super(); } })",
4098 "({ set x(_) { super(); } })",
4099 "({ f: function() { super(); } })",
4100 "(function() { super(); })",
4101 "var f = function() { super(); }",
4102 "({ f: function*() { super(); } })",
4103 "(function*() { super(); })",
4104 "var f = function*() { super(); }",
4105 NULL
4106 };
4107
4108 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
4109 always_flags, arraysize(always_flags));
4110}
4111
4112
4113TEST(SuperNewNoErrors) {
4114 const char* context_data[][2] = {
4115 {"class C { constructor() { ", " } }"},
4116 {"class C { *method() { ", " } }"},
4117 {"class C { get x() { ", " } }"},
4118 {"class C { set x(_) { ", " } }"},
4119 {"({ method() { ", " } })"},
4120 {"({ *method() { ", " } })"},
4121 {"({ get x() { ", " } })"},
4122 {"({ set x(_) { ", " } })"},
4123 {NULL, NULL}
4124 };
4125
4126 const char* expression_data[] = {
4127 "new super.x;",
4128 "new super.x();",
4129 "() => new super.x;",
4130 "() => new super.x();",
4131 NULL
4132 };
4133
4134 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4135 RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
4136 always_flags, arraysize(always_flags));
4137}
4138
4139
4140TEST(SuperNewErrors) {
4141 const char* context_data[][2] = {
4142 {"class C { method() { ", " } }"},
4143 {"class C { *method() { ", " } }"},
4144 {"class C { get x() { ", " } }"},
4145 {"class C { set x(_) { ", " } }"},
4146 {"({ method() { ", " } })"},
4147 {"({ *method() { ", " } })"},
4148 {"({ get x() { ", " } })"},
4149 {"({ set x(_) { ", " } })"},
4150 {"({ f: function() { ", " } })"},
4151 {"(function() { ", " })"},
4152 {"var f = function() { ", " }"},
4153 {"({ f: function*() { ", " } })"},
4154 {"(function*() { ", " })"},
4155 {"var f = function*() { ", " }"},
4156 {NULL, NULL}
4157 };
4158
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004159 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004160 "new super;",
4161 "new super();",
4162 "() => new super;",
4163 "() => new super();",
4164 NULL
4165 };
4166
4167 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4168 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4169 always_flags, arraysize(always_flags));
4170}
4171
4172
4173TEST(SuperErrorsNonMethods) {
4174 // super is only allowed in methods, accessors and constructors.
4175 const char* context_data[][2] = {
4176 {"", ";"},
4177 {"k = ", ";"},
4178 {"foo(", ");"},
4179 {"if (", ") {}"},
4180 {"if (true) {", "}"},
4181 {"if (false) {} else {", "}"},
4182 {"while (true) {", "}"},
4183 {"function f() {", "}"},
4184 {"class C extends (", ") {}"},
4185 {"class C { m() { function f() {", "} } }"},
4186 {"({ m() { function f() {", "} } })"},
4187 {NULL, NULL}
4188 };
4189
4190 const char* statement_data[] = {
4191 "super",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004192 "super = x",
4193 "y = super",
4194 "f(super)",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004195 "super.x",
4196 "super[27]",
4197 "super.x()",
4198 "super[27]()",
4199 "super()",
4200 "new super.x",
4201 "new super.x()",
4202 "new super[27]",
4203 "new super[27]()",
4204 NULL
4205 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004207 static const ParserFlag always_flags[] = {
4208 kAllowHarmonySloppy
4209 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004210 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4211 always_flags, arraysize(always_flags));
4212}
4213
4214
4215TEST(NoErrorsMethodDefinition) {
4216 const char* context_data[][2] = {{"({", "});"},
4217 {"'use strict'; ({", "});"},
4218 {"({*", "});"},
4219 {"'use strict'; ({*", "});"},
4220 {NULL, NULL}};
4221
4222 const char* object_literal_body_data[] = {
4223 "m() {}",
4224 "m(x) { return x; }",
4225 "m(x, y) {}, n() {}",
4226 "set(x, y) {}",
4227 "get(x, y) {}",
4228 NULL
4229 };
4230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004231 RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004232}
4233
4234
4235TEST(MethodDefinitionNames) {
4236 const char* context_data[][2] = {{"({", "(x, y) {}});"},
4237 {"'use strict'; ({", "(x, y) {}});"},
4238 {"({*", "(x, y) {}});"},
4239 {"'use strict'; ({*", "(x, y) {}});"},
4240 {NULL, NULL}};
4241
4242 const char* name_data[] = {
4243 "m",
4244 "'m'",
4245 "\"m\"",
4246 "\"m n\"",
4247 "true",
4248 "false",
4249 "null",
4250 "0",
4251 "1.2",
4252 "1e1",
4253 "1E1",
4254 "1e+1",
4255 "1e-1",
4256
4257 // Keywords
4258 "async",
4259 "await",
4260 "break",
4261 "case",
4262 "catch",
4263 "class",
4264 "const",
4265 "continue",
4266 "debugger",
4267 "default",
4268 "delete",
4269 "do",
4270 "else",
4271 "enum",
4272 "export",
4273 "extends",
4274 "finally",
4275 "for",
4276 "function",
4277 "if",
4278 "implements",
4279 "import",
4280 "in",
4281 "instanceof",
4282 "interface",
4283 "let",
4284 "new",
4285 "package",
4286 "private",
4287 "protected",
4288 "public",
4289 "return",
4290 "static",
4291 "super",
4292 "switch",
4293 "this",
4294 "throw",
4295 "try",
4296 "typeof",
4297 "var",
4298 "void",
4299 "while",
4300 "with",
4301 "yield",
4302 NULL
4303 };
4304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004305 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004306}
4307
4308
4309TEST(MethodDefinitionStrictFormalParamereters) {
4310 const char* context_data[][2] = {{"({method(", "){}});"},
4311 {"'use strict'; ({method(", "){}});"},
4312 {"({*method(", "){}});"},
4313 {"'use strict'; ({*method(", "){}});"},
4314 {NULL, NULL}};
4315
4316 const char* params_data[] = {
4317 "x, x",
4318 "x, y, x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004319 "var",
4320 "const",
4321 NULL
4322 };
4323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004324 RunParserSyncTest(context_data, params_data, kError);
4325}
4326
4327
4328TEST(MethodDefinitionEvalArguments) {
4329 const char* strict_context_data[][2] =
4330 {{"'use strict'; ({method(", "){}});"},
4331 {"'use strict'; ({*method(", "){}});"},
4332 {NULL, NULL}};
4333 const char* sloppy_context_data[][2] =
4334 {{"({method(", "){}});"},
4335 {"({*method(", "){}});"},
4336 {NULL, NULL}};
4337
4338 const char* data[] = {
4339 "eval",
4340 "arguments",
4341 NULL};
4342
4343 // Fail in strict mode
4344 RunParserSyncTest(strict_context_data, data, kError);
4345
4346 // OK in sloppy mode
4347 RunParserSyncTest(sloppy_context_data, data, kSuccess);
4348}
4349
4350
4351TEST(MethodDefinitionDuplicateEvalArguments) {
4352 const char* context_data[][2] =
4353 {{"'use strict'; ({method(", "){}});"},
4354 {"'use strict'; ({*method(", "){}});"},
4355 {"({method(", "){}});"},
4356 {"({*method(", "){}});"},
4357 {NULL, NULL}};
4358
4359 const char* data[] = {
4360 "eval, eval",
4361 "eval, a, eval",
4362 "arguments, arguments",
4363 "arguments, a, arguments",
4364 NULL};
4365
4366 // In strict mode, the error is using "eval" or "arguments" as parameter names
4367 // In sloppy mode, the error is that eval / arguments are duplicated
4368 RunParserSyncTest(context_data, data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004369}
4370
4371
4372TEST(MethodDefinitionDuplicateProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004373 const char* context_data[][2] = {{"'use strict'; ({", "});"},
4374 {NULL, NULL}};
4375
4376 const char* params_data[] = {
4377 "x: 1, x() {}",
4378 "x() {}, x: 1",
4379 "x() {}, get x() {}",
4380 "x() {}, set x(_) {}",
4381 "x() {}, x() {}",
4382 "x() {}, y() {}, x() {}",
4383 "x() {}, \"x\"() {}",
4384 "x() {}, 'x'() {}",
4385 "0() {}, '0'() {}",
4386 "1.0() {}, 1: 1",
4387
4388 "x: 1, *x() {}",
4389 "*x() {}, x: 1",
4390 "*x() {}, get x() {}",
4391 "*x() {}, set x(_) {}",
4392 "*x() {}, *x() {}",
4393 "*x() {}, y() {}, *x() {}",
4394 "*x() {}, *\"x\"() {}",
4395 "*x() {}, *'x'() {}",
4396 "*0() {}, *'0'() {}",
4397 "*1.0() {}, 1: 1",
4398
4399 NULL
4400 };
4401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004402 RunParserSyncTest(context_data, params_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004403}
4404
4405
4406TEST(ClassExpressionNoErrors) {
4407 const char* context_data[][2] = {{"(", ");"},
4408 {"var C = ", ";"},
4409 {"bar, ", ";"},
4410 {NULL, NULL}};
4411 const char* class_data[] = {
4412 "class {}",
4413 "class name {}",
4414 "class extends F {}",
4415 "class name extends F {}",
4416 "class extends (F, G) {}",
4417 "class name extends (F, G) {}",
4418 "class extends class {} {}",
4419 "class name extends class {} {}",
4420 "class extends class base {} {}",
4421 "class name extends class base {} {}",
4422 NULL};
4423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004424 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004425 RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
4426 always_flags, arraysize(always_flags));
4427}
4428
4429
4430TEST(ClassDeclarationNoErrors) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004431 const char* context_data[][2] = {{"'use strict'; ", ""},
4432 {"'use strict'; {", "}"},
4433 {"'use strict'; if (true) {", "}"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004434 {NULL, NULL}};
4435 const char* statement_data[] = {
4436 "class name {}",
4437 "class name extends F {}",
4438 "class name extends (F, G) {}",
4439 "class name extends class {} {}",
4440 "class name extends class base {} {}",
4441 NULL};
4442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004443 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004444}
4445
4446
4447TEST(ClassBodyNoErrors) {
4448 // Tests that parser and preparser accept valid class syntax.
4449 const char* context_data[][2] = {{"(class {", "});"},
4450 {"(class extends Base {", "});"},
4451 {"class C {", "}"},
4452 {"class C extends Base {", "}"},
4453 {NULL, NULL}};
4454 const char* class_body_data[] = {
4455 ";",
4456 ";;",
4457 "m() {}",
4458 "m() {};",
4459 "; m() {}",
4460 "m() {}; n(x) {}",
4461 "get x() {}",
4462 "set x(v) {}",
4463 "get() {}",
4464 "set() {}",
4465 "*g() {}",
4466 "*g() {};",
4467 "; *g() {}",
4468 "*g() {}; *h(x) {}",
4469 "static() {}",
4470 "static m() {}",
4471 "static get x() {}",
4472 "static set x(v) {}",
4473 "static get() {}",
4474 "static set() {}",
4475 "static static() {}",
4476 "static get static() {}",
4477 "static set static(v) {}",
4478 "*static() {}",
4479 "*get() {}",
4480 "*set() {}",
4481 "static *g() {}",
4482 NULL};
4483
4484 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004485 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004486 };
4487 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4488 always_flags, arraysize(always_flags));
4489}
4490
4491
4492TEST(ClassPropertyNameNoErrors) {
4493 const char* context_data[][2] = {{"(class {", "() {}});"},
4494 {"(class { get ", "() {}});"},
4495 {"(class { set ", "(v) {}});"},
4496 {"(class { static ", "() {}});"},
4497 {"(class { static get ", "() {}});"},
4498 {"(class { static set ", "(v) {}});"},
4499 {"(class { *", "() {}});"},
4500 {"(class { static *", "() {}});"},
4501 {"class C {", "() {}}"},
4502 {"class C { get ", "() {}}"},
4503 {"class C { set ", "(v) {}}"},
4504 {"class C { static ", "() {}}"},
4505 {"class C { static get ", "() {}}"},
4506 {"class C { static set ", "(v) {}}"},
4507 {"class C { *", "() {}}"},
4508 {"class C { static *", "() {}}"},
4509 {NULL, NULL}};
4510 const char* name_data[] = {
4511 "42",
4512 "42.5",
4513 "42e2",
4514 "42e+2",
4515 "42e-2",
4516 "null",
4517 "false",
4518 "true",
4519 "'str'",
4520 "\"str\"",
4521 "static",
4522 "get",
4523 "set",
4524 "var",
4525 "const",
4526 "let",
4527 "this",
4528 "class",
4529 "function",
4530 "yield",
4531 "if",
4532 "else",
4533 "for",
4534 "while",
4535 "do",
4536 "try",
4537 "catch",
4538 "finally",
4539 NULL};
4540
4541 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004542 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004543 };
4544 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
4545 always_flags, arraysize(always_flags));
4546}
4547
4548
4549TEST(ClassExpressionErrors) {
4550 const char* context_data[][2] = {{"(", ");"},
4551 {"var C = ", ";"},
4552 {"bar, ", ";"},
4553 {NULL, NULL}};
4554 const char* class_data[] = {
4555 "class",
4556 "class name",
4557 "class name extends",
4558 "class extends",
4559 "class {",
4560 "class { m }",
4561 "class { m; n }",
4562 "class { m: 1 }",
4563 "class { m(); n() }",
4564 "class { get m }",
4565 "class { get m() }",
4566 "class { get m() { }",
4567 "class { set m() {} }", // Missing required parameter.
4568 "class { m() {}, n() {} }", // No commas allowed.
4569 NULL};
4570
4571 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004572 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004573 };
4574 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4575 always_flags, arraysize(always_flags));
4576}
4577
4578
4579TEST(ClassDeclarationErrors) {
4580 const char* context_data[][2] = {{"", ""},
4581 {"{", "}"},
4582 {"if (true) {", "}"},
4583 {NULL, NULL}};
4584 const char* class_data[] = {
4585 "class",
4586 "class name",
4587 "class name extends",
4588 "class extends",
4589 "class name {",
4590 "class name { m }",
4591 "class name { m; n }",
4592 "class name { m: 1 }",
4593 "class name { m(); n() }",
4594 "class name { get x }",
4595 "class name { get x() }",
4596 "class name { set x() {) }", // missing required param
4597 "class {}", // Name is required for declaration
4598 "class extends base {}",
4599 "class name { *",
4600 "class name { * }",
4601 "class name { *; }",
4602 "class name { *get x() {} }",
4603 "class name { *set x(_) {} }",
4604 "class name { *static m() {} }",
4605 NULL};
4606
4607 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004608 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004609 };
4610 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4611 always_flags, arraysize(always_flags));
4612}
4613
4614
4615TEST(ClassNameErrors) {
4616 const char* context_data[][2] = {{"class ", "{}"},
4617 {"(class ", "{});"},
4618 {"'use strict'; class ", "{}"},
4619 {"'use strict'; (class ", "{});"},
4620 {NULL, NULL}};
4621 const char* class_name[] = {
4622 "arguments",
4623 "eval",
4624 "implements",
4625 "interface",
4626 "let",
4627 "package",
4628 "private",
4629 "protected",
4630 "public",
4631 "static",
4632 "var",
4633 "yield",
4634 NULL};
4635
4636 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004637 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004638 };
4639 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4640 always_flags, arraysize(always_flags));
4641}
4642
4643
4644TEST(ClassGetterParamNameErrors) {
4645 const char* context_data[][2] = {
4646 {"class C { get name(", ") {} }"},
4647 {"(class { get name(", ") {} });"},
4648 {"'use strict'; class C { get name(", ") {} }"},
4649 {"'use strict'; (class { get name(", ") {} })"},
4650 {NULL, NULL}
4651 };
4652
4653 const char* class_name[] = {
4654 "arguments",
4655 "eval",
4656 "implements",
4657 "interface",
4658 "let",
4659 "package",
4660 "private",
4661 "protected",
4662 "public",
4663 "static",
4664 "var",
4665 "yield",
4666 NULL};
4667
4668 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004669 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004670 };
4671 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4672 always_flags, arraysize(always_flags));
4673}
4674
4675
4676TEST(ClassStaticPrototypeErrors) {
4677 const char* context_data[][2] = {{"class C {", "}"},
4678 {"(class {", "});"},
4679 {NULL, NULL}};
4680
4681 const char* class_body_data[] = {
4682 "static prototype() {}",
4683 "static get prototype() {}",
4684 "static set prototype(_) {}",
4685 "static *prototype() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004686 "static 'prototype'() {}",
4687 "static *'prototype'() {}",
4688 "static prot\\u006ftype() {}",
4689 "static 'prot\\u006ftype'() {}",
4690 "static get 'prot\\u006ftype'() {}",
4691 "static set 'prot\\u006ftype'(_) {}",
4692 "static *'prot\\u006ftype'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004693 NULL};
4694
4695 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004696 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004697 };
4698 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4699 always_flags, arraysize(always_flags));
4700}
4701
4702
4703TEST(ClassSpecialConstructorErrors) {
4704 const char* context_data[][2] = {{"class C {", "}"},
4705 {"(class {", "});"},
4706 {NULL, NULL}};
4707
4708 const char* class_body_data[] = {
4709 "get constructor() {}",
4710 "get constructor(_) {}",
4711 "*constructor() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004712 "get 'constructor'() {}",
4713 "*'constructor'() {}",
4714 "get c\\u006fnstructor() {}",
4715 "*c\\u006fnstructor() {}",
4716 "get 'c\\u006fnstructor'() {}",
4717 "get 'c\\u006fnstructor'(_) {}",
4718 "*'c\\u006fnstructor'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004719 NULL};
4720
4721 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004722 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004723 };
4724 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4725 always_flags, arraysize(always_flags));
4726}
4727
4728
4729TEST(ClassConstructorNoErrors) {
4730 const char* context_data[][2] = {{"class C {", "}"},
4731 {"(class {", "});"},
4732 {NULL, NULL}};
4733
4734 const char* class_body_data[] = {
4735 "constructor() {}",
4736 "static constructor() {}",
4737 "static get constructor() {}",
4738 "static set constructor(_) {}",
4739 "static *constructor() {}",
4740 NULL};
4741
4742 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004743 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004744 };
4745 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4746 always_flags, arraysize(always_flags));
4747}
4748
4749
4750TEST(ClassMultipleConstructorErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004751 const char* context_data[][2] = {{"class C {", "}"},
4752 {"(class {", "});"},
4753 {NULL, NULL}};
4754
4755 const char* class_body_data[] = {
4756 "constructor() {}; constructor() {}",
4757 NULL};
4758
4759 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004760 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004761 };
4762 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4763 always_flags, arraysize(always_flags));
4764}
4765
4766
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004767TEST(ClassMultiplePropertyNamesNoErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004768 const char* context_data[][2] = {{"class C {", "}"},
4769 {"(class {", "});"},
4770 {NULL, NULL}};
4771
4772 const char* class_body_data[] = {
4773 "constructor() {}; static constructor() {}",
4774 "m() {}; static m() {}",
4775 "m() {}; m() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004776 "static m() {}; static m() {}",
4777 "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004778 NULL};
4779
4780 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004781 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004782 };
4783 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4784 always_flags, arraysize(always_flags));
4785}
4786
4787
4788TEST(ClassesAreStrictErrors) {
4789 const char* context_data[][2] = {{"", ""},
4790 {"(", ");"},
4791 {NULL, NULL}};
4792
4793 const char* class_body_data[] = {
4794 "class C { method() { with ({}) {} } }",
4795 "class C extends function() { with ({}) {} } {}",
4796 "class C { *method() { with ({}) {} } }",
4797 NULL};
4798
4799 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004800 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004801 };
4802 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4803 always_flags, arraysize(always_flags));
Ben Murdoch692be652012-01-10 18:47:50 +00004804}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004805
4806
4807TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4808 const char* context_data[][2] = {{"({", "});"},
4809 {"'use strict'; ({", "});"},
4810 {NULL, NULL}};
4811
4812 const char* name_data[] = {
4813 "break",
4814 "case",
4815 "catch",
4816 "class",
4817 "const",
4818 "continue",
4819 "debugger",
4820 "default",
4821 "delete",
4822 "do",
4823 "else",
4824 "enum",
4825 "export",
4826 "extends",
4827 "false",
4828 "finally",
4829 "for",
4830 "function",
4831 "if",
4832 "import",
4833 "in",
4834 "instanceof",
4835 "new",
4836 "null",
4837 "return",
4838 "super",
4839 "switch",
4840 "this",
4841 "throw",
4842 "true",
4843 "try",
4844 "typeof",
4845 "var",
4846 "void",
4847 "while",
4848 "with",
4849 NULL
4850 };
4851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004852 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004853}
4854
4855
4856TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4857 const char* context_data[][2] = {{"({", "});"},
4858 {NULL, NULL}};
4859
4860 const char* name_data[] = {
4861 "implements",
4862 "interface",
4863 "let",
4864 "package",
4865 "private",
4866 "protected",
4867 "public",
4868 "static",
4869 "yield",
4870 NULL
4871 };
4872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004873 RunParserSyncTest(context_data, name_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004874
4875 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4876 {NULL, NULL}};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004877 RunParserSyncTest(context_strict_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004878}
4879
4880
4881TEST(ObjectLiteralPropertyShorthandError) {
4882 const char* context_data[][2] = {{"({", "});"},
4883 {"'use strict'; ({", "});"},
4884 {NULL, NULL}};
4885
4886 const char* name_data[] = {
4887 "1",
4888 "1.2",
4889 "0",
4890 "0.1",
4891 "1.0",
4892 "1e1",
4893 "0x1",
4894 "\"s\"",
4895 "'s'",
4896 NULL
4897 };
4898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004899 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004900}
4901
4902
4903TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4904 const char* context_data[][2] = {{"", ""},
4905 {NULL, NULL}};
4906
4907 const char* name_data[] = {
4908 "function* g() { ({yield}); }",
4909 NULL
4910 };
4911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004912 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004913}
4914
4915
4916TEST(ConstParsingInForIn) {
4917 const char* context_data[][2] = {{"'use strict';", ""},
4918 {"function foo(){ 'use strict';", "}"},
4919 {NULL, NULL}};
4920
4921 const char* data[] = {
4922 "for(const x = 1; ; ) {}",
4923 "for(const x = 1, y = 2;;){}",
4924 "for(const x in [1,2,3]) {}",
4925 "for(const x of [1,2,3]) {}",
4926 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004927 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004928}
4929
4930
4931TEST(ConstParsingInForInError) {
4932 const char* context_data[][2] = {{"'use strict';", ""},
4933 {"function foo(){ 'use strict';", "}"},
4934 {NULL, NULL}};
4935
4936 const char* data[] = {
4937 "for(const x,y = 1; ; ) {}",
4938 "for(const x = 4 in [1,2,3]) {}",
4939 "for(const x = 4, y in [1,2,3]) {}",
4940 "for(const x = 4 of [1,2,3]) {}",
4941 "for(const x = 4, y of [1,2,3]) {}",
4942 "for(const x = 1, y = 2 in []) {}",
4943 "for(const x,y in []) {}",
4944 "for(const x = 1, y = 2 of []) {}",
4945 "for(const x,y of []) {}",
4946 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004947 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
4948}
4949
4950
4951TEST(InitializedDeclarationsInStrictForInError) {
4952 const char* context_data[][2] = {{"'use strict';", ""},
4953 {"function foo(){ 'use strict';", "}"},
4954 {NULL, NULL}};
4955
4956 const char* data[] = {
4957 "for (var i = 1 in {}) {}",
4958 "for (var i = void 0 in [1, 2, 3]) {}",
4959 "for (let i = 1 in {}) {}",
4960 "for (let i = void 0 in [1, 2, 3]) {}",
4961 "for (const i = 1 in {}) {}",
4962 "for (const i = void 0 in [1, 2, 3]) {}",
4963 NULL};
4964 RunParserSyncTest(context_data, data, kError);
4965}
4966
4967
4968TEST(InitializedDeclarationsInStrictForOfError) {
4969 const char* context_data[][2] = {{"'use strict';", ""},
4970 {"function foo(){ 'use strict';", "}"},
4971 {NULL, NULL}};
4972
4973 const char* data[] = {
4974 "for (var i = 1 of {}) {}",
4975 "for (var i = void 0 of [1, 2, 3]) {}",
4976 "for (let i = 1 of {}) {}",
4977 "for (let i = void 0 of [1, 2, 3]) {}",
4978 "for (const i = 1 of {}) {}",
4979 "for (const i = void 0 of [1, 2, 3]) {}",
4980 NULL};
4981 RunParserSyncTest(context_data, data, kError);
4982}
4983
4984
4985TEST(InitializedDeclarationsInSloppyForInError) {
4986 const char* context_data[][2] = {{"", ""},
4987 {"function foo(){", "}"},
4988 {NULL, NULL}};
4989
4990 const char* data[] = {
4991 "for (var i = 1 in {}) {}",
4992 "for (var i = void 0 in [1, 2, 3]) {}",
4993 NULL};
4994 // TODO(caitp): This should be an error in sloppy mode.
4995 RunParserSyncTest(context_data, data, kSuccess);
4996}
4997
4998
4999TEST(InitializedDeclarationsInSloppyForOfError) {
5000 const char* context_data[][2] = {{"", ""},
5001 {"function foo(){", "}"},
5002 {NULL, NULL}};
5003
5004 const char* data[] = {
5005 "for (var i = 1 of {}) {}",
5006 "for (var i = void 0 of [1, 2, 3]) {}",
5007 NULL};
5008 RunParserSyncTest(context_data, data, kError);
5009}
5010
5011
5012TEST(ForInMultipleDeclarationsError) {
5013 const char* context_data[][2] = {{"", ""},
5014 {"function foo(){", "}"},
5015 {"'use strict';", ""},
5016 {"function foo(){ 'use strict';", "}"},
5017 {NULL, NULL}};
5018
5019 const char* data[] = {
5020 "for (var i, j in {}) {}",
5021 "for (var i, j in [1, 2, 3]) {}",
5022 "for (var i, j = 1 in {}) {}",
5023 "for (var i, j = void 0 in [1, 2, 3]) {}",
5024
5025 "for (let i, j in {}) {}",
5026 "for (let i, j in [1, 2, 3]) {}",
5027 "for (let i, j = 1 in {}) {}",
5028 "for (let i, j = void 0 in [1, 2, 3]) {}",
5029
5030 "for (const i, j in {}) {}",
5031 "for (const i, j in [1, 2, 3]) {}",
5032 "for (const i, j = 1 in {}) {}",
5033 "for (const i, j = void 0 in [1, 2, 3]) {}",
5034 NULL};
5035 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5036 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5037 arraysize(always_flags));
5038}
5039
5040
5041TEST(ForOfMultipleDeclarationsError) {
5042 const char* context_data[][2] = {{"", ""},
5043 {"function foo(){", "}"},
5044 {"'use strict';", ""},
5045 {"function foo(){ 'use strict';", "}"},
5046 {NULL, NULL}};
5047
5048 const char* data[] = {
5049 "for (var i, j of {}) {}",
5050 "for (var i, j of [1, 2, 3]) {}",
5051 "for (var i, j = 1 of {}) {}",
5052 "for (var i, j = void 0 of [1, 2, 3]) {}",
5053
5054 "for (let i, j of {}) {}",
5055 "for (let i, j of [1, 2, 3]) {}",
5056 "for (let i, j = 1 of {}) {}",
5057 "for (let i, j = void 0 of [1, 2, 3]) {}",
5058
5059 "for (const i, j of {}) {}",
5060 "for (const i, j of [1, 2, 3]) {}",
5061 "for (const i, j = 1 of {}) {}",
5062 "for (const i, j = void 0 of [1, 2, 3]) {}",
5063 NULL};
5064 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5065 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5066 arraysize(always_flags));
5067}
5068
5069
5070TEST(ForInNoDeclarationsError) {
5071 const char* context_data[][2] = {{"", ""},
5072 {"function foo(){", "}"},
5073 {"'use strict';", ""},
5074 {"function foo(){ 'use strict';", "}"},
5075 {NULL, NULL}};
5076
5077 const char* data[] = {
5078 "for (var in {}) {}",
5079 "for (const in {}) {}",
5080 NULL};
5081 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5082 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5083 arraysize(always_flags));
5084}
5085
5086
5087TEST(ForOfNoDeclarationsError) {
5088 const char* context_data[][2] = {{"", ""},
5089 {"function foo(){", "}"},
5090 {"'use strict';", ""},
5091 {"function foo(){ 'use strict';", "}"},
5092 {NULL, NULL}};
5093
5094 const char* data[] = {
5095 "for (var of [1, 2, 3]) {}",
5096 "for (const of [1, 2, 3]) {}",
5097 NULL};
5098 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5099 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005100 arraysize(always_flags));
5101}
5102
5103
5104TEST(InvalidUnicodeEscapes) {
5105 const char* context_data[][2] = {{"", ""},
5106 {"'use strict';", ""},
5107 {NULL, NULL}};
5108 const char* data[] = {
5109 "var foob\\u123r = 0;",
5110 "var \\u123roo = 0;",
5111 "\"foob\\u123rr\"",
5112 // No escapes allowed in regexp flags
5113 "/regex/\\u0069g",
5114 "/regex/\\u006g",
5115 // Braces gone wrong
5116 "var foob\\u{c481r = 0;",
5117 "var foob\\uc481}r = 0;",
5118 "var \\u{0052oo = 0;",
5119 "var \\u0052}oo = 0;",
5120 "\"foob\\u{c481r\"",
5121 "var foob\\u{}ar = 0;",
5122 // Too high value for the unicode escape
5123 "\"\\u{110000}\"",
5124 // Not an unicode escape
5125 "var foob\\v1234r = 0;",
5126 "var foob\\U1234r = 0;",
5127 "var foob\\v{1234}r = 0;",
5128 "var foob\\U{1234}r = 0;",
5129 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005130 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005131}
5132
5133
5134TEST(UnicodeEscapes) {
5135 const char* context_data[][2] = {{"", ""},
5136 {"'use strict';", ""},
5137 {NULL, NULL}};
5138 const char* data[] = {
5139 // Identifier starting with escape
5140 "var \\u0052oo = 0;",
5141 "var \\u{0052}oo = 0;",
5142 "var \\u{52}oo = 0;",
5143 "var \\u{00000000052}oo = 0;",
5144 // Identifier with an escape but not starting with an escape
5145 "var foob\\uc481r = 0;",
5146 "var foob\\u{c481}r = 0;",
5147 // String with an escape
5148 "\"foob\\uc481r\"",
5149 "\"foob\\{uc481}r\"",
5150 // This character is a valid unicode character, representable as a surrogate
5151 // pair, not representable as 4 hex digits.
5152 "\"foo\\u{10e6d}\"",
5153 // Max value for the unicode escape
5154 "\"\\u{10ffff}\"",
5155 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005156 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005157}
5158
5159
5160TEST(ScanTemplateLiterals) {
5161 const char* context_data[][2] = {{"'use strict';", ""},
5162 {"function foo(){ 'use strict';"
5163 " var a, b, c; return ", "}"},
5164 {NULL, NULL}};
5165
5166 const char* data[] = {
5167 "``",
5168 "`no-subst-template`",
5169 "`template-head${a}`",
5170 "`${a}`",
5171 "`${a}template-tail`",
5172 "`template-head${a}template-tail`",
5173 "`${a}${b}${c}`",
5174 "`a${a}b${b}c${c}`",
5175 "`${a}a${b}b${c}c`",
5176 "`foo\n\nbar\r\nbaz`",
5177 "`foo\n\n${ bar }\r\nbaz`",
5178 "`foo${a /* comment */}`",
5179 "`foo${a // comment\n}`",
5180 "`foo${a \n}`",
5181 "`foo${a \r\n}`",
5182 "`foo${a \r}`",
5183 "`foo${/* comment */ a}`",
5184 "`foo${// comment\na}`",
5185 "`foo${\n a}`",
5186 "`foo${\r\n a}`",
5187 "`foo${\r a}`",
5188 "`foo${'a' in a}`",
5189 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005190 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005191}
5192
5193
5194TEST(ScanTaggedTemplateLiterals) {
5195 const char* context_data[][2] = {{"'use strict';", ""},
5196 {"function foo(){ 'use strict';"
5197 " function tag() {}"
5198 " var a, b, c; return ", "}"},
5199 {NULL, NULL}};
5200
5201 const char* data[] = {
5202 "tag ``",
5203 "tag `no-subst-template`",
5204 "tag`template-head${a}`",
5205 "tag `${a}`",
5206 "tag `${a}template-tail`",
5207 "tag `template-head${a}template-tail`",
5208 "tag\n`${a}${b}${c}`",
5209 "tag\r\n`a${a}b${b}c${c}`",
5210 "tag `${a}a${b}b${c}c`",
5211 "tag\t`foo\n\nbar\r\nbaz`",
5212 "tag\r`foo\n\n${ bar }\r\nbaz`",
5213 "tag`foo${a /* comment */}`",
5214 "tag`foo${a // comment\n}`",
5215 "tag`foo${a \n}`",
5216 "tag`foo${a \r\n}`",
5217 "tag`foo${a \r}`",
5218 "tag`foo${/* comment */ a}`",
5219 "tag`foo${// comment\na}`",
5220 "tag`foo${\n a}`",
5221 "tag`foo${\r\n a}`",
5222 "tag`foo${\r a}`",
5223 "tag`foo${'a' in a}`",
5224 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005225 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005226}
5227
5228
5229TEST(TemplateMaterializedLiterals) {
5230 const char* context_data[][2] = {
5231 {
5232 "'use strict';\n"
5233 "function tag() {}\n"
5234 "var a, b, c;\n"
5235 "(", ")"
5236 },
5237 {NULL, NULL}
5238 };
5239
5240 const char* data[] = {
5241 "tag``",
5242 "tag`a`",
5243 "tag`a${1}b`",
5244 "tag`a${1}b${2}c`",
5245 "``",
5246 "`a`",
5247 "`a${1}b`",
5248 "`a${1}b${2}c`",
5249 NULL
5250 };
5251
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005252 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005253}
5254
5255
5256TEST(ScanUnterminatedTemplateLiterals) {
5257 const char* context_data[][2] = {{"'use strict';", ""},
5258 {"function foo(){ 'use strict';"
5259 " var a, b, c; return ", "}"},
5260 {NULL, NULL}};
5261
5262 const char* data[] = {
5263 "`no-subst-template",
5264 "`template-head${a}",
5265 "`${a}template-tail",
5266 "`template-head${a}template-tail",
5267 "`${a}${b}${c}",
5268 "`a${a}b${b}c${c}",
5269 "`${a}a${b}b${c}c",
5270 "`foo\n\nbar\r\nbaz",
5271 "`foo\n\n${ bar }\r\nbaz",
5272 "`foo${a /* comment } */`",
5273 "`foo${a /* comment } `*/",
5274 "`foo${a // comment}`",
5275 "`foo${a \n`",
5276 "`foo${a \r\n`",
5277 "`foo${a \r`",
5278 "`foo${/* comment */ a`",
5279 "`foo${// commenta}`",
5280 "`foo${\n a`",
5281 "`foo${\r\n a`",
5282 "`foo${\r a`",
5283 "`foo${fn(}`",
5284 "`foo${1 if}`",
5285 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005286 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005287}
5288
5289
5290TEST(TemplateLiteralsIllegalTokens) {
5291 const char* context_data[][2] = {{"'use strict';", ""},
5292 {"function foo(){ 'use strict';"
5293 " var a, b, c; return ", "}"},
5294 {NULL, NULL}};
5295 const char* data[] = {
5296 "`hello\\x`",
5297 "`hello\\x${1}`",
5298 "`hello${1}\\x`",
5299 "`hello${1}\\x${2}`",
5300 "`hello\\x\n`",
5301 "`hello\\x\n${1}`",
5302 "`hello${1}\\x\n`",
5303 "`hello${1}\\x\n${2}`",
5304 NULL};
5305
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005306 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5307}
5308
5309
5310TEST(ParseRestParameters) {
5311 const char* context_data[][2] = {{"'use strict';(function(",
5312 "){ return args;})(1, [], /regexp/, 'str',"
5313 "function(){});"},
5314 {"(function(", "){ return args;})(1, [],"
5315 "/regexp/, 'str', function(){});"},
5316 {NULL, NULL}};
5317
5318 const char* data[] = {"...args",
5319 "a, ...args",
5320 "... args",
5321 "a, ... args",
5322 "...\targs",
5323 "a, ...\targs",
5324 "...\r\nargs",
5325 "a, ...\r\nargs",
5326 "...\rargs",
5327 "a, ...\rargs",
5328 "...\t\n\t\t\n args",
5329 "a, ... \n \n args",
5330 "...{ length, 0: a, 1: b}",
5331 "...{}",
5332 "...[a, b]",
5333 "...[]",
5334 "...[...[a, b, ...c]]",
5335 NULL};
5336 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
5337 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005338 arraysize(always_flags));
5339}
5340
5341
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005342TEST(ParseRestParametersErrors) {
5343 const char* context_data[][2] = {{"'use strict';(function(",
5344 "){ return args;}(1, [], /regexp/, 'str',"
5345 "function(){});"},
5346 {"(function(", "){ return args;}(1, [],"
5347 "/regexp/, 'str', function(){});"},
5348 {NULL, NULL}};
5349
5350 const char* data[] = {
5351 "...args, b",
5352 "a, ...args, b",
5353 "...args, b",
5354 "a, ...args, b",
5355 "...args,\tb",
5356 "a,...args\t,b",
5357 "...args\r\n, b",
5358 "a, ... args,\r\nb",
5359 "...args\r,b",
5360 "a, ... args,\rb",
5361 "...args\t\n\t\t\n, b",
5362 "a, ... args, \n \n b",
5363 "a, a, ...args",
5364 "a,\ta, ...args",
5365 "a,\ra, ...args",
5366 "a,\na, ...args",
5367 NULL};
5368 RunParserSyncTest(context_data, data, kError);
5369}
5370
5371
5372TEST(RestParameterInSetterMethodError) {
5373 const char* context_data[][2] = {
5374 {"'use strict';({ set prop(", ") {} }).prop = 1;"},
5375 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
5376 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
5377 {"({ set prop(", ") {} }).prop = 1;"},
5378 {"(class { static set prop(", ") {} }).prop = 1;"},
5379 {"(new (class { set prop(", ") {} })).prop = 1;"},
5380 {nullptr, nullptr}};
5381 const char* data[] = {"...a", "...arguments", "...eval", nullptr};
5382
5383 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5384 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5385 arraysize(always_flags));
5386}
5387
5388
5389TEST(RestParametersEvalArguments) {
5390 const char* strict_context_data[][2] =
5391 {{"'use strict';(function(",
5392 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5393 {NULL, NULL}};
5394 const char* sloppy_context_data[][2] =
5395 {{"(function(",
5396 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5397 {NULL, NULL}};
5398
5399 const char* data[] = {
5400 "...eval",
5401 "eval, ...args",
5402 "...arguments",
5403 "arguments, ...args",
5404 NULL};
5405
5406 // Fail in strict mode
5407 RunParserSyncTest(strict_context_data, data, kError);
5408
5409 // OK in sloppy mode
5410 RunParserSyncTest(sloppy_context_data, data, kSuccess);
5411}
5412
5413
5414TEST(RestParametersDuplicateEvalArguments) {
5415 const char* context_data[][2] =
5416 {{"'use strict';(function(",
5417 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5418 {"(function(",
5419 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5420 {NULL, NULL}};
5421
5422 const char* data[] = {
5423 "eval, ...eval",
5424 "eval, eval, ...args",
5425 "arguments, ...arguments",
5426 "arguments, arguments, ...args",
5427 NULL};
5428
5429 // In strict mode, the error is using "eval" or "arguments" as parameter names
5430 // In sloppy mode, the error is that eval / arguments are duplicated
5431 RunParserSyncTest(context_data, data, kError);
5432}
5433
5434
5435TEST(SpreadCall) {
5436 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5437 {"function fn() {} fn(", ");"},
5438 {NULL, NULL}};
5439
5440 const char* data[] = {
5441 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
5442 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
5443 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
5444 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
5445 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
5446 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
5447
5448 RunParserSyncTest(context_data, data, kSuccess);
5449}
5450
5451
5452TEST(SpreadCallErrors) {
5453 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5454 {"function fn() {} fn(", ");"},
5455 {NULL, NULL}};
5456
5457 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
5458
5459 RunParserSyncTest(context_data, data, kError);
5460}
5461
5462
5463TEST(BadRestSpread) {
5464 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
5465 {"function fn() { ", "} fn();"},
5466 {NULL, NULL}};
5467 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];",
5468 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
5469 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}",
5470 NULL};
5471 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5472}
5473
5474
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005475TEST(LexicalScopingSloppyMode) {
5476 const char* context_data[][2] = {
5477 {"", ""},
5478 {"function f() {", "}"},
5479 {"{", "}"},
5480 {NULL, NULL}};
5481 const char* bad_data[] = {
5482 "let x = 1;",
5483 "for(let x = 1;;){}",
5484 "for(let x of []){}",
5485 "for(let x in []){}",
5486 "class C {}",
5487 "class C extends D {}",
5488 "(class {})",
5489 "(class extends D {})",
5490 "(class C {})",
5491 "(class C extends D {})",
5492 NULL};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005493 static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005494 RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005495 always_false_flags, arraysize(always_false_flags));
5496
5497 const char* good_data[] = {
5498 "let = 1;",
5499 "for(let = 1;;){}",
5500 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005501 RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005502 always_false_flags, arraysize(always_false_flags));
5503}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005504
5505
5506TEST(ComputedPropertyName) {
5507 const char* context_data[][2] = {{"({[", "]: 1});"},
5508 {"({get [", "]() {}});"},
5509 {"({set [", "](_) {}});"},
5510 {"({[", "]() {}});"},
5511 {"({*[", "]() {}});"},
5512 {"(class {get [", "]() {}});"},
5513 {"(class {set [", "](_) {}});"},
5514 {"(class {[", "]() {}});"},
5515 {"(class {*[", "]() {}});"},
5516 {NULL, NULL}};
5517 const char* error_data[] = {
5518 "1, 2",
5519 "var name",
5520 NULL};
5521
5522 static const ParserFlag always_flags[] = {
5523 kAllowHarmonySloppy,
5524 };
5525 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5526 always_flags, arraysize(always_flags));
5527
5528 const char* name_data[] = {
5529 "1",
5530 "1 + 2",
5531 "'name'",
5532 "\"name\"",
5533 "[]",
5534 "{}",
5535 NULL};
5536
5537 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
5538 always_flags, arraysize(always_flags));
5539}
5540
5541
5542TEST(ComputedPropertyNameShorthandError) {
5543 const char* context_data[][2] = {{"({", "});"},
5544 {NULL, NULL}};
5545 const char* error_data[] = {
5546 "a: 1, [2]",
5547 "[1], a: 1",
5548 NULL};
5549
5550 static const ParserFlag always_flags[] = {
5551 kAllowHarmonySloppy,
5552 };
5553 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5554 always_flags, arraysize(always_flags));
5555}
5556
5557
5558TEST(BasicImportExportParsing) {
5559 i::FLAG_harmony_modules = true;
5560
5561 const char* kSources[] = {
5562 "export let x = 0;",
5563 "export var y = 0;",
5564 "export const z = 0;",
5565 "export function func() { };",
5566 "export class C { };",
5567 "export { };",
5568 "function f() {}; f(); export { f };",
5569 "var a, b, c; export { a, b as baz, c };",
5570 "var d, e; export { d as dreary, e, };",
5571 "export default function f() {}",
5572 "export default class C {}",
5573 "export default 42",
5574 "var x; export default x = 7",
5575 "export { Q } from 'somemodule.js';",
5576 "export * from 'somemodule.js';",
5577 "var foo; export { foo as for };",
5578 "export { arguments } from 'm.js';",
5579 "export { for } from 'm.js';",
5580 "export { yield } from 'm.js'",
5581 "export { static } from 'm.js'",
5582 "export { let } from 'm.js'",
5583 "var a; export { a as b, a as c };",
5584
5585 "import 'somemodule.js';",
5586 "import { } from 'm.js';",
5587 "import { a } from 'm.js';",
5588 "import { a, b as d, c, } from 'm.js';",
5589 "import * as thing from 'm.js';",
5590 "import thing from 'm.js';",
5591 "import thing, * as rest from 'm.js';",
5592 "import thing, { a, b, c } from 'm.js';",
5593 "import { arguments as a } from 'm.js';",
5594 "import { for as f } from 'm.js';",
5595 "import { yield as y } from 'm.js';",
5596 "import { static as s } from 'm.js';",
5597 "import { let as l } from 'm.js';",
5598 };
5599
5600 i::Isolate* isolate = CcTest::i_isolate();
5601 i::Factory* factory = isolate->factory();
5602
5603 v8::HandleScope handles(CcTest::isolate());
5604 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5605 v8::Context::Scope context_scope(context);
5606
5607 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5608 128 * 1024);
5609
5610 for (unsigned i = 0; i < arraysize(kSources); ++i) {
5611 i::Handle<i::String> source =
5612 factory->NewStringFromAsciiChecked(kSources[i]);
5613
5614 // Show that parsing as a module works
5615 {
5616 i::Handle<i::Script> script = factory->NewScript(source);
5617 i::Zone zone;
5618 i::ParseInfo info(&zone, script);
5619 i::Parser parser(&info);
5620 info.set_module();
5621 if (!parser.Parse(&info)) {
5622 i::Handle<i::JSObject> exception_handle(
5623 i::JSObject::cast(isolate->pending_exception()));
5624 i::Handle<i::String> message_string =
5625 i::Handle<i::String>::cast(i::Object::GetProperty(
5626 isolate, exception_handle, "message").ToHandleChecked());
5627
5628 v8::base::OS::Print(
5629 "Parser failed on:\n"
5630 "\t%s\n"
5631 "with error:\n"
5632 "\t%s\n"
5633 "However, we expected no error.",
5634 source->ToCString().get(), message_string->ToCString().get());
5635 CHECK(false);
5636 }
5637 }
5638
5639 // And that parsing a script does not.
5640 {
5641 i::Handle<i::Script> script = factory->NewScript(source);
5642 i::Zone zone;
5643 i::ParseInfo info(&zone, script);
5644 i::Parser parser(&info);
5645 info.set_global();
5646 CHECK(!parser.Parse(&info));
5647 }
5648 }
5649}
5650
5651
5652TEST(ImportExportParsingErrors) {
5653 i::FLAG_harmony_modules = true;
5654
5655 const char* kErrorSources[] = {
5656 "export {",
5657 "var a; export { a",
5658 "var a; export { a,",
5659 "var a; export { a, ;",
5660 "var a; export { a as };",
5661 "var a, b; export { a as , b};",
5662 "export }",
5663 "var foo, bar; export { foo bar };",
5664 "export { foo };",
5665 "export { , };",
5666 "export default;",
5667 "export default var x = 7;",
5668 "export default let x = 7;",
5669 "export default const x = 7;",
5670 "export *;",
5671 "export * from;",
5672 "export { Q } from;",
5673 "export default from 'module.js';",
5674 "export { for }",
5675 "export { for as foo }",
5676 "export { arguments }",
5677 "export { arguments as foo }",
5678 "var a; export { a, a };",
5679 "var a, b; export { a as b, b };",
5680 "var a, b; export { a as c, b as c };",
5681 "export default function f(){}; export default class C {};",
5682 "export default function f(){}; var a; export { a as default };",
5683
5684 "import from;",
5685 "import from 'm.js';",
5686 "import { };",
5687 "import {;",
5688 "import };",
5689 "import { , };",
5690 "import { , } from 'm.js';",
5691 "import { a } from;",
5692 "import { a } 'm.js';",
5693 "import , from 'm.js';",
5694 "import a , from 'm.js';",
5695 "import a { b, c } from 'm.js';",
5696 "import arguments from 'm.js';",
5697 "import eval from 'm.js';",
5698 "import { arguments } from 'm.js';",
5699 "import { eval } from 'm.js';",
5700 "import { a as arguments } from 'm.js';",
5701 "import { for } from 'm.js';",
5702 "import { y as yield } from 'm.js'",
5703 "import { s as static } from 'm.js'",
5704 "import { l as let } from 'm.js'",
5705 "import { x }, def from 'm.js';",
5706 "import def, def2 from 'm.js';",
5707 "import * as x, def from 'm.js';",
5708 "import * as x, * as y from 'm.js';",
5709 "import {x}, {y} from 'm.js';",
5710 "import * as x, {y} from 'm.js';",
5711
5712 // TODO(ES6): These two forms should be supported
5713 "export default function() {};",
5714 "export default class {};"
5715 };
5716
5717 i::Isolate* isolate = CcTest::i_isolate();
5718 i::Factory* factory = isolate->factory();
5719
5720 v8::HandleScope handles(CcTest::isolate());
5721 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5722 v8::Context::Scope context_scope(context);
5723
5724 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5725 128 * 1024);
5726
5727 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5728 i::Handle<i::String> source =
5729 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5730
5731 i::Handle<i::Script> script = factory->NewScript(source);
5732 i::Zone zone;
5733 i::ParseInfo info(&zone, script);
5734 i::Parser parser(&info);
5735 info.set_module();
5736 CHECK(!parser.Parse(&info));
5737 }
5738}
5739
5740
5741TEST(ModuleParsingInternals) {
5742 i::FLAG_harmony_modules = true;
5743
5744 i::Isolate* isolate = CcTest::i_isolate();
5745 i::Factory* factory = isolate->factory();
5746 v8::HandleScope handles(CcTest::isolate());
5747 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5748 v8::Context::Scope context_scope(context);
5749 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5750 128 * 1024);
5751
5752 static const char kSource[] =
5753 "let x = 5;"
5754 "export { x as y };"
5755 "import { q as z } from 'm.js';"
5756 "import n from 'n.js';"
5757 "export { a as b } from 'm.js';"
5758 "export * from 'p.js';"
5759 "import 'q.js'";
5760 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
5761 i::Handle<i::Script> script = factory->NewScript(source);
5762 i::Zone zone;
5763 i::ParseInfo info(&zone, script);
5764 i::Parser parser(&info);
5765 info.set_module();
5766 CHECK(parser.Parse(&info));
5767 CHECK(i::Compiler::Analyze(&info));
5768 i::FunctionLiteral* func = info.literal();
5769 i::Scope* module_scope = func->scope();
5770 i::Scope* outer_scope = module_scope->outer_scope();
5771 CHECK(outer_scope->is_script_scope());
5772 CHECK_NULL(outer_scope->outer_scope());
5773 CHECK(module_scope->is_module_scope());
5774 i::ModuleDescriptor* descriptor = module_scope->module();
5775 CHECK_NOT_NULL(descriptor);
5776 CHECK_EQ(1, descriptor->Length());
5777 const i::AstRawString* export_name =
5778 info.ast_value_factory()->GetOneByteString("y");
5779 const i::AstRawString* local_name =
5780 descriptor->LookupLocalExport(export_name, &zone);
5781 CHECK_NOT_NULL(local_name);
5782 CHECK(local_name->IsOneByteEqualTo("x"));
5783 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
5784 CHECK_EQ(3, declarations->length());
5785 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
5786 i::ImportDeclaration* import_decl =
5787 declarations->at(1)->AsImportDeclaration();
5788 CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
5789 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
5790 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
5791 import_decl = declarations->at(2)->AsImportDeclaration();
5792 CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
5793 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
5794 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
5795 // TODO(adamk): Add test for indirect exports once they're fully implemented.
5796 // TODO(adamk): Add test for star exports once they're fully implemented.
5797 const i::ZoneList<const i::AstRawString*>& requested_modules =
5798 descriptor->requested_modules();
5799 CHECK_EQ(4, requested_modules.length());
5800 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
5801 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
5802 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
5803 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
5804}
5805
5806
5807TEST(DuplicateProtoError) {
5808 const char* context_data[][2] = {
5809 {"({", "});"},
5810 {"'use strict'; ({", "});"},
5811 {NULL, NULL}
5812 };
5813 const char* error_data[] = {
5814 "__proto__: {}, __proto__: {}",
5815 "__proto__: {}, \"__proto__\": {}",
5816 "__proto__: {}, \"__\x70roto__\": {}",
5817 "__proto__: {}, a: 1, __proto__: {}",
5818 NULL
5819 };
5820
5821 RunParserSyncTest(context_data, error_data, kError);
5822}
5823
5824
5825TEST(DuplicateProtoNoError) {
5826 const char* context_data[][2] = {
5827 {"({", "});"},
5828 {"'use strict'; ({", "});"},
5829 {NULL, NULL}
5830 };
5831 const char* error_data[] = {
5832 "__proto__: {}, ['__proto__']: {}",
5833 "__proto__: {}, __proto__() {}",
5834 "__proto__: {}, get __proto__() {}",
5835 "__proto__: {}, set __proto__(v) {}",
5836 "__proto__: {}, __proto__",
5837 NULL
5838 };
5839
5840 RunParserSyncTest(context_data, error_data, kSuccess);
5841}
5842
5843
5844TEST(DeclarationsError) {
5845 const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5846 {"'use strict'; if (false) {} else", ""},
5847 {"'use strict'; while (false)", ""},
5848 {"'use strict'; for (;;)", ""},
5849 {"'use strict'; for (x in y)", ""},
5850 {"'use strict'; do ", " while (false)"},
5851 {"'use strong'; if (true)", ""},
5852 {"'use strong'; if (false) {} else", ""},
5853 {"'use strong'; while (false)", ""},
5854 {"'use strong'; for (;;)", ""},
5855 {"'use strong'; for (x in y)", ""},
5856 {"'use strong'; do ", " while (false)"},
5857 {NULL, NULL}};
5858
5859 const char* statement_data[] = {
5860 "let x = 1;",
5861 "const x = 1;",
5862 "class C {}",
5863 NULL};
5864
5865 static const ParserFlag always_flags[] = {kAllowStrongMode};
5866 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
5867 always_flags, arraysize(always_flags));
5868}
5869
5870
5871void TestLanguageMode(const char* source,
5872 i::LanguageMode expected_language_mode) {
5873 i::Isolate* isolate = CcTest::i_isolate();
5874 i::Factory* factory = isolate->factory();
5875 v8::HandleScope handles(CcTest::isolate());
5876 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5877 v8::Context::Scope context_scope(context);
5878 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5879 128 * 1024);
5880
5881 i::Handle<i::Script> script =
5882 factory->NewScript(factory->NewStringFromAsciiChecked(source));
5883 i::Zone zone;
5884 i::ParseInfo info(&zone, script);
5885 i::Parser parser(&info);
5886 parser.set_allow_strong_mode(true);
5887 info.set_global();
5888 parser.Parse(&info);
5889 CHECK(info.literal() != NULL);
5890 CHECK_EQ(expected_language_mode, info.literal()->language_mode());
5891}
5892
5893
5894TEST(LanguageModeDirectives) {
5895 TestLanguageMode("\"use nothing\"", i::SLOPPY);
5896 TestLanguageMode("\"use strict\"", i::STRICT);
5897 TestLanguageMode("\"use strong\"", i::STRONG);
5898
5899 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
5900 TestLanguageMode("var x = 1; \"use strong\"", i::SLOPPY);
5901
5902 // Test that multiple directives ("use strict" / "use strong") put the parser
5903 // into the correct mode.
5904 TestLanguageMode("\"use strict\"; \"use strong\";", i::STRONG);
5905 TestLanguageMode("\"use strong\"; \"use strict\";", i::STRONG);
5906
5907 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
5908 TestLanguageMode("\"use some future directive\"; \"use strong\";", i::STRONG);
5909}
5910
5911
5912TEST(PropertyNameEvalArguments) {
5913 const char* context_data[][2] = {{"'use strict';", ""},
5914 {"'use strong';", ""},
5915 {NULL, NULL}};
5916
5917 const char* statement_data[] = {
5918 "({eval: 1})",
5919 "({arguments: 1})",
5920 "({eval() {}})",
5921 "({arguments() {}})",
5922 "({*eval() {}})",
5923 "({*arguments() {}})",
5924 "({get eval() {}})",
5925 "({get arguments() {}})",
5926 "({set eval(_) {}})",
5927 "({set arguments(_) {}})",
5928
5929 "class C {eval() {}}",
5930 "class C {arguments() {}}",
5931 "class C {*eval() {}}",
5932 "class C {*arguments() {}}",
5933 "class C {get eval() {}}",
5934 "class C {get arguments() {}}",
5935 "class C {set eval(_) {}}",
5936 "class C {set arguments(_) {}}",
5937
5938 "class C {static eval() {}}",
5939 "class C {static arguments() {}}",
5940 "class C {static *eval() {}}",
5941 "class C {static *arguments() {}}",
5942 "class C {static get eval() {}}",
5943 "class C {static get arguments() {}}",
5944 "class C {static set eval(_) {}}",
5945 "class C {static set arguments(_) {}}",
5946
5947 NULL};
5948
5949 static const ParserFlag always_flags[] = {kAllowStrongMode};
5950 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
5951 always_flags, arraysize(always_flags));
5952}
5953
5954
5955TEST(FunctionLiteralDuplicateParameters) {
5956 const char* strict_context_data[][2] =
5957 {{"'use strict';(function(", "){})();"},
5958 {"(function(", ") { 'use strict'; })();"},
5959 {"'use strict'; function fn(", ") {}; fn();"},
5960 {"function fn(", ") { 'use strict'; }; fn();"},
5961 {"'use strong';(function(", "){})();"},
5962 {"(function(", ") { 'use strong'; })();"},
5963 {"'use strong'; function fn(", ") {}; fn();"},
5964 {"function fn(", ") { 'use strong'; }; fn();"},
5965 {NULL, NULL}};
5966
5967 const char* sloppy_context_data[][2] =
5968 {{"(function(", "){})();"},
5969 {"(function(", ") {})();"},
5970 {"function fn(", ") {}; fn();"},
5971 {"function fn(", ") {}; fn();"},
5972 {NULL, NULL}};
5973
5974 const char* data[] = {
5975 "a, a",
5976 "a, a, a",
5977 "b, a, a",
5978 "a, b, c, c",
5979 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
5980 NULL};
5981
5982 static const ParserFlag always_flags[] = { kAllowStrongMode };
5983 RunParserSyncTest(strict_context_data, data, kError, NULL, 0, always_flags,
5984 arraysize(always_flags));
5985 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, NULL, 0);
5986}
5987
5988
5989TEST(VarForbiddenInStrongMode) {
5990 const char* strong_context_data[][2] =
5991 {{"'use strong'; ", ""},
5992 {"function f() {'use strong'; ", "}"},
5993 {"function f() {'use strong'; while (true) { ", "} }"},
5994 {NULL, NULL}};
5995
5996 const char* strict_context_data[][2] =
5997 {{"'use strict'; ", ""},
5998 {"function f() {'use strict'; ", "}"},
5999 {"function f() {'use strict'; while (true) { ", "} }"},
6000 {NULL, NULL}};
6001
6002 const char* sloppy_context_data[][2] =
6003 {{"", ""},
6004 {"function f() { ", "}"},
6005 {NULL, NULL}};
6006
6007 const char* var_declarations[] = {
6008 "var x = 0;",
6009 "for (var i = 0; i < 10; i++) { }",
6010 NULL};
6011
6012 const char* let_declarations[] = {
6013 "let x = 0;",
6014 "for (let i = 0; i < 10; i++) { }",
6015 NULL};
6016
6017 const char* const_declarations[] = {
6018 "const x = 0;",
6019 NULL};
6020
6021 static const ParserFlag always_flags[] = {kAllowStrongMode};
6022 RunParserSyncTest(strong_context_data, var_declarations, kError, NULL, 0,
6023 always_flags, arraysize(always_flags));
6024 RunParserSyncTest(strong_context_data, let_declarations, kSuccess, NULL, 0,
6025 always_flags, arraysize(always_flags));
6026 RunParserSyncTest(strong_context_data, const_declarations, kSuccess, NULL, 0,
6027 always_flags, arraysize(always_flags));
6028
6029 RunParserSyncTest(strict_context_data, var_declarations, kSuccess, NULL, 0,
6030 always_flags, arraysize(always_flags));
6031 RunParserSyncTest(strict_context_data, let_declarations, kSuccess, NULL, 0,
6032 always_flags, arraysize(always_flags));
6033
6034 RunParserSyncTest(sloppy_context_data, var_declarations, kSuccess, NULL, 0,
6035 always_flags, arraysize(always_flags));
6036 // At the moment, let declarations are only available in strict mode.
6037 RunParserSyncTest(sloppy_context_data, let_declarations, kError, NULL, 0,
6038 always_flags, arraysize(always_flags));
6039}
6040
6041
6042TEST(StrongEmptySubStatements) {
6043 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6044 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6045 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6046
6047 const char* data_error[] = {
6048 "if (1);",
6049 "if (1) {} else;",
6050 "while (1);",
6051 "do; while (1);",
6052 "for (;;);",
6053 "for (x in []);",
6054 "for (x of []);",
6055 "for (const x = 0;;);",
6056 "for (const x in []);",
6057 "for (const x of []);",
6058 NULL};
6059
6060 const char* data_success[] = {
6061 "if (1) {} else {}",
6062 "switch(1) {}",
6063 "1+1;;",
6064 "1+1; ;",
6065 NULL};
6066
6067 static const ParserFlag always_flags[] = {
6068 kAllowStrongMode,
6069 };
6070 RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
6071 always_flags, arraysize(always_flags));
6072 RunParserSyncTest(strict_context_data, data_error, kSuccess, NULL, 0,
6073 always_flags, arraysize(always_flags));
6074 RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
6075 always_flags, arraysize(always_flags));
6076 RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
6077 always_flags, arraysize(always_flags));
6078}
6079
6080
6081TEST(StrongForIn) {
6082 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6083 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6084 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6085
6086 const char* data[] = {
6087 "for (x in []) {}",
6088 "for (const x in []) {}",
6089 NULL};
6090
6091 static const ParserFlag always_flags[] = {
6092 kAllowStrongMode,
6093 };
6094 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
6095 arraysize(always_flags));
6096 RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
6097 arraysize(always_flags));
6098 RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
6099 arraysize(always_flags));
6100}
6101
6102
6103TEST(StrongConstructorThis) {
6104 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6105 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6106 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6107
6108 const char* error_data[] = {
6109 "class C { constructor() { this; } }",
6110 "class C { constructor() { this.a; } }",
6111 "class C { constructor() { this['a']; } }",
6112 "class C { constructor() { (this); } }",
6113 "class C { constructor() { this(); } }",
6114 // TODO(rossberg): arrow functions not handled yet.
6115 // "class C { constructor() { () => this; } }",
6116 "class C { constructor() { this.a = 0, 0; } }",
6117 "class C { constructor() { (this.a = 0); } }",
6118 // "class C { constructor() { (() => this.a = 0)(); } }",
6119 "class C { constructor() { { this.a = 0; } } }",
6120 "class C { constructor() { if (1) this.a = 0; } }",
6121 "class C { constructor() { label: this.a = 0; } }",
6122 "class C { constructor() { this.a = this.b; } }",
6123 "class C { constructor() { this.a = {b: 1}; this.a.b } }",
6124 "class C { constructor() { this.a = {b: 1}; this.a.b = 0 } }",
6125 "class C { constructor() { this.a = function(){}; this.a() } }",
6126 NULL};
6127
6128 const char* success_data[] = {
6129 "class C { constructor() { this.a = 0; } }",
6130 "class C { constructor() { label: 0; this.a = 0; this.b = 6; } }",
6131 NULL};
6132
6133 static const ParserFlag always_flags[] = {kAllowStrongMode};
6134 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6135 always_flags, arraysize(always_flags));
6136 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6137 always_flags, arraysize(always_flags));
6138 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6139 always_flags, arraysize(always_flags));
6140
6141 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6142 always_flags, arraysize(always_flags));
6143 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6144 always_flags, arraysize(always_flags));
6145 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6146 always_flags, arraysize(always_flags));
6147}
6148
6149
6150TEST(StrongConstructorSuper) {
6151 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6152 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6153 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6154
6155 const char* error_data[] = {
6156 "class C extends Object { constructor() {} }",
6157 "class C extends Object { constructor() { super.a; } }",
6158 "class C extends Object { constructor() { super['a']; } }",
6159 "class C extends Object { constructor() { super.a = 0; } }",
6160 "class C extends Object { constructor() { (super.a); } }",
6161 // TODO(rossberg): arrow functions do not handle super yet.
6162 // "class C extends Object { constructor() { () => super.a; } }",
6163 "class C extends Object { constructor() { super(), 0; } }",
6164 "class C extends Object { constructor() { (super()); } }",
6165 // "class C extends Object { constructor() { (() => super())(); } }",
6166 "class C extends Object { constructor() { { super(); } } }",
6167 "class C extends Object { constructor() { if (1) super(); } }",
6168 "class C extends Object { constructor() { label: super(); } }",
6169 "class C extends Object { constructor() { super(), super(); } }",
6170 "class C extends Object { constructor() { super(); super(); } }",
6171 "class C extends Object { constructor() { super(); (super()); } }",
6172 "class C extends Object { constructor() { super(); { super() } } }",
6173 "class C extends Object { constructor() { this.a = 0, super(); } }",
6174 "class C extends Object { constructor() { this.a = 0; super(); } }",
6175 "class C extends Object { constructor() { super(this.a = 0); } }",
6176 "class C extends Object { constructor() { super().a; } }",
6177 NULL};
6178
6179 const char* success_data[] = {
6180 "class C extends Object { constructor() { super(); } }",
6181 "class C extends Object { constructor() { label: 66; super(); } }",
6182 "class C extends Object { constructor() { super(3); this.x = 0; } }",
6183 "class C extends Object { constructor() { 3; super(3); this.x = 0; } }",
6184 NULL};
6185
6186 static const ParserFlag always_flags[] = {kAllowStrongMode};
6187 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6188 always_flags, arraysize(always_flags));
6189 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6190 always_flags, arraysize(always_flags));
6191 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6192 always_flags, arraysize(always_flags));
6193
6194 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6195 always_flags, arraysize(always_flags));
6196 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6197 always_flags, arraysize(always_flags));
6198 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6199 always_flags, arraysize(always_flags));
6200}
6201
6202
6203TEST(StrongConstructorReturns) {
6204 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6205 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6206 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6207
6208 const char* error_data[] = {
6209 "class C extends Object { constructor() { super(); return {}; } }",
6210 "class C extends Object { constructor() { super(); { return {}; } } }",
6211 "class C extends Object { constructor() { super(); if (1) return {}; } }",
6212 "class C extends Object { constructor() { return; super(); } }",
6213 "class C extends Object { constructor() { { return; } super(); } }",
6214 "class C extends Object { constructor() { if (0) return; super(); } }",
6215 "class C { constructor() { return; this.a = 0; } }",
6216 "class C { constructor() { { return; } this.a = 0; } }",
6217 "class C { constructor() { if (0) return; this.a = 0; } }",
6218 "class C { constructor() { this.a = 0; if (0) return; this.b = 0; } }",
6219 NULL};
6220
6221 const char* success_data[] = {
6222 "class C extends Object { constructor() { super(); return; } }",
6223 "class C extends Object { constructor() { super(); { return } } }",
6224 "class C extends Object { constructor() { super(); if (1) return; } }",
6225 "class C { constructor() { this.a = 0; return; } }",
6226 "class C { constructor() { this.a = 0; { return; } } }",
6227 "class C { constructor() { this.a = 0; if (0) return; 65; } }",
6228 "class C extends Array { constructor() { super(); this.a = 9; return } }",
6229 NULL};
6230
6231 static const ParserFlag always_flags[] = {kAllowStrongMode};
6232 RunParserSyncTest(sloppy_context_data, error_data, kError, NULL, 0,
6233 always_flags, arraysize(always_flags));
6234 RunParserSyncTest(strict_context_data, error_data, kSuccess, NULL, 0,
6235 always_flags, arraysize(always_flags));
6236 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6237 always_flags, arraysize(always_flags));
6238
6239 RunParserSyncTest(sloppy_context_data, success_data, kError, NULL, 0,
6240 always_flags, arraysize(always_flags));
6241 RunParserSyncTest(strict_context_data, success_data, kSuccess, NULL, 0,
6242 always_flags, arraysize(always_flags));
6243 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6244 always_flags, arraysize(always_flags));
6245}
6246
6247
6248TEST(StrongConstructorDirective) {
6249 const char* context_data[][2] = {{"class c { ", " }"},
6250 {"(class c { ", " });"},
6251 {"let a = (class c { ", " });"},
6252 {NULL}};
6253
6254 const char* error_data[] = {
6255 "constructor() { \"use strong\" }",
6256 "constructor(...rest) { \"use strong\" }",
6257 "foo() {} constructor() { \"use strong\" }",
6258 "foo(...rest) { \"use strict\" } constructor() { \"use strong\" }", NULL};
6259
6260 const char* success_data[] = {
6261 "constructor() { \"use strict\" }", "foo() { \"use strong\" }",
6262 "foo() { \"use strong\" } constructor() {}", NULL};
6263
6264 static const ParserFlag always_flags[] = {
6265 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowStrongMode};
6266
6267 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
6268 arraysize(always_flags));
6269 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
6270 arraysize(always_flags));
6271}
6272
6273
6274TEST(StrongUndefinedLocal) {
6275 const char* context_data[][2] = {{"", ""}, {NULL}};
6276
6277 const char* data[] = {
6278 "function undefined() {'use strong';}",
6279 "function* undefined() {'use strong';}",
6280 "(function undefined() {'use strong';});",
6281 "{foo: (function undefined(){'use strong';})};",
6282 "(function* undefined() {'use strong';})",
6283 "{foo: (function* undefined(){'use strong';})};",
6284 "function foo(a, b, undefined, c, d) {'use strong';}",
6285 "function* foo(a, b, undefined, c, d) {'use strong';}",
6286 "(function foo(a, b, undefined, c, d) {'use strong';})",
6287 "{foo: (function foo(a, b, undefined, c, d) {'use strong';})};",
6288 "(function* foo(a, b, undefined, c, d) {'use strong';})",
6289 "{foo: (function* foo(a, b, undefined, c, d) {'use strong';})};",
6290 "class C { foo(a, b, undefined, c, d) {'use strong';} }",
6291 "class C { *foo(a, b, undefined, c, d) {'use strong';} }",
6292 "({ foo(a, b, undefined, c, d) {'use strong';} });",
6293 "{ *foo(a, b, undefined, c, d) {'use strong';} });",
6294 "class undefined {'use strong'}",
6295 "(class undefined {'use strong'});",
6296 NULL};
6297
6298 static const ParserFlag always_flags[] = {
6299 kAllowStrongMode, kAllowHarmonySloppy
6300 };
6301
6302 RunParserSyncTest(context_data, data, kError, NULL, 0,
6303 always_flags, arraysize(always_flags));
6304}
6305
6306
6307TEST(StrongUndefinedArrow) {
6308 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6309 const char* strict_context_data[][2] = {{"'use strict';", ""}, {NULL}};
6310 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6311
6312 const char* data[] = {
6313 "(undefined => {return});",
6314 "((undefined, b, c) => {return});",
6315 "((a, undefined, c) => {return});",
6316 "((a, b, undefined) => {return});",
6317 NULL};
6318
6319 const char* local_strong[] = {
6320 "(undefined => {'use strong';});",
6321 "((undefined, b, c) => {'use strong';});",
6322 "((a, undefined, c) => {'use strong';});",
6323 "((a, b, undefined) => {'use strong';});",
6324 NULL};
6325
6326 static const ParserFlag always_flags[] = {kAllowStrongMode};
6327 RunParserSyncTest(sloppy_context_data, data, kSuccess, NULL, 0, always_flags,
6328 arraysize(always_flags));
6329 RunParserSyncTest(strict_context_data, data, kSuccess, NULL, 0, always_flags,
6330 arraysize(always_flags));
6331 RunParserSyncTest(strong_context_data, data, kError, NULL, 0, always_flags,
6332 arraysize(always_flags));
6333 RunParserSyncTest(sloppy_context_data, local_strong, kError, NULL, 0,
6334 always_flags, arraysize(always_flags));
6335}
6336
6337
6338TEST(StrongDirectEval) {
6339 const char* sloppy_context_data[][2] = {{"", ""}, {NULL}};
6340 const char* strong_context_data[][2] = {{"'use strong';", ""}, {NULL}};
6341
6342 const char* error_data[] = {
6343 "eval();",
6344 "eval([]);",
6345 "(eval)();",
6346 "(((eval)))();",
6347 "eval('function f() {}');",
6348 "function f() {eval()}",
6349 NULL};
6350
6351 const char* success_data[] = {
6352 "eval;",
6353 "eval`foo`;",
6354 "let foo = eval; foo();",
6355 "(1, eval)();",
6356 NULL};
6357
6358 static const ParserFlag always_flags[] = {
6359 kAllowStrongMode
6360 };
6361
6362 RunParserSyncTest(sloppy_context_data, error_data, kSuccess, NULL, 0,
6363 always_flags, arraysize(always_flags));
6364 RunParserSyncTest(strong_context_data, error_data, kError, NULL, 0,
6365 always_flags, arraysize(always_flags));
6366 RunParserSyncTest(strong_context_data, success_data, kSuccess, NULL, 0,
6367 always_flags, arraysize(always_flags));
6368}
6369
6370
6371TEST(StrongSwitchFallthrough) {
6372 const char* sloppy_context_data[][2] = {
6373 {"function f() { foo:for(;;) { switch(1) {", "};}}"},
6374 {NULL, NULL}
6375 };
6376 const char* strong_context_data[][2] = {
6377 {"function f() { 'use strong'; foo:for(;;) { switch(1) {", "};}}"},
6378 {NULL, NULL}
6379 };
6380
6381 const char* data_success[] = {
6382 "",
6383 "case 1:",
6384 "case 1: case 2:",
6385 "case 1: break;",
6386 "default: throw new TypeError();",
6387 "case 1: case 2: null",
6388 "case 1: case 2: default: 1+1",
6389 "case 1: break; case 2: return; default:",
6390 "case 1: break foo; case 2: return; default:",
6391 "case 1: case 2: break; case 3: continue; case 4: default:",
6392 "case 1: case 2: break; case 3: continue foo; case 4: default:",
6393 "case 1: case 2: {{return;}} case 3: default:",
6394 "case 1: case 2: case 3: default: {1+1;{continue;}}",
6395 "case 1: case 2: {1+1;{1+1;{continue;}}} case 3: default:",
6396 "case 1: if (1) break; else continue; case 2: case 3: default:",
6397 "case 1: case 2: if (1) {{break;}} else break; case 3: default:",
6398 "case 1: if (1) break; else {if (1) break; else break;} case 2: default:",
6399 "case 1: if (1) {if (1) break; else break;} else break; case 2: default:",
6400 NULL};
6401
6402 const char* data_error[] = {
6403 "case 1: case 2: (function(){return}); default:",
6404 "case 1: 1+1; case 2:",
6405 "case 1: bar: break bar; case 2: break;",
6406 "case 1: bar:return; case 2:",
6407 "case 1: bar:{ continue;} case 2:",
6408 "case 1: break; case 2: bar:{ throw new TypeError() } default:",
6409 "case 1: case 2: { bar:{ { break;} } } default: break;",
6410 "case 1: if (1) break; else {}; case 2: default:",
6411 "case 1: case 2: if (1) break; default:",
6412 "case 1: case 2: if (1) break; else 0; default:",
6413 "case 1: case 2: if (1) 0; else break; default:",
6414 "case 1: case 2: case 3: if (1) {} default:",
6415 "case 1: bar:if (1) break; else continue; case 2: case 3: default:",
6416 NULL};
6417
6418 static const ParserFlag always_flags[] = {
6419 kAllowStrongMode
6420 };
6421 RunParserSyncTest(strong_context_data, data_success, kSuccess, NULL, 0,
6422 always_flags, arraysize(always_flags));
6423 RunParserSyncTest(sloppy_context_data, data_error, kSuccess, NULL, 0,
6424 always_flags, arraysize(always_flags));
6425 RunParserSyncTest(strong_context_data, data_error, kError, NULL, 0,
6426 always_flags, arraysize(always_flags));
6427}
6428
6429
6430TEST(ArrowFunctionASIErrors) {
6431 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
6432 {NULL, NULL}};
6433
6434 const char* data[] = {
6435 "(a\n=> a)(1)",
6436 "(a/*\n*/=> a)(1)",
6437 "((a)\n=> a)(1)",
6438 "((a)/*\n*/=> a)(1)",
6439 "((a, b)\n=> a + b)(1, 2)",
6440 "((a, b)/*\n*/=> a + b)(1, 2)",
6441 NULL};
6442 RunParserSyncTest(context_data, data, kError);
6443}
6444
6445
6446TEST(StrongModeFreeVariablesDeclaredByPreviousScript) {
6447 i::FLAG_strong_mode = true;
6448 i::FLAG_legacy_const = true;
6449 v8::V8::Initialize();
6450 v8::HandleScope scope(CcTest::isolate());
6451 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6452 v8::TryCatch try_catch(CcTest::isolate());
6453
6454 // Introduce a bunch of variables, in all language modes.
6455 const char* script1 =
6456 "var my_var1 = 0; \n"
6457 "function my_func1() { } \n"
6458 "const my_const1 = 0; \n";
6459 CompileRun(v8_str(script1));
6460 CHECK(!try_catch.HasCaught());
6461
6462 const char* script2 =
6463 "\"use strict\"; \n"
6464 "let my_var2 = 0; \n"
6465 "function my_func2() { } \n"
6466 "const my_const2 = 0 \n";
6467 CompileRun(v8_str(script2));
6468 CHECK(!try_catch.HasCaught());
6469
6470 const char* script3 =
6471 "\"use strong\"; \n"
6472 "let my_var3 = 0; \n"
6473 "function my_func3() { } \n"
6474 "const my_const3 = 0; \n";
6475 CompileRun(v8_str(script3));
6476 CHECK(!try_catch.HasCaught());
6477
6478 // Sloppy eval introduces variables in the surrounding scope.
6479 const char* script4 =
6480 "eval('var my_var4 = 0;') \n"
6481 "eval('function my_func4() { }') \n"
6482 "eval('const my_const4 = 0;') \n";
6483 CompileRun(v8_str(script4));
6484 CHECK(!try_catch.HasCaught());
6485
6486 // Test that referencing these variables work.
6487 const char* script5 =
6488 "\"use strong\"; \n"
6489 "my_var1; \n"
6490 "my_func1; \n"
6491 "my_const1; \n"
6492 "my_var2; \n"
6493 "my_func2; \n"
6494 "my_const2; \n"
6495 "my_var3; \n"
6496 "my_func3; \n"
6497 "my_const3; \n"
6498 "my_var4; \n"
6499 "my_func4; \n"
6500 "my_const4; \n";
6501 CompileRun(v8_str(script5));
6502 CHECK(!try_catch.HasCaught());
6503}
6504
6505
6506TEST(StrongModeFreeVariablesDeclaredByLanguage) {
6507 i::FLAG_strong_mode = true;
6508 v8::V8::Initialize();
6509 v8::HandleScope scope(CcTest::isolate());
6510 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6511 v8::TryCatch try_catch(CcTest::isolate());
6512
6513 const char* script1 =
6514 "\"use strong\"; \n"
6515 "Math; \n"
6516 "RegExp; \n";
6517 CompileRun(v8_str(script1));
6518 CHECK(!try_catch.HasCaught());
6519}
6520
6521
6522TEST(StrongModeFreeVariablesDeclaredInGlobalPrototype) {
6523 i::FLAG_strong_mode = true;
6524 v8::V8::Initialize();
6525 v8::HandleScope scope(CcTest::isolate());
6526 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6527 v8::TryCatch try_catch(CcTest::isolate());
6528
6529 const char* script1 = "this.__proto__.my_var = 0;\n";
6530 CompileRun(v8_str(script1));
6531 CHECK(!try_catch.HasCaught());
6532
6533 const char* script2 =
6534 "\"use strong\"; \n"
6535 "my_var; \n";
6536 CompileRun(v8_str(script2));
6537 CHECK(!try_catch.HasCaught());
6538}
6539
6540
6541TEST(StrongModeFreeVariablesNotDeclared) {
6542 i::FLAG_strong_mode = true;
6543 v8::V8::Initialize();
6544 v8::HandleScope scope(CcTest::isolate());
6545 v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
6546 v8::TryCatch try_catch(CcTest::isolate());
6547
6548 // Test that referencing unintroduced variables in sloppy mode is ok.
6549 const char* script1 =
6550 "if (false) { \n"
6551 " not_there1; \n"
6552 "} \n";
6553 CompileRun(v8_str(script1));
6554 CHECK(!try_catch.HasCaught());
6555
6556 // But not in strong mode.
6557 {
6558 const char* script2 =
6559 "\"use strong\"; \n"
6560 "if (false) { \n"
6561 " not_there2; \n"
6562 "} \n";
6563 v8::TryCatch try_catch2(CcTest::isolate());
6564 v8_compile(v8_str(script2));
6565 CHECK(try_catch2.HasCaught());
6566 v8::String::Utf8Value exception(try_catch2.Exception());
6567 CHECK_EQ(0,
6568 strcmp(
6569 "ReferenceError: In strong mode, using an undeclared global "
6570 "variable 'not_there2' is not allowed",
6571 *exception));
6572 }
6573
6574 // Check that the variable reference is detected inside a strong function too,
6575 // even if the script scope is not strong.
6576 {
6577 const char* script3 =
6578 "(function not_lazy() { \n"
6579 " \"use strong\"; \n"
6580 " if (false) { \n"
6581 " not_there3; \n"
6582 " } \n"
6583 "})(); \n";
6584 v8::TryCatch try_catch2(CcTest::isolate());
6585 v8_compile(v8_str(script3));
6586 CHECK(try_catch2.HasCaught());
6587 v8::String::Utf8Value exception(try_catch2.Exception());
6588 CHECK_EQ(0,
6589 strcmp(
6590 "ReferenceError: In strong mode, using an undeclared global "
6591 "variable 'not_there3' is not allowed",
6592 *exception));
6593 }
6594}
6595
6596
6597TEST(DestructuringPositiveTests) {
6598 i::FLAG_harmony_destructuring_bind = true;
6599
6600 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6601 {"var ", " = {};"},
6602 {"'use strict'; const ", " = {};"},
6603 {"function f(", ") {}"},
6604 {"function f(argument1, ", ") {}"},
6605 {"var f = (", ") => {};"},
6606 {"var f = (argument1,", ") => {};"},
6607 {"try {} catch(", ") {}"},
6608 {NULL, NULL}};
6609
6610 // clang-format off
6611 const char* data[] = {
6612 "a",
6613 "{ x : y }",
6614 "{ x : y = 1 }",
6615 "{ get, set }",
6616 "{ get = 1, set = 2 }",
6617 "[a]",
6618 "[a = 1]",
6619 "[a,b,c]",
6620 "[a, b = 42, c]",
6621 "{ x : x, y : y }",
6622 "{ x : x = 1, y : y }",
6623 "{ x : x, y : y = 42 }",
6624 "[]",
6625 "{}",
6626 "[{x:x, y:y}, [a,b,c]]",
6627 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
6628 "{x}",
6629 "{x, y}",
6630 "{x = 42, y = 15}",
6631 "[a,,b]",
6632 "{42 : x}",
6633 "{42 : x = 42}",
6634 "{42e-2 : x}",
6635 "{42e-2 : x = 42}",
6636 "{x : y, x : z}",
6637 "{'hi' : x}",
6638 "{'hi' : x = 42}",
6639 "{var: x}",
6640 "{var: x = 42}",
6641 "{[x] : z}",
6642 "{[1+1] : z}",
6643 "{[foo()] : z}",
6644 "{}",
6645 "[...rest]",
6646 "[a,b,...rest]",
6647 "[a,,...rest]",
6648 NULL};
6649 // clang-format on
6650 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
6651 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
6652 arraysize(always_flags));
6653}
6654
6655
6656TEST(DestructuringNegativeTests) {
6657 i::FLAG_harmony_destructuring_bind = true;
6658 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
6659
6660 { // All modes.
6661 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6662 {"var ", " = {};"},
6663 {"'use strict'; const ", " = {};"},
6664 {"function f(", ") {}"},
6665 {"function f(argument1, ", ") {}"},
6666 {"var f = (", ") => {};"},
6667 {"var f = ", " => {};"},
6668 {"var f = (argument1,", ") => {};"},
6669 {"try {} catch(", ") {}"},
6670 {NULL, NULL}};
6671
6672 // clang-format off
6673 const char* data[] = {
6674 "a++",
6675 "++a",
6676 "delete a",
6677 "void a",
6678 "typeof a",
6679 "--a",
6680 "+a",
6681 "-a",
6682 "~a",
6683 "!a",
6684 "{ x : y++ }",
6685 "[a++]",
6686 "(x => y)",
6687 "a[i]", "a()",
6688 "a.b",
6689 "new a",
6690 "a + a",
6691 "a - a",
6692 "a * a",
6693 "a / a",
6694 "a == a",
6695 "a != a",
6696 "a > a",
6697 "a < a",
6698 "a <<< a",
6699 "a >>> a",
6700 "function a() {}",
6701 "a`bcd`",
6702 "this",
6703 "null",
6704 "true",
6705 "false",
6706 "1",
6707 "'abc'",
6708 "/abc/",
6709 "`abc`",
6710 "class {}",
6711 "{+2 : x}",
6712 "{-2 : x}",
6713 "var",
6714 "[var]",
6715 "{x : {y : var}}",
6716 "{x : x = a+}",
6717 "{x : x = (a+)}",
6718 "{x : x += a}",
6719 "{m() {} = 0}",
6720 "{[1+1]}",
6721 "[...rest, x]",
6722 "[a,b,...rest, x]",
6723 "[a,,...rest, x]",
6724 "[...rest,]",
6725 "[a,b,...rest,]",
6726 "[a,,...rest,]",
6727 "[...rest,...rest1]",
6728 "[a,b,...rest,...rest1]",
6729 "[a,,..rest,...rest1]",
6730 "{ x : 3 }",
6731 "{ x : 'foo' }",
6732 "{ x : /foo/ }",
6733 "{ x : `foo` }",
6734 "{ get a() {} }",
6735 "{ set a() {} }",
6736 "{ method() {} }",
6737 "{ *method() {} }",
6738 NULL};
6739 // clang-format on
6740 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6741 arraysize(always_flags));
6742 }
6743
6744 { // All modes.
6745 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6746 {"var ", " = {};"},
6747 {"'use strict'; const ", " = {};"},
6748 {"function f(", ") {}"},
6749 {"function f(argument1, ", ") {}"},
6750 {"var f = (", ") => {};"},
6751 {"var f = (argument1,", ") => {};"},
6752 {NULL, NULL}};
6753
6754 // clang-format off
6755 const char* data[] = {
6756 "x => x",
6757 "() => x",
6758 NULL};
6759 // clang-format on
6760 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6761 arraysize(always_flags));
6762 }
6763
6764 { // Strict mode.
6765 const char* context_data[][2] = {
6766 {"'use strict'; let ", " = {};"},
6767 {"'use strict'; const ", " = {};"},
6768 {"'use strict'; function f(", ") {}"},
6769 {"'use strict'; function f(argument1, ", ") {}"},
6770 {NULL, NULL}};
6771
6772 // clang-format off
6773 const char* data[] = {
6774 "[eval]",
6775 "{ a : arguments }",
6776 "[public]",
6777 "{ x : private }",
6778 NULL};
6779 // clang-format on
6780 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6781 arraysize(always_flags));
6782 }
6783
6784 { // 'yield' in generators.
6785 const char* context_data[][2] = {
6786 {"function*() { var ", " = {};"},
6787 {"function*() { 'use strict'; let ", " = {};"},
6788 {"function*() { 'use strict'; const ", " = {};"},
6789 {NULL, NULL}};
6790
6791 // clang-format off
6792 const char* data[] = {
6793 "yield",
6794 "[yield]",
6795 "{ x : yield }",
6796 NULL};
6797 // clang-format on
6798 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6799 arraysize(always_flags));
6800 }
6801
6802 { // Declaration-specific errors
6803 const char* context_data[][2] = {{"'use strict'; var ", ""},
6804 {"'use strict'; let ", ""},
6805 {"'use strict'; const ", ""},
6806 {"'use strict'; for (var ", ";;) {}"},
6807 {"'use strict'; for (let ", ";;) {}"},
6808 {"'use strict'; for (const ", ";;) {}"},
6809 {"var ", ""},
6810 {"let ", ""},
6811 {"const ", ""},
6812 {"for (var ", ";;) {}"},
6813 {"for (let ", ";;) {}"},
6814 {"for (const ", ";;) {}"},
6815 {NULL, NULL}};
6816
6817 // clang-format off
6818 const char* data[] = {
6819 "{ a }",
6820 "[ a ]",
6821 NULL};
6822 // clang-format on
6823 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
6824 kAllowHarmonySloppyLet};
6825 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6826 arraysize(always_flags));
6827 }
6828}
6829
6830
6831TEST(DestructuringAssignmentPositiveTests) {
6832 const char* context_data[][2] = {
6833 {"'use strict'; let x, y, z; (", " = {});"},
6834 {"var x, y, z; (", " = {});"},
6835 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6836 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6837 {"var x, y, z; for (x in ", " = {});"},
6838 {"var x, y, z; for (x of ", " = {});"},
6839 {"var x, y, z; for (", " in {});"},
6840 {"var x, y, z; for (", " of {});"},
6841 {"'use strict'; var x, y, z; for (", " in {});"},
6842 {"'use strict'; var x, y, z; for (", " of {});"},
6843 {NULL, NULL}};
6844
6845 const char* mixed_assignments_context_data[][2] = {
6846 {"'use strict'; let x, y, z; (", " = z = {});"},
6847 {"var x, y, z; (", " = z = {});"},
6848 {"'use strict'; let x, y, z; (x = ", " = z = {});"},
6849 {"var x, y, z; (x = ", " = z = {});"},
6850 {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
6851 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
6852 {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
6853 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
6854 {"var x, y, z; for (x in ", " = z = {});"},
6855 {"var x, y, z; for (x in x = ", " = z = {});"},
6856 {"var x, y, z; for (x of ", " = z = {});"},
6857 {"var x, y, z; for (x of x = ", " = z = {});"},
6858 {NULL, NULL}};
6859
6860 // clang-format off
6861 const char* data[] = {
6862 "x",
6863
6864 "{ x : y }",
6865 "{ x : foo().y }",
6866 "{ x : foo()[y] }",
6867 "{ x : y.z }",
6868 "{ x : y[z] }",
6869 "{ x : { y } }",
6870 "{ x : { foo: y } }",
6871 "{ x : { foo: foo().y } }",
6872 "{ x : { foo: foo()[y] } }",
6873 "{ x : { foo: y.z } }",
6874 "{ x : { foo: y[z] } }",
6875 "{ x : [ y ] }",
6876 "{ x : [ foo().y ] }",
6877 "{ x : [ foo()[y] ] }",
6878 "{ x : [ y.z ] }",
6879 "{ x : [ y[z] ] }",
6880
6881 "{ x : y = 10 }",
6882 "{ x : foo().y = 10 }",
6883 "{ x : foo()[y] = 10 }",
6884 "{ x : y.z = 10 }",
6885 "{ x : y[z] = 10 }",
6886 "{ x : { y = 10 } = {} }",
6887 "{ x : { foo: y = 10 } = {} }",
6888 "{ x : { foo: foo().y = 10 } = {} }",
6889 "{ x : { foo: foo()[y] = 10 } = {} }",
6890 "{ x : { foo: y.z = 10 } = {} }",
6891 "{ x : { foo: y[z] = 10 } = {} }",
6892 "{ x : [ y = 10 ] = {} }",
6893 "{ x : [ foo().y = 10 ] = {} }",
6894 "{ x : [ foo()[y] = 10 ] = {} }",
6895 "{ x : [ y.z = 10 ] = {} }",
6896 "{ x : [ y[z] = 10 ] = {} }",
6897
6898 "[ x ]",
6899 "[ foo().x ]",
6900 "[ foo()[x] ]",
6901 "[ x.y ]",
6902 "[ x[y] ]",
6903 "[ { x } ]",
6904 "[ { x : y } ]",
6905 "[ { x : foo().y } ]",
6906 "[ { x : foo()[y] } ]",
6907 "[ { x : x.y } ]",
6908 "[ { x : x[y] } ]",
6909 "[ [ x ] ]",
6910 "[ [ foo().x ] ]",
6911 "[ [ foo()[x] ] ]",
6912 "[ [ x.y ] ]",
6913 "[ [ x[y] ] ]",
6914
6915 "[ x = 10 ]",
6916 "[ foo().x = 10 ]",
6917 "[ foo()[x] = 10 ]",
6918 "[ x.y = 10 ]",
6919 "[ x[y] = 10 ]",
6920 "[ { x = 10 } = {} ]",
6921 "[ { x : y = 10 } = {} ]",
6922 "[ { x : foo().y = 10 } = {} ]",
6923 "[ { x : foo()[y] = 10 } = {} ]",
6924 "[ { x : x.y = 10 } = {} ]",
6925 "[ { x : x[y] = 10 } = {} ]",
6926 "[ [ x = 10 ] = {} ]",
6927 "[ [ foo().x = 10 ] = {} ]",
6928 "[ [ foo()[x] = 10 ] = {} ]",
6929 "[ [ x.y = 10 ] = {} ]",
6930 "[ [ x[y] = 10 ] = {} ]",
6931 "{ x : y = 1 }",
6932 "{ x }",
6933 "{ x, y, z }",
6934 "{ x = 1, y: z, z: y }",
6935 "{x = 42, y = 15}",
6936 "[x]",
6937 "[x = 1]",
6938 "[x,y,z]",
6939 "[x, y = 42, z]",
6940 "{ x : x, y : y }",
6941 "{ x : x = 1, y : y }",
6942 "{ x : x, y : y = 42 }",
6943 "[]",
6944 "{}",
6945 "[{x:x, y:y}, [,x,z,]]",
6946 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
6947 "[x,,y]",
6948 "[(x),,(y)]",
6949 "[(x)]",
6950 "{42 : x}",
6951 "{42 : x = 42}",
6952 "{42e-2 : x}",
6953 "{42e-2 : x = 42}",
6954 "{'hi' : x}",
6955 "{'hi' : x = 42}",
6956 "{var: x}",
6957 "{var: x = 42}",
6958 "{var: (x) = 42}",
6959 "{[x] : z}",
6960 "{[1+1] : z}",
6961 "{[1+1] : (z)}",
6962 "{[foo()] : z}",
6963 "{[foo()] : (z)}",
6964 "{[foo()] : foo().bar}",
6965 "{[foo()] : foo()['bar']}",
6966 "{[foo()] : this.bar}",
6967 "{[foo()] : this['bar']}",
6968 "{[foo()] : 'foo'.bar}",
6969 "{[foo()] : 'foo'['bar']}",
6970 "[...x]",
6971 "[x,y,...z]",
6972 "[x,,...z]",
6973 "{ x: y }",
6974 "[x, y]",
6975 "[((x, y) => z).x]",
6976 "{x: ((y, z) => z).x}",
6977 "[((x, y) => z)['x']]",
6978 "{x: ((y, z) => z)['x']}",
6979
6980 "{x: { y = 10 } }",
6981 "[(({ x } = { x: 1 }) => x).a]",
6982
6983 // v8:4662
6984 "{ x: (y) }",
6985 "{ x: (y) = [] }",
6986 "{ x: (foo.bar) }",
6987 "{ x: (foo['bar']) }",
6988 "[ ...(a) ]",
6989 "[ ...(foo['bar']) ]",
6990 "[ ...(foo.bar) ]",
6991 "[ (y) ]",
6992 "[ (foo.bar) ]",
6993 "[ (foo['bar']) ]",
6994
6995 NULL};
6996 // clang-format on
6997 static const ParserFlag always_flags[] = {
6998 kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
6999 kAllowHarmonyDefaultParameters};
7000 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7001 arraysize(always_flags));
7002
7003 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess, NULL, 0,
7004 always_flags, arraysize(always_flags));
7005
7006 const char* empty_context_data[][2] = {
7007 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7008
7009 // CoverInitializedName ambiguity handling in various contexts
7010 const char* ambiguity_data[] = {
7011 "var foo = { x = 10 } = {};",
7012 "var foo = { q } = { x = 10 } = {};",
7013 "var foo; foo = { x = 10 } = {};",
7014 "var foo; foo = { q } = { x = 10 } = {};",
7015 "var x; ({ x = 10 } = {});",
7016 "var q, x; ({ q } = { x = 10 } = {});",
7017 "var x; [{ x = 10 } = {}]",
7018 "var x; (true ? { x = true } = {} : { x = false } = {})",
7019 "var q, x; (q, { x = 10 } = {});",
7020 "var { x = 10 } = { x = 20 } = {};",
7021 "var { x = 10 } = (o = { x = 20 } = {});",
7022 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
7023 NULL,
7024 };
7025 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess, NULL, 0,
7026 always_flags, arraysize(always_flags));
7027}
7028
7029
7030TEST(DestructuringAssignmentNegativeTests) {
7031 const char* context_data[][2] = {
7032 {"'use strict'; let x, y, z; (", " = {});"},
7033 {"var x, y, z; (", " = {});"},
7034 {"'use strict'; let x, y, z; for (x in ", " = {});"},
7035 {"'use strict'; let x, y, z; for (x of ", " = {});"},
7036 {"var x, y, z; for (x in ", " = {});"},
7037 {"var x, y, z; for (x of ", " = {});"},
7038 {NULL, NULL}};
7039
7040 // clang-format off
7041 const char* data[] = {
7042 "{ x : ++y }",
7043 "{ x : y * 2 }",
7044 "{ ...x }",
7045 "{ get x() {} }",
7046 "{ set x() {} }",
7047 "{ x: y() }",
7048 "{ this }",
7049 "{ x: this }",
7050 "{ x: this = 1 }",
7051 "{ super }",
7052 "{ x: super }",
7053 "{ x: super = 1 }",
7054 "{ new.target }",
7055 "{ x: new.target }",
7056 "{ x: new.target = 1 }",
7057 "[x--]",
7058 "[--x = 1]",
7059 "[x()]",
7060 "[this]",
7061 "[this = 1]",
7062 "[new.target]",
7063 "[new.target = 1]",
7064 "[super]",
7065 "[super = 1]",
7066 "[function f() {}]",
7067 "[50]",
7068 "[(50)]",
7069 "[(function() {})]",
7070 "[(foo())]",
7071 "{ x: 50 }",
7072 "{ x: (50) }",
7073 "['str']",
7074 "{ x: 'str' }",
7075 "{ x: ('str') }",
7076 "{ x: (foo()) }",
7077 "{ x: (function() {}) }",
7078 "{ x: y } = 'str'",
7079 "[x, y] = 'str'",
7080 "[(x,y) => z]",
7081 "{x: (y) => z}",
7082 "[x, ...y, z]",
7083 "[...x,]",
7084 "[x, y, ...z = 1]",
7085 "[...z = 1]",
7086
7087 // v8:4657
7088 "({ x: x4, x: (x+=1e4) })",
7089 "(({ x: x4, x: (x+=1e4) }))",
7090 "({ x: x4, x: (x+=1e4) } = {})",
7091 "(({ x: x4, x: (x+=1e4) } = {}))",
7092 "(({ x: x4, x: (x+=1e4) }) = {})",
7093 "({ x: y } = {})",
7094 "(({ x: y } = {}))",
7095 "(({ x: y }) = {})",
7096 "([a])",
7097 "(([a]))",
7098 "([a] = [])",
7099 "(([a] = []))",
7100 "(([a]) = [])",
7101
7102 // v8:4662
7103 "{ x: ([y]) }",
7104 "{ x: ([y] = []) }",
7105 "{ x: ({y}) }",
7106 "{ x: ({y} = {}) }",
7107 "{ x: (++y) }",
7108 "[ (...[a]) ]",
7109 "[ ...([a]) ]",
7110 "[ ...([a] = [])",
7111 "[ ...[ ( [ a ] ) ] ]",
7112 "[ ([a]) ]",
7113 "[ (...[a]) ]",
7114 "[ ([a] = []) ]",
7115 "[ (++y) ]",
7116 "[ ...(++y) ]",
7117
7118 "[ x += x ]",
7119 "{ foo: x += x }",
7120
7121 NULL};
7122 // clang-format on
7123 static const ParserFlag always_flags[] = {
7124 kAllowHarmonyDestructuringAssignment, kAllowHarmonyDestructuring,
7125 kAllowHarmonyDefaultParameters};
7126 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7127 arraysize(always_flags));
7128
7129 const char* empty_context_data[][2] = {
7130 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7131
7132 // CoverInitializedName ambiguity handling in various contexts
7133 const char* ambiguity_data[] = {
7134 "var foo = { x = 10 };",
7135 "var foo = { q } = { x = 10 };",
7136 "var foo; foo = { x = 10 };",
7137 "var foo; foo = { q } = { x = 10 };",
7138 "var x; ({ x = 10 });",
7139 "var q, x; ({ q } = { x = 10 });",
7140 "var x; [{ x = 10 }]",
7141 "var x; (true ? { x = true } : { x = false })",
7142 "var q, x; (q, { x = 10 });",
7143 "var { x = 10 } = { x = 20 };",
7144 "var { x = 10 } = (o = { x = 20 });",
7145 "var x; (({ x = 10 } = { x = 20 }) => x)({})",
7146
7147 // Not ambiguous, but uses same context data
7148 "switch([window %= []] = []) { default: }",
7149
7150 NULL,
7151 };
7152 RunParserSyncTest(empty_context_data, ambiguity_data, kError, NULL, 0,
7153 always_flags, arraysize(always_flags));
7154
7155 // Strict mode errors
7156 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
7157 {"'use strict'; for (", " of {}) {}"},
7158 {"'use strict'; for (", " in {}) {}"},
7159 {NULL, NULL}};
7160 const char* strict_data[] = {"{ eval }",
7161 "{ arguments }",
7162 "{ foo: eval }",
7163 "{ foo: arguments }",
7164 "{ eval = 0 }",
7165 "{ arguments = 0 }",
7166 "{ foo: eval = 0 }",
7167 "{ foo: arguments = 0 }",
7168 "[ eval ]",
7169 "[ arguments ]",
7170 "[ eval = 0 ]",
7171 "[ arguments = 0 ]",
7172
7173 // v8:4662
7174 "{ x: (eval) }",
7175 "{ x: (arguments) }",
7176 "{ x: (eval = 0) }",
7177 "{ x: (arguments = 0) }",
7178 "{ x: (eval) = 0 }",
7179 "{ x: (arguments) = 0 }",
7180 "[ (eval) ]",
7181 "[ (arguments) ]",
7182 "[ (eval = 0) ]",
7183 "[ (arguments = 0) ]",
7184 "[ (eval) = 0 ]",
7185 "[ (arguments) = 0 ]",
7186 "[ ...(eval) ]",
7187 "[ ...(arguments) ]",
7188 "[ ...(eval = 0) ]",
7189 "[ ...(arguments = 0) ]",
7190 "[ ...(eval) = 0 ]",
7191 "[ ...(arguments) = 0 ]",
7192
7193 NULL};
7194 RunParserSyncTest(strict_context_data, strict_data, kError, NULL, 0,
7195 always_flags, arraysize(always_flags));
7196}
7197
7198
7199TEST(DestructuringDisallowPatternsInForVarIn) {
7200 i::FLAG_harmony_destructuring_bind = true;
7201 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7202 const char* context_data[][2] = {
7203 {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
7204 // clang-format off
7205 const char* error_data[] = {
7206 "for (let x = {} in null);",
7207 "for (let x = {} of null);",
7208 NULL};
7209 // clang-format on
7210 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7211 arraysize(always_flags));
7212
7213 // clang-format off
7214 const char* success_data[] = {
7215 "for (var x = {} in null);",
7216 NULL};
7217 // clang-format on
7218 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
7219 arraysize(always_flags));
7220}
7221
7222
7223TEST(DestructuringDuplicateParams) {
7224 i::FLAG_harmony_destructuring_bind = true;
7225 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7226 const char* context_data[][2] = {{"'use strict';", ""},
7227 {"function outer() { 'use strict';", "}"},
7228 {nullptr, nullptr}};
7229
7230
7231 // clang-format off
7232 const char* error_data[] = {
7233 "function f(x,x){}",
7234 "function f(x, {x : x}){}",
7235 "function f(x, {x}){}",
7236 "function f({x,x}) {}",
7237 "function f([x,x]) {}",
7238 "function f(x, [y,{z:x}]) {}",
7239 "function f([x,{y:x}]) {}",
7240 // non-simple parameter list causes duplicates to be errors in sloppy mode.
7241 "function f(x, x, {a}) {}",
7242 nullptr};
7243 // clang-format on
7244 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7245 arraysize(always_flags));
7246}
7247
7248
7249TEST(DestructuringDuplicateParamsSloppy) {
7250 i::FLAG_harmony_destructuring_bind = true;
7251 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7252 const char* context_data[][2] = {
7253 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
7254
7255
7256 // clang-format off
7257 const char* error_data[] = {
7258 // non-simple parameter list causes duplicates to be errors in sloppy mode.
7259 "function f(x, {x : x}){}",
7260 "function f(x, {x}){}",
7261 "function f({x,x}) {}",
7262 "function f(x, x, {a}) {}",
7263 nullptr};
7264 // clang-format on
7265 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7266 arraysize(always_flags));
7267}
7268
7269
7270TEST(DestructuringDisallowPatternsInSingleParamArrows) {
7271 i::FLAG_harmony_destructuring_bind = true;
7272 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
7273 const char* context_data[][2] = {{"'use strict';", ""},
7274 {"function outer() { 'use strict';", "}"},
7275 {"", ""},
7276 {"function outer() { ", "}"},
7277 {nullptr, nullptr}};
7278
7279 // clang-format off
7280 const char* error_data[] = {
7281 "var f = {x} => {};",
7282 "var f = {x,y} => {};",
7283 nullptr};
7284 // clang-format on
7285 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7286 arraysize(always_flags));
7287}
7288
7289
7290TEST(DefaultParametersYieldInInitializers) {
7291 // clang-format off
7292 const char* sloppy_function_context_data[][2] = {
7293 {"(function f(", ") { });"},
7294 {NULL, NULL}
7295 };
7296
7297 const char* strict_function_context_data[][2] = {
7298 {"'use strong'; (function f(", ") { });"},
7299 {"'use strict'; (function f(", ") { });"},
7300 {NULL, NULL}
7301 };
7302
7303 const char* sloppy_arrow_context_data[][2] = {
7304 {"((", ")=>{});"},
7305 {NULL, NULL}
7306 };
7307
7308 const char* strict_arrow_context_data[][2] = {
7309 {"'use strong'; ((", ")=>{});"},
7310 {"'use strict'; ((", ")=>{});"},
7311 {NULL, NULL}
7312 };
7313
7314 const char* generator_context_data[][2] = {
7315 {"'use strong'; (function *g(", ") { });"},
7316 {"'use strict'; (function *g(", ") { });"},
7317 {"(function *g(", ") { });"},
7318 {NULL, NULL}
7319 };
7320
7321 const char* parameter_data[] = {
7322 "x=yield",
7323 "x, y=yield",
7324 "{x=yield}",
7325 "[x=yield]",
7326
7327 "x=(yield)",
7328 "x, y=(yield)",
7329 "{x=(yield)}",
7330 "[x=(yield)]",
7331
7332 "x=f(yield)",
7333 "x, y=f(yield)",
7334 "{x=f(yield)}",
7335 "[x=f(yield)]",
7336 NULL
7337 };
7338
7339 // TODO(wingo): These aren't really destructuring assignment patterns; we're
7340 // just splitting them for now until the parser gets support for arrow
7341 // function arguments that look like destructuring assignments. When that
7342 // happens we should unify destructuring_assignment_data and parameter_data.
7343 const char* destructuring_assignment_data[] = {
7344 "{x}=yield",
7345 "[x]=yield",
7346
7347 "{x}=(yield)",
7348 "[x]=(yield)",
7349
7350 "{x}=f(yield)",
7351 "[x]=f(yield)",
7352 NULL
7353 };
7354
7355 // clang-format on
7356 static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring,
7357 kAllowHarmonyDefaultParameters,
7358 kAllowStrongMode};
7359
7360 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess,
7361 NULL, 0, always_flags, arraysize(always_flags));
7362 RunParserSyncTest(sloppy_function_context_data, destructuring_assignment_data,
7363 kSuccess, NULL, 0, always_flags, arraysize(always_flags));
7364 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess, NULL,
7365 0, always_flags, arraysize(always_flags));
7366 RunParserSyncTest(sloppy_arrow_context_data, destructuring_assignment_data,
7367 kSuccess, NULL, 0, always_flags, arraysize(always_flags));
7368
7369 RunParserSyncTest(strict_function_context_data, parameter_data, kError, NULL,
7370 0, always_flags, arraysize(always_flags));
7371 RunParserSyncTest(strict_function_context_data, destructuring_assignment_data,
7372 kError, NULL, 0, always_flags, arraysize(always_flags));
7373 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError, NULL, 0,
7374 always_flags, arraysize(always_flags));
7375 RunParserSyncTest(strict_arrow_context_data, destructuring_assignment_data,
7376 kError, NULL, 0, always_flags, arraysize(always_flags));
7377
7378 RunParserSyncTest(generator_context_data, parameter_data, kError, NULL, 0,
7379 always_flags, arraysize(always_flags));
7380 RunParserSyncTest(generator_context_data, destructuring_assignment_data,
7381 kError, NULL, 0, always_flags, arraysize(always_flags));
7382}
7383
7384
7385TEST(SpreadArray) {
7386 const char* context_data[][2] = {
7387 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7388
7389 // clang-format off
7390 const char* data[] = {
7391 "[...a]",
7392 "[a, ...b]",
7393 "[...a,]",
7394 "[...a, ,]",
7395 "[, ...a]",
7396 "[...a, ...b]",
7397 "[...a, , ...b]",
7398 "[...[...a]]",
7399 "[, ...a]",
7400 "[, , ...a]",
7401 NULL};
7402 // clang-format on
7403 RunParserSyncTest(context_data, data, kSuccess);
7404}
7405
7406
7407TEST(SpreadArrayError) {
7408 const char* context_data[][2] = {
7409 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
7410
7411 // clang-format off
7412 const char* data[] = {
7413 "[...]",
7414 "[a, ...]",
7415 "[..., ]",
7416 "[..., ...]",
7417 "[ (...a)]",
7418 NULL};
7419 // clang-format on
7420 RunParserSyncTest(context_data, data, kError);
7421}
7422
7423
7424TEST(NewTarget) {
7425 // clang-format off
7426 const char* good_context_data[][2] = {
7427 {"function f() {", "}"},
7428 {"'use strict'; function f() {", "}"},
7429 {"var f = function() {", "}"},
7430 {"'use strict'; var f = function() {", "}"},
7431 {"({m: function() {", "}})"},
7432 {"'use strict'; ({m: function() {", "}})"},
7433 {"({m() {", "}})"},
7434 {"'use strict'; ({m() {", "}})"},
7435 {"({get x() {", "}})"},
7436 {"'use strict'; ({get x() {", "}})"},
7437 {"({set x(_) {", "}})"},
7438 {"'use strict'; ({set x(_) {", "}})"},
7439 {"class C {m() {", "}}"},
7440 {"class C {get x() {", "}}"},
7441 {"class C {set x(_) {", "}}"},
7442 {NULL}
7443 };
7444
7445 const char* bad_context_data[][2] = {
7446 {"", ""},
7447 {"'use strict';", ""},
7448 {NULL}
7449 };
7450
7451 const char* data[] = {
7452 "new.target",
7453 "{ new.target }",
7454 "() => { new.target }",
7455 "() => new.target",
7456 "if (1) { new.target }",
7457 "if (1) {} else { new.target }",
7458 "while (0) { new.target }",
7459 "do { new.target } while (0)",
7460 NULL
7461 };
7462
7463 static const ParserFlag always_flags[] = {
7464 kAllowHarmonyNewTarget,
7465 kAllowHarmonySloppy,
7466 };
7467 // clang-format on
7468
7469 RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags,
7470 arraysize(always_flags));
7471 RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags,
7472 arraysize(always_flags));
7473}
7474
7475
7476TEST(ConstLegacy) {
7477 // clang-format off
7478 const char* context_data[][2] = {
7479 {"", ""},
7480 {"{", "}"},
7481 {NULL, NULL}
7482 };
7483
7484 const char* data[] = {
7485 "const x",
7486 "const x = 1",
7487 "for (const x = 1; x < 1; x++) {}",
7488 "for (const x in {}) {}",
7489 "for (const x of []) {}",
7490 NULL
7491 };
7492 // clang-format on
7493
7494
7495 static const ParserFlag always_flags[] = {kNoLegacyConst};
7496 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7497 arraysize(always_flags));
7498 RunParserSyncTest(context_data, data, kSuccess);
7499}
7500
7501
7502TEST(ConstSloppy) {
7503 // clang-format off
7504 const char* context_data[][2] = {
7505 {"", ""},
7506 {"{", "}"},
7507 {NULL, NULL}
7508 };
7509
7510 const char* data[] = {
7511 "const x = 1",
7512 "for (const x = 1; x < 1; x++) {}",
7513 "for (const x in {}) {}",
7514 "for (const x of []) {}",
7515 NULL
7516 };
7517 // clang-format on
7518 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7519 kNoLegacyConst};
7520 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7521 arraysize(always_flags));
7522}
7523
7524
7525TEST(LetSloppy) {
7526 // clang-format off
7527 const char* context_data[][2] = {
7528 {"", ""},
7529 {"'use strict';", ""},
7530 {"{", "}"},
7531 {NULL, NULL}
7532 };
7533
7534 const char* data[] = {
7535 "let x",
7536 "let x = 1",
7537 "for (let x = 1; x < 1; x++) {}",
7538 "for (let x in {}) {}",
7539 "for (let x of []) {}",
7540 NULL
7541 };
7542 // clang-format on
7543
7544 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7545 kAllowHarmonySloppyLet};
7546 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7547 arraysize(always_flags));
7548}
7549
7550
7551TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
7552 // TC39 deemed "use strict" directives to be an error when occurring in the
7553 // body of a function with non-simple parameter list, on 29/7/2015.
7554 // https://goo.gl/ueA7Ln
7555 //
7556 // In V8, this also applies to "use strong " directives.
7557 const char* context_data[][2] = {
7558 {"function f(", ") { 'use strict'; }"},
7559 {"function f(", ") { 'use strong'; }"},
7560 {"function* g(", ") { 'use strict'; }"},
7561 {"function* g(", ") { 'use strong'; }"},
7562 {"class c { foo(", ") { 'use strict' }"},
7563 {"class c { foo(", ") { 'use strong' }"},
7564 {"var a = (", ") => { 'use strict'; }"},
7565 {"var a = (", ") => { 'use strong'; }"},
7566 {"var o = { m(", ") { 'use strict'; }"},
7567 {"var o = { m(", ") { 'use strong'; }"},
7568 {"var o = { *gm(", ") { 'use strict'; }"},
7569 {"var o = { *gm(", ") { 'use strong'; }"},
7570 {"var c = { m(", ") { 'use strict'; }"},
7571 {"var c = { m(", ") { 'use strong'; }"},
7572 {"var c = { *gm(", ") { 'use strict'; }"},
7573 {"var c = { *gm(", ") { 'use strong'; }"},
7574
7575 {"'use strict'; function f(", ") { 'use strict'; }"},
7576 {"'use strict'; function f(", ") { 'use strong'; }"},
7577 {"'use strict'; function* g(", ") { 'use strict'; }"},
7578 {"'use strict'; function* g(", ") { 'use strong'; }"},
7579 {"'use strict'; class c { foo(", ") { 'use strict' }"},
7580 {"'use strict'; class c { foo(", ") { 'use strong' }"},
7581 {"'use strict'; var a = (", ") => { 'use strict'; }"},
7582 {"'use strict'; var a = (", ") => { 'use strong'; }"},
7583 {"'use strict'; var o = { m(", ") { 'use strict'; }"},
7584 {"'use strict'; var o = { m(", ") { 'use strong'; }"},
7585 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
7586 {"'use strict'; var o = { *gm(", ") { 'use strong'; }"},
7587 {"'use strict'; var c = { m(", ") { 'use strict'; }"},
7588 {"'use strict'; var c = { m(", ") { 'use strong'; }"},
7589 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
7590 {"'use strict'; var c = { *gm(", ") { 'use strong'; }"},
7591
7592 {"'use strong'; function f(", ") { 'use strict'; }"},
7593 {"'use strong'; function f(", ") { 'use strong'; }"},
7594 {"'use strong'; function* g(", ") { 'use strict'; }"},
7595 {"'use strong'; function* g(", ") { 'use strong'; }"},
7596 {"'use strong'; class c { foo(", ") { 'use strict' }"},
7597 {"'use strong'; class c { foo(", ") { 'use strong' }"},
7598 {"'use strong'; var a = (", ") => { 'use strict'; }"},
7599 {"'use strong'; var a = (", ") => { 'use strong'; }"},
7600 {"'use strong'; var o = { m(", ") { 'use strict'; }"},
7601 {"'use strong'; var o = { m(", ") { 'use strong'; }"},
7602 {"'use strong'; var o = { *gm(", ") { 'use strict'; }"},
7603 {"'use strong'; var o = { *gm(", ") { 'use strong'; }"},
7604 {"'use strong'; var c = { m(", ") { 'use strict'; }"},
7605 {"'use strong'; var c = { m(", ") { 'use strong'; }"},
7606 {"'use strong'; var c = { *gm(", ") { 'use strict'; }"},
7607 {"'use strong'; var c = { *gm(", ") { 'use strong'; }"},
7608
7609 {NULL, NULL}};
7610
7611 const char* data[] = {
7612 // TODO(@caitp): support formal parameter initializers
7613 "{}",
7614 "[]",
7615 "[{}]",
7616 "{a}",
7617 "a, {b}",
7618 "a, b, {c, d, e}",
7619 "initializer = true",
7620 "a, b, c = 1",
7621 "...args",
7622 "a, b, ...rest",
7623 "[a, b, ...rest]",
7624 "{ bindingPattern = {} }",
7625 "{ initializedBindingPattern } = { initializedBindingPattern: true }",
7626 NULL};
7627
7628 static const ParserFlag always_flags[] = {
7629 kAllowHarmonyDefaultParameters, kAllowHarmonyDestructuring,
7630 kAllowHarmonySloppy, kAllowStrongMode};
7631 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
7632 arraysize(always_flags));
7633}
7634
7635
7636TEST(LetSloppyOnly) {
7637 // clang-format off
7638 const char* context_data[][2] = {
7639 {"", ""},
7640 {"{", "}"},
7641 {"(function() {", "})()"},
7642 {NULL, NULL}
7643 };
7644
7645 const char* data[] = {
7646 "let",
7647 "let = 1",
7648 "for (let = 1; let < 1; let++) {}",
7649 "for (let in {}) {}",
7650 "for (var let = 1; let < 1; let++) {}",
7651 "for (var let in {}) {}",
7652 "for (var [let] = 1; let < 1; let++) {}",
7653 "for (var [let] in {}) {}",
7654 "var let",
7655 "var [let] = []",
7656 "for (const let = 1; let < 1; let++) {}",
7657 "for (const let in {}) {}",
7658 "for (const [let] = 1; let < 1; let++) {}",
7659 "for (const [let] in {}) {}",
7660 "const let",
7661 "const [let] = []",
7662 NULL
7663 };
7664 // clang-format on
7665
7666 static const ParserFlag always_flags[] = {
7667 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
7668 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7669 arraysize(always_flags));
7670
7671 // Some things should be rejected even in sloppy mode
7672 // This addresses BUG(v8:4403).
7673
7674 // clang-format off
7675 const char* fail_data[] = {
7676 "let let = 1",
7677 "for (let let = 1; let < 1; let++) {}",
7678 "for (let let in {}) {}",
7679 "for (let let of []) {}",
7680 "const let = 1",
7681 "for (const let = 1; let < 1; let++) {}",
7682 "for (const let in {}) {}",
7683 "for (const let of []) {}",
7684 "let [let] = 1",
7685 "for (let [let] = 1; let < 1; let++) {}",
7686 "for (let [let] in {}) {}",
7687 "for (let [let] of []) {}",
7688 "const [let] = 1",
7689 "for (const [let] = 1; let < 1; let++) {}",
7690 "for (const [let] in {}) {}",
7691 "for (const [let] of []) {}",
7692 NULL
7693 };
7694 // clang-format on
7695
7696 static const ParserFlag fail_flags[] = {
7697 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst,
7698 kAllowHarmonyDestructuring};
7699 RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags,
7700 arraysize(fail_flags));
7701}
7702
7703
7704TEST(EscapedKeywords) {
7705 // clang-format off
7706 const char* sloppy_context_data[][2] = {
7707 {"", ""},
7708 {NULL, NULL}
7709 };
7710
7711 const char* strict_context_data[][2] = {
7712 {"'use strict';", ""},
7713 {NULL, NULL}
7714 };
7715
7716 const char* fail_data[] = {
7717 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
7718 "cl\\u0061ss Foo {}",
7719 "var x = cl\\u0061ss {}",
7720 "\\u0063onst foo = 1;",
7721 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
7722 "d\\u0065bugger;",
7723 "d\\u0065lete this.a;",
7724 "\\u0063o { } while(0)",
7725 "if (d\\u006f { true }) {}",
7726 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
7727 "e\\u0078port var foo;",
7728 "try { } catch (e) {} f\\u0069nally { }",
7729 "f\\u006fr (var i = 0; i < 10; ++i);",
7730 "f\\u0075nction fn() {}",
7731 "var f = f\\u0075nction() {}",
7732 "\\u0069f (true) { }",
7733 "\\u0069mport blah from './foo.js';",
7734 "n\\u0065w function f() {}",
7735 "(function() { r\\u0065turn; })()",
7736 "class C extends function() {} { constructor() { sup\\u0065r() } }",
7737 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
7738 "sw\\u0069tch (this.a) {}",
7739 "var x = th\\u0069s;",
7740 "th\\u0069s.a = 1;",
7741 "thr\\u006fw 'boo';",
7742 "t\\u0072y { true } catch (e) {}",
7743 "var x = typ\\u0065of 'blah'",
7744 "v\\u0061r a = true",
7745 "var v\\u0061r = true",
7746 "(function() { return v\\u006fid 0; })()",
7747 "wh\\u0069le (true) { }",
7748 "w\\u0069th (this.scope) { }",
7749 "(function*() { y\\u0069eld 1; })()",
7750
7751 "var \\u0065num = 1;",
7752 "var { \\u0065num } = {}",
7753 "(\\u0065num = 1);",
7754
7755 // Null / Boolean literals
7756 "(x === n\\u0075ll);",
7757 "var x = n\\u0075ll;",
7758 "var n\\u0075ll = 1;",
7759 "var { n\\u0075ll } = { 1 };",
7760 "n\\u0075ll = 1;",
7761 "(x === tr\\u0075e);",
7762 "var x = tr\\u0075e;",
7763 "var tr\\u0075e = 1;",
7764 "var { tr\\u0075e } = {};",
7765 "tr\\u0075e = 1;",
7766 "(x === f\\u0061lse);",
7767 "var x = f\\u0061lse;",
7768 "var f\\u0061lse = 1;",
7769 "var { f\\u0061lse } = {};",
7770 "f\\u0061lse = 1;",
7771
7772 // TODO(caitp): consistent error messages for labeled statements and
7773 // expressions
7774 "switch (this.a) { c\\u0061se 6: break; }",
7775 "try { } c\\u0061tch (e) {}",
7776 "switch (this.a) { d\\u0065fault: break; }",
7777 "class C \\u0065xtends function B() {} {}",
7778 "for (var a i\\u006e this) {}",
7779 "if ('foo' \\u0069n this) {}",
7780 "if (this \\u0069nstanceof Array) {}",
7781 "(n\\u0065w function f() {})",
7782 "(typ\\u0065of 123)",
7783 "(v\\u006fid 0)",
7784 "do { ; } wh\\u0069le (true) { }",
7785 "(function*() { return (n++, y\\u0069eld 1); })()",
7786 "class C { st\\u0061tic bar() {} }",
7787
7788 "(y\\u0069eld);",
7789 "var y\\u0069eld = 1;",
7790 "var { y\\u0069eld } = {};",
7791 NULL
7792 };
7793 // clang-format on
7794
7795 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
7796 kAllowHarmonyDestructuring};
7797 RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7798 always_flags, arraysize(always_flags));
7799 RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0,
7800 always_flags, arraysize(always_flags));
7801 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7802 always_flags, arraysize(always_flags));
7803
7804 // clang-format off
7805 const char* let_data[] = {
7806 "var l\\u0065t = 1;",
7807 "l\\u0065t = 1;",
7808 "(l\\u0065t === 1);",
7809 NULL
7810 };
7811 // clang-format on
7812
7813 RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
7814 always_flags, arraysize(always_flags));
7815 RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
7816 always_flags, arraysize(always_flags));
7817
7818 static const ParserFlag sloppy_let_flags[] = {
7819 kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
7820 RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
7821 sloppy_let_flags, arraysize(sloppy_let_flags));
7822
7823 // Non-errors in sloppy mode
7824 const char* valid_data[] = {"(\\u0069mplements = 1);",
7825 "var impl\\u0065ments = 1;",
7826 "var { impl\\u0065ments } = {};",
7827 "(\\u0069nterface = 1);",
7828 "var int\\u0065rface = 1;",
7829 "var { int\\u0065rface } = {};",
7830 "(p\\u0061ckage = 1);",
7831 "var packa\\u0067e = 1;",
7832 "var { packa\\u0067e } = {};",
7833 "(p\\u0072ivate = 1);",
7834 "var p\\u0072ivate;",
7835 "var { p\\u0072ivate } = {};",
7836 "(prot\\u0065cted);",
7837 "var prot\\u0065cted = 1;",
7838 "var { prot\\u0065cted } = {};",
7839 "(publ\\u0069c);",
7840 "var publ\\u0069c = 1;",
7841 "var { publ\\u0069c } = {};",
7842 NULL};
7843 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
7844 always_flags, arraysize(always_flags));
7845 RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7846 always_flags, arraysize(always_flags));
7847 RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7848 always_flags, arraysize(always_flags));
7849}
7850
7851
7852TEST(MiscSyntaxErrors) {
7853 const char* context_data[][2] = {
7854 {"'use strict'", ""}, {"", ""}, {NULL, NULL}};
7855 const char* error_data[] = {"for (();;) {}", NULL};
7856
7857 RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
7858}