blob: ae278d83384958f840b871779f763772fe3708f0 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blockd0582a62009-12-15 09:54:21 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -080028#include <stdio.h>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029#include <stdlib.h>
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080030#include <string.h>
Steve Blockd0582a62009-12-15 09:54:21 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/v8.h"
Steve Blockd0582a62009-12-15 09:54:21 +000033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034#include "src/ast/ast.h"
35#include "src/ast/ast-numbering.h"
36#include "src/ast/ast-value-factory.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037#include "src/compiler.h"
38#include "src/execution.h"
39#include "src/isolate.h"
40#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041#include "src/parsing/parser.h"
42#include "src/parsing/preparser.h"
43#include "src/parsing/rewriter.h"
44#include "src/parsing/scanner-character-streams.h"
45#include "src/parsing/token.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046#include "src/utils.h"
47
48#include "test/cctest/cctest.h"
Steve Blockd0582a62009-12-15 09:54:21 +000049
Ben Murdoch69a99ed2011-11-30 16:03:39 +000050TEST(ScanKeywords) {
Steve Blockd0582a62009-12-15 09:54:21 +000051 struct KeywordToken {
52 const char* keyword;
53 i::Token::Value token;
54 };
55
56 static const KeywordToken keywords[] = {
57#define KEYWORD(t, s, d) { s, i::Token::t },
Ben Murdoch69a99ed2011-11-30 16:03:39 +000058 TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
Steve Blockd0582a62009-12-15 09:54:21 +000059#undef KEYWORD
60 { NULL, i::Token::IDENTIFIER }
61 };
62
Steve Blockd0582a62009-12-15 09:54:21 +000063 KeywordToken key_token;
Ben Murdoch69a99ed2011-11-30 16:03:39 +000064 i::UnicodeCache unicode_cache;
65 i::byte buffer[32];
Steve Blockd0582a62009-12-15 09:54:21 +000066 for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +000067 const i::byte* keyword =
68 reinterpret_cast<const i::byte*>(key_token.keyword);
69 int length = i::StrLength(key_token.keyword);
70 CHECK(static_cast<int>(sizeof(buffer)) >= length);
71 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010072 i::Utf8ToUtf16CharacterStream stream(keyword, length);
73 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000074 scanner.Initialize(&stream);
75 CHECK_EQ(key_token.token, scanner.Next());
76 CHECK_EQ(i::Token::EOS, scanner.Next());
Steve Blockd0582a62009-12-15 09:54:21 +000077 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000078 // Removing characters will make keyword matching fail.
79 {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010080 i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
81 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000082 scanner.Initialize(&stream);
83 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
84 CHECK_EQ(i::Token::EOS, scanner.Next());
Steve Blockd0582a62009-12-15 09:54:21 +000085 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +000086 // Adding characters will make keyword matching fail.
87 static const char chars_to_append[] = { 'z', '0', '_' };
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 for (int j = 0; j < static_cast<int>(arraysize(chars_to_append)); ++j) {
89 i::MemMove(buffer, keyword, length);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000090 buffer[length] = chars_to_append[j];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010091 i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
92 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000093 scanner.Initialize(&stream);
94 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
95 CHECK_EQ(i::Token::EOS, scanner.Next());
96 }
97 // Replacing characters will make keyword matching fail.
98 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 i::MemMove(buffer, keyword, length);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000100 buffer[length - 1] = '_';
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100101 i::Utf8ToUtf16CharacterStream stream(buffer, length);
102 i::Scanner scanner(&unicode_cache);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000103 scanner.Initialize(&stream);
104 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
105 CHECK_EQ(i::Token::EOS, scanner.Next());
106 }
Steve Blockd0582a62009-12-15 09:54:21 +0000107 }
Steve Blockd0582a62009-12-15 09:54:21 +0000108}
109
Iain Merrick9ac36c92010-09-13 15:29:50 +0100110
111TEST(ScanHTMLEndComments) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000112 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 v8::Isolate* isolate = CcTest::isolate();
114 v8::HandleScope handles(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000115
Iain Merrick9ac36c92010-09-13 15:29:50 +0100116 // Regression test. See:
117 // http://code.google.com/p/chromium/issues/detail?id=53548
118 // Tests that --> is correctly interpreted as comment-to-end-of-line if there
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000119 // is only whitespace before it on the line (with comments considered as
120 // whitespace, even a multiline-comment containing a newline).
121 // This was not the case if it occurred before the first real token
Iain Merrick9ac36c92010-09-13 15:29:50 +0100122 // in the input.
123 const char* tests[] = {
124 // Before first real token.
125 "--> is eol-comment\nvar y = 37;\n",
126 "\n --> is eol-comment\nvar y = 37;\n",
127 "/* precomment */ --> is eol-comment\nvar y = 37;\n",
128 "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
129 // After first real token.
130 "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
131 "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
132 NULL
133 };
134
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000135 const char* fail_tests[] = {
136 "x --> is eol-comment\nvar y = 37;\n",
137 "\"\\n\" --> is eol-comment\nvar y = 37;\n",
138 "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
139 "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
140 "var x = 42; --> is eol-comment\nvar y = 37;\n",
141 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
142 NULL
143 };
144
Iain Merrick9ac36c92010-09-13 15:29:50 +0100145 // Parser/Scanner needs a stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 CcTest::i_isolate()->stack_guard()->SetStackLimit(
147 i::GetCurrentStackPosition() - 128 * 1024);
148 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100149 for (int i = 0; tests[i]; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 const i::byte* source =
151 reinterpret_cast<const i::byte*>(tests[i]);
152 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
153 i::CompleteParserRecorder log;
154 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
155 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100156 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 i::AstValueFactory ast_value_factory(
158 &zone, CcTest::i_isolate()->heap()->HashSeed());
159 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
160 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 preparser.set_allow_lazy(true);
162 i::PreParser::PreParseResult result = preparser.PreParseProgram();
163 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
164 CHECK(!log.HasError());
Iain Merrick9ac36c92010-09-13 15:29:50 +0100165 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000166
167 for (int i = 0; fail_tests[i]; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 const i::byte* source =
169 reinterpret_cast<const i::byte*>(fail_tests[i]);
170 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
171 i::CompleteParserRecorder log;
172 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
173 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100174 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 i::AstValueFactory ast_value_factory(
176 &zone, CcTest::i_isolate()->heap()->HashSeed());
177 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
178 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 preparser.set_allow_lazy(true);
180 i::PreParser::PreParseResult result = preparser.PreParseProgram();
181 // Even in the case of a syntax error, kPreParseSuccess is returned.
182 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
183 CHECK(log.HasError());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000184 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100185}
186
187
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188class ScriptResource : public v8::String::ExternalOneByteStringResource {
Iain Merrick9ac36c92010-09-13 15:29:50 +0100189 public:
190 ScriptResource(const char* data, size_t length)
191 : data_(data), length_(length) { }
192
193 const char* data() const { return data_; }
194 size_t length() const { return length_; }
195
196 private:
197 const char* data_;
198 size_t length_;
199};
200
201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202TEST(UsingCachedData) {
Ben Murdochda12d292016-06-02 14:46:10 +0100203 // Producing cached parser data while parsing eagerly is not supported.
204 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 v8::Isolate* isolate = CcTest::isolate();
207 v8::HandleScope handles(isolate);
208 v8::Local<v8::Context> context = v8::Context::New(isolate);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100209 v8::Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 CcTest::i_isolate()->stack_guard()->SetStackLimit(
211 i::GetCurrentStackPosition() - 128 * 1024);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100212
213 // Source containing functions that might be lazily compiled and all types
214 // of symbols (string, propertyName, regexp).
215 const char* source =
216 "var x = 42;"
217 "function foo(a) { return function nolazy(b) { return a + b; } }"
218 "function bar(a) { if (a) return function lazy(b) { return b; } }"
219 "var z = {'string': 'string literal', bareword: 'propertyName', "
220 " 42: 'number literal', for: 'keyword as propertyName', "
221 " f\\u006fr: 'keyword propertyname with escape'};"
222 "var v = /RegExp Literal/;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 "var w = /RegExp Literal\\u0020With Escape/gi;"
Iain Merrick9ac36c92010-09-13 15:29:50 +0100224 "var y = { get getter() { return 42; }, "
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 " set setter(v) { this.value = v; }};"
226 "var f = a => function (b) { return a + b; };"
227 "var g = a => b => a + b;";
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100228 int source_length = i::StrLength(source);
Iain Merrick9ac36c92010-09-13 15:29:50 +0100229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 // ScriptResource will be deleted when the corresponding String is GCd.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 v8::ScriptCompiler::Source script_source(
232 v8::String::NewExternalOneByte(isolate,
233 new ScriptResource(source, source_length))
234 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 i::FLAG_min_preparse_length = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
237 v8::ScriptCompiler::kProduceParserCache)
238 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 CHECK(script_source.GetCachedData());
240
241 // Compile the script again, using the cached data.
Iain Merrick9ac36c92010-09-13 15:29:50 +0100242 bool lazy_flag = i::FLAG_lazy;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 i::FLAG_lazy = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source,
245 v8::ScriptCompiler::kConsumeParserCache)
246 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 i::FLAG_lazy = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 v8::ScriptCompiler::CompileUnboundScript(
249 isolate, &script_source, v8::ScriptCompiler::kConsumeParserCache)
250 .ToLocalChecked();
Iain Merrick9ac36c92010-09-13 15:29:50 +0100251 i::FLAG_lazy = lazy_flag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252}
Iain Merrick9ac36c92010-09-13 15:29:50 +0100253
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254
255TEST(PreparseFunctionDataIsUsed) {
Ben Murdochda12d292016-06-02 14:46:10 +0100256 // Producing cached parser data while parsing eagerly is not supported.
257 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
258
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 // This tests that we actually do use the function data generated by the
260 // preparser.
261
262 // Make preparsing work for short scripts.
263 i::FLAG_min_preparse_length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264
265 v8::Isolate* isolate = CcTest::isolate();
266 v8::HandleScope handles(isolate);
267 v8::Local<v8::Context> context = v8::Context::New(isolate);
268 v8::Context::Scope context_scope(context);
269 CcTest::i_isolate()->stack_guard()->SetStackLimit(
270 i::GetCurrentStackPosition() - 128 * 1024);
271
272 const char* good_code[] = {
273 "function this_is_lazy() { var a; } function foo() { return 25; } foo();",
274 "var this_is_lazy = () => { var a; }; var foo = () => 25; foo();",
275 };
276
277 // Insert a syntax error inside the lazy function.
278 const char* bad_code[] = {
279 "function this_is_lazy() { if ( } function foo() { return 25; } foo();",
280 "var this_is_lazy = () => { if ( }; var foo = () => 25; foo();",
281 };
282
283 for (unsigned i = 0; i < arraysize(good_code); i++) {
284 v8::ScriptCompiler::Source good_source(v8_str(good_code[i]));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &good_source,
286 v8::ScriptCompiler::kProduceParserCache)
287 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288
289 const v8::ScriptCompiler::CachedData* cached_data =
290 good_source.GetCachedData();
291 CHECK(cached_data->data != NULL);
292 CHECK_GT(cached_data->length, 0);
293
294 // Now compile the erroneous code with the good preparse data. If the
295 // preparse data is used, the lazy function is skipped and it should
296 // compile fine.
297 v8::ScriptCompiler::Source bad_source(
298 v8_str(bad_code[i]), new v8::ScriptCompiler::CachedData(
299 cached_data->data, cached_data->length));
300 v8::Local<v8::Value> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 CompileRun(isolate->GetCurrentContext(), &bad_source,
302 v8::ScriptCompiler::kConsumeParserCache);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 CHECK_EQ(25, result->Int32Value(isolate->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000305 }
Iain Merrick9ac36c92010-09-13 15:29:50 +0100306}
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800307
308
309TEST(StandAlonePreParser) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000310 v8::V8::Initialize();
311
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 CcTest::i_isolate()->stack_guard()->SetStackLimit(
313 i::GetCurrentStackPosition() - 128 * 1024);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800314
315 const char* programs[] = {
316 "{label: 42}",
317 "var x = 42;",
318 "function foo(x, y) { return x + y; }",
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000319 "%ArgleBargle(glop);",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800320 "var x = new new Function('this.x = 42');",
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 "var f = (x, y) => x + y;",
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800322 NULL
323 };
324
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800326 for (int i = 0; programs[i]; i++) {
327 const char* program = programs[i];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100328 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100329 reinterpret_cast<const i::byte*>(program),
330 static_cast<unsigned>(strlen(program)));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800331 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100333 scanner.Initialize(&stream);
334
Ben Murdochda12d292016-06-02 14:46:10 +0100335 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 i::AstValueFactory ast_value_factory(
337 &zone, CcTest::i_isolate()->heap()->HashSeed());
338 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
339 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 preparser.set_allow_lazy(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 preparser.set_allow_natives(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 i::PreParser::PreParseResult result = preparser.PreParseProgram();
343 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
344 CHECK(!log.HasError());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800345 }
346}
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800347
348
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100349TEST(StandAlonePreParserNoNatives) {
350 v8::V8::Initialize();
351
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 CcTest::i_isolate()->stack_guard()->SetStackLimit(
353 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354
355 const char* programs[] = {
356 "%ArgleBargle(glop);",
357 "var x = %_IsSmi(42);",
358 NULL
359 };
360
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 for (int i = 0; programs[i]; i++) {
363 const char* program = programs[i];
364 i::Utf8ToUtf16CharacterStream stream(
365 reinterpret_cast<const i::byte*>(program),
366 static_cast<unsigned>(strlen(program)));
367 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100369 scanner.Initialize(&stream);
370
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 // Preparser defaults to disallowing natives syntax.
Ben Murdochda12d292016-06-02 14:46:10 +0100372 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 i::AstValueFactory ast_value_factory(
374 &zone, CcTest::i_isolate()->heap()->HashSeed());
375 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
376 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 preparser.set_allow_lazy(true);
378 i::PreParser::PreParseResult result = preparser.PreParseProgram();
379 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
380 CHECK(log.HasError());
381 }
382}
383
384
385TEST(PreparsingObjectLiterals) {
386 // Regression test for a bug where the symbol stream produced by PreParser
387 // didn't match what Parser wanted to consume.
388 v8::Isolate* isolate = CcTest::isolate();
389 v8::HandleScope handles(isolate);
390 v8::Local<v8::Context> context = v8::Context::New(isolate);
391 v8::Context::Scope context_scope(context);
392 CcTest::i_isolate()->stack_guard()->SetStackLimit(
393 i::GetCurrentStackPosition() - 128 * 1024);
394
395 {
396 const char* source = "var myo = {if: \"foo\"}; myo.if;";
397 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
398 CHECK(result->IsString());
399 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 }
402
403 {
404 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
405 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
406 CHECK(result->IsString());
407 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 }
410
411 {
412 const char* source = "var myo = {1: \"foo\"}; myo[1];";
413 v8::Local<v8::Value> result = ParserCacheCompileRun(source);
414 CHECK(result->IsString());
415 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 CHECK_EQ(0, strcmp("foo", *utf8));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100417 }
418}
419
420
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800421TEST(RegressChromium62639) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000422 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
426 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800427
428 const char* program = "var x = 'something';\n"
429 "escape: function() {}";
430 // Fails parsing expecting an identifier after "function".
431 // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
432 // and then used the invalid currently scanned literal. This always
433 // failed in debug mode, and sometimes crashed in release mode.
434
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100435 i::Utf8ToUtf16CharacterStream stream(
436 reinterpret_cast<const i::byte*>(program),
437 static_cast<unsigned>(strlen(program)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 i::CompleteParserRecorder log;
439 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
440 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100441 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 i::AstValueFactory ast_value_factory(&zone,
443 CcTest::i_isolate()->heap()->HashSeed());
444 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 CcTest::i_isolate()->stack_guard()->real_climit());
446 preparser.set_allow_lazy(true);
447 i::PreParser::PreParseResult result = preparser.PreParseProgram();
448 // Even in the case of a syntax error, kPreParseSuccess is returned.
449 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
450 CHECK(log.HasError());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800451}
452
453
454TEST(Regress928) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000455 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 i::Isolate* isolate = CcTest::i_isolate();
457 i::Factory* factory = isolate->factory();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000458
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800459 // Preparsing didn't consider the catch clause of a try statement
460 // as with-content, which made it assume that a function inside
461 // the block could be lazily compiled, and an extra, unexpected,
462 // entry was added to the data.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
464 128 * 1024);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800465
466 const char* program =
467 "try { } catch (e) { var foo = function () { /* first */ } }"
468 "var bar = function () { /* second */ }";
469
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 v8::HandleScope handles(CcTest::isolate());
471 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
472 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
473 i::CompleteParserRecorder log;
474 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
475 scanner.Initialize(&stream);
Ben Murdochda12d292016-06-02 14:46:10 +0100476 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 i::AstValueFactory ast_value_factory(&zone,
478 CcTest::i_isolate()->heap()->HashSeed());
479 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 CcTest::i_isolate()->stack_guard()->real_climit());
481 preparser.set_allow_lazy(true);
482 i::PreParser::PreParseResult result = preparser.PreParseProgram();
483 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
484 i::ScriptData* sd = log.GetScriptData();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400485 i::ParseData* pd = i::ParseData::FromCachedData(sd);
486 pd->Initialize();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800487
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100488 int first_function =
489 static_cast<int>(strstr(program, "function") - program);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100490 int first_lbrace = first_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800491 CHECK_EQ('{', program[first_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400492 i::FunctionEntry entry1 = pd->GetFunctionEntry(first_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800493 CHECK(!entry1.is_valid());
494
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100495 int second_function =
496 static_cast<int>(strstr(program + first_lbrace, "function") - program);
497 int second_lbrace =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100498 second_function + i::StrLength("function () ");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800499 CHECK_EQ('{', program[second_lbrace]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500 i::FunctionEntry entry2 = pd->GetFunctionEntry(second_lbrace);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800501 CHECK(entry2.is_valid());
502 CHECK_EQ('}', program[entry2.end_pos() - 1]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 delete pd;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800505}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100506
507
508TEST(PreParseOverflow) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000509 v8::V8::Initialize();
510
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 CcTest::i_isolate()->stack_guard()->SetStackLimit(
512 i::GetCurrentStackPosition() - 128 * 1024);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
514 size_t kProgramSize = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 v8::base::SmartArrayPointer<char> program(
516 i::NewArray<char>(kProgramSize + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 memset(program.get(), '(', kProgramSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100518 program[kProgramSize] = '\0';
519
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100521
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100522 i::Utf8ToUtf16CharacterStream stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 reinterpret_cast<const i::byte*>(program.get()),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100524 static_cast<unsigned>(kProgramSize));
525 i::CompleteParserRecorder log;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100527 scanner.Initialize(&stream);
528
Ben Murdochda12d292016-06-02 14:46:10 +0100529 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000530 i::AstValueFactory ast_value_factory(&zone,
531 CcTest::i_isolate()->heap()->HashSeed());
532 i::PreParser preparser(&zone, &scanner, &ast_value_factory, &log,
533 stack_limit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 preparser.set_allow_lazy(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 i::PreParser::PreParseResult result = preparser.PreParseProgram();
536 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537}
538
539
540class TestExternalResource: public v8::String::ExternalStringResource {
541 public:
542 explicit TestExternalResource(uint16_t* data, int length)
543 : data_(data), length_(static_cast<size_t>(length)) { }
544
545 ~TestExternalResource() { }
546
547 const uint16_t* data() const {
548 return data_;
549 }
550
551 size_t length() const {
552 return length_;
553 }
554 private:
555 uint16_t* data_;
556 size_t length_;
557};
558
559
560#define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
561
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562void TestCharacterStream(const char* one_byte_source, unsigned length,
563 unsigned start = 0, unsigned end = 0) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100564 if (end == 0) end = length;
565 unsigned sub_length = end - start;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 i::Isolate* isolate = CcTest::i_isolate();
567 i::Factory* factory = isolate->factory();
568 i::HandleScope test_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 v8::base::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100570 for (unsigned i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 uc16_buffer[i] = static_cast<i::uc16>(one_byte_source[i]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100572 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 i::Vector<const char> one_byte_vector(one_byte_source,
574 static_cast<int>(length));
575 i::Handle<i::String> one_byte_string =
576 factory->NewStringFromAscii(one_byte_vector).ToHandleChecked();
577 TestExternalResource resource(uc16_buffer.get(), length);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100578 i::Handle<i::String> uc16_string(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100580
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100581 i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100582 i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 i::GenericStringUtf16CharacterStream string_stream(one_byte_string, start,
584 end);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100585 i::Utf8ToUtf16CharacterStream utf8_stream(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 reinterpret_cast<const i::byte*>(one_byte_source), end);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100587 utf8_stream.SeekForward(start);
588
589 unsigned i = start;
590 while (i < end) {
591 // Read streams one char at a time
592 CHECK_EQU(i, uc16_stream.pos());
593 CHECK_EQU(i, string_stream.pos());
594 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100596 int32_t c1 = uc16_stream.Advance();
597 int32_t c2 = string_stream.Advance();
598 int32_t c3 = utf8_stream.Advance();
599 i++;
600 CHECK_EQ(c0, c1);
601 CHECK_EQ(c0, c2);
602 CHECK_EQ(c0, c3);
603 CHECK_EQU(i, uc16_stream.pos());
604 CHECK_EQU(i, string_stream.pos());
605 CHECK_EQU(i, utf8_stream.pos());
606 }
607 while (i > start + sub_length / 4) {
608 // Pushback, re-read, pushback again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 int32_t c0 = one_byte_source[i - 1];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100610 CHECK_EQU(i, uc16_stream.pos());
611 CHECK_EQU(i, string_stream.pos());
612 CHECK_EQU(i, utf8_stream.pos());
613 uc16_stream.PushBack(c0);
614 string_stream.PushBack(c0);
615 utf8_stream.PushBack(c0);
616 i--;
617 CHECK_EQU(i, uc16_stream.pos());
618 CHECK_EQU(i, string_stream.pos());
619 CHECK_EQU(i, utf8_stream.pos());
620 int32_t c1 = uc16_stream.Advance();
621 int32_t c2 = string_stream.Advance();
622 int32_t c3 = utf8_stream.Advance();
623 i++;
624 CHECK_EQU(i, uc16_stream.pos());
625 CHECK_EQU(i, string_stream.pos());
626 CHECK_EQU(i, utf8_stream.pos());
627 CHECK_EQ(c0, c1);
628 CHECK_EQ(c0, c2);
629 CHECK_EQ(c0, c3);
630 uc16_stream.PushBack(c0);
631 string_stream.PushBack(c0);
632 utf8_stream.PushBack(c0);
633 i--;
634 CHECK_EQU(i, uc16_stream.pos());
635 CHECK_EQU(i, string_stream.pos());
636 CHECK_EQU(i, utf8_stream.pos());
637 }
638 unsigned halfway = start + sub_length / 2;
639 uc16_stream.SeekForward(halfway - i);
640 string_stream.SeekForward(halfway - i);
641 utf8_stream.SeekForward(halfway - i);
642 i = halfway;
643 CHECK_EQU(i, uc16_stream.pos());
644 CHECK_EQU(i, string_stream.pos());
645 CHECK_EQU(i, utf8_stream.pos());
646
647 while (i < end) {
648 // Read streams one char at a time
649 CHECK_EQU(i, uc16_stream.pos());
650 CHECK_EQU(i, string_stream.pos());
651 CHECK_EQU(i, utf8_stream.pos());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 int32_t c0 = one_byte_source[i];
Ben Murdochb0fe1622011-05-05 13:52:32 +0100653 int32_t c1 = uc16_stream.Advance();
654 int32_t c2 = string_stream.Advance();
655 int32_t c3 = utf8_stream.Advance();
656 i++;
657 CHECK_EQ(c0, c1);
658 CHECK_EQ(c0, c2);
659 CHECK_EQ(c0, c3);
660 CHECK_EQU(i, uc16_stream.pos());
661 CHECK_EQU(i, string_stream.pos());
662 CHECK_EQU(i, utf8_stream.pos());
663 }
664
665 int32_t c1 = uc16_stream.Advance();
666 int32_t c2 = string_stream.Advance();
667 int32_t c3 = utf8_stream.Advance();
668 CHECK_LT(c1, 0);
669 CHECK_LT(c2, 0);
670 CHECK_LT(c3, 0);
671}
672
673
674TEST(CharacterStreams) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675 v8::Isolate* isolate = CcTest::isolate();
676 v8::HandleScope handles(isolate);
677 v8::Local<v8::Context> context = v8::Context::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 v8::Context::Scope context_scope(context);
679
680 TestCharacterStream("abc\0\n\r\x7f", 7);
681 static const unsigned kBigStringSize = 4096;
682 char buffer[kBigStringSize + 1];
683 for (unsigned i = 0; i < kBigStringSize; i++) {
684 buffer[i] = static_cast<char>(i & 0x7f);
685 }
686 TestCharacterStream(buffer, kBigStringSize);
687
688 TestCharacterStream(buffer, kBigStringSize, 576, 3298);
689
690 TestCharacterStream("\0", 1);
691 TestCharacterStream("", 0);
692}
693
694
695TEST(Utf8CharacterStream) {
696 static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
697 static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
698
699 static const int kAllUtf8CharsSize =
700 (unibrow::Utf8::kMaxOneByteChar + 1) +
701 (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
702 (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
703 static const unsigned kAllUtf8CharsSizeU =
704 static_cast<unsigned>(kAllUtf8CharsSize);
705
706 char buffer[kAllUtf8CharsSizeU];
707 unsigned cursor = 0;
708 for (int i = 0; i <= kMaxUC16Char; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 cursor += unibrow::Utf8::Encode(buffer + cursor, i,
710 unibrow::Utf16::kNoPreviousCharacter, true);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 CHECK(cursor == kAllUtf8CharsSizeU);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100713
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100714 i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
715 kAllUtf8CharsSizeU);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 int32_t bad = unibrow::Utf8::kBadChar;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717 for (int i = 0; i <= kMaxUC16Char; i++) {
718 CHECK_EQU(i, stream.pos());
719 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 if (i >= 0xd800 && i <= 0xdfff) {
721 CHECK_EQ(bad, c);
722 } else {
723 CHECK_EQ(i, c);
724 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100725 CHECK_EQU(i + 1, stream.pos());
726 }
727 for (int i = kMaxUC16Char; i >= 0; i--) {
728 CHECK_EQU(i + 1, stream.pos());
729 stream.PushBack(i);
730 CHECK_EQU(i, stream.pos());
731 }
732 int i = 0;
733 while (stream.pos() < kMaxUC16CharU) {
734 CHECK_EQU(i, stream.pos());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 int progress = static_cast<int>(stream.SeekForward(12));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 i += progress;
737 int32_t c = stream.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 if (i >= 0xd800 && i <= 0xdfff) {
739 CHECK_EQ(bad, c);
740 } else if (i <= kMaxUC16Char) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100741 CHECK_EQ(i, c);
742 } else {
743 CHECK_EQ(-1, c);
744 }
745 i += 1;
746 CHECK_EQU(i, stream.pos());
747 }
748}
749
750#undef CHECK_EQU
751
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100752void TestStreamScanner(i::Utf16CharacterStream* stream,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100753 i::Token::Value* expected_tokens,
754 int skip_pos = 0, // Zero means not skipping.
755 int skip_to = 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Steve Block9fac8402011-05-12 15:51:54 +0100757 scanner.Initialize(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758
759 int i = 0;
760 do {
761 i::Token::Value expected = expected_tokens[i];
762 i::Token::Value actual = scanner.Next();
763 CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
764 if (scanner.location().end_pos == skip_pos) {
765 scanner.SeekForward(skip_to);
766 }
767 i++;
768 } while (expected_tokens[i] != i::Token::ILLEGAL);
769}
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772TEST(StreamScanner) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000773 v8::V8::Initialize();
774
Ben Murdochb0fe1622011-05-05 13:52:32 +0100775 const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100776 i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
777 static_cast<unsigned>(strlen(str1)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778 i::Token::Value expectations1[] = {
779 i::Token::LBRACE,
780 i::Token::IDENTIFIER,
781 i::Token::IDENTIFIER,
782 i::Token::FOR,
783 i::Token::COLON,
784 i::Token::MUL,
785 i::Token::DIV,
786 i::Token::LT,
787 i::Token::SUB,
788 i::Token::IDENTIFIER,
789 i::Token::EOS,
790 i::Token::ILLEGAL
791 };
792 TestStreamScanner(&stream1, expectations1, 0, 0);
793
794 const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100795 i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
796 static_cast<unsigned>(strlen(str2)));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100797 i::Token::Value expectations2[] = {
798 i::Token::CASE,
799 i::Token::DEFAULT,
800 i::Token::CONST,
801 i::Token::LBRACE,
802 // Skipped part here
803 i::Token::RBRACE,
804 i::Token::DO,
805 i::Token::EOS,
806 i::Token::ILLEGAL
807 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 CHECK_EQ('{', str2[19]);
809 CHECK_EQ('}', str2[37]);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100810 TestStreamScanner(&stream2, expectations2, 20, 37);
811
812 const char* str3 = "{}}}}";
813 i::Token::Value expectations3[] = {
814 i::Token::LBRACE,
815 i::Token::RBRACE,
816 i::Token::RBRACE,
817 i::Token::RBRACE,
818 i::Token::RBRACE,
819 i::Token::EOS,
820 i::Token::ILLEGAL
821 };
822 // Skip zero-four RBRACEs.
823 for (int i = 0; i <= 4; i++) {
824 expectations3[6 - i] = i::Token::ILLEGAL;
825 expectations3[5 - i] = i::Token::EOS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100826 i::Utf8ToUtf16CharacterStream stream3(
Ben Murdochb0fe1622011-05-05 13:52:32 +0100827 reinterpret_cast<const i::byte*>(str3),
828 static_cast<unsigned>(strlen(str3)));
829 TestStreamScanner(&stream3, expectations3, 1, 1 + i);
830 }
831}
Ben Murdoch086aeea2011-05-13 15:57:08 +0100832
833
834void TestScanRegExp(const char* re_source, const char* expected) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100835 i::Utf8ToUtf16CharacterStream stream(
Ben Murdoch086aeea2011-05-13 15:57:08 +0100836 reinterpret_cast<const i::byte*>(re_source),
837 static_cast<unsigned>(strlen(re_source)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 i::HandleScope scope(CcTest::i_isolate());
839 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
Ben Murdoch086aeea2011-05-13 15:57:08 +0100840 scanner.Initialize(&stream);
841
842 i::Token::Value start = scanner.peek();
843 CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
844 CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
845 scanner.Next(); // Current token is now the regexp literal.
Ben Murdochda12d292016-06-02 14:46:10 +0100846 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 i::AstValueFactory ast_value_factory(&zone,
848 CcTest::i_isolate()->heap()->HashSeed());
849 ast_value_factory.Internalize(CcTest::i_isolate());
850 i::Handle<i::String> val =
851 scanner.CurrentSymbol(&ast_value_factory)->string();
852 i::DisallowHeapAllocation no_alloc;
853 i::String::FlatContent content = val->GetFlatContent();
854 CHECK(content.IsOneByte());
855 i::Vector<const uint8_t> actual = content.ToOneByteVector();
Ben Murdoch086aeea2011-05-13 15:57:08 +0100856 for (int i = 0; i < actual.length(); i++) {
857 CHECK_NE('\0', expected[i]);
858 CHECK_EQ(expected[i], actual[i]);
859 }
860}
861
862
863TEST(RegExpScanning) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000864 v8::V8::Initialize();
865
Ben Murdoch086aeea2011-05-13 15:57:08 +0100866 // RegExp token with added garbage at the end. The scanner should only
867 // scan the RegExp until the terminating slash just before "flipperwald".
868 TestScanRegExp("/b/flipperwald", "b");
869 // Incomplete escape sequences doesn't hide the terminating slash.
870 TestScanRegExp("/\\x/flipperwald", "\\x");
871 TestScanRegExp("/\\u/flipperwald", "\\u");
872 TestScanRegExp("/\\u1/flipperwald", "\\u1");
873 TestScanRegExp("/\\u12/flipperwald", "\\u12");
874 TestScanRegExp("/\\u123/flipperwald", "\\u123");
875 TestScanRegExp("/\\c/flipperwald", "\\c");
876 TestScanRegExp("/\\c//flipperwald", "\\c");
877 // Slashes inside character classes are not terminating.
878 TestScanRegExp("/[/]/flipperwald", "[/]");
879 TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
880 // Incomplete escape sequences inside a character class doesn't hide
881 // the end of the character class.
882 TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
883 TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
884 TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
885 TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
886 TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
887 TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
888 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
889 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
890 // Escaped ']'s wont end the character class.
891 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
892 // Escaped slashes are not terminating.
893 TestScanRegExp("/\\//flipperwald", "\\/");
894 // Starting with '=' works too.
895 TestScanRegExp("/=/", "=");
896 TestScanRegExp("/=?/", "=?");
897}
Ben Murdoch692be652012-01-10 18:47:50 +0000898
899
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100900static int Utf8LengthHelper(const char* s) {
901 int len = i::StrLength(s);
902 int character_length = len;
903 for (int i = 0; i < len; i++) {
904 unsigned char c = s[i];
905 int input_offset = 0;
906 int output_adjust = 0;
907 if (c > 0x7f) {
908 if (c < 0xc0) continue;
909 if (c >= 0xf0) {
910 if (c >= 0xf8) {
911 // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
912 // byte.
913 continue; // Handle first UTF-8 byte.
914 }
915 if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
916 // This 4 byte sequence could have been coded as a 3 byte sequence.
917 // Record a single kBadChar for the first byte and continue.
918 continue;
919 }
920 input_offset = 3;
921 // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
922 character_length -= 2;
923 } else if (c >= 0xe0) {
924 if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
925 // This 3 byte sequence could have been coded as a 2 byte sequence.
926 // Record a single kBadChar for the first byte and continue.
927 continue;
928 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 if (c == 0xed) {
930 unsigned char d = s[i + 1];
931 if ((d < 0x80) || (d > 0x9f)) {
932 // This 3 byte sequence is part of a surrogate pair which is not
933 // supported by UTF-8. Record a single kBadChar for the first byte
934 // and continue.
935 continue;
936 }
937 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100938 input_offset = 2;
939 // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
940 output_adjust = 2;
941 } else {
942 if ((c & 0x1e) == 0) {
943 // This 2 byte sequence could have been coded as a 1 byte sequence.
944 // Record a single kBadChar for the first byte and continue.
945 continue;
946 }
947 input_offset = 1;
948 // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
949 output_adjust = 1;
950 }
951 bool bad = false;
952 for (int j = 1; j <= input_offset; j++) {
953 if ((s[i + j] & 0xc0) != 0x80) {
954 // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
955 // which is a single UTF-16 code unit.
956 bad = true;
957 break;
958 }
959 }
960 if (!bad) {
961 i += input_offset;
962 character_length -= output_adjust;
963 }
964 }
965 }
966 return character_length;
967}
968
969
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400970TEST(ScopeUsesArgumentsSuperThis) {
971 static const struct {
972 const char* prefix;
973 const char* suffix;
974 } surroundings[] = {
975 { "function f() {", "}" },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 { "var f = () => {", "};" },
977 { "class C { constructor() {", "} }" },
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400978 };
979
980 enum Expected {
981 NONE = 0,
982 ARGUMENTS = 1,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 SUPER_PROPERTY = 1 << 1,
984 THIS = 1 << 2,
985 EVAL = 1 << 4
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 };
987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 // clang-format off
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 static const struct {
990 const char* body;
991 int expected;
992 } source_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 {"", NONE},
994 {"return this", THIS},
995 {"return arguments", ARGUMENTS},
996 {"return super.x", SUPER_PROPERTY},
997 {"return arguments[0]", ARGUMENTS},
998 {"return this + arguments[0]", ARGUMENTS | THIS},
999 {"return this + arguments[0] + super.x",
1000 ARGUMENTS | SUPER_PROPERTY | THIS},
1001 {"return x => this + x", THIS},
1002 {"return x => super.f() + x", SUPER_PROPERTY},
1003 {"this.foo = 42;", THIS},
1004 {"this.foo();", THIS},
1005 {"if (foo()) { this.f() }", THIS},
1006 {"if (foo()) { super.f() }", SUPER_PROPERTY},
1007 {"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
1008 {"while (true) { this.f() }", THIS},
1009 {"while (true) { super.f() }", SUPER_PROPERTY},
1010 {"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
1011 // Multiple nesting levels must work as well.
1012 {"while (true) { while (true) { while (true) return this } }", THIS},
1013 {"while (true) { while (true) { while (true) return super.f() } }",
1014 SUPER_PROPERTY},
1015 {"if (1) { return () => { while (true) new this() } }", THIS},
1016 {"return function (x) { return this + x }", NONE},
1017 {"return { m(x) { return super.m() + x } }", NONE},
1018 {"var x = function () { this.foo = 42 };", NONE},
1019 {"var x = { m() { super.foo = 42 } };", NONE},
1020 {"if (1) { return function () { while (true) new this() } }", NONE},
1021 {"if (1) { return { m() { while (true) super.m() } } }", NONE},
1022 {"return function (x) { return () => this }", NONE},
1023 {"return { m(x) { return () => super.m() } }", NONE},
1024 // Flags must be correctly set when using block scoping.
1025 {"\"use strict\"; while (true) { let x; this, arguments; }",
1026 THIS},
1027 {"\"use strict\"; while (true) { let x; this, super.f(), arguments; }",
1028 SUPER_PROPERTY | THIS},
1029 {"\"use strict\"; if (foo()) { let x; this.f() }", THIS},
1030 {"\"use strict\"; if (foo()) { let x; super.f() }", SUPER_PROPERTY},
1031 {"\"use strict\"; if (1) {"
1032 " let x; return { m() { return this + super.m() + arguments } }"
1033 "}",
1034 NONE},
1035 {"eval(42)", EVAL},
1036 {"if (1) { eval(42) }", EVAL},
1037 {"eval('super.x')", EVAL},
1038 {"eval('this.x')", EVAL},
1039 {"eval('arguments')", EVAL},
1040 };
1041 // clang-format on
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042
1043 i::Isolate* isolate = CcTest::i_isolate();
1044 i::Factory* factory = isolate->factory();
1045
1046 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001048 v8::Context::Scope context_scope(context);
1049
1050 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1051 128 * 1024);
1052
1053 for (unsigned j = 0; j < arraysize(surroundings); ++j) {
1054 for (unsigned i = 0; i < arraysize(source_data); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 // Super property is only allowed in constructor and method.
1056 if (((source_data[i].expected & SUPER_PROPERTY) ||
1057 (source_data[i].expected == NONE)) && j != 2) {
1058 continue;
1059 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001060 int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
1061 i::StrLength(surroundings[j].suffix) +
1062 i::StrLength(source_data[i].body);
1063 i::ScopedVector<char> program(kProgramByteSize + 1);
1064 i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
1065 source_data[i].body, surroundings[j].suffix);
1066 i::Handle<i::String> source =
1067 factory->NewStringFromUtf8(i::CStrVector(program.start()))
1068 .ToHandleChecked();
1069 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001070 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071 i::ParseInfo info(&zone, script);
1072 i::Parser parser(&info);
1073 parser.set_allow_harmony_sloppy(true);
1074 info.set_global();
1075 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001076 CHECK(i::Rewriter::Rewrite(&info));
1077 CHECK(i::Scope::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 CHECK(info.literal() != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 i::Scope* script_scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 CHECK(script_scope->is_script_scope());
1082 CHECK_EQ(1, script_scope->inner_scopes()->length());
1083
1084 i::Scope* scope = script_scope->inner_scopes()->at(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 // Adjust for constructor scope.
1086 if (j == 2) {
1087 CHECK_EQ(1, scope->inner_scopes()->length());
1088 scope = scope->inner_scopes()->at(0);
1089 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001090 CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
1091 scope->uses_arguments());
1092 CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
1093 scope->uses_super_property());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 if ((source_data[i].expected & THIS) != 0) {
1095 // Currently the is_used() flag is conservative; all variables in a
1096 // script scope are marked as used.
1097 CHECK(
1098 scope->Lookup(info.ast_value_factory()->this_string())->is_used());
1099 }
1100 CHECK_EQ((source_data[i].expected & EVAL) != 0, scope->calls_eval());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001101 }
1102 }
1103}
1104
1105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106static void CheckParsesToNumber(const char* source, bool with_dot) {
1107 v8::V8::Initialize();
1108 HandleAndZoneScope handles;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001110 i::Isolate* isolate = CcTest::i_isolate();
1111 i::Factory* factory = isolate->factory();
1112
1113 std::string full_source = "function f() { return ";
1114 full_source += source;
1115 full_source += "; }";
1116
1117 i::Handle<i::String> source_code =
1118 factory->NewStringFromUtf8(i::CStrVector(full_source.c_str()))
1119 .ToHandleChecked();
1120
1121 i::Handle<i::Script> script = factory->NewScript(source_code);
1122
1123 i::ParseInfo info(handles.main_zone(), script);
1124 i::Parser parser(&info);
1125 parser.set_allow_harmony_sloppy(true);
1126 info.set_global();
1127 info.set_lazy(false);
1128 info.set_allow_lazy_parsing(false);
1129 info.set_toplevel(true);
1130
1131 i::CompilationInfo compilation_info(&info);
1132 CHECK(i::Compiler::ParseAndAnalyze(&info));
1133
1134 CHECK(info.scope()->declarations()->length() == 1);
1135 i::FunctionLiteral* fun =
1136 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun();
1137 CHECK(fun->body()->length() == 1);
1138 CHECK(fun->body()->at(0)->IsReturnStatement());
1139 i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
1140 i::Literal* lit = ret->expression()->AsLiteral();
1141 if (lit != NULL) {
1142 const i::AstValue* val = lit->raw_value();
1143 CHECK(with_dot == val->ContainsDot());
1144 } else if (with_dot) {
1145 i::BinaryOperation* bin = ret->expression()->AsBinaryOperation();
1146 CHECK(bin != NULL);
1147 CHECK_EQ(i::Token::MUL, bin->op());
1148 i::Literal* rlit = bin->right()->AsLiteral();
1149 const i::AstValue* val = rlit->raw_value();
1150 CHECK(with_dot == val->ContainsDot());
1151 CHECK_EQ(1.0, val->AsNumber());
1152 }
1153}
1154
1155
1156TEST(ParseNumbers) {
1157 CheckParsesToNumber("1.", true);
1158 CheckParsesToNumber("1.34", true);
1159 CheckParsesToNumber("134", false);
1160 CheckParsesToNumber("134e44", false);
1161 CheckParsesToNumber("134.e44", true);
1162 CheckParsesToNumber("134.44e44", true);
1163 CheckParsesToNumber(".44", true);
1164
1165 CheckParsesToNumber("-1.", true);
1166 CheckParsesToNumber("-1.0", true);
1167 CheckParsesToNumber("-1.34", true);
1168 CheckParsesToNumber("-134", false);
1169 CheckParsesToNumber("-134e44", false);
1170 CheckParsesToNumber("-134.e44", true);
1171 CheckParsesToNumber("-134.44e44", true);
1172 CheckParsesToNumber("-.44", true);
1173
1174 CheckParsesToNumber("+x", true);
1175}
1176
1177
1178TEST(ScopePositions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001179 // Test the parser for correctly setting the start and end positions
1180 // of a scope. We check the scope positions of exactly one scope
1181 // nested in the global scope of a program. 'inner source' is the
1182 // source code that determines the part of the source belonging
1183 // to the nested scope. 'outer_prefix' and 'outer_suffix' are
1184 // parts of the source that belong to the global scope.
1185 struct SourceData {
1186 const char* outer_prefix;
1187 const char* inner_source;
1188 const char* outer_suffix;
1189 i::ScopeType scope_type;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 i::LanguageMode language_mode;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001191 };
1192
1193 const SourceData source_data[] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
1195 { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001196 { " with ({}) ", "{\n"
1197 " block;\n"
1198 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199 " more;", i::WITH_SCOPE, i::SLOPPY },
1200 { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001201 { " with ({}) ", "statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001203 { " with ({})\n"
1204 " ", "statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205 " more;", i::WITH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001206 { " try {} catch ", "(e) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001208 { " try {} catch ", "(e) { block; }", "; more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001209 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001210 { " try {} catch ", "(e) {\n"
1211 " block;\n"
1212 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213 " more;", i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001214 { " try {} catch ", "(e) { block; }", " finally { block; } more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001215 i::CATCH_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001216 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001217 " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001218 { " start;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001219 " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001220 { " start;\n"
1221 " ", "{\n"
1222 " let block;\n"
1223 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001225 { " start;\n"
1226 " function fun", "(a,b) { infunction; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001228 { " start;\n"
1229 " function fun", "(a,b) {\n"
1230 " infunction;\n"
1231 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001232 " more;", i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 { " start;\n", "(a,b) => a + b", "; more;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 { " start;\n", "(a,b) => { return a+b; }", "\nmore;",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 { " start;\n"
1238 " (function fun", "(a,b) { infunction; }", ")();",
1239 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001240 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001242 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; 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) {\n"
1245 " block;\n"
1246 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001248 { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001250 { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001252 { " for ", "(let x = 1 ; x < 10; ++ x)\n"
1253 " statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001254 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001255 { " for ", "(let x in {}) { block; }", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001257 { " for ", "(let x in {}) { block; }", "; 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 {}) {\n"
1260 " block;\n"
1261 " }", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001263 { " for ", "(let x in {}) statement;", " more;",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001265 { " for ", "(let x in {}) statement", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001267 { " for ", "(let x in {})\n"
1268 " statement;", "\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269 " more;", i::BLOCK_SCOPE, i::STRICT },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001270 // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1271 // the preparser off in terms of byte offsets.
1272 // 6 byte encoding.
1273 { " 'foo\355\240\201\355\260\211';\n"
1274 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001276 // 4 byte encoding.
1277 { " 'foo\360\220\220\212';\n"
1278 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001280 // 3 byte encoding of \u0fff.
1281 { " 'foo\340\277\277';\n"
1282 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001284 // Broken 6 byte encoding with missing last byte.
1285 { " 'foo\355\240\201\355\211';\n"
1286 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001288 // Broken 3 byte encoding of \u0fff with missing last byte.
1289 { " 'foo\340\277';\n"
1290 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001292 // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1293 { " 'foo\340';\n"
1294 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001296 // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1297 { " 'foo\340\203\277';\n"
1298 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001300 // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1301 { " 'foo\340\201\277';\n"
1302 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001303 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001304 // Unpaired lead surrogate.
1305 { " 'foo\355\240\201';\n"
1306 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001308 // Unpaired lead surrogate where following code point is a 3 byte sequence.
1309 { " 'foo\355\240\201\340\277\277';\n"
1310 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001312 // Unpaired lead surrogate where following code point is a 4 byte encoding
1313 // of a trail surrogate.
1314 { " 'foo\355\240\201\360\215\260\211';\n"
1315 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001317 // Unpaired trail surrogate.
1318 { " 'foo\355\260\211';\n"
1319 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001321 // 2 byte encoding of \u00ff.
1322 { " 'foo\303\277';\n"
1323 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001324 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001325 // Broken 2 byte encoding of \u00ff with missing last byte.
1326 { " 'foo\303';\n"
1327 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001329 // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1330 { " 'foo\301\277';\n"
1331 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001333 // Illegal 5 byte encoding.
1334 { " 'foo\370\277\277\277\277';\n"
1335 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001336 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001337 // Illegal 6 byte encoding.
1338 { " 'foo\374\277\277\277\277\277';\n"
1339 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001341 // Illegal 0xfe byte
1342 { " 'foo\376\277\277\277\277\277\277';\n"
1343 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001345 // Illegal 0xff byte
1346 { " 'foo\377\277\277\277\277\277\277\277';\n"
1347 " (function fun", "(a,b) { infunction; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001349 { " 'foo';\n"
1350 " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 i::FUNCTION_SCOPE, i::SLOPPY },
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001352 { " 'foo';\n"
1353 " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 i::FUNCTION_SCOPE, i::SLOPPY },
1355 { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001356 };
1357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 i::Isolate* isolate = CcTest::i_isolate();
1359 i::Factory* factory = isolate->factory();
1360
1361 v8::HandleScope handles(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001362 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001363 v8::Context::Scope context_scope(context);
1364
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
1366 128 * 1024);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001367
1368 for (int i = 0; source_data[i].outer_prefix; i++) {
1369 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1370 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1371 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1372 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1373 int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1374 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1375 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1376 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 i::ScopedVector<char> program(kProgramByteSize + 1);
1378 i::SNPrintF(program, "%s%s%s",
1379 source_data[i].outer_prefix,
1380 source_data[i].inner_source,
1381 source_data[i].outer_suffix);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001382
1383 // Parse program source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 i::Handle<i::String> source = factory->NewStringFromUtf8(
1385 i::CStrVector(program.start())).ToHandleChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001386 CHECK_EQ(source->length(), kProgramSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01001388 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001389 i::ParseInfo info(&zone, script);
1390 i::Parser parser(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001391 parser.set_allow_lazy(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392 info.set_global();
1393 info.set_language_mode(source_data[i].language_mode);
1394 parser.Parse(&info);
1395 CHECK(info.literal() != NULL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001396
1397 // Check scope types and positions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001398 i::Scope* scope = info.literal()->scope();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001399 CHECK(scope->is_script_scope());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001400 CHECK_EQ(scope->start_position(), 0);
1401 CHECK_EQ(scope->end_position(), kProgramSize);
1402 CHECK_EQ(scope->inner_scopes()->length(), 1);
1403
1404 i::Scope* inner_scope = scope->inner_scopes()->at(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405 CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001406 CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1407 // The end position of a token is one position after the last
1408 // character belonging to that token.
1409 CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1410 }
1411}
1412
1413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414TEST(DiscardFunctionBody) {
1415 // Test that inner function bodies are discarded if possible.
1416 // See comments in ParseFunctionLiteral in parser.cc.
1417 const char* discard_sources[] = {
1418 "(function f() { function g() { var a; } })();",
1419 "(function f() { function g() { { function h() { } } } })();",
1420 /* TODO(conradw): In future it may be possible to apply this optimisation
1421 * to these productions.
1422 "(function f() { 0, function g() { var a; } })();",
1423 "(function f() { 0, { g() { var a; } } })();",
1424 "(function f() { 0, class c { g() { var a; } } })();", */
1425 NULL};
1426
1427 i::Isolate* isolate = CcTest::i_isolate();
1428 i::Factory* factory = isolate->factory();
1429 v8::HandleScope handles(CcTest::isolate());
1430 i::FunctionLiteral* function;
1431
1432 for (int i = 0; discard_sources[i]; i++) {
1433 const char* source = discard_sources[i];
1434 i::Handle<i::String> source_code =
1435 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
1436 i::Handle<i::Script> script = factory->NewScript(source_code);
Ben Murdochda12d292016-06-02 14:46:10 +01001437 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 i::ParseInfo info(&zone, script);
1439 info.set_allow_lazy_parsing();
1440 i::Parser parser(&info);
1441 parser.set_allow_harmony_sloppy(true);
1442 parser.Parse(&info);
1443 function = info.literal();
1444 CHECK_NOT_NULL(function);
1445 CHECK_NOT_NULL(function->body());
1446 CHECK_EQ(1, function->body()->length());
1447 i::FunctionLiteral* inner =
1448 function->body()->first()->AsExpressionStatement()->expression()->
1449 AsCall()->expression()->AsFunctionLiteral();
1450 i::Scope* inner_scope = inner->scope();
1451 i::FunctionLiteral* fun = nullptr;
1452 if (inner_scope->declarations()->length() > 1) {
1453 fun = inner_scope->declarations()->at(1)->AsFunctionDeclaration()->fun();
1454 } else {
1455 // TODO(conradw): This path won't be hit until the other test cases can be
1456 // uncommented.
1457 UNREACHABLE();
1458 CHECK_NOT_NULL(inner->body());
1459 CHECK_GE(2, inner->body()->length());
1460 i::Expression* exp = inner->body()->at(1)->AsExpressionStatement()->
1461 expression()->AsBinaryOperation()->right();
1462 if (exp->IsFunctionLiteral()) {
1463 fun = exp->AsFunctionLiteral();
1464 } else if (exp->IsObjectLiteral()) {
1465 fun = exp->AsObjectLiteral()->properties()->at(0)->value()->
1466 AsFunctionLiteral();
1467 } else {
1468 fun = exp->AsClassLiteral()->properties()->at(0)->value()->
1469 AsFunctionLiteral();
1470 }
1471 }
1472 CHECK_NULL(fun->body());
1473 }
1474}
1475
1476
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477const char* ReadString(unsigned* start) {
1478 int length = start[0];
1479 char* result = i::NewArray<char>(length + 1);
1480 for (int i = 0; i < length; i++) {
1481 result[i] = start[i + 1];
1482 }
1483 result[length] = '\0';
1484 return result;
1485}
1486
1487
1488i::Handle<i::String> FormatMessage(i::Vector<unsigned> data) {
1489 i::Isolate* isolate = CcTest::i_isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 int message = data[i::PreparseDataConstants::kMessageTemplatePos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 int arg_count = data[i::PreparseDataConstants::kMessageArgCountPos];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001492 i::Handle<i::Object> arg_object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001493 if (arg_count == 1) {
1494 // Position after text found by skipping past length field and
1495 // length field content words.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001496 const char* arg =
1497 ReadString(&data[i::PreparseDataConstants::kMessageArgPos]);
1498 arg_object = v8::Utils::OpenHandle(*v8_str(arg));
1499 i::DeleteArray(arg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001500 } else {
1501 CHECK_EQ(0, arg_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001502 arg_object = isolate->factory()->undefined_value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 }
1504
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001505 data.Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507}
1508
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509enum ParserFlag {
1510 kAllowLazy,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001511 kAllowNatives,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001512 kAllowHarmonySloppy,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513 kAllowHarmonySloppyLet,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514 kAllowHarmonyNewTarget,
Ben Murdochda12d292016-06-02 14:46:10 +01001515 kAllowHarmonyFunctionSent,
1516 kAllowHarmonyRestrictiveDeclarations,
1517 kAllowHarmonyExponentiationOperator
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518};
1519
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520enum ParserSyncTestResult {
1521 kSuccessOrError,
1522 kSuccess,
1523 kError
1524};
1525
1526template <typename Traits>
1527void SetParserFlags(i::ParserBase<Traits>* parser,
1528 i::EnumSet<ParserFlag> flags) {
1529 parser->set_allow_lazy(flags.Contains(kAllowLazy));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001530 parser->set_allow_natives(flags.Contains(kAllowNatives));
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));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001533 parser->set_allow_harmony_function_sent(
1534 flags.Contains(kAllowHarmonyFunctionSent));
Ben Murdochda12d292016-06-02 14:46:10 +01001535 parser->set_allow_harmony_restrictive_declarations(
1536 flags.Contains(kAllowHarmonyRestrictiveDeclarations));
1537 parser->set_allow_harmony_exponentiation_operator(
1538 flags.Contains(kAllowHarmonyExponentiationOperator));
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 Murdochda12d292016-06-02 14:46:10 +01001559 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 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 Murdochda12d292016-06-02 14:46:10 +01001576 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 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()));
Ben Murdochda12d292016-06-02 14:46:10 +01001598 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
1599 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
1600 .ToHandleChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001601
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) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001912 RunParserSyncTest(context_data, statement_data, result, flags, flags_len,
1913 always_true_flags, always_true_len, always_false_flags,
1914 always_false_len, true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001915}
1916
1917
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918TEST(ErrorsEvalAndArguments) {
1919 // Tests that both preparsing and parsing produce the right kind of errors for
1920 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1921 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1922 // isn't.
1923 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 {"\"use strict\";", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001925 {"var eval; function test_func() {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001926 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001927
1928 const char* statement_data[] = {
1929 "var eval;",
1930 "var arguments",
1931 "var foo, eval;",
1932 "var foo, arguments;",
1933 "try { } catch (eval) { }",
1934 "try { } catch (arguments) { }",
1935 "function eval() { }",
1936 "function arguments() { }",
1937 "function foo(eval) { }",
1938 "function foo(arguments) { }",
1939 "function foo(bar, eval) { }",
1940 "function foo(bar, arguments) { }",
1941 "(eval) => { }",
1942 "(arguments) => { }",
1943 "(foo, eval) => { }",
1944 "(foo, arguments) => { }",
1945 "eval = 1;",
1946 "arguments = 1;",
1947 "var foo = eval = 1;",
1948 "var foo = arguments = 1;",
1949 "++eval;",
1950 "++arguments;",
1951 "eval++;",
1952 "arguments++;",
1953 NULL
1954 };
1955
Ben Murdochda12d292016-06-02 14:46:10 +01001956 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001957}
1958
1959
1960TEST(NoErrorsEvalAndArgumentsSloppy) {
1961 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1962 // identifiers when needed.
1963 const char* context_data[][2] = {
1964 { "", "" },
1965 { "function test_func() {", "}"},
1966 { NULL, NULL }
1967 };
1968
1969 const char* statement_data[] = {
1970 "var eval;",
1971 "var arguments",
1972 "var foo, eval;",
1973 "var foo, arguments;",
1974 "try { } catch (eval) { }",
1975 "try { } catch (arguments) { }",
1976 "function eval() { }",
1977 "function arguments() { }",
1978 "function foo(eval) { }",
1979 "function foo(arguments) { }",
1980 "function foo(bar, eval) { }",
1981 "function foo(bar, arguments) { }",
1982 "eval = 1;",
1983 "arguments = 1;",
1984 "var foo = eval = 1;",
1985 "var foo = arguments = 1;",
1986 "++eval;",
1987 "++arguments;",
1988 "eval++;",
1989 "arguments++;",
1990 NULL
1991 };
1992
1993 RunParserSyncTest(context_data, statement_data, kSuccess);
1994}
1995
1996
1997TEST(NoErrorsEvalAndArgumentsStrict) {
1998 const char* context_data[][2] = {
1999 { "\"use strict\";", "" },
2000 { "function test_func() { \"use strict\";", "}" },
2001 { "() => { \"use strict\"; ", "}" },
2002 { NULL, NULL }
2003 };
2004
2005 const char* statement_data[] = {
2006 "eval;",
2007 "arguments;",
2008 "var foo = eval;",
2009 "var foo = arguments;",
2010 "var foo = { eval: 1 };",
2011 "var foo = { arguments: 1 };",
2012 "var foo = { }; foo.eval = {};",
2013 "var foo = { }; foo.arguments = {};",
2014 NULL
2015 };
2016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002017 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002018}
2019
2020
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002021#define FUTURE_STRICT_RESERVED_WORDS(V) \
2022 V(implements) \
2023 V(interface) \
2024 V(let) \
2025 V(package) \
2026 V(private) \
2027 V(protected) \
2028 V(public) \
2029 V(static) \
2030 V(yield)
2031
2032
2033#define LIMITED_FUTURE_STRICT_RESERVED_WORDS(V) \
2034 V(implements) \
2035 V(let) \
2036 V(static) \
2037 V(yield)
2038
2039
2040#define FUTURE_STRICT_RESERVED_STATEMENTS(NAME) \
2041 "var " #NAME ";", \
2042 "var foo, " #NAME ";", \
2043 "try { } catch (" #NAME ") { }", \
2044 "function " #NAME "() { }", \
2045 "(function " #NAME "() { })", \
2046 "function foo(" #NAME ") { }", \
2047 "function foo(bar, " #NAME ") { }", \
2048 #NAME " = 1;", \
2049 #NAME " += 1;", \
2050 "var foo = " #NAME " = 1;", \
2051 "++" #NAME ";", \
2052 #NAME " ++;",
2053
2054
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002055TEST(ErrorsFutureStrictReservedWords) {
2056 // Tests that both preparsing and parsing produce the right kind of errors for
2057 // using future strict reserved words as identifiers. Without the strict mode,
2058 // it's ok to use future strict reserved words as identifiers. With the strict
2059 // mode, it isn't.
2060 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002061 {"function test_func() {\"use strict\"; ", "}"},
2062 {"() => { \"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002063 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002064
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002065 const char* statement_data[] {
2066 LIMITED_FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002067 NULL
2068 };
2069
Ben Murdochda12d292016-06-02 14:46:10 +01002070 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071}
2072
2073
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002074#undef LIMITED_FUTURE_STRICT_RESERVED_WORDS
2075
2076
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002077TEST(NoErrorsFutureStrictReservedWords) {
2078 const char* context_data[][2] = {
2079 { "", "" },
2080 { "function test_func() {", "}"},
2081 { "() => {", "}" },
2082 { NULL, NULL }
2083 };
2084
2085 const char* statement_data[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002086 FUTURE_STRICT_RESERVED_WORDS(FUTURE_STRICT_RESERVED_STATEMENTS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087 NULL
2088 };
2089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002090 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002091}
2092
2093
2094TEST(ErrorsReservedWords) {
2095 // Tests that both preparsing and parsing produce the right kind of errors for
2096 // using future reserved words as identifiers. These tests don't depend on the
2097 // strict mode.
2098 const char* context_data[][2] = {
2099 { "", "" },
2100 { "\"use strict\";", "" },
2101 { "var eval; function test_func() {", "}"},
2102 { "var eval; function test_func() {\"use strict\"; ", "}"},
2103 { "var eval; () => {", "}"},
2104 { "var eval; () => {\"use strict\"; ", "}"},
2105 { NULL, NULL }
2106 };
2107
2108 const char* statement_data[] = {
2109 "var super;",
2110 "var foo, super;",
2111 "try { } catch (super) { }",
2112 "function super() { }",
2113 "function foo(super) { }",
2114 "function foo(bar, super) { }",
2115 "(super) => { }",
2116 "(bar, super) => { }",
2117 "super = 1;",
2118 "var foo = super = 1;",
2119 "++super;",
2120 "super++;",
2121 "function foo super",
2122 NULL
2123 };
2124
2125 RunParserSyncTest(context_data, statement_data, kError);
2126}
2127
2128
2129TEST(NoErrorsLetSloppyAllModes) {
2130 // In sloppy mode, it's okay to use "let" as identifier.
2131 const char* context_data[][2] = {
2132 { "", "" },
2133 { "function f() {", "}" },
2134 { "(function f() {", "})" },
2135 { NULL, NULL }
2136 };
2137
2138 const char* statement_data[] = {
2139 "var let;",
2140 "var foo, let;",
2141 "try { } catch (let) { }",
2142 "function let() { }",
2143 "(function let() { })",
2144 "function foo(let) { }",
2145 "function foo(bar, let) { }",
2146 "let = 1;",
2147 "var foo = let = 1;",
2148 "let * 2;",
2149 "++let;",
2150 "let++;",
2151 "let: 34",
2152 "function let(let) { let: let(let + let(0)); }",
2153 "({ let: 1 })",
2154 "({ get let() { 1 } })",
2155 "let(100)",
2156 NULL
2157 };
2158
2159 RunParserSyncTest(context_data, statement_data, kSuccess);
2160}
2161
2162
2163TEST(NoErrorsYieldSloppyAllModes) {
2164 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2165 // generator (see other test).
2166 const char* context_data[][2] = {
2167 { "", "" },
2168 { "function not_gen() {", "}" },
2169 { "(function not_gen() {", "})" },
2170 { NULL, NULL }
2171 };
2172
2173 const char* statement_data[] = {
2174 "var yield;",
2175 "var foo, yield;",
2176 "try { } catch (yield) { }",
2177 "function yield() { }",
2178 "(function yield() { })",
2179 "function foo(yield) { }",
2180 "function foo(bar, yield) { }",
2181 "yield = 1;",
2182 "var foo = yield = 1;",
2183 "yield * 2;",
2184 "++yield;",
2185 "yield++;",
2186 "yield: 34",
2187 "function yield(yield) { yield: yield (yield + yield(0)); }",
2188 "({ yield: 1 })",
2189 "({ get yield() { 1 } })",
2190 "yield(100)",
2191 "yield[100]",
2192 NULL
2193 };
2194
2195 RunParserSyncTest(context_data, statement_data, kSuccess);
2196}
2197
2198
2199TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
2200 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
2201 // generator (see next test).
2202 const char* context_data[][2] = {
2203 { "", "" },
2204 { "function not_gen() {", "}" },
2205 { "function * gen() { function not_gen() {", "} }" },
2206 { "(function not_gen() {", "})" },
2207 { "(function * gen() { (function not_gen() {", "}) })" },
2208 { NULL, NULL }
2209 };
2210
2211 const char* statement_data[] = {
2212 "var yield;",
2213 "var foo, yield;",
2214 "try { } catch (yield) { }",
2215 "function yield() { }",
2216 "(function yield() { })",
2217 "function foo(yield) { }",
2218 "function foo(bar, yield) { }",
2219 "function * yield() { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002220 "yield = 1;",
2221 "var foo = yield = 1;",
2222 "yield * 2;",
2223 "++yield;",
2224 "yield++;",
2225 "yield: 34",
2226 "function yield(yield) { yield: yield (yield + yield(0)); }",
2227 "({ yield: 1 })",
2228 "({ get yield() { 1 } })",
2229 "yield(100)",
2230 "yield[100]",
2231 NULL
2232 };
2233
2234 RunParserSyncTest(context_data, statement_data, kSuccess);
2235}
2236
2237
2238TEST(ErrorsYieldStrict) {
2239 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240 {"\"use strict\";", ""},
2241 {"\"use strict\"; function not_gen() {", "}"},
2242 {"function test_func() {\"use strict\"; ", "}"},
2243 {"\"use strict\"; function * gen() { function not_gen() {", "} }"},
2244 {"\"use strict\"; (function not_gen() {", "})"},
2245 {"\"use strict\"; (function * gen() { (function not_gen() {", "}) })"},
2246 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002247 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248
2249 const char* statement_data[] = {
2250 "var yield;",
2251 "var foo, yield;",
2252 "try { } catch (yield) { }",
2253 "function yield() { }",
2254 "(function yield() { })",
2255 "function foo(yield) { }",
2256 "function foo(bar, yield) { }",
2257 "function * yield() { }",
2258 "(function * yield() { })",
2259 "yield = 1;",
2260 "var foo = yield = 1;",
2261 "++yield;",
2262 "yield++;",
2263 "yield: 34;",
2264 NULL
2265 };
2266
Ben Murdochda12d292016-06-02 14:46:10 +01002267 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002268}
2269
2270
2271TEST(ErrorsYieldSloppy) {
2272 const char* context_data[][2] = {
2273 { "", "" },
2274 { "function not_gen() {", "}" },
2275 { "(function not_gen() {", "})" },
2276 { NULL, NULL }
2277 };
2278
2279 const char* statement_data[] = {
2280 "(function * yield() { })",
2281 NULL
2282 };
2283
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002284 RunParserSyncTest(context_data, statement_data, kError);
2285}
2286
2287
2288TEST(NoErrorsGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002289 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002290 const char* context_data[][2] = {
2291 { "function * gen() {", "}" },
2292 { "(function * gen() {", "})" },
2293 { "(function * () {", "})" },
2294 { NULL, NULL }
2295 };
2296
2297 const char* statement_data[] = {
2298 // A generator without a body is valid.
2299 ""
2300 // Valid yield expressions inside generators.
2301 "yield 2;",
2302 "yield * 2;",
2303 "yield * \n 2;",
2304 "yield yield 1;",
2305 "yield * yield * 1;",
2306 "yield 3 + (yield 4);",
2307 "yield * 3 + (yield * 4);",
2308 "(yield * 3) + (yield * 4);",
2309 "yield 3; yield 4;",
2310 "yield * 3; yield * 4;",
2311 "(function (yield) { })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002312 "(function yield() { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002313 "yield { yield: 12 }",
2314 "yield /* comment */ { yield: 12 }",
2315 "yield * \n { yield: 12 }",
2316 "yield /* comment */ * \n { yield: 12 }",
2317 // You can return in a generator.
2318 "yield 1; return",
2319 "yield * 1; return",
2320 "yield 1; return 37",
2321 "yield * 1; return 37",
2322 "yield 1; return 37; yield 'dead';",
2323 "yield * 1; return 37; yield * 'dead';",
2324 // Yield is still a valid key in object literals.
2325 "({ yield: 1 })",
2326 "({ get yield() { } })",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002327 // And in assignment pattern computed properties
2328 "({ [yield]: x } = { })",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002329 // Yield without RHS.
2330 "yield;",
2331 "yield",
2332 "yield\n",
2333 "yield /* comment */"
2334 "yield // comment\n"
2335 "(yield)",
2336 "[yield]",
2337 "{yield}",
2338 "yield, yield",
2339 "yield; yield",
2340 "(yield) ? yield : yield",
2341 "(yield) \n ? yield : yield",
2342 // If there is a newline before the next token, we don't look for RHS.
2343 "yield\nfor (;;) {}",
Ben Murdochda12d292016-06-02 14:46:10 +01002344 "x = class extends (yield) {}",
2345 "x = class extends f(yield) {}",
2346 "x = class extends (null, yield) { }",
2347 "x = class extends (a ? null : yield) { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002348 NULL
2349 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002351
Ben Murdochda12d292016-06-02 14:46:10 +01002352 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
2353 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002354 always_flags, arraysize(always_flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002355}
2356
2357
2358TEST(ErrorsYieldGenerator) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002359 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002360 const char* context_data[][2] = {
2361 { "function * gen() {", "}" },
2362 { "\"use strict\"; function * gen() {", "}" },
2363 { NULL, NULL }
2364 };
2365
2366 const char* statement_data[] = {
2367 // Invalid yield expressions inside generators.
2368 "var yield;",
2369 "var foo, yield;",
2370 "try { } catch (yield) { }",
2371 "function yield() { }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002372 // The name of the NFE is bound in the generator, which does not permit
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002373 // yield to be an identifier.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002374 "(function * yield() { })",
2375 // Yield isn't valid as a formal parameter for generators.
2376 "function * foo(yield) { }",
2377 "(function * foo(yield) { })",
2378 "yield = 1;",
2379 "var foo = yield = 1;",
2380 "++yield;",
2381 "yield++;",
2382 "yield *",
2383 "(yield *)",
2384 // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
2385 // is invalid.
2386 "yield 3 + yield 4;",
2387 "yield: 34",
2388 "yield ? 1 : 2",
2389 // Parses as yield (/ yield): invalid.
2390 "yield / yield",
2391 "+ yield",
2392 "+ yield 3",
2393 // Invalid (no newline allowed between yield and *).
2394 "yield\n*3",
2395 // Invalid (we see a newline, so we parse {yield:42} as a statement, not an
2396 // object literal, and yield is not a valid label).
2397 "yield\n{yield: 42}",
2398 "yield /* comment */\n {yield: 42}",
2399 "yield //comment\n {yield: 42}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002400 // Destructuring binding and assignment are both disallowed
2401 "var [yield] = [42];",
2402 "var {foo: yield} = {a: 42};",
2403 "[yield] = [42];",
2404 "({a: yield} = {a: 42});",
2405 // Also disallow full yield expressions on LHS
2406 "var [yield 24] = [42];",
2407 "var {foo: yield 24} = {a: 42};",
2408 "[yield 24] = [42];",
2409 "({a: yield 24} = {a: 42});",
Ben Murdochda12d292016-06-02 14:46:10 +01002410 "class C extends yield { }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002411 NULL
2412 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002413 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002414
2415 RunParserSyncTest(context_data, statement_data, kError);
2416}
2417
2418
2419TEST(ErrorsNameOfStrictFunction) {
2420 // Tests that illegal tokens as names of a strict function produce the correct
2421 // errors.
2422 const char* context_data[][2] = {
2423 { "function ", ""},
2424 { "\"use strict\"; function", ""},
2425 { "function * ", ""},
2426 { "\"use strict\"; function * ", ""},
2427 { NULL, NULL }
2428 };
2429
2430 const char* statement_data[] = {
2431 "eval() {\"use strict\";}",
2432 "arguments() {\"use strict\";}",
2433 "interface() {\"use strict\";}",
2434 "yield() {\"use strict\";}",
2435 // Future reserved words are always illegal
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002436 "super() { }",
2437 "super() {\"use strict\";}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 NULL
2439 };
2440
Ben Murdochda12d292016-06-02 14:46:10 +01002441 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002442}
2443
2444
2445TEST(NoErrorsNameOfStrictFunction) {
2446 const char* context_data[][2] = {
2447 { "function ", ""},
2448 { NULL, NULL }
2449 };
2450
2451 const char* statement_data[] = {
2452 "eval() { }",
2453 "arguments() { }",
2454 "interface() { }",
2455 "yield() { }",
2456 NULL
2457 };
2458
2459 RunParserSyncTest(context_data, statement_data, kSuccess);
2460}
2461
2462
2463TEST(NoErrorsNameOfStrictGenerator) {
2464 const char* context_data[][2] = {
2465 { "function * ", ""},
2466 { NULL, NULL }
2467 };
2468
2469 const char* statement_data[] = {
2470 "eval() { }",
2471 "arguments() { }",
2472 "interface() { }",
2473 "yield() { }",
2474 NULL
2475 };
2476
2477 RunParserSyncTest(context_data, statement_data, kSuccess);
2478}
2479
2480
2481TEST(ErrorsIllegalWordsAsLabelsSloppy) {
2482 // Using future reserved words as labels is always an error.
2483 const char* context_data[][2] = {
2484 { "", ""},
2485 { "function test_func() {", "}" },
2486 { "() => {", "}" },
2487 { NULL, NULL }
2488 };
2489
2490 const char* statement_data[] = {
2491 "super: while(true) { break super; }",
2492 NULL
2493 };
2494
2495 RunParserSyncTest(context_data, statement_data, kError);
2496}
2497
2498
2499TEST(ErrorsIllegalWordsAsLabelsStrict) {
2500 // Tests that illegal tokens as labels produce the correct errors.
2501 const char* context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002502 {"\"use strict\";", ""},
2503 {"function test_func() {\"use strict\"; ", "}"},
2504 {"() => {\"use strict\"; ", "}"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002505 {NULL, NULL}};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002506
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002507#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002508 const char* statement_data[] = {
2509 "super: while(true) { break super; }",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002510 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002511 NULL
2512 };
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002513#undef LABELLED_WHILE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002514
Ben Murdochda12d292016-06-02 14:46:10 +01002515 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002516}
2517
2518
2519TEST(NoErrorsIllegalWordsAsLabels) {
2520 // Using eval and arguments as labels is legal even in strict mode.
2521 const char* context_data[][2] = {
2522 { "", ""},
2523 { "function test_func() {", "}" },
2524 { "() => {", "}" },
2525 { "\"use strict\";", "" },
2526 { "\"use strict\"; function test_func() {", "}" },
2527 { "\"use strict\"; () => {", "}" },
2528 { NULL, NULL }
2529 };
2530
2531 const char* statement_data[] = {
2532 "mylabel: while(true) { break mylabel; }",
2533 "eval: while(true) { break eval; }",
2534 "arguments: while(true) { break arguments; }",
2535 NULL
2536 };
2537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002538 RunParserSyncTest(context_data, statement_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002539}
2540
2541
2542TEST(NoErrorsFutureStrictReservedAsLabelsSloppy) {
2543 const char* context_data[][2] = {
2544 { "", ""},
2545 { "function test_func() {", "}" },
2546 { "() => {", "}" },
2547 { NULL, NULL }
2548 };
2549
2550#define LABELLED_WHILE(NAME) #NAME ": while (true) { break " #NAME "; }",
2551 const char* statement_data[] {
2552 FUTURE_STRICT_RESERVED_WORDS(LABELLED_WHILE)
2553 NULL
2554 };
2555#undef LABELLED_WHILE
2556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002557 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002558}
2559
2560
2561TEST(ErrorsParenthesizedLabels) {
2562 // Parenthesized identifiers shouldn't be recognized as labels.
2563 const char* context_data[][2] = {
2564 { "", ""},
2565 { "function test_func() {", "}" },
2566 { "() => {", "}" },
2567 { NULL, NULL }
2568 };
2569
2570 const char* statement_data[] = {
2571 "(mylabel): while(true) { break mylabel; }",
2572 NULL
2573 };
2574
2575 RunParserSyncTest(context_data, statement_data, kError);
2576}
2577
2578
2579TEST(NoErrorsParenthesizedDirectivePrologue) {
2580 // Parenthesized directive prologue shouldn't be recognized.
2581 const char* context_data[][2] = {
2582 { "", ""},
2583 { NULL, NULL }
2584 };
2585
2586 const char* statement_data[] = {
2587 "(\"use strict\"); var eval;",
2588 NULL
2589 };
2590
Ben Murdochda12d292016-06-02 14:46:10 +01002591 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002592}
2593
2594
2595TEST(ErrorsNotAnIdentifierName) {
2596 const char* context_data[][2] = {
2597 { "", ""},
2598 { "\"use strict\";", ""},
2599 { NULL, NULL }
2600 };
2601
2602 const char* statement_data[] = {
2603 "var foo = {}; foo.{;",
2604 "var foo = {}; foo.};",
2605 "var foo = {}; foo.=;",
2606 "var foo = {}; foo.888;",
2607 "var foo = {}; foo.-;",
2608 "var foo = {}; foo.--;",
2609 NULL
2610 };
2611
2612 RunParserSyncTest(context_data, statement_data, kError);
2613}
2614
2615
2616TEST(NoErrorsIdentifierNames) {
2617 // Keywords etc. are valid as property names.
2618 const char* context_data[][2] = {
2619 { "", ""},
2620 { "\"use strict\";", ""},
2621 { NULL, NULL }
2622 };
2623
2624 const char* statement_data[] = {
2625 "var foo = {}; foo.if;",
2626 "var foo = {}; foo.yield;",
2627 "var foo = {}; foo.super;",
2628 "var foo = {}; foo.interface;",
2629 "var foo = {}; foo.eval;",
2630 "var foo = {}; foo.arguments;",
2631 NULL
2632 };
2633
2634 RunParserSyncTest(context_data, statement_data, kSuccess);
2635}
2636
2637
2638TEST(DontRegressPreParserDataSizes) {
2639 // These tests make sure that Parser doesn't start producing less "preparse
2640 // data" (data which the embedder can cache).
2641 v8::V8::Initialize();
2642 v8::Isolate* isolate = CcTest::isolate();
2643 v8::HandleScope handles(isolate);
2644
2645 CcTest::i_isolate()->stack_guard()->SetStackLimit(
2646 i::GetCurrentStackPosition() - 128 * 1024);
2647
2648 struct TestCase {
2649 const char* program;
2650 int functions;
2651 } test_cases[] = {
2652 // No functions.
2653 {"var x = 42;", 0},
2654 // Functions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002655 {"function foo() {}", 1},
2656 {"function foo() {} function bar() {}", 2},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002657 // Getter / setter functions are recorded as functions if they're on the top
2658 // level.
2659 {"var x = {get foo(){} };", 1},
2660 // Functions insize lazy functions are not recorded.
2661 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
2662 {"function lazy() { var x = {get foo(){} } }", 1},
2663 {NULL, 0}
2664 };
2665
2666 for (int i = 0; test_cases[i].program; i++) {
2667 const char* program = test_cases[i].program;
2668 i::Factory* factory = CcTest::i_isolate()->factory();
2669 i::Handle<i::String> source =
2670 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
2671 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01002672 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002673 i::ParseInfo info(&zone, script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002674 i::ScriptData* sd = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002675 info.set_cached_data(&sd);
2676 info.set_compile_options(v8::ScriptCompiler::kProduceParserCache);
2677 info.set_allow_lazy_parsing();
2678 i::Parser::ParseStatic(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002679 i::ParseData* pd = i::ParseData::FromCachedData(sd);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002680
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002681 if (pd->FunctionCount() != test_cases[i].functions) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002682 v8::base::OS::Print(
2683 "Expected preparse data for program:\n"
2684 "\t%s\n"
2685 "to contain %d functions, however, received %d functions.\n",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002686 program, test_cases[i].functions, pd->FunctionCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002687 CHECK(false);
2688 }
2689 delete sd;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002690 delete pd;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002691 }
2692}
2693
2694
2695TEST(FunctionDeclaresItselfStrict) {
2696 // Tests that we produce the right kinds of errors when a function declares
2697 // itself strict (we cannot produce there errors as soon as we see the
2698 // offending identifiers, because we don't know at that point whether the
2699 // function is strict or not).
2700 const char* context_data[][2] = {
2701 {"function eval() {", "}"},
2702 {"function arguments() {", "}"},
2703 {"function yield() {", "}"},
2704 {"function interface() {", "}"},
2705 {"function foo(eval) {", "}"},
2706 {"function foo(arguments) {", "}"},
2707 {"function foo(yield) {", "}"},
2708 {"function foo(interface) {", "}"},
2709 {"function foo(bar, eval) {", "}"},
2710 {"function foo(bar, arguments) {", "}"},
2711 {"function foo(bar, yield) {", "}"},
2712 {"function foo(bar, interface) {", "}"},
2713 {"function foo(bar, bar) {", "}"},
2714 { NULL, NULL }
2715 };
2716
2717 const char* strict_statement_data[] = {
2718 "\"use strict\";",
2719 NULL
2720 };
2721
2722 const char* non_strict_statement_data[] = {
2723 ";",
2724 NULL
2725 };
2726
Ben Murdochda12d292016-06-02 14:46:10 +01002727 RunParserSyncTest(context_data, strict_statement_data, kError);
2728 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002729}
2730
2731
2732TEST(ErrorsTryWithoutCatchOrFinally) {
2733 const char* context_data[][2] = {
2734 {"", ""},
2735 { NULL, NULL }
2736 };
2737
2738 const char* statement_data[] = {
2739 "try { }",
2740 "try { } foo();",
2741 "try { } catch (e) foo();",
2742 "try { } catch { }",
2743 "try { } finally foo();",
2744 NULL
2745 };
2746
2747 RunParserSyncTest(context_data, statement_data, kError);
2748}
2749
2750
2751TEST(NoErrorsTryCatchFinally) {
2752 const char* context_data[][2] = {
2753 {"", ""},
2754 { NULL, NULL }
2755 };
2756
2757 const char* statement_data[] = {
2758 "try { } catch (e) { }",
2759 "try { } catch (e) { } finally { }",
2760 "try { } finally { }",
2761 NULL
2762 };
2763
2764 RunParserSyncTest(context_data, statement_data, kSuccess);
2765}
2766
2767
2768TEST(ErrorsRegexpLiteral) {
2769 const char* context_data[][2] = {
2770 {"var r = ", ""},
2771 { NULL, NULL }
2772 };
2773
2774 const char* statement_data[] = {
2775 "/unterminated",
2776 NULL
2777 };
2778
2779 RunParserSyncTest(context_data, statement_data, kError);
2780}
2781
2782
2783TEST(NoErrorsRegexpLiteral) {
2784 const char* context_data[][2] = {
2785 {"var r = ", ""},
2786 { NULL, NULL }
2787 };
2788
2789 const char* statement_data[] = {
2790 "/foo/",
2791 "/foo/g",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002792 NULL
2793 };
2794
2795 RunParserSyncTest(context_data, statement_data, kSuccess);
2796}
2797
2798
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002799TEST(NoErrorsNewExpression) {
2800 const char* context_data[][2] = {
2801 {"", ""},
2802 {"var f =", ""},
2803 { NULL, NULL }
2804 };
2805
2806 const char* statement_data[] = {
2807 "new foo",
2808 "new foo();",
2809 "new foo(1);",
2810 "new foo(1, 2);",
2811 // The first () will be processed as a part of the NewExpression and the
2812 // second () will be processed as part of LeftHandSideExpression.
2813 "new foo()();",
2814 // The first () will be processed as a part of the inner NewExpression and
2815 // the second () will be processed as a part of the outer NewExpression.
2816 "new new foo()();",
2817 "new foo.bar;",
2818 "new foo.bar();",
2819 "new foo.bar.baz;",
2820 "new foo.bar().baz;",
2821 "new foo[bar];",
2822 "new foo[bar]();",
2823 "new foo[bar][baz];",
2824 "new foo[bar]()[baz];",
2825 "new foo[bar].baz(baz)()[bar].baz;",
2826 "new \"foo\"", // Runtime error
2827 "new 1", // Runtime error
2828 // This even runs:
2829 "(new new Function(\"this.x = 1\")).x;",
2830 "new new Test_Two(String, 2).v(0123).length;",
2831 NULL
2832 };
2833
2834 RunParserSyncTest(context_data, statement_data, kSuccess);
2835}
2836
2837
2838TEST(ErrorsNewExpression) {
2839 const char* context_data[][2] = {
2840 {"", ""},
2841 {"var f =", ""},
2842 { NULL, NULL }
2843 };
2844
2845 const char* statement_data[] = {
2846 "new foo bar",
2847 "new ) foo",
2848 "new ++foo",
2849 "new foo ++",
2850 NULL
2851 };
2852
2853 RunParserSyncTest(context_data, statement_data, kError);
2854}
2855
2856
2857TEST(StrictObjectLiteralChecking) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002858 const char* context_data[][2] = {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002859 {"\"use strict\"; var myobject = {", "};"},
2860 {"\"use strict\"; var myobject = {", ",};"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002861 {"var myobject = {", "};"},
2862 {"var myobject = {", ",};"},
2863 { NULL, NULL }
2864 };
2865
2866 // These are only errors in strict mode.
2867 const char* statement_data[] = {
2868 "foo: 1, foo: 2",
2869 "\"foo\": 1, \"foo\": 2",
2870 "foo: 1, \"foo\": 2",
2871 "1: 1, 1: 2",
2872 "1: 1, \"1\": 2",
2873 "get: 1, get: 2", // Not a getter for real, just a property called get.
2874 "set: 1, set: 2", // Not a setter for real, just a property called set.
2875 NULL
2876 };
2877
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002878 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002879}
2880
2881
2882TEST(ErrorsObjectLiteralChecking) {
2883 const char* context_data[][2] = {
2884 {"\"use strict\"; var myobject = {", "};"},
2885 {"var myobject = {", "};"},
2886 { NULL, NULL }
2887 };
2888
2889 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002890 ",",
2891 // Wrong number of parameters
2892 "get bar(x) {}",
2893 "get bar(x, y) {}",
2894 "set bar() {}",
2895 "set bar(x, y) {}",
2896 // Parsing FunctionLiteral for getter or setter fails
2897 "get foo( +",
2898 "get foo() \"error\"",
2899 NULL
2900 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002901
2902 RunParserSyncTest(context_data, statement_data, kError);
2903}
2904
2905
2906TEST(NoErrorsObjectLiteralChecking) {
2907 const char* context_data[][2] = {
2908 {"var myobject = {", "};"},
2909 {"var myobject = {", ",};"},
2910 {"\"use strict\"; var myobject = {", "};"},
2911 {"\"use strict\"; var myobject = {", ",};"},
2912 { NULL, NULL }
2913 };
2914
2915 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002916 "foo: 1, get foo() {}",
2917 "foo: 1, set foo(v) {}",
2918 "\"foo\": 1, get \"foo\"() {}",
2919 "\"foo\": 1, set \"foo\"(v) {}",
2920 "1: 1, get 1() {}",
2921 "1: 1, set 1(v) {}",
2922 "get foo() {}, get foo() {}",
2923 "set foo(_) {}, set foo(v) {}",
2924 "foo: 1, get \"foo\"() {}",
2925 "foo: 1, set \"foo\"(v) {}",
2926 "\"foo\": 1, get foo() {}",
2927 "\"foo\": 1, set foo(v) {}",
2928 "1: 1, get \"1\"() {}",
2929 "1: 1, set \"1\"(v) {}",
2930 "\"1\": 1, get 1() {}",
2931 "\"1\": 1, set 1(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002932 "foo: 1, bar: 2",
2933 "\"foo\": 1, \"bar\": 2",
2934 "1: 1, 2: 2",
2935 // Syntax: IdentifierName ':' AssignmentExpression
2936 "foo: bar = 5 + baz",
2937 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2938 "get foo() {}",
2939 "get \"foo\"() {}",
2940 "get 1() {}",
2941 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2942 // '{' FunctionBody '}'
2943 "set foo(v) {}",
2944 "set \"foo\"(v) {}",
2945 "set 1(v) {}",
2946 // Non-colliding getters and setters -> no errors
2947 "foo: 1, get bar() {}",
2948 "foo: 1, set bar(v) {}",
2949 "\"foo\": 1, get \"bar\"() {}",
2950 "\"foo\": 1, set \"bar\"(v) {}",
2951 "1: 1, get 2() {}",
2952 "1: 1, set 2(v) {}",
2953 "get: 1, get foo() {}",
2954 "set: 1, set foo(_) {}",
2955 // Keywords, future reserved and strict future reserved are also allowed as
2956 // property names.
2957 "if: 4",
2958 "interface: 5",
2959 "super: 6",
2960 "eval: 7",
2961 "arguments: 8",
2962 NULL
2963 };
2964
2965 RunParserSyncTest(context_data, statement_data, kSuccess);
2966}
2967
2968
2969TEST(TooManyArguments) {
2970 const char* context_data[][2] = {
2971 {"foo(", "0)"},
2972 { NULL, NULL }
2973 };
2974
2975 using v8::internal::Code;
2976 char statement[Code::kMaxArguments * 2 + 1];
2977 for (int i = 0; i < Code::kMaxArguments; ++i) {
2978 statement[2 * i] = '0';
2979 statement[2 * i + 1] = ',';
2980 }
2981 statement[Code::kMaxArguments * 2] = 0;
2982
2983 const char* statement_data[] = {
2984 statement,
2985 NULL
2986 };
2987
2988 // The test is quite slow, so run it with a reduced set of flags.
2989 static const ParserFlag empty_flags[] = {kAllowLazy};
2990 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2991}
2992
2993
2994TEST(StrictDelete) {
2995 // "delete <Identifier>" is not allowed in strict mode.
2996 const char* strict_context_data[][2] = {
2997 {"\"use strict\"; ", ""},
2998 { NULL, NULL }
2999 };
3000
3001 const char* sloppy_context_data[][2] = {
3002 {"", ""},
3003 { NULL, NULL }
3004 };
3005
3006 // These are errors in the strict mode.
3007 const char* sloppy_statement_data[] = {
3008 "delete foo;",
3009 "delete foo + 1;",
3010 "delete (foo);",
3011 "delete eval;",
3012 "delete interface;",
3013 NULL
3014 };
3015
3016 // These are always OK
3017 const char* good_statement_data[] = {
3018 "delete this;",
3019 "delete 1;",
3020 "delete 1 + 2;",
3021 "delete foo();",
3022 "delete foo.bar;",
3023 "delete foo[bar];",
3024 "delete foo--;",
3025 "delete --foo;",
3026 "delete new foo();",
3027 "delete new foo(bar);",
3028 NULL
3029 };
3030
3031 // These are always errors
3032 const char* bad_statement_data[] = {
3033 "delete if;",
3034 NULL
3035 };
3036
Ben Murdochda12d292016-06-02 14:46:10 +01003037 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
3038 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003039
Ben Murdochda12d292016-06-02 14:46:10 +01003040 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
3041 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003042
Ben Murdochda12d292016-06-02 14:46:10 +01003043 RunParserSyncTest(strict_context_data, bad_statement_data, kError);
3044 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003045}
3046
3047
3048TEST(NoErrorsDeclsInCase) {
3049 const char* context_data[][2] = {
3050 {"'use strict'; switch(x) { case 1:", "}"},
3051 {"function foo() {'use strict'; switch(x) { case 1:", "}}"},
3052 {"'use strict'; switch(x) { case 1: case 2:", "}"},
3053 {"function foo() {'use strict'; switch(x) { case 1: case 2:", "}}"},
3054 {"'use strict'; switch(x) { default:", "}"},
3055 {"function foo() {'use strict'; switch(x) { default:", "}}"},
3056 {"'use strict'; switch(x) { case 1: default:", "}"},
3057 {"function foo() {'use strict'; switch(x) { case 1: default:", "}}"},
3058 { nullptr, nullptr }
3059 };
3060
3061 const char* statement_data[] = {
3062 "function f() { }",
3063 "class C { }",
3064 "class C extends Q {}",
3065 "function f() { } class C {}",
3066 "function f() { }; class C {}",
3067 "class C {}; function f() {}",
3068 nullptr
3069 };
3070
3071 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003072}
3073
3074
3075TEST(InvalidLeftHandSide) {
3076 const char* assignment_context_data[][2] = {
3077 {"", " = 1;"},
3078 {"\"use strict\"; ", " = 1;"},
3079 { NULL, NULL }
3080 };
3081
3082 const char* prefix_context_data[][2] = {
3083 {"++", ";"},
3084 {"\"use strict\"; ++", ";"},
3085 {NULL, NULL},
3086 };
3087
3088 const char* postfix_context_data[][2] = {
3089 {"", "++;"},
3090 {"\"use strict\"; ", "++;"},
3091 { NULL, NULL }
3092 };
3093
3094 // Good left hand sides for assigment or prefix / postfix operations.
3095 const char* good_statement_data[] = {
3096 "foo",
3097 "foo.bar",
3098 "foo[bar]",
3099 "foo()[bar]",
3100 "foo().bar",
3101 "this.foo",
3102 "this[foo]",
3103 "new foo()[bar]",
3104 "new foo().bar",
3105 "foo()",
3106 "foo(bar)",
3107 "foo[bar]()",
3108 "foo.bar()",
3109 "this()",
3110 "this.foo()",
3111 "this[foo].bar()",
3112 "this.foo[foo].bar(this)(bar)[foo]()",
3113 NULL
3114 };
3115
3116 // Bad left hand sides for assigment or prefix / postfix operations.
3117 const char* bad_statement_data_common[] = {
3118 "2",
3119 "new foo",
3120 "new foo()",
3121 "null",
3122 "if", // Unexpected token
3123 "{x: 1}", // Unexpected token
3124 "this",
3125 "\"bar\"",
3126 "(foo + bar)",
3127 "new new foo()[bar]", // means: new (new foo()[bar])
3128 "new new foo().bar", // means: new (new foo()[bar])
3129 NULL
3130 };
3131
3132 // These are not okay for assignment, but okay for prefix / postix.
3133 const char* bad_statement_data_for_assignment[] = {
3134 "++foo",
3135 "foo++",
3136 "foo + bar",
3137 NULL
3138 };
3139
3140 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
3141 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
3142 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
3143 kError);
3144
3145 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
3146 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
3147
3148 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
3149 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
3150}
3151
3152
3153TEST(FuncNameInferrerBasic) {
3154 // Tests that function names are inferred properly.
3155 i::FLAG_allow_natives_syntax = true;
3156 v8::Isolate* isolate = CcTest::isolate();
3157 v8::HandleScope scope(isolate);
3158 LocalContext env;
3159 CompileRun("var foo1 = function() {}; "
3160 "var foo2 = function foo3() {}; "
3161 "function not_ctor() { "
3162 " var foo4 = function() {}; "
3163 " return %FunctionGetInferredName(foo4); "
3164 "} "
3165 "function Ctor() { "
3166 " var foo5 = function() {}; "
3167 " return %FunctionGetInferredName(foo5); "
3168 "} "
3169 "var obj1 = { foo6: function() {} }; "
3170 "var obj2 = { 'foo7': function() {} }; "
3171 "var obj3 = {}; "
3172 "obj3[1] = function() {}; "
3173 "var obj4 = {}; "
3174 "obj4[1] = function foo8() {}; "
3175 "var obj5 = {}; "
3176 "obj5['foo9'] = function() {}; "
3177 "var obj6 = { obj7 : { foo10: function() {} } };");
3178 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
3179 // foo2 is not unnamed -> its name is not inferred.
3180 ExpectString("%FunctionGetInferredName(foo2)", "");
3181 ExpectString("not_ctor()", "foo4");
3182 ExpectString("Ctor()", "Ctor.foo5");
3183 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
3184 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
3185 ExpectString("%FunctionGetInferredName(obj3[1])",
3186 "obj3.(anonymous function)");
3187 ExpectString("%FunctionGetInferredName(obj4[1])", "");
3188 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
3189 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
3190}
3191
3192
3193TEST(FuncNameInferrerTwoByte) {
3194 // Tests function name inferring in cases where some parts of the inferred
3195 // function name are two-byte strings.
3196 i::FLAG_allow_natives_syntax = true;
3197 v8::Isolate* isolate = CcTest::isolate();
3198 v8::HandleScope scope(isolate);
3199 LocalContext env;
3200 uint16_t* two_byte_source = AsciiToTwoByteString(
3201 "var obj1 = { oXj2 : { foo1: function() {} } }; "
3202 "%FunctionGetInferredName(obj1.oXj2.foo1)");
3203 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3204 // Make it really non-Latin1 (replace the Xs with a non-Latin1 character).
3205 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
3206 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003207 v8::String::NewFromTwoByte(isolate, two_byte_source,
3208 v8::NewStringType::kNormal)
3209 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003210 v8::Local<v8::Value> result = CompileRun(source);
3211 CHECK(result->IsString());
3212 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003213 v8::String::NewFromTwoByte(isolate, two_byte_name,
3214 v8::NewStringType::kNormal)
3215 .ToLocalChecked();
3216 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003217 i::DeleteArray(two_byte_source);
3218 i::DeleteArray(two_byte_name);
3219}
3220
3221
3222TEST(FuncNameInferrerEscaped) {
3223 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
3224 // character as a unicode escape.
3225 i::FLAG_allow_natives_syntax = true;
3226 v8::Isolate* isolate = CcTest::isolate();
3227 v8::HandleScope scope(isolate);
3228 LocalContext env;
3229 uint16_t* two_byte_source = AsciiToTwoByteString(
3230 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
3231 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
3232 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
3233 // Fix to correspond to the non-ASCII name in two_byte_source.
3234 two_byte_name[6] = 0x010d;
3235 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003236 v8::String::NewFromTwoByte(isolate, two_byte_source,
3237 v8::NewStringType::kNormal)
3238 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003239 v8::Local<v8::Value> result = CompileRun(source);
3240 CHECK(result->IsString());
3241 v8::Local<v8::String> expected_name =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003242 v8::String::NewFromTwoByte(isolate, two_byte_name,
3243 v8::NewStringType::kNormal)
3244 .ToLocalChecked();
3245 CHECK(result->Equals(isolate->GetCurrentContext(), expected_name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003246 i::DeleteArray(two_byte_source);
3247 i::DeleteArray(two_byte_name);
3248}
3249
3250
3251TEST(RegressionLazyFunctionWithErrorWithArg) {
Ben Murdochda12d292016-06-02 14:46:10 +01003252 // Test only applies when lazy parsing.
3253 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
3254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003255 // The bug occurred when a lazy function had an error which requires a
3256 // parameter (such as "unknown label" here). The error message was processed
3257 // before the AstValueFactory containing the error message string was
3258 // internalized.
3259 v8::Isolate* isolate = CcTest::isolate();
3260 v8::HandleScope scope(isolate);
3261 LocalContext env;
3262 i::FLAG_lazy = true;
3263 i::FLAG_min_preparse_length = 0;
3264 CompileRun("function this_is_lazy() {\n"
3265 " break p;\n"
3266 "}\n"
3267 "this_is_lazy();\n");
3268}
3269
3270
3271TEST(SerializationOfMaybeAssignmentFlag) {
3272 i::Isolate* isolate = CcTest::i_isolate();
3273 i::Factory* factory = isolate->factory();
3274 i::HandleScope scope(isolate);
3275 LocalContext env;
3276
3277 const char* src =
3278 "function h() {"
3279 " var result = [];"
3280 " function f() {"
3281 " result.push(2);"
3282 " }"
3283 " function assertResult(r) {"
3284 " f();"
3285 " result = [];"
3286 " }"
3287 " assertResult([2]);"
3288 " assertResult([2]);"
3289 " return f;"
3290 "};"
3291 "h();";
3292
3293 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3294 i::SNPrintF(program, "%s", src);
3295 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3296 source->PrintOn(stdout);
3297 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003298 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003299 v8::Local<v8::Value> v = CompileRun(src);
3300 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3301 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3302 i::Context* context = f->context();
3303 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3304 avf.Internalize(isolate);
3305 const i::AstRawString* name = avf.GetOneByteString("result");
3306 i::Handle<i::String> str = name->string();
3307 CHECK(str->IsInternalizedString());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003308 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003309 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003310 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003311 i::Scope* s =
3312 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3313 CHECK(s != script_scope);
3314 CHECK(name != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003315
3316 // Get result from h's function context (that is f's context)
3317 i::Variable* var = s->Lookup(name);
3318
3319 CHECK(var != NULL);
3320 // Maybe assigned should survive deserialization
3321 CHECK(var->maybe_assigned() == i::kMaybeAssigned);
3322 // TODO(sigurds) Figure out if is_used should survive context serialization.
3323}
3324
3325
3326TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) {
3327 i::Isolate* isolate = CcTest::i_isolate();
3328 i::Factory* factory = isolate->factory();
3329 i::HandleScope scope(isolate);
3330 LocalContext env;
3331
3332
3333 const char* src =
3334 "function f(x) {"
3335 " var a = arguments;"
3336 " function g(i) {"
3337 " ++a[0];"
3338 " };"
3339 " return g;"
3340 " }"
3341 "f(0);";
3342
3343 i::ScopedVector<char> program(Utf8LengthHelper(src) + 1);
3344 i::SNPrintF(program, "%s", src);
3345 i::Handle<i::String> source = factory->InternalizeUtf8String(program.start());
3346 source->PrintOn(stdout);
3347 printf("\n");
Ben Murdochda12d292016-06-02 14:46:10 +01003348 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003349 v8::Local<v8::Value> v = CompileRun(src);
3350 i::Handle<i::Object> o = v8::Utils::OpenHandle(*v);
3351 i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
3352 i::Context* context = f->context();
3353 i::AstValueFactory avf(&zone, isolate->heap()->HashSeed());
3354 avf.Internalize(isolate);
3355
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003356 i::Scope* script_scope =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003357 new (&zone) i::Scope(&zone, NULL, i::SCRIPT_SCOPE, &avf);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003358 script_scope->Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003359 i::Scope* s =
3360 i::Scope::DeserializeScopeChain(isolate, &zone, context, script_scope);
3361 CHECK(s != script_scope);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003362 const i::AstRawString* name_x = avf.GetOneByteString("x");
3363
3364 // Get result from f's function context (that is g's outer context)
3365 i::Variable* var_x = s->Lookup(name_x);
3366 CHECK(var_x != NULL);
3367 CHECK(var_x->maybe_assigned() == i::kMaybeAssigned);
3368}
3369
3370
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003371TEST(InnerAssignment) {
3372 i::Isolate* isolate = CcTest::i_isolate();
3373 i::Factory* factory = isolate->factory();
3374 i::HandleScope scope(isolate);
3375 LocalContext env;
3376
3377 const char* prefix = "function f() {";
3378 const char* midfix = " function g() {";
3379 const char* suffix = "}}";
3380 struct { const char* source; bool assigned; bool strict; } outers[] = {
3381 // Actual assignments.
3382 { "var x; var x = 5;", true, false },
3383 { "var x; { var x = 5; }", true, false },
3384 { "'use strict'; let x; x = 6;", true, true },
3385 { "var x = 5; function x() {}", true, false },
3386 // Actual non-assignments.
3387 { "var x;", false, false },
3388 { "var x = 5;", false, false },
3389 { "'use strict'; let x;", false, true },
3390 { "'use strict'; let x = 6;", false, true },
3391 { "'use strict'; var x = 0; { let x = 6; }", false, true },
3392 { "'use strict'; var x = 0; { let x; x = 6; }", false, true },
3393 { "'use strict'; let x = 0; { let x = 6; }", false, true },
3394 { "'use strict'; let x = 0; { let x; x = 6; }", false, true },
3395 { "var x; try {} catch (x) { x = 5; }", false, false },
3396 { "function x() {}", false, false },
3397 // Eval approximation.
3398 { "var x; eval('');", true, false },
3399 { "eval(''); var x;", true, false },
3400 { "'use strict'; let x; eval('');", true, true },
3401 { "'use strict'; eval(''); let x;", true, true },
3402 // Non-assignments not recognized, because the analysis is approximative.
3403 { "var x; var x;", true, false },
3404 { "var x = 5; var x;", true, false },
3405 { "var x; { var x; }", true, false },
3406 { "var x; function x() {}", true, false },
3407 { "function x() {}; var x;", true, false },
3408 { "var x; try {} catch (x) { var x = 5; }", true, false },
3409 };
3410 struct { const char* source; bool assigned; bool with; } inners[] = {
3411 // Actual assignments.
3412 { "x = 1;", true, false },
3413 { "x++;", true, false },
3414 { "++x;", true, false },
3415 { "x--;", true, false },
3416 { "--x;", true, false },
3417 { "{ x = 1; }", true, false },
3418 { "'use strict'; { let x; }; x = 0;", true, false },
3419 { "'use strict'; { const x = 1; }; x = 0;", true, false },
3420 { "'use strict'; { function x() {} }; x = 0;", true, false },
3421 { "with ({}) { x = 1; }", true, true },
3422 { "eval('');", true, false },
3423 { "'use strict'; { let y; eval('') }", true, false },
3424 { "function h() { x = 0; }", true, false },
3425 { "(function() { x = 0; })", true, false },
3426 { "(function() { x = 0; })", true, false },
3427 { "with ({}) (function() { x = 0; })", true, true },
3428 // Actual non-assignments.
3429 { "", false, false },
3430 { "x;", false, false },
3431 { "var x;", false, false },
3432 { "var x = 8;", false, false },
3433 { "var x; x = 8;", false, false },
3434 { "'use strict'; let x;", false, false },
3435 { "'use strict'; let x = 8;", false, false },
3436 { "'use strict'; let x; x = 8;", false, false },
3437 { "'use strict'; const x = 8;", false, false },
3438 { "function x() {}", false, false },
3439 { "function x() { x = 0; }", false, false },
3440 { "function h(x) { x = 0; }", false, false },
3441 { "'use strict'; { let x; x = 0; }", false, false },
3442 { "{ var x; }; x = 0;", false, false },
3443 { "with ({}) {}", false, true },
3444 { "var x; { with ({}) { x = 1; } }", false, true },
3445 { "try {} catch(x) { x = 0; }", false, false },
3446 { "try {} catch(x) { with ({}) { x = 1; } }", false, true },
3447 // Eval approximation.
3448 { "eval('');", true, false },
3449 { "function h() { eval(''); }", true, false },
3450 { "(function() { eval(''); })", true, false },
3451 // Shadowing not recognized because of eval approximation.
3452 { "var x; eval('');", true, false },
3453 { "'use strict'; let x; eval('');", true, false },
3454 { "try {} catch(x) { eval(''); }", true, false },
3455 { "function x() { eval(''); }", true, false },
3456 { "(function(x) { eval(''); })", true, false },
3457 };
3458
3459 // Used to trigger lazy compilation of function
3460 int comment_len = 2048;
3461 i::ScopedVector<char> comment(comment_len + 1);
3462 i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0);
3463 int prefix_len = Utf8LengthHelper(prefix);
3464 int midfix_len = Utf8LengthHelper(midfix);
3465 int suffix_len = Utf8LengthHelper(suffix);
3466 for (unsigned i = 0; i < arraysize(outers); ++i) {
3467 const char* outer = outers[i].source;
3468 int outer_len = Utf8LengthHelper(outer);
3469 for (unsigned j = 0; j < arraysize(inners); ++j) {
3470 for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) {
3471 for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) {
3472 if (outers[i].strict && inners[j].with) continue;
3473 const char* inner = inners[j].source;
3474 int inner_len = Utf8LengthHelper(inner);
3475
3476 int outer_comment_len = outer_lazy ? comment_len : 0;
3477 int inner_comment_len = inner_lazy ? comment_len : 0;
3478 const char* outer_comment = outer_lazy ? comment.start() : "";
3479 const char* inner_comment = inner_lazy ? comment.start() : "";
3480 int len = prefix_len + outer_comment_len + outer_len + midfix_len +
3481 inner_comment_len + inner_len + suffix_len;
3482 i::ScopedVector<char> program(len + 1);
3483
3484 i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer,
3485 midfix, inner_comment, inner, suffix);
3486 i::Handle<i::String> source =
3487 factory->InternalizeUtf8String(program.start());
3488 source->PrintOn(stdout);
3489 printf("\n");
3490
3491 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01003492 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003493 i::ParseInfo info(&zone, script);
3494 i::Parser parser(&info);
3495 CHECK(parser.Parse(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003496 CHECK(i::Compiler::Analyze(&info));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003497 CHECK(info.literal() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003498
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003499 i::Scope* scope = info.literal()->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003500 CHECK_EQ(scope->inner_scopes()->length(), 1);
3501 i::Scope* inner_scope = scope->inner_scopes()->at(0);
3502 const i::AstRawString* var_name =
3503 info.ast_value_factory()->GetOneByteString("x");
3504 i::Variable* var = inner_scope->Lookup(var_name);
3505 bool expected = outers[i].assigned || inners[j].assigned;
3506 CHECK(var != NULL);
3507 CHECK(var->is_used() || !expected);
3508 CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected);
3509 }
3510 }
3511 }
3512 }
3513}
3514
3515namespace {
3516
3517int* global_use_counts = NULL;
3518
3519void MockUseCounterCallback(v8::Isolate* isolate,
3520 v8::Isolate::UseCounterFeature feature) {
3521 ++global_use_counts[feature];
3522}
3523
3524}
3525
3526
3527TEST(UseAsmUseCount) {
3528 i::Isolate* isolate = CcTest::i_isolate();
3529 i::HandleScope scope(isolate);
3530 LocalContext env;
3531 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3532 global_use_counts = use_counts;
3533 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3534 CompileRun("\"use asm\";\n"
3535 "var foo = 1;\n"
3536 "\"use asm\";\n" // Only the first one counts.
3537 "function bar() { \"use asm\"; var baz = 1; }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003538 // Optimizing will double-count because the source is parsed twice.
3539 CHECK_EQ(i::FLAG_always_opt ? 4 : 2, use_counts[v8::Isolate::kUseAsm]);
3540}
3541
3542
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003543TEST(StrictModeUseCount) {
3544 i::Isolate* isolate = CcTest::i_isolate();
3545 i::HandleScope scope(isolate);
3546 LocalContext env;
3547 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3548 global_use_counts = use_counts;
3549 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3550 CompileRun(
3551 "\"use strict\";\n"
3552 "function bar() { var baz = 1; }"); // strict mode inherits
3553 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3554 CHECK_EQ(0, use_counts[v8::Isolate::kSloppyMode]);
3555}
3556
3557
3558TEST(SloppyModeUseCount) {
3559 i::Isolate* isolate = CcTest::i_isolate();
3560 i::HandleScope scope(isolate);
3561 LocalContext env;
3562 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3563 global_use_counts = use_counts;
3564 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3565 CompileRun("function bar() { var baz = 1; }");
3566 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3567 CHECK_EQ(0, use_counts[v8::Isolate::kStrictMode]);
3568}
3569
3570
3571TEST(BothModesUseCount) {
3572 i::Isolate* isolate = CcTest::i_isolate();
3573 i::HandleScope scope(isolate);
3574 LocalContext env;
3575 int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
3576 global_use_counts = use_counts;
3577 CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
3578 CompileRun("function bar() { 'use strict'; var baz = 1; }");
3579 CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]);
3580 CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
3581}
3582
3583
3584TEST(ErrorsArrowFormalParameters) {
3585 const char* context_data[][2] = {
3586 { "()", "=>{}" },
3587 { "()", "=>{};" },
3588 { "var x = ()", "=>{}" },
3589 { "var x = ()", "=>{};" },
3590
3591 { "a", "=>{}" },
3592 { "a", "=>{};" },
3593 { "var x = a", "=>{}" },
3594 { "var x = a", "=>{};" },
3595
3596 { "(a)", "=>{}" },
3597 { "(a)", "=>{};" },
3598 { "var x = (a)", "=>{}" },
3599 { "var x = (a)", "=>{};" },
3600
3601 { "(...a)", "=>{}" },
3602 { "(...a)", "=>{};" },
3603 { "var x = (...a)", "=>{}" },
3604 { "var x = (...a)", "=>{};" },
3605
3606 { "(a,b)", "=>{}" },
3607 { "(a,b)", "=>{};" },
3608 { "var x = (a,b)", "=>{}" },
3609 { "var x = (a,b)", "=>{};" },
3610
3611 { "(a,...b)", "=>{}" },
3612 { "(a,...b)", "=>{};" },
3613 { "var x = (a,...b)", "=>{}" },
3614 { "var x = (a,...b)", "=>{};" },
3615
3616 { nullptr, nullptr }
3617 };
3618 const char* assignment_expression_suffix_data[] = {
3619 "?c:d=>{}",
3620 "=c=>{}",
3621 "()",
3622 "(c)",
3623 "[1]",
3624 "[c]",
3625 ".c",
3626 "-c",
3627 "+c",
3628 "c++",
3629 "`c`",
3630 "`${c}`",
3631 "`template-head${c}`",
3632 "`${c}template-tail`",
3633 "`template-head${c}template-tail`",
3634 "`${c}template-tail`",
3635 nullptr
3636 };
3637
3638 RunParserSyncTest(context_data, assignment_expression_suffix_data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003639}
3640
3641
3642TEST(ErrorsArrowFunctions) {
3643 // Tests that parser and preparser generate the same kind of errors
3644 // on invalid arrow function syntax.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003645
3646 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003647 const char* context_data[][2] = {
3648 {"", ";"},
3649 {"v = ", ";"},
3650 {"bar ? (", ") : baz;"},
3651 {"bar ? baz : (", ");"},
3652 {"bar[", "];"},
3653 {"bar, ", ";"},
3654 {"", ", bar;"},
3655 {NULL, NULL}
3656 };
3657
3658 const char* statement_data[] = {
3659 "=> 0",
3660 "=>",
3661 "() =>",
3662 "=> {}",
3663 ") => {}",
3664 ", => {}",
3665 "(,) => {}",
3666 "return => {}",
3667 "() => {'value': 42}",
3668
3669 // Check that the early return introduced in ParsePrimaryExpression
3670 // does not accept stray closing parentheses.
3671 ")",
3672 ") => 0",
3673 "foo[()]",
3674 "()",
3675
3676 // Parameter lists with extra parens should be recognized as errors.
3677 "(()) => 0",
3678 "((x)) => 0",
3679 "((x, y)) => 0",
3680 "(x, (y)) => 0",
3681 "((x, y, z)) => 0",
3682 "(x, (y, z)) => 0",
3683 "((x, y), z) => 0",
3684
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003685 // Arrow function formal parameters are parsed as StrictFormalParameters,
3686 // which confusingly only implies that there are no duplicates. Words
3687 // reserved in strict mode, and eval or arguments, are indeed valid in
3688 // sloppy mode.
3689 "eval => { 'use strict'; 0 }",
3690 "arguments => { 'use strict'; 0 }",
3691 "yield => { 'use strict'; 0 }",
3692 "interface => { 'use strict'; 0 }",
3693 "(eval) => { 'use strict'; 0 }",
3694 "(arguments) => { 'use strict'; 0 }",
3695 "(yield) => { 'use strict'; 0 }",
3696 "(interface) => { 'use strict'; 0 }",
3697 "(eval, bar) => { 'use strict'; 0 }",
3698 "(bar, eval) => { 'use strict'; 0 }",
3699 "(bar, arguments) => { 'use strict'; 0 }",
3700 "(bar, yield) => { 'use strict'; 0 }",
3701 "(bar, interface) => { 'use strict'; 0 }",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003702 // TODO(aperez): Detecting duplicates does not work in PreParser.
3703 // "(bar, bar) => {}",
3704
3705 // The parameter list is parsed as an expression, but only
3706 // a comma-separated list of identifier is valid.
3707 "32 => {}",
3708 "(32) => {}",
3709 "(a, 32) => {}",
3710 "if => {}",
3711 "(if) => {}",
3712 "(a, if) => {}",
3713 "a + b => {}",
3714 "(a + b) => {}",
3715 "(a + b, c) => {}",
3716 "(a, b - c) => {}",
3717 "\"a\" => {}",
3718 "(\"a\") => {}",
3719 "(\"a\", b) => {}",
3720 "(a, \"b\") => {}",
3721 "-a => {}",
3722 "(-a) => {}",
3723 "(-a, b) => {}",
3724 "(a, -b) => {}",
3725 "{} => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003726 "a++ => {}",
3727 "(a++) => {}",
3728 "(a++, b) => {}",
3729 "(a, b++) => {}",
3730 "[] => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003731 "(foo ? bar : baz) => {}",
3732 "(a, foo ? bar : baz) => {}",
3733 "(foo ? bar : baz, a) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003734 "(a.b, c) => {}",
3735 "(c, a.b) => {}",
3736 "(a['b'], c) => {}",
3737 "(c, a['b']) => {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01003738
3739 // crbug.com/582626
3740 "(...rest - a) => b",
3741 "(a, ...b - 10) => b",
3742
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003743 NULL
3744 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01003745 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003746
3747 // The test is quite slow, so run it with a reduced set of flags.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003748 static const ParserFlag flags[] = {kAllowLazy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003749 RunParserSyncTest(context_data, statement_data, kError, flags,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003750 arraysize(flags));
3751
3752 // In a context where a concise arrow body is parsed with [~In] variant,
3753 // ensure that an error is reported in both full parser and preparser.
3754 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3755 {nullptr, nullptr}};
3756 const char* loop_expr_data[] = {"f => 'key' in {}", nullptr};
3757 RunParserSyncTest(loop_context_data, loop_expr_data, kError, flags,
3758 arraysize(flags));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003759}
3760
3761
3762TEST(NoErrorsArrowFunctions) {
3763 // Tests that parser and preparser accept valid arrow functions syntax.
Ben Murdochda12d292016-06-02 14:46:10 +01003764 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003765 const char* context_data[][2] = {
3766 {"", ";"},
3767 {"bar ? (", ") : baz;"},
3768 {"bar ? baz : (", ");"},
3769 {"bar, ", ";"},
3770 {"", ", bar;"},
3771 {NULL, NULL}
3772 };
3773
3774 const char* statement_data[] = {
3775 "() => {}",
3776 "() => { return 42 }",
3777 "x => { return x; }",
3778 "(x) => { return x; }",
3779 "(x, y) => { return x + y; }",
3780 "(x, y, z) => { return x + y + z; }",
3781 "(x, y) => { x.a = y; }",
3782 "() => 42",
3783 "x => x",
3784 "x => x * x",
3785 "(x) => x",
3786 "(x) => x * x",
3787 "(x, y) => x + y",
3788 "(x, y, z) => x, y, z",
3789 "(x, y) => x.a = y",
3790 "() => ({'value': 42})",
3791 "x => y => x + y",
3792 "(x, y) => (u, v) => x*u + y*v",
3793 "(x, y) => z => z * (x + y)",
3794 "x => (y, z) => z * (x + y)",
3795
3796 // Those are comma-separated expressions, with arrow functions as items.
3797 // They stress the code for validating arrow function parameter lists.
3798 "a, b => 0",
3799 "a, b, (c, d) => 0",
3800 "(a, b, (c, d) => 0)",
3801 "(a, b) => 0, (c, d) => 1",
3802 "(a, b => {}, a => a + 1)",
3803 "((a, b) => {}, (a => a + 1))",
3804 "(a, (a, (b, c) => 0))",
3805
3806 // Arrow has more precedence, this is the same as: foo ? bar : (baz = {})
3807 "foo ? bar : baz => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003808
3809 // Arrows with non-simple parameters.
Ben Murdochda12d292016-06-02 14:46:10 +01003810 "({}) => {}",
3811 "(a, {}) => {}",
3812 "({}, a) => {}",
3813 "([]) => {}",
3814 "(a, []) => {}",
3815 "([], a) => {}",
3816 "(a = b) => {}",
3817 "(a = b, c) => {}",
3818 "(a, b = c) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003819 "({a}) => {}",
3820 "(x = 9) => {}",
3821 "(x, y = 9) => {}",
3822 "(x = 9, y) => {}",
3823 "(x, y = 9, z) => {}",
3824 "(x, y = 9, z = 8) => {}",
3825 "(...a) => {}",
3826 "(x, ...a) => {}",
3827 "(x = 9, ...a) => {}",
3828 "(x, y = 9, ...a) => {}",
3829 "(x, y = 9, {b}, z = 8, ...a) => {}",
Ben Murdochda12d292016-06-02 14:46:10 +01003830 "({a} = {}) => {}",
3831 "([x] = []) => {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003832 "({a = 42}) => {}",
3833 "([x = 0]) => {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003834 NULL
3835 };
Ben Murdochda12d292016-06-02 14:46:10 +01003836 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003837
Ben Murdochda12d292016-06-02 14:46:10 +01003838 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003839
3840 static const ParserFlag flags[] = {kAllowLazy};
3841 // In a context where a concise arrow body is parsed with [~In] variant,
3842 // ensure that nested expressions can still use the 'in' operator,
3843 const char* loop_context_data[][2] = {{"for (", "; 0;);"},
3844 {nullptr, nullptr}};
3845 const char* loop_expr_data[] = {"f => ('key' in {})", nullptr};
3846 RunParserSyncTest(loop_context_data, loop_expr_data, kSuccess, flags,
3847 arraysize(flags));
3848}
3849
3850
3851TEST(ArrowFunctionsSloppyParameterNames) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003852 const char* strict_context_data[][2] = {
3853 {"'use strict'; ", ";"},
3854 {"'use strict'; bar ? (", ") : baz;"},
3855 {"'use strict'; bar ? baz : (", ");"},
3856 {"'use strict'; bar, ", ";"},
3857 {"'use strict'; ", ", bar;"},
3858 {NULL, NULL}
3859 };
3860
3861 const char* sloppy_context_data[][2] = {
3862 {"", ";"},
3863 {"bar ? (", ") : baz;"},
3864 {"bar ? baz : (", ");"},
3865 {"bar, ", ";"},
3866 {"", ", bar;"},
3867 {NULL, NULL}
3868 };
3869
3870 const char* statement_data[] = {
3871 "eval => {}",
3872 "arguments => {}",
3873 "yield => {}",
3874 "interface => {}",
3875 "(eval) => {}",
3876 "(arguments) => {}",
3877 "(yield) => {}",
3878 "(interface) => {}",
3879 "(eval, bar) => {}",
3880 "(bar, eval) => {}",
3881 "(bar, arguments) => {}",
3882 "(bar, yield) => {}",
3883 "(bar, interface) => {}",
3884 "(interface, eval) => {}",
3885 "(interface, arguments) => {}",
3886 "(eval, interface) => {}",
3887 "(arguments, interface) => {}",
3888 NULL
3889 };
3890
Ben Murdochda12d292016-06-02 14:46:10 +01003891 RunParserSyncTest(strict_context_data, statement_data, kError);
3892 RunParserSyncTest(sloppy_context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003893}
3894
3895
3896TEST(ArrowFunctionsYieldParameterNameInGenerator) {
3897 const char* sloppy_function_context_data[][2] = {
3898 {"(function f() { (", "); });"},
3899 {NULL, NULL}
3900 };
3901
3902 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003903 {"(function f() {'use strict'; (", "); });"},
3904 {NULL, NULL}
3905 };
3906
3907 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003908 {"(function *g() {'use strict'; (", "); });"},
3909 {"(function *g() { (", "); });"},
3910 {NULL, NULL}
3911 };
3912
3913 const char* arrow_data[] = {
3914 "yield => {}",
3915 "(yield) => {}",
3916 "(a, yield) => {}",
3917 "(yield, a) => {}",
3918 "(yield, ...a) => {}",
3919 "(a, ...yield) => {}",
3920 "({yield}) => {}",
3921 "([yield]) => {}",
3922 NULL
3923 };
3924
Ben Murdochda12d292016-06-02 14:46:10 +01003925 RunParserSyncTest(sloppy_function_context_data, arrow_data, kSuccess);
3926 RunParserSyncTest(strict_function_context_data, arrow_data, kError);
3927 RunParserSyncTest(generator_context_data, arrow_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003928}
3929
3930
3931TEST(SuperNoErrors) {
3932 // Tests that parser and preparser accept 'super' keyword in right places.
3933 const char* context_data[][2] = {
3934 {"class C { m() { ", "; } }"},
3935 {"class C { m() { k = ", "; } }"},
3936 {"class C { m() { foo(", "); } }"},
3937 {"class C { m() { () => ", "; } }"},
3938 {NULL, NULL}
3939 };
3940
3941 const char* statement_data[] = {
3942 "super.x",
3943 "super[27]",
3944 "new super.x",
3945 "new super.x()",
3946 "new super[27]",
3947 "new super[27]()",
3948 "z.super", // Ok, property lookup.
3949 NULL
3950 };
3951
3952 static const ParserFlag always_flags[] = {
3953 kAllowHarmonySloppy
3954 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003955 RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
3956 always_flags, arraysize(always_flags));
3957}
3958
3959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003960TEST(SuperErrors) {
3961 const char* context_data[][2] = {
3962 {"class C { m() { ", "; } }"},
3963 {"class C { m() { k = ", "; } }"},
3964 {"class C { m() { foo(", "); } }"},
3965 {"class C { m() { () => ", "; } }"},
3966 {NULL, NULL}
3967 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003968
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003969 const char* expression_data[] = {
3970 "super",
3971 "super = x",
3972 "y = super",
3973 "f(super)",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003974 "new super",
3975 "new super()",
3976 "new super(12, 45)",
3977 "new new super",
3978 "new new super()",
3979 "new new super()()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003980 NULL
3981 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003982
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003983 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
3984 RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003985 always_flags, arraysize(always_flags));
3986}
3987
3988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003989TEST(SuperCall) {
3990 const char* context_data[][2] = {{"", ""},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003991 {NULL, NULL}};
3992
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003993 const char* success_data[] = {
3994 "class C extends B { constructor() { super(); } }",
3995 "class C extends B { constructor() { () => super(); } }",
3996 NULL
3997 };
3998
3999 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4000 RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
4001 always_flags, arraysize(always_flags));
4002
4003 const char* error_data[] = {
4004 "class C { constructor() { super(); } }",
4005 "class C { method() { super(); } }",
4006 "class C { method() { () => super(); } }",
4007 "class C { *method() { super(); } }",
4008 "class C { get x() { super(); } }",
4009 "class C { set x(_) { super(); } }",
4010 "({ method() { super(); } })",
4011 "({ *method() { super(); } })",
4012 "({ get x() { super(); } })",
4013 "({ set x(_) { super(); } })",
4014 "({ f: function() { super(); } })",
4015 "(function() { super(); })",
4016 "var f = function() { super(); }",
4017 "({ f: function*() { super(); } })",
4018 "(function*() { super(); })",
4019 "var f = function*() { super(); }",
4020 NULL
4021 };
4022
4023 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
4024 always_flags, arraysize(always_flags));
4025}
4026
4027
4028TEST(SuperNewNoErrors) {
4029 const char* context_data[][2] = {
4030 {"class C { constructor() { ", " } }"},
4031 {"class C { *method() { ", " } }"},
4032 {"class C { get x() { ", " } }"},
4033 {"class C { set x(_) { ", " } }"},
4034 {"({ method() { ", " } })"},
4035 {"({ *method() { ", " } })"},
4036 {"({ get x() { ", " } })"},
4037 {"({ set x(_) { ", " } })"},
4038 {NULL, NULL}
4039 };
4040
4041 const char* expression_data[] = {
4042 "new super.x;",
4043 "new super.x();",
4044 "() => new super.x;",
4045 "() => new super.x();",
4046 NULL
4047 };
4048
4049 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4050 RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
4051 always_flags, arraysize(always_flags));
4052}
4053
4054
4055TEST(SuperNewErrors) {
4056 const char* context_data[][2] = {
4057 {"class C { method() { ", " } }"},
4058 {"class C { *method() { ", " } }"},
4059 {"class C { get x() { ", " } }"},
4060 {"class C { set x(_) { ", " } }"},
4061 {"({ method() { ", " } })"},
4062 {"({ *method() { ", " } })"},
4063 {"({ get x() { ", " } })"},
4064 {"({ set x(_) { ", " } })"},
4065 {"({ f: function() { ", " } })"},
4066 {"(function() { ", " })"},
4067 {"var f = function() { ", " }"},
4068 {"({ f: function*() { ", " } })"},
4069 {"(function*() { ", " })"},
4070 {"var f = function*() { ", " }"},
4071 {NULL, NULL}
4072 };
4073
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004074 const char* statement_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004075 "new super;",
4076 "new super();",
4077 "() => new super;",
4078 "() => new super();",
4079 NULL
4080 };
4081
4082 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4083 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4084 always_flags, arraysize(always_flags));
4085}
4086
4087
4088TEST(SuperErrorsNonMethods) {
4089 // super is only allowed in methods, accessors and constructors.
4090 const char* context_data[][2] = {
4091 {"", ";"},
4092 {"k = ", ";"},
4093 {"foo(", ");"},
4094 {"if (", ") {}"},
4095 {"if (true) {", "}"},
4096 {"if (false) {} else {", "}"},
4097 {"while (true) {", "}"},
4098 {"function f() {", "}"},
4099 {"class C extends (", ") {}"},
4100 {"class C { m() { function f() {", "} } }"},
4101 {"({ m() { function f() {", "} } })"},
4102 {NULL, NULL}
4103 };
4104
4105 const char* statement_data[] = {
4106 "super",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004107 "super = x",
4108 "y = super",
4109 "f(super)",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004110 "super.x",
4111 "super[27]",
4112 "super.x()",
4113 "super[27]()",
4114 "super()",
4115 "new super.x",
4116 "new super.x()",
4117 "new super[27]",
4118 "new super[27]()",
4119 NULL
4120 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004121
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004122 static const ParserFlag always_flags[] = {
4123 kAllowHarmonySloppy
4124 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004125 RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
4126 always_flags, arraysize(always_flags));
4127}
4128
4129
4130TEST(NoErrorsMethodDefinition) {
4131 const char* context_data[][2] = {{"({", "});"},
4132 {"'use strict'; ({", "});"},
4133 {"({*", "});"},
4134 {"'use strict'; ({*", "});"},
4135 {NULL, NULL}};
4136
4137 const char* object_literal_body_data[] = {
4138 "m() {}",
4139 "m(x) { return x; }",
4140 "m(x, y) {}, n() {}",
4141 "set(x, y) {}",
4142 "get(x, y) {}",
4143 NULL
4144 };
4145
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004146 RunParserSyncTest(context_data, object_literal_body_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004147}
4148
4149
4150TEST(MethodDefinitionNames) {
4151 const char* context_data[][2] = {{"({", "(x, y) {}});"},
4152 {"'use strict'; ({", "(x, y) {}});"},
4153 {"({*", "(x, y) {}});"},
4154 {"'use strict'; ({*", "(x, y) {}});"},
4155 {NULL, NULL}};
4156
4157 const char* name_data[] = {
4158 "m",
4159 "'m'",
4160 "\"m\"",
4161 "\"m n\"",
4162 "true",
4163 "false",
4164 "null",
4165 "0",
4166 "1.2",
4167 "1e1",
4168 "1E1",
4169 "1e+1",
4170 "1e-1",
4171
4172 // Keywords
4173 "async",
4174 "await",
4175 "break",
4176 "case",
4177 "catch",
4178 "class",
4179 "const",
4180 "continue",
4181 "debugger",
4182 "default",
4183 "delete",
4184 "do",
4185 "else",
4186 "enum",
4187 "export",
4188 "extends",
4189 "finally",
4190 "for",
4191 "function",
4192 "if",
4193 "implements",
4194 "import",
4195 "in",
4196 "instanceof",
4197 "interface",
4198 "let",
4199 "new",
4200 "package",
4201 "private",
4202 "protected",
4203 "public",
4204 "return",
4205 "static",
4206 "super",
4207 "switch",
4208 "this",
4209 "throw",
4210 "try",
4211 "typeof",
4212 "var",
4213 "void",
4214 "while",
4215 "with",
4216 "yield",
4217 NULL
4218 };
4219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004220 RunParserSyncTest(context_data, name_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004221}
4222
4223
4224TEST(MethodDefinitionStrictFormalParamereters) {
4225 const char* context_data[][2] = {{"({method(", "){}});"},
4226 {"'use strict'; ({method(", "){}});"},
4227 {"({*method(", "){}});"},
4228 {"'use strict'; ({*method(", "){}});"},
4229 {NULL, NULL}};
4230
4231 const char* params_data[] = {
4232 "x, x",
4233 "x, y, x",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004234 "var",
4235 "const",
4236 NULL
4237 };
4238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004239 RunParserSyncTest(context_data, params_data, kError);
4240}
4241
4242
4243TEST(MethodDefinitionEvalArguments) {
4244 const char* strict_context_data[][2] =
4245 {{"'use strict'; ({method(", "){}});"},
4246 {"'use strict'; ({*method(", "){}});"},
4247 {NULL, NULL}};
4248 const char* sloppy_context_data[][2] =
4249 {{"({method(", "){}});"},
4250 {"({*method(", "){}});"},
4251 {NULL, NULL}};
4252
4253 const char* data[] = {
4254 "eval",
4255 "arguments",
4256 NULL};
4257
4258 // Fail in strict mode
4259 RunParserSyncTest(strict_context_data, data, kError);
4260
4261 // OK in sloppy mode
4262 RunParserSyncTest(sloppy_context_data, data, kSuccess);
4263}
4264
4265
4266TEST(MethodDefinitionDuplicateEvalArguments) {
4267 const char* context_data[][2] =
4268 {{"'use strict'; ({method(", "){}});"},
4269 {"'use strict'; ({*method(", "){}});"},
4270 {"({method(", "){}});"},
4271 {"({*method(", "){}});"},
4272 {NULL, NULL}};
4273
4274 const char* data[] = {
4275 "eval, eval",
4276 "eval, a, eval",
4277 "arguments, arguments",
4278 "arguments, a, arguments",
4279 NULL};
4280
4281 // In strict mode, the error is using "eval" or "arguments" as parameter names
4282 // In sloppy mode, the error is that eval / arguments are duplicated
4283 RunParserSyncTest(context_data, data, kError);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004284}
4285
4286
4287TEST(MethodDefinitionDuplicateProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004288 const char* context_data[][2] = {{"'use strict'; ({", "});"},
4289 {NULL, NULL}};
4290
4291 const char* params_data[] = {
4292 "x: 1, x() {}",
4293 "x() {}, x: 1",
4294 "x() {}, get x() {}",
4295 "x() {}, set x(_) {}",
4296 "x() {}, x() {}",
4297 "x() {}, y() {}, x() {}",
4298 "x() {}, \"x\"() {}",
4299 "x() {}, 'x'() {}",
4300 "0() {}, '0'() {}",
4301 "1.0() {}, 1: 1",
4302
4303 "x: 1, *x() {}",
4304 "*x() {}, x: 1",
4305 "*x() {}, get x() {}",
4306 "*x() {}, set x(_) {}",
4307 "*x() {}, *x() {}",
4308 "*x() {}, y() {}, *x() {}",
4309 "*x() {}, *\"x\"() {}",
4310 "*x() {}, *'x'() {}",
4311 "*0() {}, *'0'() {}",
4312 "*1.0() {}, 1: 1",
4313
4314 NULL
4315 };
4316
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004317 RunParserSyncTest(context_data, params_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004318}
4319
4320
4321TEST(ClassExpressionNoErrors) {
4322 const char* context_data[][2] = {{"(", ");"},
4323 {"var C = ", ";"},
4324 {"bar, ", ";"},
4325 {NULL, NULL}};
4326 const char* class_data[] = {
4327 "class {}",
4328 "class name {}",
4329 "class extends F {}",
4330 "class name extends F {}",
4331 "class extends (F, G) {}",
4332 "class name extends (F, G) {}",
4333 "class extends class {} {}",
4334 "class name extends class {} {}",
4335 "class extends class base {} {}",
4336 "class name extends class base {} {}",
4337 NULL};
4338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004339 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004340 RunParserSyncTest(context_data, class_data, kSuccess, NULL, 0,
4341 always_flags, arraysize(always_flags));
4342}
4343
4344
4345TEST(ClassDeclarationNoErrors) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004346 const char* context_data[][2] = {{"'use strict'; ", ""},
4347 {"'use strict'; {", "}"},
4348 {"'use strict'; if (true) {", "}"},
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004349 {NULL, NULL}};
4350 const char* statement_data[] = {
4351 "class name {}",
4352 "class name extends F {}",
4353 "class name extends (F, G) {}",
4354 "class name extends class {} {}",
4355 "class name extends class base {} {}",
4356 NULL};
4357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004358 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004359}
4360
4361
4362TEST(ClassBodyNoErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004363 // clang-format off
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004364 // Tests that parser and preparser accept valid class syntax.
4365 const char* context_data[][2] = {{"(class {", "});"},
4366 {"(class extends Base {", "});"},
4367 {"class C {", "}"},
4368 {"class C extends Base {", "}"},
4369 {NULL, NULL}};
4370 const char* class_body_data[] = {
4371 ";",
4372 ";;",
4373 "m() {}",
4374 "m() {};",
4375 "; m() {}",
4376 "m() {}; n(x) {}",
4377 "get x() {}",
4378 "set x(v) {}",
4379 "get() {}",
4380 "set() {}",
4381 "*g() {}",
4382 "*g() {};",
4383 "; *g() {}",
4384 "*g() {}; *h(x) {}",
4385 "static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004386 "get static() {}",
4387 "set static(v) {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004388 "static m() {}",
4389 "static get x() {}",
4390 "static set x(v) {}",
4391 "static get() {}",
4392 "static set() {}",
4393 "static static() {}",
4394 "static get static() {}",
4395 "static set static(v) {}",
4396 "*static() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004397 "static *static() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004398 "*get() {}",
4399 "*set() {}",
4400 "static *g() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01004401
4402 // Escaped 'static' should be allowed anywhere
4403 // static-as-PropertyName is.
4404 "st\\u0061tic() {}",
4405 "get st\\u0061tic() {}",
4406 "set st\\u0061tic(v) {}",
4407 "static st\\u0061tic() {}",
4408 "static get st\\u0061tic() {}",
4409 "static set st\\u0061tic(v) {}",
4410 "*st\\u0061tic() {}",
4411 "static *st\\u0061tic() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004412 NULL};
Ben Murdoch097c5b22016-05-18 11:27:45 +01004413 // clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004414
4415 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004416 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004417 };
4418 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4419 always_flags, arraysize(always_flags));
4420}
4421
4422
4423TEST(ClassPropertyNameNoErrors) {
4424 const char* context_data[][2] = {{"(class {", "() {}});"},
4425 {"(class { get ", "() {}});"},
4426 {"(class { set ", "(v) {}});"},
4427 {"(class { static ", "() {}});"},
4428 {"(class { static get ", "() {}});"},
4429 {"(class { static set ", "(v) {}});"},
4430 {"(class { *", "() {}});"},
4431 {"(class { static *", "() {}});"},
4432 {"class C {", "() {}}"},
4433 {"class C { get ", "() {}}"},
4434 {"class C { set ", "(v) {}}"},
4435 {"class C { static ", "() {}}"},
4436 {"class C { static get ", "() {}}"},
4437 {"class C { static set ", "(v) {}}"},
4438 {"class C { *", "() {}}"},
4439 {"class C { static *", "() {}}"},
4440 {NULL, NULL}};
4441 const char* name_data[] = {
4442 "42",
4443 "42.5",
4444 "42e2",
4445 "42e+2",
4446 "42e-2",
4447 "null",
4448 "false",
4449 "true",
4450 "'str'",
4451 "\"str\"",
4452 "static",
4453 "get",
4454 "set",
4455 "var",
4456 "const",
4457 "let",
4458 "this",
4459 "class",
4460 "function",
4461 "yield",
4462 "if",
4463 "else",
4464 "for",
4465 "while",
4466 "do",
4467 "try",
4468 "catch",
4469 "finally",
4470 NULL};
4471
4472 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004473 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004474 };
4475 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
4476 always_flags, arraysize(always_flags));
4477}
4478
4479
4480TEST(ClassExpressionErrors) {
4481 const char* context_data[][2] = {{"(", ");"},
4482 {"var C = ", ";"},
4483 {"bar, ", ";"},
4484 {NULL, NULL}};
4485 const char* class_data[] = {
4486 "class",
4487 "class name",
4488 "class name extends",
4489 "class extends",
4490 "class {",
4491 "class { m }",
4492 "class { m; n }",
4493 "class { m: 1 }",
4494 "class { m(); n() }",
4495 "class { get m }",
4496 "class { get m() }",
4497 "class { get m() { }",
4498 "class { set m() {} }", // Missing required parameter.
4499 "class { m() {}, n() {} }", // No commas allowed.
4500 NULL};
4501
4502 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004503 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004504 };
4505 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4506 always_flags, arraysize(always_flags));
4507}
4508
4509
4510TEST(ClassDeclarationErrors) {
4511 const char* context_data[][2] = {{"", ""},
4512 {"{", "}"},
4513 {"if (true) {", "}"},
4514 {NULL, NULL}};
4515 const char* class_data[] = {
4516 "class",
4517 "class name",
4518 "class name extends",
4519 "class extends",
4520 "class name {",
4521 "class name { m }",
4522 "class name { m; n }",
4523 "class name { m: 1 }",
4524 "class name { m(); n() }",
4525 "class name { get x }",
4526 "class name { get x() }",
4527 "class name { set x() {) }", // missing required param
4528 "class {}", // Name is required for declaration
4529 "class extends base {}",
4530 "class name { *",
4531 "class name { * }",
4532 "class name { *; }",
4533 "class name { *get x() {} }",
4534 "class name { *set x(_) {} }",
4535 "class name { *static m() {} }",
4536 NULL};
4537
4538 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004539 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004540 };
4541 RunParserSyncTest(context_data, class_data, kError, NULL, 0,
4542 always_flags, arraysize(always_flags));
4543}
4544
4545
4546TEST(ClassNameErrors) {
4547 const char* context_data[][2] = {{"class ", "{}"},
4548 {"(class ", "{});"},
4549 {"'use strict'; class ", "{}"},
4550 {"'use strict'; (class ", "{});"},
4551 {NULL, NULL}};
4552 const char* class_name[] = {
4553 "arguments",
4554 "eval",
4555 "implements",
4556 "interface",
4557 "let",
4558 "package",
4559 "private",
4560 "protected",
4561 "public",
4562 "static",
4563 "var",
4564 "yield",
4565 NULL};
4566
4567 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004568 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004569 };
4570 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4571 always_flags, arraysize(always_flags));
4572}
4573
4574
4575TEST(ClassGetterParamNameErrors) {
4576 const char* context_data[][2] = {
4577 {"class C { get name(", ") {} }"},
4578 {"(class { get name(", ") {} });"},
4579 {"'use strict'; class C { get name(", ") {} }"},
4580 {"'use strict'; (class { get name(", ") {} })"},
4581 {NULL, NULL}
4582 };
4583
4584 const char* class_name[] = {
4585 "arguments",
4586 "eval",
4587 "implements",
4588 "interface",
4589 "let",
4590 "package",
4591 "private",
4592 "protected",
4593 "public",
4594 "static",
4595 "var",
4596 "yield",
4597 NULL};
4598
4599 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004600 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004601 };
4602 RunParserSyncTest(context_data, class_name, kError, NULL, 0,
4603 always_flags, arraysize(always_flags));
4604}
4605
4606
4607TEST(ClassStaticPrototypeErrors) {
4608 const char* context_data[][2] = {{"class C {", "}"},
4609 {"(class {", "});"},
4610 {NULL, NULL}};
4611
4612 const char* class_body_data[] = {
4613 "static prototype() {}",
4614 "static get prototype() {}",
4615 "static set prototype(_) {}",
4616 "static *prototype() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004617 "static 'prototype'() {}",
4618 "static *'prototype'() {}",
4619 "static prot\\u006ftype() {}",
4620 "static 'prot\\u006ftype'() {}",
4621 "static get 'prot\\u006ftype'() {}",
4622 "static set 'prot\\u006ftype'(_) {}",
4623 "static *'prot\\u006ftype'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004624 NULL};
4625
4626 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004627 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004628 };
4629 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4630 always_flags, arraysize(always_flags));
4631}
4632
4633
4634TEST(ClassSpecialConstructorErrors) {
4635 const char* context_data[][2] = {{"class C {", "}"},
4636 {"(class {", "});"},
4637 {NULL, NULL}};
4638
4639 const char* class_body_data[] = {
4640 "get constructor() {}",
4641 "get constructor(_) {}",
4642 "*constructor() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004643 "get 'constructor'() {}",
4644 "*'constructor'() {}",
4645 "get c\\u006fnstructor() {}",
4646 "*c\\u006fnstructor() {}",
4647 "get 'c\\u006fnstructor'() {}",
4648 "get 'c\\u006fnstructor'(_) {}",
4649 "*'c\\u006fnstructor'() {}",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004650 NULL};
4651
4652 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004653 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004654 };
4655 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4656 always_flags, arraysize(always_flags));
4657}
4658
4659
4660TEST(ClassConstructorNoErrors) {
4661 const char* context_data[][2] = {{"class C {", "}"},
4662 {"(class {", "});"},
4663 {NULL, NULL}};
4664
4665 const char* class_body_data[] = {
4666 "constructor() {}",
4667 "static constructor() {}",
4668 "static get constructor() {}",
4669 "static set constructor(_) {}",
4670 "static *constructor() {}",
4671 NULL};
4672
4673 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004674 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004675 };
4676 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4677 always_flags, arraysize(always_flags));
4678}
4679
4680
4681TEST(ClassMultipleConstructorErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004682 const char* context_data[][2] = {{"class C {", "}"},
4683 {"(class {", "});"},
4684 {NULL, NULL}};
4685
4686 const char* class_body_data[] = {
4687 "constructor() {}; constructor() {}",
4688 NULL};
4689
4690 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004691 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004692 };
4693 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4694 always_flags, arraysize(always_flags));
4695}
4696
4697
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004698TEST(ClassMultiplePropertyNamesNoErrors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004699 const char* context_data[][2] = {{"class C {", "}"},
4700 {"(class {", "});"},
4701 {NULL, NULL}};
4702
4703 const char* class_body_data[] = {
4704 "constructor() {}; static constructor() {}",
4705 "m() {}; static m() {}",
4706 "m() {}; m() {}",
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004707 "static m() {}; static m() {}",
4708 "get m() {}; set m(_) {}; get m() {}; set m(_) {};",
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004709 NULL};
4710
4711 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004712 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004713 };
4714 RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0,
4715 always_flags, arraysize(always_flags));
4716}
4717
4718
4719TEST(ClassesAreStrictErrors) {
4720 const char* context_data[][2] = {{"", ""},
4721 {"(", ");"},
4722 {NULL, NULL}};
4723
4724 const char* class_body_data[] = {
4725 "class C { method() { with ({}) {} } }",
4726 "class C extends function() { with ({}) {} } {}",
4727 "class C { *method() { with ({}) {} } }",
4728 NULL};
4729
4730 static const ParserFlag always_flags[] = {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004731 kAllowHarmonySloppy
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004732 };
4733 RunParserSyncTest(context_data, class_body_data, kError, NULL, 0,
4734 always_flags, arraysize(always_flags));
Ben Murdoch692be652012-01-10 18:47:50 +00004735}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004736
4737
4738TEST(ObjectLiteralPropertyShorthandKeywordsError) {
4739 const char* context_data[][2] = {{"({", "});"},
4740 {"'use strict'; ({", "});"},
4741 {NULL, NULL}};
4742
4743 const char* name_data[] = {
4744 "break",
4745 "case",
4746 "catch",
4747 "class",
4748 "const",
4749 "continue",
4750 "debugger",
4751 "default",
4752 "delete",
4753 "do",
4754 "else",
4755 "enum",
4756 "export",
4757 "extends",
4758 "false",
4759 "finally",
4760 "for",
4761 "function",
4762 "if",
4763 "import",
4764 "in",
4765 "instanceof",
4766 "new",
4767 "null",
4768 "return",
4769 "super",
4770 "switch",
4771 "this",
4772 "throw",
4773 "true",
4774 "try",
4775 "typeof",
4776 "var",
4777 "void",
4778 "while",
4779 "with",
4780 NULL
4781 };
4782
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004783 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004784}
4785
4786
4787TEST(ObjectLiteralPropertyShorthandStrictKeywords) {
4788 const char* context_data[][2] = {{"({", "});"},
4789 {NULL, NULL}};
4790
4791 const char* name_data[] = {
4792 "implements",
4793 "interface",
4794 "let",
4795 "package",
4796 "private",
4797 "protected",
4798 "public",
4799 "static",
4800 "yield",
4801 NULL
4802 };
4803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004804 RunParserSyncTest(context_data, name_data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004805
4806 const char* context_strict_data[][2] = {{"'use strict'; ({", "});"},
4807 {NULL, NULL}};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004808 RunParserSyncTest(context_strict_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004809}
4810
4811
4812TEST(ObjectLiteralPropertyShorthandError) {
4813 const char* context_data[][2] = {{"({", "});"},
4814 {"'use strict'; ({", "});"},
4815 {NULL, NULL}};
4816
4817 const char* name_data[] = {
4818 "1",
4819 "1.2",
4820 "0",
4821 "0.1",
4822 "1.0",
4823 "1e1",
4824 "0x1",
4825 "\"s\"",
4826 "'s'",
4827 NULL
4828 };
4829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004830 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004831}
4832
4833
4834TEST(ObjectLiteralPropertyShorthandYieldInGeneratorError) {
4835 const char* context_data[][2] = {{"", ""},
4836 {NULL, NULL}};
4837
4838 const char* name_data[] = {
4839 "function* g() { ({yield}); }",
4840 NULL
4841 };
4842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004843 RunParserSyncTest(context_data, name_data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004844}
4845
4846
4847TEST(ConstParsingInForIn) {
4848 const char* context_data[][2] = {{"'use strict';", ""},
4849 {"function foo(){ 'use strict';", "}"},
4850 {NULL, NULL}};
4851
4852 const char* data[] = {
4853 "for(const x = 1; ; ) {}",
4854 "for(const x = 1, y = 2;;){}",
4855 "for(const x in [1,2,3]) {}",
4856 "for(const x of [1,2,3]) {}",
4857 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004858 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, nullptr, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004859}
4860
4861
Ben Murdoch097c5b22016-05-18 11:27:45 +01004862TEST(StatementParsingInForIn) {
4863 const char* context_data[][2] = {{"", ""},
4864 {"'use strict';", ""},
4865 {"function foo(){ 'use strict';", "}"},
4866 {NULL, NULL}};
4867
4868 const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
4869 "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
4870 NULL};
4871
Ben Murdochda12d292016-06-02 14:46:10 +01004872 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
4873 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01004874 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
4875 arraysize(always_flags));
4876}
4877
4878
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004879TEST(ConstParsingInForInError) {
4880 const char* context_data[][2] = {{"'use strict';", ""},
4881 {"function foo(){ 'use strict';", "}"},
4882 {NULL, NULL}};
4883
4884 const char* data[] = {
4885 "for(const x,y = 1; ; ) {}",
4886 "for(const x = 4 in [1,2,3]) {}",
4887 "for(const x = 4, y in [1,2,3]) {}",
4888 "for(const x = 4 of [1,2,3]) {}",
4889 "for(const x = 4, y of [1,2,3]) {}",
4890 "for(const x = 1, y = 2 in []) {}",
4891 "for(const x,y in []) {}",
4892 "for(const x = 1, y = 2 of []) {}",
4893 "for(const x,y of []) {}",
4894 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004895 RunParserSyncTest(context_data, data, kError, nullptr, 0, nullptr, 0);
4896}
4897
4898
4899TEST(InitializedDeclarationsInStrictForInError) {
4900 const char* context_data[][2] = {{"'use strict';", ""},
4901 {"function foo(){ 'use strict';", "}"},
4902 {NULL, NULL}};
4903
4904 const char* data[] = {
4905 "for (var i = 1 in {}) {}",
4906 "for (var i = void 0 in [1, 2, 3]) {}",
4907 "for (let i = 1 in {}) {}",
4908 "for (let i = void 0 in [1, 2, 3]) {}",
4909 "for (const i = 1 in {}) {}",
4910 "for (const i = void 0 in [1, 2, 3]) {}",
4911 NULL};
4912 RunParserSyncTest(context_data, data, kError);
4913}
4914
4915
4916TEST(InitializedDeclarationsInStrictForOfError) {
4917 const char* context_data[][2] = {{"'use strict';", ""},
4918 {"function foo(){ 'use strict';", "}"},
4919 {NULL, NULL}};
4920
4921 const char* data[] = {
4922 "for (var i = 1 of {}) {}",
4923 "for (var i = void 0 of [1, 2, 3]) {}",
4924 "for (let i = 1 of {}) {}",
4925 "for (let i = void 0 of [1, 2, 3]) {}",
4926 "for (const i = 1 of {}) {}",
4927 "for (const i = void 0 of [1, 2, 3]) {}",
4928 NULL};
4929 RunParserSyncTest(context_data, data, kError);
4930}
4931
4932
4933TEST(InitializedDeclarationsInSloppyForInError) {
4934 const char* context_data[][2] = {{"", ""},
4935 {"function foo(){", "}"},
4936 {NULL, NULL}};
4937
4938 const char* data[] = {
4939 "for (var i = 1 in {}) {}",
4940 "for (var i = void 0 in [1, 2, 3]) {}",
4941 NULL};
4942 // TODO(caitp): This should be an error in sloppy mode.
4943 RunParserSyncTest(context_data, data, kSuccess);
4944}
4945
4946
4947TEST(InitializedDeclarationsInSloppyForOfError) {
4948 const char* context_data[][2] = {{"", ""},
4949 {"function foo(){", "}"},
4950 {NULL, NULL}};
4951
4952 const char* data[] = {
4953 "for (var i = 1 of {}) {}",
4954 "for (var i = void 0 of [1, 2, 3]) {}",
4955 NULL};
4956 RunParserSyncTest(context_data, data, kError);
4957}
4958
4959
4960TEST(ForInMultipleDeclarationsError) {
4961 const char* context_data[][2] = {{"", ""},
4962 {"function foo(){", "}"},
4963 {"'use strict';", ""},
4964 {"function foo(){ 'use strict';", "}"},
4965 {NULL, NULL}};
4966
4967 const char* data[] = {
4968 "for (var i, j in {}) {}",
4969 "for (var i, j in [1, 2, 3]) {}",
4970 "for (var i, j = 1 in {}) {}",
4971 "for (var i, j = void 0 in [1, 2, 3]) {}",
4972
4973 "for (let i, j in {}) {}",
4974 "for (let i, j in [1, 2, 3]) {}",
4975 "for (let i, j = 1 in {}) {}",
4976 "for (let i, j = void 0 in [1, 2, 3]) {}",
4977
4978 "for (const i, j in {}) {}",
4979 "for (const i, j in [1, 2, 3]) {}",
4980 "for (const i, j = 1 in {}) {}",
4981 "for (const i, j = void 0 in [1, 2, 3]) {}",
4982 NULL};
4983 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
4984 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
4985 arraysize(always_flags));
4986}
4987
4988
4989TEST(ForOfMultipleDeclarationsError) {
4990 const char* context_data[][2] = {{"", ""},
4991 {"function foo(){", "}"},
4992 {"'use strict';", ""},
4993 {"function foo(){ 'use strict';", "}"},
4994 {NULL, NULL}};
4995
4996 const char* data[] = {
4997 "for (var i, j of {}) {}",
4998 "for (var i, j of [1, 2, 3]) {}",
4999 "for (var i, j = 1 of {}) {}",
5000 "for (var i, j = void 0 of [1, 2, 3]) {}",
5001
5002 "for (let i, j of {}) {}",
5003 "for (let i, j of [1, 2, 3]) {}",
5004 "for (let i, j = 1 of {}) {}",
5005 "for (let i, j = void 0 of [1, 2, 3]) {}",
5006
5007 "for (const i, j of {}) {}",
5008 "for (const i, j of [1, 2, 3]) {}",
5009 "for (const i, j = 1 of {}) {}",
5010 "for (const i, j = void 0 of [1, 2, 3]) {}",
5011 NULL};
5012 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5013 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5014 arraysize(always_flags));
5015}
5016
5017
5018TEST(ForInNoDeclarationsError) {
5019 const char* context_data[][2] = {{"", ""},
5020 {"function foo(){", "}"},
5021 {"'use strict';", ""},
5022 {"function foo(){ 'use strict';", "}"},
5023 {NULL, NULL}};
5024
5025 const char* data[] = {
5026 "for (var in {}) {}",
5027 "for (const in {}) {}",
5028 NULL};
5029 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5030 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5031 arraysize(always_flags));
5032}
5033
5034
5035TEST(ForOfNoDeclarationsError) {
5036 const char* context_data[][2] = {{"", ""},
5037 {"function foo(){", "}"},
5038 {"'use strict';", ""},
5039 {"function foo(){ 'use strict';", "}"},
5040 {NULL, NULL}};
5041
5042 const char* data[] = {
5043 "for (var of [1, 2, 3]) {}",
5044 "for (const of [1, 2, 3]) {}",
5045 NULL};
5046 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5047 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005048 arraysize(always_flags));
5049}
5050
5051
Ben Murdoch097c5b22016-05-18 11:27:45 +01005052TEST(ForOfInOperator) {
5053 const char* context_data[][2] = {{"", ""},
5054 {"'use strict';", ""},
5055 {"function foo(){ 'use strict';", "}"},
5056 {NULL, NULL}};
5057
5058 const char* data[] = {
5059 "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
5060 "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
5061
Ben Murdochda12d292016-06-02 14:46:10 +01005062 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
5063 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01005064 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5065 arraysize(always_flags));
5066}
5067
5068
5069TEST(ForOfYieldIdentifier) {
5070 const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
5071
5072 const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
5073 "for(let x of yield) {}", "for(const x of yield) {}",
5074 NULL};
5075
Ben Murdochda12d292016-06-02 14:46:10 +01005076 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
5077 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01005078 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5079 arraysize(always_flags));
5080}
5081
5082
5083TEST(ForOfYieldExpression) {
5084 const char* context_data[][2] = {{"", ""},
5085 {"'use strict';", ""},
5086 {"function foo(){ 'use strict';", "}"},
5087 {NULL, NULL}};
5088
5089 const char* data[] = {"function* g() { for(x of yield) {} }",
5090 "function* g() { for(var x of yield) {} }",
5091 "function* g() { for(let x of yield) {} }",
5092 "function* g() { for(const x of yield) {} }", NULL};
5093
Ben Murdochda12d292016-06-02 14:46:10 +01005094 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
5095 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01005096 RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
5097 arraysize(always_flags));
5098}
5099
5100
5101TEST(ForOfExpressionError) {
5102 const char* context_data[][2] = {{"", ""},
5103 {"'use strict';", ""},
5104 {"function foo(){ 'use strict';", "}"},
5105 {NULL, NULL}};
5106
5107 const char* data[] = {
5108 "for(x of [], []) {}", "for(var x of [], []) {}",
5109 "for(let x of [], []) {}", "for(const x of [], []) {}",
5110
5111 // AssignmentExpression should be validated statically:
5112 "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
5113 "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
5114
Ben Murdochda12d292016-06-02 14:46:10 +01005115 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
5116 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01005117 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5118 arraysize(always_flags));
5119}
5120
5121
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005122TEST(InvalidUnicodeEscapes) {
5123 const char* context_data[][2] = {{"", ""},
5124 {"'use strict';", ""},
5125 {NULL, NULL}};
5126 const char* data[] = {
5127 "var foob\\u123r = 0;",
5128 "var \\u123roo = 0;",
5129 "\"foob\\u123rr\"",
5130 // No escapes allowed in regexp flags
5131 "/regex/\\u0069g",
5132 "/regex/\\u006g",
5133 // Braces gone wrong
5134 "var foob\\u{c481r = 0;",
5135 "var foob\\uc481}r = 0;",
5136 "var \\u{0052oo = 0;",
5137 "var \\u0052}oo = 0;",
5138 "\"foob\\u{c481r\"",
5139 "var foob\\u{}ar = 0;",
5140 // Too high value for the unicode escape
5141 "\"\\u{110000}\"",
5142 // Not an unicode escape
5143 "var foob\\v1234r = 0;",
5144 "var foob\\U1234r = 0;",
5145 "var foob\\v{1234}r = 0;",
5146 "var foob\\U{1234}r = 0;",
5147 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005148 RunParserSyncTest(context_data, data, kError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005149}
5150
5151
5152TEST(UnicodeEscapes) {
5153 const char* context_data[][2] = {{"", ""},
5154 {"'use strict';", ""},
5155 {NULL, NULL}};
5156 const char* data[] = {
5157 // Identifier starting with escape
5158 "var \\u0052oo = 0;",
5159 "var \\u{0052}oo = 0;",
5160 "var \\u{52}oo = 0;",
5161 "var \\u{00000000052}oo = 0;",
5162 // Identifier with an escape but not starting with an escape
5163 "var foob\\uc481r = 0;",
5164 "var foob\\u{c481}r = 0;",
5165 // String with an escape
5166 "\"foob\\uc481r\"",
5167 "\"foob\\{uc481}r\"",
5168 // This character is a valid unicode character, representable as a surrogate
5169 // pair, not representable as 4 hex digits.
5170 "\"foo\\u{10e6d}\"",
5171 // Max value for the unicode escape
5172 "\"\\u{10ffff}\"",
5173 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005174 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005175}
5176
5177
5178TEST(ScanTemplateLiterals) {
5179 const char* context_data[][2] = {{"'use strict';", ""},
5180 {"function foo(){ 'use strict';"
5181 " var a, b, c; return ", "}"},
5182 {NULL, NULL}};
5183
5184 const char* data[] = {
5185 "``",
5186 "`no-subst-template`",
5187 "`template-head${a}`",
5188 "`${a}`",
5189 "`${a}template-tail`",
5190 "`template-head${a}template-tail`",
5191 "`${a}${b}${c}`",
5192 "`a${a}b${b}c${c}`",
5193 "`${a}a${b}b${c}c`",
5194 "`foo\n\nbar\r\nbaz`",
5195 "`foo\n\n${ bar }\r\nbaz`",
5196 "`foo${a /* comment */}`",
5197 "`foo${a // comment\n}`",
5198 "`foo${a \n}`",
5199 "`foo${a \r\n}`",
5200 "`foo${a \r}`",
5201 "`foo${/* comment */ a}`",
5202 "`foo${// comment\na}`",
5203 "`foo${\n a}`",
5204 "`foo${\r\n a}`",
5205 "`foo${\r a}`",
5206 "`foo${'a' in a}`",
5207 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005208 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005209}
5210
5211
5212TEST(ScanTaggedTemplateLiterals) {
5213 const char* context_data[][2] = {{"'use strict';", ""},
5214 {"function foo(){ 'use strict';"
5215 " function tag() {}"
5216 " var a, b, c; return ", "}"},
5217 {NULL, NULL}};
5218
5219 const char* data[] = {
5220 "tag ``",
5221 "tag `no-subst-template`",
5222 "tag`template-head${a}`",
5223 "tag `${a}`",
5224 "tag `${a}template-tail`",
5225 "tag `template-head${a}template-tail`",
5226 "tag\n`${a}${b}${c}`",
5227 "tag\r\n`a${a}b${b}c${c}`",
5228 "tag `${a}a${b}b${c}c`",
5229 "tag\t`foo\n\nbar\r\nbaz`",
5230 "tag\r`foo\n\n${ bar }\r\nbaz`",
5231 "tag`foo${a /* comment */}`",
5232 "tag`foo${a // comment\n}`",
5233 "tag`foo${a \n}`",
5234 "tag`foo${a \r\n}`",
5235 "tag`foo${a \r}`",
5236 "tag`foo${/* comment */ a}`",
5237 "tag`foo${// comment\na}`",
5238 "tag`foo${\n a}`",
5239 "tag`foo${\r\n a}`",
5240 "tag`foo${\r a}`",
5241 "tag`foo${'a' in a}`",
5242 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005243 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005244}
5245
5246
5247TEST(TemplateMaterializedLiterals) {
5248 const char* context_data[][2] = {
5249 {
5250 "'use strict';\n"
5251 "function tag() {}\n"
5252 "var a, b, c;\n"
5253 "(", ")"
5254 },
5255 {NULL, NULL}
5256 };
5257
5258 const char* data[] = {
5259 "tag``",
5260 "tag`a`",
5261 "tag`a${1}b`",
5262 "tag`a${1}b${2}c`",
5263 "``",
5264 "`a`",
5265 "`a${1}b`",
5266 "`a${1}b${2}c`",
5267 NULL
5268 };
5269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005270 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005271}
5272
5273
5274TEST(ScanUnterminatedTemplateLiterals) {
5275 const char* context_data[][2] = {{"'use strict';", ""},
5276 {"function foo(){ 'use strict';"
5277 " var a, b, c; return ", "}"},
5278 {NULL, NULL}};
5279
5280 const char* data[] = {
5281 "`no-subst-template",
5282 "`template-head${a}",
5283 "`${a}template-tail",
5284 "`template-head${a}template-tail",
5285 "`${a}${b}${c}",
5286 "`a${a}b${b}c${c}",
5287 "`${a}a${b}b${c}c",
5288 "`foo\n\nbar\r\nbaz",
5289 "`foo\n\n${ bar }\r\nbaz",
5290 "`foo${a /* comment } */`",
5291 "`foo${a /* comment } `*/",
5292 "`foo${a // comment}`",
5293 "`foo${a \n`",
5294 "`foo${a \r\n`",
5295 "`foo${a \r`",
5296 "`foo${/* comment */ a`",
5297 "`foo${// commenta}`",
5298 "`foo${\n a`",
5299 "`foo${\r\n a`",
5300 "`foo${\r a`",
5301 "`foo${fn(}`",
5302 "`foo${1 if}`",
5303 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005304 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005305}
5306
5307
5308TEST(TemplateLiteralsIllegalTokens) {
5309 const char* context_data[][2] = {{"'use strict';", ""},
5310 {"function foo(){ 'use strict';"
5311 " var a, b, c; return ", "}"},
5312 {NULL, NULL}};
5313 const char* data[] = {
5314 "`hello\\x`",
5315 "`hello\\x${1}`",
5316 "`hello${1}\\x`",
5317 "`hello${1}\\x${2}`",
5318 "`hello\\x\n`",
5319 "`hello\\x\n${1}`",
5320 "`hello${1}\\x\n`",
5321 "`hello${1}\\x\n${2}`",
5322 NULL};
5323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005324 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5325}
5326
5327
5328TEST(ParseRestParameters) {
5329 const char* context_data[][2] = {{"'use strict';(function(",
5330 "){ return args;})(1, [], /regexp/, 'str',"
5331 "function(){});"},
5332 {"(function(", "){ return args;})(1, [],"
5333 "/regexp/, 'str', function(){});"},
5334 {NULL, NULL}};
5335
5336 const char* data[] = {"...args",
5337 "a, ...args",
5338 "... args",
5339 "a, ... args",
5340 "...\targs",
5341 "a, ...\targs",
5342 "...\r\nargs",
5343 "a, ...\r\nargs",
5344 "...\rargs",
5345 "a, ...\rargs",
5346 "...\t\n\t\t\n args",
5347 "a, ... \n \n args",
5348 "...{ length, 0: a, 1: b}",
5349 "...{}",
5350 "...[a, b]",
5351 "...[]",
5352 "...[...[a, b, ...c]]",
5353 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01005354 RunParserSyncTest(context_data, data, kSuccess);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005355}
5356
5357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005358TEST(ParseRestParametersErrors) {
5359 const char* context_data[][2] = {{"'use strict';(function(",
5360 "){ return args;}(1, [], /regexp/, 'str',"
5361 "function(){});"},
5362 {"(function(", "){ return args;}(1, [],"
5363 "/regexp/, 'str', function(){});"},
5364 {NULL, NULL}};
5365
5366 const char* data[] = {
5367 "...args, b",
5368 "a, ...args, b",
5369 "...args, b",
5370 "a, ...args, b",
5371 "...args,\tb",
5372 "a,...args\t,b",
5373 "...args\r\n, b",
5374 "a, ... args,\r\nb",
5375 "...args\r,b",
5376 "a, ... args,\rb",
5377 "...args\t\n\t\t\n, b",
5378 "a, ... args, \n \n b",
5379 "a, a, ...args",
5380 "a,\ta, ...args",
5381 "a,\ra, ...args",
5382 "a,\na, ...args",
5383 NULL};
5384 RunParserSyncTest(context_data, data, kError);
5385}
5386
5387
5388TEST(RestParameterInSetterMethodError) {
5389 const char* context_data[][2] = {
5390 {"'use strict';({ set prop(", ") {} }).prop = 1;"},
5391 {"'use strict';(class { static set prop(", ") {} }).prop = 1;"},
5392 {"'use strict';(new (class { set prop(", ") {} })).prop = 1;"},
5393 {"({ set prop(", ") {} }).prop = 1;"},
5394 {"(class { static set prop(", ") {} }).prop = 1;"},
5395 {"(new (class { set prop(", ") {} })).prop = 1;"},
5396 {nullptr, nullptr}};
5397 const char* data[] = {"...a", "...arguments", "...eval", nullptr};
5398
5399 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
5400 RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
5401 arraysize(always_flags));
5402}
5403
5404
5405TEST(RestParametersEvalArguments) {
5406 const char* strict_context_data[][2] =
5407 {{"'use strict';(function(",
5408 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5409 {NULL, NULL}};
5410 const char* sloppy_context_data[][2] =
5411 {{"(function(",
5412 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5413 {NULL, NULL}};
5414
5415 const char* data[] = {
5416 "...eval",
5417 "eval, ...args",
5418 "...arguments",
5419 "arguments, ...args",
5420 NULL};
5421
5422 // Fail in strict mode
5423 RunParserSyncTest(strict_context_data, data, kError);
5424
5425 // OK in sloppy mode
5426 RunParserSyncTest(sloppy_context_data, data, kSuccess);
5427}
5428
5429
5430TEST(RestParametersDuplicateEvalArguments) {
5431 const char* context_data[][2] =
5432 {{"'use strict';(function(",
5433 "){ return;})(1, [], /regexp/, 'str',function(){});"},
5434 {"(function(",
5435 "){ return;})(1, [],/regexp/, 'str', function(){});"},
5436 {NULL, NULL}};
5437
5438 const char* data[] = {
5439 "eval, ...eval",
5440 "eval, eval, ...args",
5441 "arguments, ...arguments",
5442 "arguments, arguments, ...args",
5443 NULL};
5444
5445 // In strict mode, the error is using "eval" or "arguments" as parameter names
5446 // In sloppy mode, the error is that eval / arguments are duplicated
5447 RunParserSyncTest(context_data, data, kError);
5448}
5449
5450
5451TEST(SpreadCall) {
5452 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5453 {"function fn() {} fn(", ");"},
5454 {NULL, NULL}};
5455
5456 const char* data[] = {
5457 "...([1, 2, 3])", "...'123', ...'456'", "...new Set([1, 2, 3]), 4",
5458 "1, ...[2, 3], 4", "...Array(...[1,2,3,4])", "...NaN",
5459 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89'",
5460 "0, 1, ...[2, 3, 4], 5, 6, 7, ...'89', 10",
5461 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9",
5462 "...[0, 1, 2], 3, 4, 5, 6, ...'7', 8, 9, ...[10]", NULL};
5463
5464 RunParserSyncTest(context_data, data, kSuccess);
5465}
5466
5467
5468TEST(SpreadCallErrors) {
5469 const char* context_data[][2] = {{"function fn() { 'use strict';} fn(", ");"},
5470 {"function fn() {} fn(", ");"},
5471 {NULL, NULL}};
5472
5473 const char* data[] = {"(...[1, 2, 3])", "......[1,2,3]", NULL};
5474
5475 RunParserSyncTest(context_data, data, kError);
5476}
5477
5478
5479TEST(BadRestSpread) {
5480 const char* context_data[][2] = {{"function fn() { 'use strict';", "} fn();"},
5481 {"function fn() { ", "} fn();"},
5482 {NULL, NULL}};
5483 const char* data[] = {"return ...[1,2,3];", "var ...x = [1,2,3];",
5484 "var [...x,] = [1,2,3];", "var [...x, y] = [1,2,3];",
5485 "var {...x} = [1,2,3];", "var { x } = {x: ...[1,2,3]}",
5486 NULL};
5487 RunParserSyncTest(context_data, data, kError, NULL, 0, NULL, 0);
5488}
5489
5490
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005491TEST(LexicalScopingSloppyMode) {
5492 const char* context_data[][2] = {
5493 {"", ""},
5494 {"function f() {", "}"},
5495 {"{", "}"},
5496 {NULL, NULL}};
5497 const char* bad_data[] = {
5498 "let x = 1;",
5499 "for(let x = 1;;){}",
5500 "for(let x of []){}",
5501 "for(let x in []){}",
5502 "class C {}",
5503 "class C extends D {}",
5504 "(class {})",
5505 "(class extends D {})",
5506 "(class C {})",
5507 "(class C extends D {})",
5508 NULL};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005509 static const ParserFlag always_false_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005510 RunParserSyncTest(context_data, bad_data, kError, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005511 always_false_flags, arraysize(always_false_flags));
5512
5513 const char* good_data[] = {
5514 "let = 1;",
5515 "for(let = 1;;){}",
5516 NULL};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005517 RunParserSyncTest(context_data, good_data, kSuccess, NULL, 0, NULL, 0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005518 always_false_flags, arraysize(always_false_flags));
5519}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005520
5521
5522TEST(ComputedPropertyName) {
5523 const char* context_data[][2] = {{"({[", "]: 1});"},
5524 {"({get [", "]() {}});"},
5525 {"({set [", "](_) {}});"},
5526 {"({[", "]() {}});"},
5527 {"({*[", "]() {}});"},
5528 {"(class {get [", "]() {}});"},
5529 {"(class {set [", "](_) {}});"},
5530 {"(class {[", "]() {}});"},
5531 {"(class {*[", "]() {}});"},
5532 {NULL, NULL}};
5533 const char* error_data[] = {
5534 "1, 2",
5535 "var name",
5536 NULL};
5537
5538 static const ParserFlag always_flags[] = {
5539 kAllowHarmonySloppy,
5540 };
5541 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5542 always_flags, arraysize(always_flags));
5543
5544 const char* name_data[] = {
5545 "1",
5546 "1 + 2",
5547 "'name'",
5548 "\"name\"",
5549 "[]",
5550 "{}",
5551 NULL};
5552
5553 RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
5554 always_flags, arraysize(always_flags));
5555}
5556
5557
5558TEST(ComputedPropertyNameShorthandError) {
5559 const char* context_data[][2] = {{"({", "});"},
5560 {NULL, NULL}};
5561 const char* error_data[] = {
5562 "a: 1, [2]",
5563 "[1], a: 1",
5564 NULL};
5565
5566 static const ParserFlag always_flags[] = {
5567 kAllowHarmonySloppy,
5568 };
5569 RunParserSyncTest(context_data, error_data, kError, NULL, 0,
5570 always_flags, arraysize(always_flags));
5571}
5572
5573
5574TEST(BasicImportExportParsing) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005575 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005576 const char* kSources[] = {
5577 "export let x = 0;",
5578 "export var y = 0;",
5579 "export const z = 0;",
5580 "export function func() { };",
5581 "export class C { };",
5582 "export { };",
5583 "function f() {}; f(); export { f };",
5584 "var a, b, c; export { a, b as baz, c };",
5585 "var d, e; export { d as dreary, e, };",
5586 "export default function f() {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005587 "export default function() {}",
5588 "export default function*() {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005589 "export default class C {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005590 "export default class {}"
5591 "export default class extends C {}"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005592 "export default 42",
5593 "var x; export default x = 7",
5594 "export { Q } from 'somemodule.js';",
5595 "export * from 'somemodule.js';",
5596 "var foo; export { foo as for };",
5597 "export { arguments } from 'm.js';",
5598 "export { for } from 'm.js';",
5599 "export { yield } from 'm.js'",
5600 "export { static } from 'm.js'",
5601 "export { let } from 'm.js'",
5602 "var a; export { a as b, a as c };",
5603
5604 "import 'somemodule.js';",
5605 "import { } from 'm.js';",
5606 "import { a } from 'm.js';",
5607 "import { a, b as d, c, } from 'm.js';",
5608 "import * as thing from 'm.js';",
5609 "import thing from 'm.js';",
5610 "import thing, * as rest from 'm.js';",
5611 "import thing, { a, b, c } from 'm.js';",
5612 "import { arguments as a } from 'm.js';",
5613 "import { for as f } from 'm.js';",
5614 "import { yield as y } from 'm.js';",
5615 "import { static as s } from 'm.js';",
5616 "import { let as l } from 'm.js';",
5617 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005618 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005619
5620 i::Isolate* isolate = CcTest::i_isolate();
5621 i::Factory* factory = isolate->factory();
5622
5623 v8::HandleScope handles(CcTest::isolate());
5624 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5625 v8::Context::Scope context_scope(context);
5626
5627 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5628 128 * 1024);
5629
5630 for (unsigned i = 0; i < arraysize(kSources); ++i) {
5631 i::Handle<i::String> source =
5632 factory->NewStringFromAsciiChecked(kSources[i]);
5633
5634 // Show that parsing as a module works
5635 {
5636 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005637 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005638 i::ParseInfo info(&zone, script);
5639 i::Parser parser(&info);
5640 info.set_module();
5641 if (!parser.Parse(&info)) {
5642 i::Handle<i::JSObject> exception_handle(
5643 i::JSObject::cast(isolate->pending_exception()));
Ben Murdochda12d292016-06-02 14:46:10 +01005644 i::Handle<i::String> message_string = i::Handle<i::String>::cast(
5645 i::JSReceiver::GetProperty(isolate, exception_handle, "message")
5646 .ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005647
5648 v8::base::OS::Print(
5649 "Parser failed on:\n"
5650 "\t%s\n"
5651 "with error:\n"
5652 "\t%s\n"
5653 "However, we expected no error.",
5654 source->ToCString().get(), message_string->ToCString().get());
5655 CHECK(false);
5656 }
5657 }
5658
5659 // And that parsing a script does not.
5660 {
5661 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005662 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005663 i::ParseInfo info(&zone, script);
5664 i::Parser parser(&info);
5665 info.set_global();
5666 CHECK(!parser.Parse(&info));
5667 }
5668 }
5669}
5670
5671
5672TEST(ImportExportParsingErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005673 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005674 const char* kErrorSources[] = {
5675 "export {",
5676 "var a; export { a",
5677 "var a; export { a,",
5678 "var a; export { a, ;",
5679 "var a; export { a as };",
5680 "var a, b; export { a as , b};",
5681 "export }",
5682 "var foo, bar; export { foo bar };",
5683 "export { foo };",
5684 "export { , };",
5685 "export default;",
5686 "export default var x = 7;",
5687 "export default let x = 7;",
5688 "export default const x = 7;",
5689 "export *;",
5690 "export * from;",
5691 "export { Q } from;",
5692 "export default from 'module.js';",
5693 "export { for }",
5694 "export { for as foo }",
5695 "export { arguments }",
5696 "export { arguments as foo }",
5697 "var a; export { a, a };",
5698 "var a, b; export { a as b, b };",
5699 "var a, b; export { a as c, b as c };",
5700 "export default function f(){}; export default class C {};",
5701 "export default function f(){}; var a; export { a as default };",
Ben Murdoch097c5b22016-05-18 11:27:45 +01005702 "export function() {}",
5703 "export function*() {}",
5704 "export class {}",
5705 "export class extends C {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005706
5707 "import from;",
5708 "import from 'm.js';",
5709 "import { };",
5710 "import {;",
5711 "import };",
5712 "import { , };",
5713 "import { , } from 'm.js';",
5714 "import { a } from;",
5715 "import { a } 'm.js';",
5716 "import , from 'm.js';",
5717 "import a , from 'm.js';",
5718 "import a { b, c } from 'm.js';",
5719 "import arguments from 'm.js';",
5720 "import eval from 'm.js';",
5721 "import { arguments } from 'm.js';",
5722 "import { eval } from 'm.js';",
5723 "import { a as arguments } from 'm.js';",
5724 "import { for } from 'm.js';",
5725 "import { y as yield } from 'm.js'",
5726 "import { s as static } from 'm.js'",
5727 "import { l as let } from 'm.js'",
5728 "import { x }, def from 'm.js';",
5729 "import def, def2 from 'm.js';",
5730 "import * as x, def from 'm.js';",
5731 "import * as x, * as y from 'm.js';",
5732 "import {x}, {y} from 'm.js';",
5733 "import * as x, {y} from 'm.js';",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005734 };
Ben Murdoch097c5b22016-05-18 11:27:45 +01005735 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005736
5737 i::Isolate* isolate = CcTest::i_isolate();
5738 i::Factory* factory = isolate->factory();
5739
5740 v8::HandleScope handles(CcTest::isolate());
5741 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5742 v8::Context::Scope context_scope(context);
5743
5744 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5745 128 * 1024);
5746
5747 for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
5748 i::Handle<i::String> source =
5749 factory->NewStringFromAsciiChecked(kErrorSources[i]);
5750
5751 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005752 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005753 i::ParseInfo info(&zone, script);
5754 i::Parser parser(&info);
5755 info.set_module();
5756 CHECK(!parser.Parse(&info));
5757 }
5758}
5759
5760
5761TEST(ModuleParsingInternals) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005762 i::Isolate* isolate = CcTest::i_isolate();
5763 i::Factory* factory = isolate->factory();
5764 v8::HandleScope handles(CcTest::isolate());
5765 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5766 v8::Context::Scope context_scope(context);
5767 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5768 128 * 1024);
5769
5770 static const char kSource[] =
5771 "let x = 5;"
5772 "export { x as y };"
5773 "import { q as z } from 'm.js';"
5774 "import n from 'n.js';"
5775 "export { a as b } from 'm.js';"
5776 "export * from 'p.js';"
5777 "import 'q.js'";
5778 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(kSource);
5779 i::Handle<i::Script> script = factory->NewScript(source);
Ben Murdochda12d292016-06-02 14:46:10 +01005780 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005781 i::ParseInfo info(&zone, script);
5782 i::Parser parser(&info);
5783 info.set_module();
5784 CHECK(parser.Parse(&info));
5785 CHECK(i::Compiler::Analyze(&info));
5786 i::FunctionLiteral* func = info.literal();
5787 i::Scope* module_scope = func->scope();
5788 i::Scope* outer_scope = module_scope->outer_scope();
5789 CHECK(outer_scope->is_script_scope());
5790 CHECK_NULL(outer_scope->outer_scope());
5791 CHECK(module_scope->is_module_scope());
5792 i::ModuleDescriptor* descriptor = module_scope->module();
5793 CHECK_NOT_NULL(descriptor);
5794 CHECK_EQ(1, descriptor->Length());
5795 const i::AstRawString* export_name =
5796 info.ast_value_factory()->GetOneByteString("y");
5797 const i::AstRawString* local_name =
5798 descriptor->LookupLocalExport(export_name, &zone);
5799 CHECK_NOT_NULL(local_name);
5800 CHECK(local_name->IsOneByteEqualTo("x"));
5801 i::ZoneList<i::Declaration*>* declarations = module_scope->declarations();
5802 CHECK_EQ(3, declarations->length());
5803 CHECK(declarations->at(0)->proxy()->raw_name()->IsOneByteEqualTo("x"));
5804 i::ImportDeclaration* import_decl =
5805 declarations->at(1)->AsImportDeclaration();
5806 CHECK(import_decl->import_name()->IsOneByteEqualTo("q"));
5807 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("z"));
5808 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("m.js"));
5809 import_decl = declarations->at(2)->AsImportDeclaration();
5810 CHECK(import_decl->import_name()->IsOneByteEqualTo("default"));
5811 CHECK(import_decl->proxy()->raw_name()->IsOneByteEqualTo("n"));
5812 CHECK(import_decl->module_specifier()->IsOneByteEqualTo("n.js"));
5813 // TODO(adamk): Add test for indirect exports once they're fully implemented.
5814 // TODO(adamk): Add test for star exports once they're fully implemented.
5815 const i::ZoneList<const i::AstRawString*>& requested_modules =
5816 descriptor->requested_modules();
5817 CHECK_EQ(4, requested_modules.length());
5818 CHECK(requested_modules[0]->IsOneByteEqualTo("m.js"));
5819 CHECK(requested_modules[1]->IsOneByteEqualTo("n.js"));
5820 CHECK(requested_modules[2]->IsOneByteEqualTo("p.js"));
5821 CHECK(requested_modules[3]->IsOneByteEqualTo("q.js"));
5822}
5823
5824
5825TEST(DuplicateProtoError) {
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__: {}, \"__\x70roto__\": {}",
5835 "__proto__: {}, a: 1, __proto__: {}",
5836 NULL
5837 };
5838
5839 RunParserSyncTest(context_data, error_data, kError);
5840}
5841
5842
5843TEST(DuplicateProtoNoError) {
5844 const char* context_data[][2] = {
5845 {"({", "});"},
5846 {"'use strict'; ({", "});"},
5847 {NULL, NULL}
5848 };
5849 const char* error_data[] = {
5850 "__proto__: {}, ['__proto__']: {}",
5851 "__proto__: {}, __proto__() {}",
5852 "__proto__: {}, get __proto__() {}",
5853 "__proto__: {}, set __proto__(v) {}",
5854 "__proto__: {}, __proto__",
5855 NULL
5856 };
5857
5858 RunParserSyncTest(context_data, error_data, kSuccess);
5859}
5860
5861
5862TEST(DeclarationsError) {
5863 const char* context_data[][2] = {{"'use strict'; if (true)", ""},
5864 {"'use strict'; if (false) {} else", ""},
5865 {"'use strict'; while (false)", ""},
5866 {"'use strict'; for (;;)", ""},
5867 {"'use strict'; for (x in y)", ""},
5868 {"'use strict'; do ", " while (false)"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005869 {NULL, NULL}};
5870
5871 const char* statement_data[] = {
5872 "let x = 1;",
5873 "const x = 1;",
5874 "class C {}",
5875 NULL};
5876
Ben Murdochda12d292016-06-02 14:46:10 +01005877 RunParserSyncTest(context_data, statement_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005878}
5879
5880
5881void TestLanguageMode(const char* source,
5882 i::LanguageMode expected_language_mode) {
5883 i::Isolate* isolate = CcTest::i_isolate();
5884 i::Factory* factory = isolate->factory();
5885 v8::HandleScope handles(CcTest::isolate());
5886 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
5887 v8::Context::Scope context_scope(context);
5888 isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
5889 128 * 1024);
5890
5891 i::Handle<i::Script> script =
5892 factory->NewScript(factory->NewStringFromAsciiChecked(source));
Ben Murdochda12d292016-06-02 14:46:10 +01005893 i::Zone zone(CcTest::i_isolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005894 i::ParseInfo info(&zone, script);
5895 i::Parser parser(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005896 info.set_global();
5897 parser.Parse(&info);
5898 CHECK(info.literal() != NULL);
5899 CHECK_EQ(expected_language_mode, info.literal()->language_mode());
5900}
5901
5902
5903TEST(LanguageModeDirectives) {
5904 TestLanguageMode("\"use nothing\"", i::SLOPPY);
5905 TestLanguageMode("\"use strict\"", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005906
5907 TestLanguageMode("var x = 1; \"use strict\"", i::SLOPPY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005908
5909 TestLanguageMode("\"use some future directive\"; \"use strict\";", i::STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005910}
5911
5912
5913TEST(PropertyNameEvalArguments) {
5914 const char* context_data[][2] = {{"'use strict';", ""},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005915 {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
Ben Murdochda12d292016-06-02 14:46:10 +01005949 RunParserSyncTest(context_data, statement_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005950}
5951
5952
5953TEST(FunctionLiteralDuplicateParameters) {
5954 const char* strict_context_data[][2] =
5955 {{"'use strict';(function(", "){})();"},
5956 {"(function(", ") { 'use strict'; })();"},
5957 {"'use strict'; function fn(", ") {}; fn();"},
5958 {"function fn(", ") { 'use strict'; }; fn();"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005959 {NULL, NULL}};
5960
5961 const char* sloppy_context_data[][2] =
5962 {{"(function(", "){})();"},
5963 {"(function(", ") {})();"},
5964 {"function fn(", ") {}; fn();"},
5965 {"function fn(", ") {}; fn();"},
5966 {NULL, NULL}};
5967
5968 const char* data[] = {
5969 "a, a",
5970 "a, a, a",
5971 "b, a, a",
5972 "a, b, c, c",
5973 "a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, w",
5974 NULL};
5975
Ben Murdochda12d292016-06-02 14:46:10 +01005976 RunParserSyncTest(strict_context_data, data, kError);
5977 RunParserSyncTest(sloppy_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005978}
5979
5980
5981TEST(ArrowFunctionASIErrors) {
5982 const char* context_data[][2] = {{"'use strict';", ""}, {"", ""},
5983 {NULL, NULL}};
5984
5985 const char* data[] = {
5986 "(a\n=> a)(1)",
5987 "(a/*\n*/=> a)(1)",
5988 "((a)\n=> a)(1)",
5989 "((a)/*\n*/=> a)(1)",
5990 "((a, b)\n=> a + b)(1, 2)",
5991 "((a, b)/*\n*/=> a + b)(1, 2)",
5992 NULL};
5993 RunParserSyncTest(context_data, data, kError);
5994}
5995
5996
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005997TEST(DestructuringPositiveTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005998 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
5999 {"var ", " = {};"},
6000 {"'use strict'; const ", " = {};"},
6001 {"function f(", ") {}"},
6002 {"function f(argument1, ", ") {}"},
6003 {"var f = (", ") => {};"},
6004 {"var f = (argument1,", ") => {};"},
6005 {"try {} catch(", ") {}"},
6006 {NULL, NULL}};
6007
6008 // clang-format off
6009 const char* data[] = {
6010 "a",
6011 "{ x : y }",
6012 "{ x : y = 1 }",
6013 "{ get, set }",
6014 "{ get = 1, set = 2 }",
6015 "[a]",
6016 "[a = 1]",
6017 "[a,b,c]",
6018 "[a, b = 42, c]",
6019 "{ x : x, y : y }",
6020 "{ x : x = 1, y : y }",
6021 "{ x : x, y : y = 42 }",
6022 "[]",
6023 "{}",
6024 "[{x:x, y:y}, [a,b,c]]",
6025 "[{x:x = 1, y:y = 2}, [a = 3, b = 4, c = 5]]",
6026 "{x}",
6027 "{x, y}",
6028 "{x = 42, y = 15}",
6029 "[a,,b]",
6030 "{42 : x}",
6031 "{42 : x = 42}",
6032 "{42e-2 : x}",
6033 "{42e-2 : x = 42}",
6034 "{x : y, x : z}",
6035 "{'hi' : x}",
6036 "{'hi' : x = 42}",
6037 "{var: x}",
6038 "{var: x = 42}",
6039 "{[x] : z}",
6040 "{[1+1] : z}",
6041 "{[foo()] : z}",
6042 "{}",
6043 "[...rest]",
6044 "[a,b,...rest]",
6045 "[a,,...rest]",
6046 NULL};
6047 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006048 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006049}
6050
6051
6052TEST(DestructuringNegativeTests) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006053 { // All modes.
6054 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6055 {"var ", " = {};"},
6056 {"'use strict'; const ", " = {};"},
6057 {"function f(", ") {}"},
6058 {"function f(argument1, ", ") {}"},
6059 {"var f = (", ") => {};"},
6060 {"var f = ", " => {};"},
6061 {"var f = (argument1,", ") => {};"},
6062 {"try {} catch(", ") {}"},
6063 {NULL, NULL}};
6064
6065 // clang-format off
6066 const char* data[] = {
6067 "a++",
6068 "++a",
6069 "delete a",
6070 "void a",
6071 "typeof a",
6072 "--a",
6073 "+a",
6074 "-a",
6075 "~a",
6076 "!a",
6077 "{ x : y++ }",
6078 "[a++]",
6079 "(x => y)",
6080 "a[i]", "a()",
6081 "a.b",
6082 "new a",
6083 "a + a",
6084 "a - a",
6085 "a * a",
6086 "a / a",
6087 "a == a",
6088 "a != a",
6089 "a > a",
6090 "a < a",
6091 "a <<< a",
6092 "a >>> a",
6093 "function a() {}",
6094 "a`bcd`",
6095 "this",
6096 "null",
6097 "true",
6098 "false",
6099 "1",
6100 "'abc'",
6101 "/abc/",
6102 "`abc`",
6103 "class {}",
6104 "{+2 : x}",
6105 "{-2 : x}",
6106 "var",
6107 "[var]",
6108 "{x : {y : var}}",
6109 "{x : x = a+}",
6110 "{x : x = (a+)}",
6111 "{x : x += a}",
6112 "{m() {} = 0}",
6113 "{[1+1]}",
6114 "[...rest, x]",
6115 "[a,b,...rest, x]",
6116 "[a,,...rest, x]",
6117 "[...rest,]",
6118 "[a,b,...rest,]",
6119 "[a,,...rest,]",
6120 "[...rest,...rest1]",
6121 "[a,b,...rest,...rest1]",
6122 "[a,,..rest,...rest1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006123 "[x, y, ...z = 1]",
6124 "[...z = 1]",
6125 "[x, y, ...[z] = [1]]",
6126 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006127 "{ x : 3 }",
6128 "{ x : 'foo' }",
6129 "{ x : /foo/ }",
6130 "{ x : `foo` }",
6131 "{ get a() {} }",
6132 "{ set a() {} }",
6133 "{ method() {} }",
6134 "{ *method() {} }",
6135 NULL};
6136 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006137 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006138 }
6139
6140 { // All modes.
6141 const char* context_data[][2] = {{"'use strict'; let ", " = {};"},
6142 {"var ", " = {};"},
6143 {"'use strict'; const ", " = {};"},
6144 {"function f(", ") {}"},
6145 {"function f(argument1, ", ") {}"},
6146 {"var f = (", ") => {};"},
6147 {"var f = (argument1,", ") => {};"},
6148 {NULL, NULL}};
6149
6150 // clang-format off
6151 const char* data[] = {
6152 "x => x",
6153 "() => x",
6154 NULL};
6155 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006156 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006157 }
6158
6159 { // Strict mode.
6160 const char* context_data[][2] = {
6161 {"'use strict'; let ", " = {};"},
6162 {"'use strict'; const ", " = {};"},
6163 {"'use strict'; function f(", ") {}"},
6164 {"'use strict'; function f(argument1, ", ") {}"},
6165 {NULL, NULL}};
6166
6167 // clang-format off
6168 const char* data[] = {
6169 "[eval]",
6170 "{ a : arguments }",
6171 "[public]",
6172 "{ x : private }",
6173 NULL};
6174 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006175 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006176 }
6177
6178 { // 'yield' in generators.
6179 const char* context_data[][2] = {
6180 {"function*() { var ", " = {};"},
6181 {"function*() { 'use strict'; let ", " = {};"},
6182 {"function*() { 'use strict'; const ", " = {};"},
6183 {NULL, NULL}};
6184
6185 // clang-format off
6186 const char* data[] = {
6187 "yield",
6188 "[yield]",
6189 "{ x : yield }",
6190 NULL};
6191 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006192 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006193 }
6194
6195 { // Declaration-specific errors
6196 const char* context_data[][2] = {{"'use strict'; var ", ""},
6197 {"'use strict'; let ", ""},
6198 {"'use strict'; const ", ""},
6199 {"'use strict'; for (var ", ";;) {}"},
6200 {"'use strict'; for (let ", ";;) {}"},
6201 {"'use strict'; for (const ", ";;) {}"},
6202 {"var ", ""},
6203 {"let ", ""},
6204 {"const ", ""},
6205 {"for (var ", ";;) {}"},
6206 {"for (let ", ";;) {}"},
6207 {"for (const ", ";;) {}"},
6208 {NULL, NULL}};
6209
6210 // clang-format off
6211 const char* data[] = {
6212 "{ a }",
6213 "[ a ]",
6214 NULL};
6215 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006216 static const ParserFlag always_flags[] = {kAllowHarmonySloppyLet};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006217 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6218 arraysize(always_flags));
6219 }
6220}
6221
6222
6223TEST(DestructuringAssignmentPositiveTests) {
6224 const char* context_data[][2] = {
6225 {"'use strict'; let x, y, z; (", " = {});"},
6226 {"var x, y, z; (", " = {});"},
6227 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6228 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6229 {"var x, y, z; for (x in ", " = {});"},
6230 {"var x, y, z; for (x of ", " = {});"},
6231 {"var x, y, z; for (", " in {});"},
6232 {"var x, y, z; for (", " of {});"},
6233 {"'use strict'; var x, y, z; for (", " in {});"},
6234 {"'use strict'; var x, y, z; for (", " of {});"},
6235 {NULL, NULL}};
6236
6237 const char* mixed_assignments_context_data[][2] = {
6238 {"'use strict'; let x, y, z; (", " = z = {});"},
6239 {"var x, y, z; (", " = z = {});"},
6240 {"'use strict'; let x, y, z; (x = ", " = z = {});"},
6241 {"var x, y, z; (x = ", " = z = {});"},
6242 {"'use strict'; let x, y, z; for (x in ", " = z = {});"},
6243 {"'use strict'; let x, y, z; for (x in x = ", " = z = {});"},
6244 {"'use strict'; let x, y, z; for (x of ", " = z = {});"},
6245 {"'use strict'; let x, y, z; for (x of x = ", " = z = {});"},
6246 {"var x, y, z; for (x in ", " = z = {});"},
6247 {"var x, y, z; for (x in x = ", " = z = {});"},
6248 {"var x, y, z; for (x of ", " = z = {});"},
6249 {"var x, y, z; for (x of x = ", " = z = {});"},
6250 {NULL, NULL}};
6251
6252 // clang-format off
6253 const char* data[] = {
6254 "x",
6255
6256 "{ x : y }",
6257 "{ x : foo().y }",
6258 "{ x : foo()[y] }",
6259 "{ x : y.z }",
6260 "{ x : y[z] }",
6261 "{ x : { y } }",
6262 "{ x : { foo: y } }",
6263 "{ x : { foo: foo().y } }",
6264 "{ x : { foo: foo()[y] } }",
6265 "{ x : { foo: y.z } }",
6266 "{ x : { foo: y[z] } }",
6267 "{ x : [ y ] }",
6268 "{ x : [ foo().y ] }",
6269 "{ x : [ foo()[y] ] }",
6270 "{ x : [ y.z ] }",
6271 "{ x : [ y[z] ] }",
6272
6273 "{ x : y = 10 }",
6274 "{ x : foo().y = 10 }",
6275 "{ x : foo()[y] = 10 }",
6276 "{ x : y.z = 10 }",
6277 "{ x : y[z] = 10 }",
6278 "{ x : { y = 10 } = {} }",
6279 "{ x : { foo: y = 10 } = {} }",
6280 "{ x : { foo: foo().y = 10 } = {} }",
6281 "{ x : { foo: foo()[y] = 10 } = {} }",
6282 "{ x : { foo: y.z = 10 } = {} }",
6283 "{ x : { foo: y[z] = 10 } = {} }",
6284 "{ x : [ y = 10 ] = {} }",
6285 "{ x : [ foo().y = 10 ] = {} }",
6286 "{ x : [ foo()[y] = 10 ] = {} }",
6287 "{ x : [ y.z = 10 ] = {} }",
6288 "{ x : [ y[z] = 10 ] = {} }",
6289
6290 "[ x ]",
6291 "[ foo().x ]",
6292 "[ foo()[x] ]",
6293 "[ x.y ]",
6294 "[ x[y] ]",
6295 "[ { x } ]",
6296 "[ { x : y } ]",
6297 "[ { x : foo().y } ]",
6298 "[ { x : foo()[y] } ]",
6299 "[ { x : x.y } ]",
6300 "[ { x : x[y] } ]",
6301 "[ [ x ] ]",
6302 "[ [ foo().x ] ]",
6303 "[ [ foo()[x] ] ]",
6304 "[ [ x.y ] ]",
6305 "[ [ x[y] ] ]",
6306
6307 "[ x = 10 ]",
6308 "[ foo().x = 10 ]",
6309 "[ foo()[x] = 10 ]",
6310 "[ x.y = 10 ]",
6311 "[ x[y] = 10 ]",
6312 "[ { x = 10 } = {} ]",
6313 "[ { x : y = 10 } = {} ]",
6314 "[ { x : foo().y = 10 } = {} ]",
6315 "[ { x : foo()[y] = 10 } = {} ]",
6316 "[ { x : x.y = 10 } = {} ]",
6317 "[ { x : x[y] = 10 } = {} ]",
6318 "[ [ x = 10 ] = {} ]",
6319 "[ [ foo().x = 10 ] = {} ]",
6320 "[ [ foo()[x] = 10 ] = {} ]",
6321 "[ [ x.y = 10 ] = {} ]",
6322 "[ [ x[y] = 10 ] = {} ]",
6323 "{ x : y = 1 }",
6324 "{ x }",
6325 "{ x, y, z }",
6326 "{ x = 1, y: z, z: y }",
6327 "{x = 42, y = 15}",
6328 "[x]",
6329 "[x = 1]",
6330 "[x,y,z]",
6331 "[x, y = 42, z]",
6332 "{ x : x, y : y }",
6333 "{ x : x = 1, y : y }",
6334 "{ x : x, y : y = 42 }",
6335 "[]",
6336 "{}",
6337 "[{x:x, y:y}, [,x,z,]]",
6338 "[{x:x = 1, y:y = 2}, [z = 3, z = 4, z = 5]]",
6339 "[x,,y]",
6340 "[(x),,(y)]",
6341 "[(x)]",
6342 "{42 : x}",
6343 "{42 : x = 42}",
6344 "{42e-2 : x}",
6345 "{42e-2 : x = 42}",
6346 "{'hi' : x}",
6347 "{'hi' : x = 42}",
6348 "{var: x}",
6349 "{var: x = 42}",
6350 "{var: (x) = 42}",
6351 "{[x] : z}",
6352 "{[1+1] : z}",
6353 "{[1+1] : (z)}",
6354 "{[foo()] : z}",
6355 "{[foo()] : (z)}",
6356 "{[foo()] : foo().bar}",
6357 "{[foo()] : foo()['bar']}",
6358 "{[foo()] : this.bar}",
6359 "{[foo()] : this['bar']}",
6360 "{[foo()] : 'foo'.bar}",
6361 "{[foo()] : 'foo'['bar']}",
6362 "[...x]",
6363 "[x,y,...z]",
6364 "[x,,...z]",
6365 "{ x: y }",
6366 "[x, y]",
6367 "[((x, y) => z).x]",
6368 "{x: ((y, z) => z).x}",
6369 "[((x, y) => z)['x']]",
6370 "{x: ((y, z) => z)['x']}",
6371
6372 "{x: { y = 10 } }",
6373 "[(({ x } = { x: 1 }) => x).a]",
6374
6375 // v8:4662
6376 "{ x: (y) }",
6377 "{ x: (y) = [] }",
6378 "{ x: (foo.bar) }",
6379 "{ x: (foo['bar']) }",
6380 "[ ...(a) ]",
6381 "[ ...(foo['bar']) ]",
6382 "[ ...(foo.bar) ]",
6383 "[ (y) ]",
6384 "[ (foo.bar) ]",
6385 "[ (foo['bar']) ]",
6386
6387 NULL};
6388 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006389 RunParserSyncTest(context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006390
Ben Murdochda12d292016-06-02 14:46:10 +01006391 RunParserSyncTest(mixed_assignments_context_data, data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006392
6393 const char* empty_context_data[][2] = {
6394 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6395
6396 // CoverInitializedName ambiguity handling in various contexts
6397 const char* ambiguity_data[] = {
6398 "var foo = { x = 10 } = {};",
6399 "var foo = { q } = { x = 10 } = {};",
6400 "var foo; foo = { x = 10 } = {};",
6401 "var foo; foo = { q } = { x = 10 } = {};",
6402 "var x; ({ x = 10 } = {});",
6403 "var q, x; ({ q } = { x = 10 } = {});",
6404 "var x; [{ x = 10 } = {}]",
6405 "var x; (true ? { x = true } = {} : { x = false } = {})",
6406 "var q, x; (q, { x = 10 } = {});",
6407 "var { x = 10 } = { x = 20 } = {};",
6408 "var { x = 10 } = (o = { x = 20 } = {});",
6409 "var x; (({ x = 10 } = { x = 20 } = {}) => x)({})",
6410 NULL,
6411 };
Ben Murdochda12d292016-06-02 14:46:10 +01006412 RunParserSyncTest(empty_context_data, ambiguity_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006413}
6414
6415
6416TEST(DestructuringAssignmentNegativeTests) {
6417 const char* context_data[][2] = {
6418 {"'use strict'; let x, y, z; (", " = {});"},
6419 {"var x, y, z; (", " = {});"},
6420 {"'use strict'; let x, y, z; for (x in ", " = {});"},
6421 {"'use strict'; let x, y, z; for (x of ", " = {});"},
6422 {"var x, y, z; for (x in ", " = {});"},
6423 {"var x, y, z; for (x of ", " = {});"},
6424 {NULL, NULL}};
6425
6426 // clang-format off
6427 const char* data[] = {
6428 "{ x : ++y }",
6429 "{ x : y * 2 }",
6430 "{ ...x }",
6431 "{ get x() {} }",
6432 "{ set x() {} }",
6433 "{ x: y() }",
6434 "{ this }",
6435 "{ x: this }",
6436 "{ x: this = 1 }",
6437 "{ super }",
6438 "{ x: super }",
6439 "{ x: super = 1 }",
6440 "{ new.target }",
6441 "{ x: new.target }",
6442 "{ x: new.target = 1 }",
6443 "[x--]",
6444 "[--x = 1]",
6445 "[x()]",
6446 "[this]",
6447 "[this = 1]",
6448 "[new.target]",
6449 "[new.target = 1]",
6450 "[super]",
6451 "[super = 1]",
6452 "[function f() {}]",
6453 "[50]",
6454 "[(50)]",
6455 "[(function() {})]",
6456 "[(foo())]",
6457 "{ x: 50 }",
6458 "{ x: (50) }",
6459 "['str']",
6460 "{ x: 'str' }",
6461 "{ x: ('str') }",
6462 "{ x: (foo()) }",
6463 "{ x: (function() {}) }",
6464 "{ x: y } = 'str'",
6465 "[x, y] = 'str'",
6466 "[(x,y) => z]",
6467 "{x: (y) => z}",
6468 "[x, ...y, z]",
6469 "[...x,]",
6470 "[x, y, ...z = 1]",
6471 "[...z = 1]",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006472 "[x, y, ...[z] = [1]]",
6473 "[...[z] = [1]]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006474
6475 // v8:4657
6476 "({ x: x4, x: (x+=1e4) })",
6477 "(({ x: x4, x: (x+=1e4) }))",
6478 "({ x: x4, x: (x+=1e4) } = {})",
6479 "(({ x: x4, x: (x+=1e4) } = {}))",
6480 "(({ x: x4, x: (x+=1e4) }) = {})",
6481 "({ x: y } = {})",
6482 "(({ x: y } = {}))",
6483 "(({ x: y }) = {})",
6484 "([a])",
6485 "(([a]))",
6486 "([a] = [])",
6487 "(([a] = []))",
6488 "(([a]) = [])",
6489
6490 // v8:4662
6491 "{ x: ([y]) }",
6492 "{ x: ([y] = []) }",
6493 "{ x: ({y}) }",
6494 "{ x: ({y} = {}) }",
6495 "{ x: (++y) }",
6496 "[ (...[a]) ]",
6497 "[ ...([a]) ]",
6498 "[ ...([a] = [])",
6499 "[ ...[ ( [ a ] ) ] ]",
6500 "[ ([a]) ]",
6501 "[ (...[a]) ]",
6502 "[ ([a] = []) ]",
6503 "[ (++y) ]",
6504 "[ ...(++y) ]",
6505
6506 "[ x += x ]",
6507 "{ foo: x += x }",
6508
6509 NULL};
6510 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006511 RunParserSyncTest(context_data, data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006512
6513 const char* empty_context_data[][2] = {
6514 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6515
6516 // CoverInitializedName ambiguity handling in various contexts
6517 const char* ambiguity_data[] = {
6518 "var foo = { x = 10 };",
6519 "var foo = { q } = { x = 10 };",
6520 "var foo; foo = { x = 10 };",
6521 "var foo; foo = { q } = { x = 10 };",
6522 "var x; ({ x = 10 });",
6523 "var q, x; ({ q } = { x = 10 });",
6524 "var x; [{ x = 10 }]",
6525 "var x; (true ? { x = true } : { x = false })",
6526 "var q, x; (q, { x = 10 });",
6527 "var { x = 10 } = { x = 20 };",
6528 "var { x = 10 } = (o = { x = 20 });",
6529 "var x; (({ x = 10 } = { x = 20 }) => x)({})",
6530
6531 // Not ambiguous, but uses same context data
6532 "switch([window %= []] = []) { default: }",
6533
6534 NULL,
6535 };
Ben Murdochda12d292016-06-02 14:46:10 +01006536 RunParserSyncTest(empty_context_data, ambiguity_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006537
6538 // Strict mode errors
6539 const char* strict_context_data[][2] = {{"'use strict'; (", " = {})"},
6540 {"'use strict'; for (", " of {}) {}"},
6541 {"'use strict'; for (", " in {}) {}"},
6542 {NULL, NULL}};
6543 const char* strict_data[] = {"{ eval }",
6544 "{ arguments }",
6545 "{ foo: eval }",
6546 "{ foo: arguments }",
6547 "{ eval = 0 }",
6548 "{ arguments = 0 }",
6549 "{ foo: eval = 0 }",
6550 "{ foo: arguments = 0 }",
6551 "[ eval ]",
6552 "[ arguments ]",
6553 "[ eval = 0 ]",
6554 "[ arguments = 0 ]",
6555
6556 // v8:4662
6557 "{ x: (eval) }",
6558 "{ x: (arguments) }",
6559 "{ x: (eval = 0) }",
6560 "{ x: (arguments = 0) }",
6561 "{ x: (eval) = 0 }",
6562 "{ x: (arguments) = 0 }",
6563 "[ (eval) ]",
6564 "[ (arguments) ]",
6565 "[ (eval = 0) ]",
6566 "[ (arguments = 0) ]",
6567 "[ (eval) = 0 ]",
6568 "[ (arguments) = 0 ]",
6569 "[ ...(eval) ]",
6570 "[ ...(arguments) ]",
6571 "[ ...(eval = 0) ]",
6572 "[ ...(arguments = 0) ]",
6573 "[ ...(eval) = 0 ]",
6574 "[ ...(arguments) = 0 ]",
6575
6576 NULL};
Ben Murdochda12d292016-06-02 14:46:10 +01006577 RunParserSyncTest(strict_context_data, strict_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006578}
6579
6580
6581TEST(DestructuringDisallowPatternsInForVarIn) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006582 const char* context_data[][2] = {
6583 {"", ""}, {"function f() {", "}"}, {NULL, NULL}};
6584 // clang-format off
6585 const char* error_data[] = {
6586 "for (let x = {} in null);",
6587 "for (let x = {} of null);",
6588 NULL};
6589 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006590 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006591
6592 // clang-format off
6593 const char* success_data[] = {
6594 "for (var x = {} in null);",
6595 NULL};
6596 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006597 RunParserSyncTest(context_data, success_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006598}
6599
6600
6601TEST(DestructuringDuplicateParams) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006602 const char* context_data[][2] = {{"'use strict';", ""},
6603 {"function outer() { 'use strict';", "}"},
6604 {nullptr, nullptr}};
6605
6606
6607 // clang-format off
6608 const char* error_data[] = {
6609 "function f(x,x){}",
6610 "function f(x, {x : x}){}",
6611 "function f(x, {x}){}",
6612 "function f({x,x}) {}",
6613 "function f([x,x]) {}",
6614 "function f(x, [y,{z:x}]) {}",
6615 "function f([x,{y:x}]) {}",
6616 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6617 "function f(x, x, {a}) {}",
6618 nullptr};
6619 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006620 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006621}
6622
6623
6624TEST(DestructuringDuplicateParamsSloppy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006625 const char* context_data[][2] = {
6626 {"", ""}, {"function outer() {", "}"}, {nullptr, nullptr}};
6627
6628
6629 // clang-format off
6630 const char* error_data[] = {
6631 // non-simple parameter list causes duplicates to be errors in sloppy mode.
6632 "function f(x, {x : x}){}",
6633 "function f(x, {x}){}",
6634 "function f({x,x}) {}",
6635 "function f(x, x, {a}) {}",
6636 nullptr};
6637 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006638 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006639}
6640
6641
6642TEST(DestructuringDisallowPatternsInSingleParamArrows) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006643 const char* context_data[][2] = {{"'use strict';", ""},
6644 {"function outer() { 'use strict';", "}"},
6645 {"", ""},
6646 {"function outer() { ", "}"},
6647 {nullptr, nullptr}};
6648
6649 // clang-format off
6650 const char* error_data[] = {
6651 "var f = {x} => {};",
6652 "var f = {x,y} => {};",
6653 nullptr};
6654 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006655 RunParserSyncTest(context_data, error_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006656}
6657
6658
6659TEST(DefaultParametersYieldInInitializers) {
6660 // clang-format off
6661 const char* sloppy_function_context_data[][2] = {
6662 {"(function f(", ") { });"},
6663 {NULL, NULL}
6664 };
6665
6666 const char* strict_function_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006667 {"'use strict'; (function f(", ") { });"},
6668 {NULL, NULL}
6669 };
6670
6671 const char* sloppy_arrow_context_data[][2] = {
6672 {"((", ")=>{});"},
6673 {NULL, NULL}
6674 };
6675
6676 const char* strict_arrow_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006677 {"'use strict'; ((", ")=>{});"},
6678 {NULL, NULL}
6679 };
6680
6681 const char* generator_context_data[][2] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006682 {"'use strict'; (function *g(", ") { });"},
6683 {"(function *g(", ") { });"},
Ben Murdochda12d292016-06-02 14:46:10 +01006684 // Arrow function within generator has the same rules.
6685 {"'use strict'; (function *g() { (", ") => {} });"},
6686 {"(function *g() { (", ") => {} });"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006687 {NULL, NULL}
6688 };
6689
6690 const char* parameter_data[] = {
6691 "x=yield",
6692 "x, y=yield",
6693 "{x=yield}",
6694 "[x=yield]",
6695
6696 "x=(yield)",
6697 "x, y=(yield)",
6698 "{x=(yield)}",
6699 "[x=(yield)]",
6700
6701 "x=f(yield)",
6702 "x, y=f(yield)",
6703 "{x=f(yield)}",
6704 "[x=f(yield)]",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006706 "{x}=yield",
6707 "[x]=yield",
6708
6709 "{x}=(yield)",
6710 "[x]=(yield)",
6711
6712 "{x}=f(yield)",
6713 "[x]=f(yield)",
6714 NULL
6715 };
6716
Ben Murdochda12d292016-06-02 14:46:10 +01006717 // Because classes are always in strict mode, these are always errors.
6718 const char* always_error_param_data[] = {
6719 "x = class extends (yield) { }",
6720 "x = class extends f(yield) { }",
6721 "x = class extends (null, yield) { }",
6722 "x = class extends (a ? null : yield) { }",
6723 "[x] = [class extends (a ? null : yield) { }]",
6724 "[x = class extends (a ? null : yield) { }]",
6725 "[x = class extends (a ? null : yield) { }] = [null]",
6726 "x = class { [yield]() { } }",
6727 "x = class { static [yield]() { } }",
6728 "x = class { [(yield, 1)]() { } }",
6729 "x = class { [y = (yield, 1)]() { } }",
6730 NULL
6731 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006732 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006733
Ben Murdochda12d292016-06-02 14:46:10 +01006734 RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess);
6735 RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006736
Ben Murdochda12d292016-06-02 14:46:10 +01006737 RunParserSyncTest(strict_function_context_data, parameter_data, kError);
6738 RunParserSyncTest(strict_arrow_context_data, parameter_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006739
Ben Murdochda12d292016-06-02 14:46:10 +01006740 RunParserSyncTest(generator_context_data, parameter_data, kError);
6741 RunParserSyncTest(generator_context_data, always_error_param_data, kError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006742}
6743
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006744TEST(SpreadArray) {
6745 const char* context_data[][2] = {
6746 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6747
6748 // clang-format off
6749 const char* data[] = {
6750 "[...a]",
6751 "[a, ...b]",
6752 "[...a,]",
6753 "[...a, ,]",
6754 "[, ...a]",
6755 "[...a, ...b]",
6756 "[...a, , ...b]",
6757 "[...[...a]]",
6758 "[, ...a]",
6759 "[, , ...a]",
6760 NULL};
6761 // clang-format on
6762 RunParserSyncTest(context_data, data, kSuccess);
6763}
6764
6765
6766TEST(SpreadArrayError) {
6767 const char* context_data[][2] = {
6768 {"'use strict';", ""}, {"", ""}, {NULL, NULL}};
6769
6770 // clang-format off
6771 const char* data[] = {
6772 "[...]",
6773 "[a, ...]",
6774 "[..., ]",
6775 "[..., ...]",
6776 "[ (...a)]",
6777 NULL};
6778 // clang-format on
6779 RunParserSyncTest(context_data, data, kError);
6780}
6781
6782
6783TEST(NewTarget) {
6784 // clang-format off
6785 const char* good_context_data[][2] = {
6786 {"function f() {", "}"},
6787 {"'use strict'; function f() {", "}"},
6788 {"var f = function() {", "}"},
6789 {"'use strict'; var f = function() {", "}"},
6790 {"({m: function() {", "}})"},
6791 {"'use strict'; ({m: function() {", "}})"},
6792 {"({m() {", "}})"},
6793 {"'use strict'; ({m() {", "}})"},
6794 {"({get x() {", "}})"},
6795 {"'use strict'; ({get x() {", "}})"},
6796 {"({set x(_) {", "}})"},
6797 {"'use strict'; ({set x(_) {", "}})"},
6798 {"class C {m() {", "}}"},
6799 {"class C {get x() {", "}}"},
6800 {"class C {set x(_) {", "}}"},
6801 {NULL}
6802 };
6803
6804 const char* bad_context_data[][2] = {
6805 {"", ""},
6806 {"'use strict';", ""},
6807 {NULL}
6808 };
6809
6810 const char* data[] = {
6811 "new.target",
6812 "{ new.target }",
6813 "() => { new.target }",
6814 "() => new.target",
6815 "if (1) { new.target }",
6816 "if (1) {} else { new.target }",
6817 "while (0) { new.target }",
6818 "do { new.target } while (0)",
6819 NULL
6820 };
6821
6822 static const ParserFlag always_flags[] = {
6823 kAllowHarmonyNewTarget,
6824 kAllowHarmonySloppy,
6825 };
6826 // clang-format on
6827
6828 RunParserSyncTest(good_context_data, data, kSuccess, NULL, 0, always_flags,
6829 arraysize(always_flags));
6830 RunParserSyncTest(bad_context_data, data, kError, NULL, 0, always_flags,
6831 arraysize(always_flags));
6832}
6833
6834
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006835TEST(ConstSloppy) {
6836 // clang-format off
6837 const char* context_data[][2] = {
6838 {"", ""},
6839 {"{", "}"},
6840 {NULL, NULL}
6841 };
6842
6843 const char* data[] = {
6844 "const x = 1",
6845 "for (const x = 1; x < 1; x++) {}",
6846 "for (const x in {}) {}",
6847 "for (const x of []) {}",
6848 NULL
6849 };
6850 // clang-format on
Ben Murdochda12d292016-06-02 14:46:10 +01006851 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006852 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
6853 arraysize(always_flags));
6854}
6855
6856
6857TEST(LetSloppy) {
6858 // clang-format off
6859 const char* context_data[][2] = {
6860 {"", ""},
6861 {"'use strict';", ""},
6862 {"{", "}"},
6863 {NULL, NULL}
6864 };
6865
6866 const char* data[] = {
6867 "let x",
6868 "let x = 1",
6869 "for (let x = 1; x < 1; x++) {}",
6870 "for (let x in {}) {}",
6871 "for (let x of []) {}",
6872 NULL
6873 };
6874 // clang-format on
6875
6876 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
6877 kAllowHarmonySloppyLet};
6878 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
6879 arraysize(always_flags));
6880}
6881
6882
6883TEST(LanguageModeDirectivesNonSimpleParameterListErrors) {
6884 // TC39 deemed "use strict" directives to be an error when occurring in the
6885 // body of a function with non-simple parameter list, on 29/7/2015.
6886 // https://goo.gl/ueA7Ln
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006887 const char* context_data[][2] = {
6888 {"function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006889 {"function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006890 {"class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006891 {"var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006892 {"var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006893 {"var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006894 {"var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006895 {"var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006896
6897 {"'use strict'; function f(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006898 {"'use strict'; function* g(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006899 {"'use strict'; class c { foo(", ") { 'use strict' }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006900 {"'use strict'; var a = (", ") => { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006901 {"'use strict'; var o = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006902 {"'use strict'; var o = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006903 {"'use strict'; var c = { m(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006904 {"'use strict'; var c = { *gm(", ") { 'use strict'; }"},
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006905
6906 {NULL, NULL}};
6907
6908 const char* data[] = {
6909 // TODO(@caitp): support formal parameter initializers
6910 "{}",
6911 "[]",
6912 "[{}]",
6913 "{a}",
6914 "a, {b}",
6915 "a, b, {c, d, e}",
6916 "initializer = true",
6917 "a, b, c = 1",
6918 "...args",
6919 "a, b, ...rest",
6920 "[a, b, ...rest]",
6921 "{ bindingPattern = {} }",
6922 "{ initializedBindingPattern } = { initializedBindingPattern: true }",
6923 NULL};
6924
Ben Murdochda12d292016-06-02 14:46:10 +01006925 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006926 RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
6927 arraysize(always_flags));
6928}
6929
6930
6931TEST(LetSloppyOnly) {
6932 // clang-format off
6933 const char* context_data[][2] = {
6934 {"", ""},
6935 {"{", "}"},
6936 {"(function() {", "})()"},
6937 {NULL, NULL}
6938 };
6939
6940 const char* data[] = {
6941 "let",
6942 "let = 1",
6943 "for (let = 1; let < 1; let++) {}",
6944 "for (let in {}) {}",
6945 "for (var let = 1; let < 1; let++) {}",
6946 "for (var let in {}) {}",
6947 "for (var [let] = 1; let < 1; let++) {}",
6948 "for (var [let] in {}) {}",
6949 "var let",
6950 "var [let] = []",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006951 NULL
6952 };
6953 // clang-format on
6954
Ben Murdochda12d292016-06-02 14:46:10 +01006955 static const ParserFlag always_flags[] = {kAllowHarmonySloppy,
6956 kAllowHarmonySloppyLet};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006957 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
6958 arraysize(always_flags));
6959
6960 // Some things should be rejected even in sloppy mode
6961 // This addresses BUG(v8:4403).
6962
6963 // clang-format off
6964 const char* fail_data[] = {
6965 "let let = 1",
6966 "for (let let = 1; let < 1; let++) {}",
6967 "for (let let in {}) {}",
6968 "for (let let of []) {}",
6969 "const let = 1",
6970 "for (const let = 1; let < 1; let++) {}",
6971 "for (const let in {}) {}",
6972 "for (const let of []) {}",
6973 "let [let] = 1",
6974 "for (let [let] = 1; let < 1; let++) {}",
6975 "for (let [let] in {}) {}",
6976 "for (let [let] of []) {}",
6977 "const [let] = 1",
6978 "for (const [let] = 1; let < 1; let++) {}",
6979 "for (const [let] in {}) {}",
6980 "for (const [let] of []) {}",
Ben Murdoch097c5b22016-05-18 11:27:45 +01006981
6982 // Sprinkle in the escaped version too.
6983 "let l\\u0065t = 1",
6984 "const l\\u0065t = 1",
6985 "let [l\\u0065t] = 1",
6986 "const [l\\u0065t] = 1",
6987 "for (let l\\u0065t in {}) {}",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006988 NULL
6989 };
6990 // clang-format on
6991
Ben Murdochda12d292016-06-02 14:46:10 +01006992 static const ParserFlag fail_flags[] = {kAllowHarmonySloppy,
6993 kAllowHarmonySloppyLet};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006994 RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags,
6995 arraysize(fail_flags));
6996}
6997
6998
6999TEST(EscapedKeywords) {
7000 // clang-format off
7001 const char* sloppy_context_data[][2] = {
7002 {"", ""},
7003 {NULL, NULL}
7004 };
7005
7006 const char* strict_context_data[][2] = {
7007 {"'use strict';", ""},
7008 {NULL, NULL}
7009 };
7010
7011 const char* fail_data[] = {
7012 "for (var i = 0; i < 100; ++i) { br\\u0065ak; }",
7013 "cl\\u0061ss Foo {}",
7014 "var x = cl\\u0061ss {}",
7015 "\\u0063onst foo = 1;",
7016 "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }",
7017 "d\\u0065bugger;",
7018 "d\\u0065lete this.a;",
7019 "\\u0063o { } while(0)",
7020 "if (d\\u006f { true }) {}",
7021 "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }",
7022 "e\\u0078port var foo;",
7023 "try { } catch (e) {} f\\u0069nally { }",
7024 "f\\u006fr (var i = 0; i < 10; ++i);",
7025 "f\\u0075nction fn() {}",
7026 "var f = f\\u0075nction() {}",
7027 "\\u0069f (true) { }",
7028 "\\u0069mport blah from './foo.js';",
7029 "n\\u0065w function f() {}",
7030 "(function() { r\\u0065turn; })()",
7031 "class C extends function() {} { constructor() { sup\\u0065r() } }",
7032 "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }",
7033 "sw\\u0069tch (this.a) {}",
7034 "var x = th\\u0069s;",
7035 "th\\u0069s.a = 1;",
7036 "thr\\u006fw 'boo';",
7037 "t\\u0072y { true } catch (e) {}",
7038 "var x = typ\\u0065of 'blah'",
7039 "v\\u0061r a = true",
7040 "var v\\u0061r = true",
7041 "(function() { return v\\u006fid 0; })()",
7042 "wh\\u0069le (true) { }",
7043 "w\\u0069th (this.scope) { }",
7044 "(function*() { y\\u0069eld 1; })()",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007045 "(function*() { var y\\u0069eld = 1; })()",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007046
7047 "var \\u0065num = 1;",
7048 "var { \\u0065num } = {}",
7049 "(\\u0065num = 1);",
7050
7051 // Null / Boolean literals
7052 "(x === n\\u0075ll);",
7053 "var x = n\\u0075ll;",
7054 "var n\\u0075ll = 1;",
7055 "var { n\\u0075ll } = { 1 };",
7056 "n\\u0075ll = 1;",
7057 "(x === tr\\u0075e);",
7058 "var x = tr\\u0075e;",
7059 "var tr\\u0075e = 1;",
7060 "var { tr\\u0075e } = {};",
7061 "tr\\u0075e = 1;",
7062 "(x === f\\u0061lse);",
7063 "var x = f\\u0061lse;",
7064 "var f\\u0061lse = 1;",
7065 "var { f\\u0061lse } = {};",
7066 "f\\u0061lse = 1;",
7067
7068 // TODO(caitp): consistent error messages for labeled statements and
7069 // expressions
7070 "switch (this.a) { c\\u0061se 6: break; }",
7071 "try { } c\\u0061tch (e) {}",
7072 "switch (this.a) { d\\u0065fault: break; }",
7073 "class C \\u0065xtends function B() {} {}",
7074 "for (var a i\\u006e this) {}",
7075 "if ('foo' \\u0069n this) {}",
7076 "if (this \\u0069nstanceof Array) {}",
7077 "(n\\u0065w function f() {})",
7078 "(typ\\u0065of 123)",
7079 "(v\\u006fid 0)",
7080 "do { ; } wh\\u0069le (true) { }",
7081 "(function*() { return (n++, y\\u0069eld 1); })()",
7082 "class C { st\\u0061tic bar() {} }",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007083 "class C { st\\u0061tic *bar() {} }",
7084 "class C { st\\u0061tic get bar() {} }",
7085 "class C { st\\u0061tic set bar() {} }",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007086
Ben Murdoch097c5b22016-05-18 11:27:45 +01007087 // TODO(adamk): These should not be errors in sloppy mode.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007088 "(y\\u0069eld);",
7089 "var y\\u0069eld = 1;",
7090 "var { y\\u0069eld } = {};",
7091 NULL
7092 };
7093 // clang-format on
7094
Ben Murdochda12d292016-06-02 14:46:10 +01007095 static const ParserFlag always_flags[] = {kAllowHarmonySloppy};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007096 RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7097 always_flags, arraysize(always_flags));
7098 RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0,
7099 always_flags, arraysize(always_flags));
7100 RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0,
7101 always_flags, arraysize(always_flags));
7102
7103 // clang-format off
7104 const char* let_data[] = {
7105 "var l\\u0065t = 1;",
7106 "l\\u0065t = 1;",
7107 "(l\\u0065t === 1);",
7108 NULL
7109 };
7110 // clang-format on
7111
Ben Murdoch097c5b22016-05-18 11:27:45 +01007112 RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007113 always_flags, arraysize(always_flags));
7114 RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
7115 always_flags, arraysize(always_flags));
7116
Ben Murdochda12d292016-06-02 14:46:10 +01007117 static const ParserFlag sloppy_let_flags[] = {kAllowHarmonySloppy,
7118 kAllowHarmonySloppyLet};
Ben Murdoch097c5b22016-05-18 11:27:45 +01007119 RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007120 sloppy_let_flags, arraysize(sloppy_let_flags));
7121
7122 // Non-errors in sloppy mode
7123 const char* valid_data[] = {"(\\u0069mplements = 1);",
7124 "var impl\\u0065ments = 1;",
7125 "var { impl\\u0065ments } = {};",
7126 "(\\u0069nterface = 1);",
7127 "var int\\u0065rface = 1;",
7128 "var { int\\u0065rface } = {};",
7129 "(p\\u0061ckage = 1);",
7130 "var packa\\u0067e = 1;",
7131 "var { packa\\u0067e } = {};",
7132 "(p\\u0072ivate = 1);",
7133 "var p\\u0072ivate;",
7134 "var { p\\u0072ivate } = {};",
7135 "(prot\\u0065cted);",
7136 "var prot\\u0065cted = 1;",
7137 "var { prot\\u0065cted } = {};",
7138 "(publ\\u0069c);",
7139 "var publ\\u0069c = 1;",
7140 "var { publ\\u0069c } = {};",
Ben Murdoch097c5b22016-05-18 11:27:45 +01007141 "(st\\u0061tic);",
7142 "var st\\u0061tic = 1;",
7143 "var { st\\u0061tic } = {};",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007144 NULL};
7145 RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
7146 always_flags, arraysize(always_flags));
7147 RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7148 always_flags, arraysize(always_flags));
7149 RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0,
7150 always_flags, arraysize(always_flags));
7151}
7152
7153
7154TEST(MiscSyntaxErrors) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007155 // clang-format off
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007156 const char* context_data[][2] = {
Ben Murdoch097c5b22016-05-18 11:27:45 +01007157 { "'use strict'", "" },
7158 { "", "" },
7159 { NULL, NULL }
7160 };
7161 const char* error_data[] = {
7162 "for (();;) {}",
7163
7164 // crbug.com/582626
7165 "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
7166 NULL
7167 };
7168 // clang-format on
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007169
7170 RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
7171}
Ben Murdoch097c5b22016-05-18 11:27:45 +01007172
Ben Murdochda12d292016-06-02 14:46:10 +01007173
7174TEST(EscapeSequenceErrors) {
7175 // clang-format off
7176 const char* context_data[][2] = {
7177 { "'", "'" },
7178 { "\"", "\"" },
7179 { "`", "`" },
7180 { "`${'", "'}`" },
7181 { "`${\"", "\"}`" },
7182 { "`${`", "`}`" },
7183 { "f(tag`", "`);" },
7184 { NULL, NULL }
7185 };
7186 const char* error_data[] = {
7187 "\\uABCG",
7188 "\\u{ZZ}",
7189 "\\u{FFZ}",
7190 "\\u{FFFFFFFFFF }",
7191 "\\u{110000}",
7192 "\\u{110000",
7193 "\\u{FFFD }",
7194 "\\xZF",
7195 NULL
7196 };
7197 // clang-format on
7198
7199 RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
7200}
7201
7202
Ben Murdoch097c5b22016-05-18 11:27:45 +01007203TEST(FunctionSentErrors) {
7204 // clang-format off
7205 const char* context_data[][2] = {
7206 { "'use strict'", "" },
7207 { "", "" },
7208 { NULL, NULL }
7209 };
7210 const char* error_data[] = {
7211 "var x = function.sent",
7212 "function* g() { yield function.s\\u0065nt; }",
7213 NULL
7214 };
7215 // clang-format on
7216
7217 static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
7218 RunParserSyncTest(context_data, error_data, kError, always_flags,
7219 arraysize(always_flags));
7220}
7221
7222TEST(NewTargetErrors) {
7223 // clang-format off
7224 const char* context_data[][2] = {
7225 { "'use strict'", "" },
7226 { "", "" },
7227 { NULL, NULL }
7228 };
7229 const char* error_data[] = {
7230 "var x = new.target",
7231 "function f() { return new.t\\u0061rget; }",
7232 NULL
7233 };
7234 // clang-format on
7235 RunParserSyncTest(context_data, error_data, kError);
7236}
Ben Murdochda12d292016-06-02 14:46:10 +01007237
7238TEST(FunctionDeclarationError) {
7239 // clang-format off
7240 const char* strict_context[][2] = {
7241 { "'use strict';", "" },
7242 { "'use strict'; { ", "}" },
7243 {"(function() { 'use strict';", "})()"},
7244 {"(function() { 'use strict'; {", "} })()"},
7245 { NULL, NULL }
7246 };
7247 const char* sloppy_context[][2] = {
7248 { "", "" },
7249 { "{", "}" },
7250 {"(function() {", "})()"},
7251 {"(function() { {", "} })()"},
7252 { NULL, NULL }
7253 };
7254 // Invalid in all contexts
7255 const char* error_data[] = {
7256 "try function foo() {} catch (e) {}",
7257 NULL
7258 };
7259 // Valid in sloppy mode only, and only when the
7260 // --harmony-restrictive-declarations flag is off
7261 const char* unrestricted_data[] = {
7262 "do function foo() {} while (0);",
7263 "for (;false;) function foo() {}",
7264 "for (var i = 0; i < 1; i++) function f() { };",
7265 "for (var x in {a: 1}) function f() { };",
7266 "for (var x in {}) function f() { };",
7267 "for (var x in {}) function foo() {}",
7268 "for (x in {a: 1}) function f() { };",
7269 "for (x in {}) function f() { };",
7270 "var x; for (x in {}) function foo() {}",
7271 "with ({}) function f() { };",
7272 "do label: function foo() {} while (0);",
7273 "for (;false;) label: function foo() {}",
7274 "for (var i = 0; i < 1; i++) label: function f() { };",
7275 "for (var x in {a: 1}) label: function f() { };",
7276 "for (var x in {}) label: function f() { };",
7277 "for (var x in {}) label: function foo() {}",
7278 "for (x in {a: 1}) label: function f() { };",
7279 "for (x in {}) label: function f() { };",
7280 "var x; for (x in {}) label: function foo() {}",
7281 "with ({}) label: function f() { };",
7282 "if (true) label: function f() {}",
7283 "if (true) {} else label: function f() {}",
7284 NULL
7285 };
7286 // Valid only in sloppy mode, with or without
7287 // --harmony-restrictive-declarations
7288 const char* sloppy_data[] = {
7289 "if (true) function foo() {}",
7290 "if (false) {} else function f() { };",
7291 "label: function f() { }",
7292 "label: if (true) function f() { }",
7293 "label: if (true) {} else function f() { }",
7294 NULL
7295 };
7296 // clang-format on
7297
7298 static const ParserFlag restrictive_flags[] = {
7299 kAllowHarmonyRestrictiveDeclarations};
7300
7301 // Nothing parses in strict mode without a SyntaxError
7302 RunParserSyncTest(strict_context, error_data, kError);
7303 RunParserSyncTest(strict_context, error_data, kError, NULL, 0,
7304 restrictive_flags, arraysize(restrictive_flags));
7305 RunParserSyncTest(strict_context, unrestricted_data, kError);
7306 RunParserSyncTest(strict_context, unrestricted_data, kError, NULL, 0,
7307 restrictive_flags, arraysize(restrictive_flags));
7308 RunParserSyncTest(strict_context, sloppy_data, kError);
7309 RunParserSyncTest(strict_context, sloppy_data, kError, NULL, 0,
7310 restrictive_flags, arraysize(restrictive_flags));
7311
7312 // In sloppy mode, some things are successful, depending on the flag
7313 RunParserSyncTest(sloppy_context, error_data, kError);
7314 RunParserSyncTest(sloppy_context, error_data, kError, NULL, 0,
7315 restrictive_flags, arraysize(restrictive_flags));
7316 RunParserSyncTest(sloppy_context, unrestricted_data, kSuccess);
7317 RunParserSyncTest(sloppy_context, unrestricted_data, kError, NULL, 0,
7318 restrictive_flags, arraysize(restrictive_flags));
7319 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess);
7320 RunParserSyncTest(sloppy_context, sloppy_data, kSuccess, restrictive_flags,
7321 arraysize(restrictive_flags));
7322}
7323
7324TEST(ExponentiationOperator) {
7325 // clang-format off
7326 const char* context_data[][2] = {
7327 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7328 { "var O = { p: 1 }, x = 10; ; (", ")" },
7329 { "var O = { p: 1 }, x = 10; foo(", ")" },
7330 { NULL, NULL }
7331 };
7332 const char* data[] = {
7333 "(delete O.p) ** 10",
7334 "(delete x) ** 10",
7335 "(~O.p) ** 10",
7336 "(~x) ** 10",
7337 "(!O.p) ** 10",
7338 "(!x) ** 10",
7339 "(+O.p) ** 10",
7340 "(+x) ** 10",
7341 "(-O.p) ** 10",
7342 "(-x) ** 10",
7343 "(typeof O.p) ** 10",
7344 "(typeof x) ** 10",
7345 "(void 0) ** 10",
7346 "(void O.p) ** 10",
7347 "(void x) ** 10",
7348 "++O.p ** 10",
7349 "++x ** 10",
7350 "--O.p ** 10",
7351 "--x ** 10",
7352 "O.p++ ** 10",
7353 "x++ ** 10",
7354 "O.p-- ** 10",
7355 "x-- ** 10",
7356 NULL
7357 };
7358 // clang-format on
7359
7360 static const ParserFlag always_flags[] = {
7361 kAllowHarmonyExponentiationOperator};
7362 RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
7363 arraysize(always_flags));
7364}
7365
7366TEST(ExponentiationOperatorErrors) {
7367 // clang-format off
7368 const char* context_data[][2] = {
7369 { "var O = { p: 1 }, x = 10; ; if (", ") { foo(); }" },
7370 { "var O = { p: 1 }, x = 10; ; (", ")" },
7371 { "var O = { p: 1 }, x = 10; foo(", ")" },
7372 { NULL, NULL }
7373 };
7374 const char* error_data[] = {
7375 "delete O.p ** 10",
7376 "delete x ** 10",
7377 "~O.p ** 10",
7378 "~x ** 10",
7379 "!O.p ** 10",
7380 "!x ** 10",
7381 "+O.p ** 10",
7382 "+x ** 10",
7383 "-O.p ** 10",
7384 "-x ** 10",
7385 "typeof O.p ** 10",
7386 "typeof x ** 10",
7387 "void ** 10",
7388 "void O.p ** 10",
7389 "void x ** 10",
7390 "++delete O.p ** 10",
7391 "--delete O.p ** 10",
7392 "++~O.p ** 10",
7393 "++~x ** 10",
7394 "--!O.p ** 10",
7395 "--!x ** 10",
7396 "++-O.p ** 10",
7397 "++-x ** 10",
7398 "--+O.p ** 10",
7399 "--+x ** 10",
7400 "[ x ] **= [ 2 ]",
7401 "[ x **= 2 ] = [ 2 ]",
7402 "{ x } **= { x: 2 }",
7403 "{ x: x **= 2 ] = { x: 2 }",
7404 // TODO(caitp): a Call expression as LHS should be an early ReferenceError!
7405 // "Array() **= 10",
7406 NULL
7407 };
7408 // clang-format on
7409
7410 static const ParserFlag always_flags[] = {
7411 kAllowHarmonyExponentiationOperator};
7412 RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
7413 arraysize(always_flags));
7414}